mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-18 08:50:29 +02:00
Merge pull request #22020 from hrydgard/sdl-window-rework
SDL GL/Vulkan init rework
This commit is contained in:
7 files changed
+191
-142
No files matched your search
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Launch PPSSPPSDL (WSL)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build PPSSPP (WSL debug)",
|
||||
"program": "/home/hrydg/ppsspp/build/PPSSPPSDL",
|
||||
"osx": {
|
||||
"program": "${workspaceFolder}/build/PPSSPPSDL.app/Contents/MacOS/PPSSPPSDL"
|
||||
},
|
||||
"linux": {
|
||||
"program": "/home/hrydg/ppsspp/build/PPSSPPSDL"
|
||||
},
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/home/hrydg/ppsspp",
|
||||
"sourceFileMap": {
|
||||
"/home/hrydg/ppsspp": "${workspaceFolder}"
|
||||
},
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"logging": {
|
||||
"programOutput": true
|
||||
},
|
||||
"MIMode": "gdb",
|
||||
"pipeTransport": {
|
||||
"pipeProgram": "wsl.exe",
|
||||
"pipeArgs": [
|
||||
"-d",
|
||||
"Ubuntu",
|
||||
"--"
|
||||
],
|
||||
"pipeCwd": "C:/",
|
||||
"quoteArgs": false,
|
||||
"debuggerPath": "/usr/bin/gdb"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"comment": "Copy this to launch.json if you want to, or edit as desired first",
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(lldb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"osx": {
|
||||
"program": "${workspaceFolder}/build/PPSSPPSDL.app/Contents/MacOS/PPSSPPSDL"
|
||||
},
|
||||
"linux": {
|
||||
"program": "${workspaceRoot}/build/PPSSPPSDL"
|
||||
},
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Common/System/Display.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
#include "Common/GPU/MiscTypes.h"
|
||||
#include "Common/Log.h"
|
||||
|
||||
DisplayProperties g_display;
|
||||
|
||||
@@ -70,6 +71,7 @@ DisplayProperties::DisplayProperties() {
|
||||
}
|
||||
|
||||
bool DisplayProperties::Recalculate(int new_pixel_xres, int new_pixel_yres, float new_scale_x, float new_scale_y, float customScale) {
|
||||
INFO_LOG(Log::G3D, "recalculate: %dx%d, %f, %f, %f", new_pixel_xres, new_pixel_yres, new_scale_x, new_scale_y, customScale);
|
||||
bool px_changed = false;
|
||||
if (new_pixel_xres > 0 && pixel_xres != new_pixel_xres) {
|
||||
pixel_xres = new_pixel_xres;
|
||||
|
||||
@@ -255,7 +255,7 @@ void ScreenManager::deviceRestored(Draw::DrawContext *draw) {
|
||||
}
|
||||
|
||||
void ScreenManager::resized() {
|
||||
INFO_LOG(Log::UI, "ScreenManager::resized(dp: %dx%d)", g_display.dp_xres, g_display.dp_yres);
|
||||
INFO_LOG(Log::UI, "ScreenManager::resized(g_display.dp_xres/dp_yres: %dx%d)", g_display.dp_xres, g_display.dp_yres);
|
||||
// Have to notify the whole stack, otherwise there will be problems when going back
|
||||
// to non-top screens.
|
||||
for (auto &layer : stack_) {
|
||||
|
||||
@@ -286,10 +286,15 @@ void EGL_Close() {
|
||||
|
||||
#endif // USING_EGL
|
||||
|
||||
// TODO: All this stuff doesn't really belong here.
|
||||
bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) {
|
||||
SDL_Window *window = *(SDL_Window **)data1;
|
||||
int mode = (int)(uintptr_t)data2;
|
||||
SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, int forceGLVersion, SDL_GLContext *glContextOut) {
|
||||
// We start hidden because we have to try several windows.
|
||||
// On Mac, full screen animates so each attempt is slow.
|
||||
mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN;
|
||||
SDL_Window *window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
struct GLVersionPair {
|
||||
int major;
|
||||
int minor;
|
||||
@@ -303,24 +308,14 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
#endif
|
||||
};
|
||||
|
||||
// We start hidden because we have to try several windows.
|
||||
// On Mac, full screen animates so each attempt is slow.
|
||||
mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
SDL_GetWindowPosition(window, &x, &y);
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
glContext_ = nullptr;
|
||||
SDL_GLContext glContext{};
|
||||
for (size_t i = 0; i < ARRAY_SIZE(attemptVersions); ++i) {
|
||||
const auto &ver = attemptVersions[i];
|
||||
// If we force a specific OpenGL version, skip the ones
|
||||
// that do not match, which may be all of them - e.g.
|
||||
// requesting nonsensical "--graphics=opengl0" reliably
|
||||
// skips straight to fallback code below.
|
||||
if (force_gl_version_ >= 0 && 10 * ver.major + ver.minor != force_gl_version_)
|
||||
if (forceGLVersion >= 0 && 10 * ver.major + ver.minor != forceGLVersion)
|
||||
continue;
|
||||
// Make sure to request a somewhat modern GL context at least - the
|
||||
// latest supported by MacOS X (really, really sad...)
|
||||
@@ -343,12 +338,8 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
glContext_ = SDL_GL_CreateContext(window);
|
||||
if (glContext_ != nullptr) {
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext != nullptr) {
|
||||
// Victory, got one.
|
||||
break;
|
||||
}
|
||||
@@ -358,7 +349,7 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
if (glContext_ == nullptr) {
|
||||
if (glContext == nullptr) {
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
@@ -366,28 +357,22 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", w, h, (SDL_WindowFlags)mode);
|
||||
if (window == nullptr) {
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
glContext_ = SDL_GL_CreateContext(window);
|
||||
if (glContext_ == nullptr) {
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (glContext == nullptr) {
|
||||
// OK, now we really have tried everything.
|
||||
NativeShutdown();
|
||||
fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we have a window that we can show finally.
|
||||
SDL_ShowWindow(window);
|
||||
// For some reason we have to set the position here, can't wait until after the window is shown (??).
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
#ifdef USING_EGL
|
||||
if (EGL_Open(window) != 0) {
|
||||
@@ -409,7 +394,7 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
// glx is not required, igore.
|
||||
if (glew_err != GLEW_OK && glew_err != GLEW_ERROR_NO_GLX_DISPLAY) {
|
||||
fprintf(stderr, "Failed to initialize glew!\n");
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
// Unfortunately, glew will generate an invalid enum error, ignore.
|
||||
if (gl_extensions.IsCoreContext)
|
||||
@@ -419,9 +404,17 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
fprintf(stderr, "OpenGL 2.0 or higher.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Sorry, this program requires OpenGL 2.0.\n");
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
*glContextOut = glContext;
|
||||
return window;
|
||||
}
|
||||
|
||||
bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) {
|
||||
SDL_Window *window = (SDL_Window *)data1;
|
||||
SDL_GLContext glContext = (SDL_GLContext)data2;
|
||||
glContext_ = glContext;
|
||||
|
||||
// Finally we can do the regular initialization.
|
||||
CheckGLExtensions();
|
||||
@@ -441,17 +434,12 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
SDL_GL_SwapWindow(window_);
|
||||
#endif
|
||||
});
|
||||
|
||||
renderManager_->SetSwapIntervalFunction([&](int interval) {
|
||||
INFO_LOG(Log::G3D, "SDL SwapInterval: %d", interval);
|
||||
SDL_GL_SetSwapInterval(interval);
|
||||
});
|
||||
|
||||
window_ = window;
|
||||
|
||||
// HACK: Ensure that the swap interval is set after context creation (needed for kmsdrm)
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -461,7 +449,7 @@ void SDLGLGraphicsContext::ShutdownSurface() {
|
||||
renderManager_ = nullptr;
|
||||
}
|
||||
|
||||
bool SDLGLGraphicsContext::InitAPI(void *wnd, std::string *deviceName, std::string *errorMessage) {
|
||||
bool SDLGLGraphicsContext::InitAPI(void *ctx, std::string *deviceName, std::string *errorMessage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
class SDLGLGraphicsContext : public GraphicsContext {
|
||||
public:
|
||||
SDLGLGraphicsContext(int force_gl_version) : force_gl_version_(force_gl_version) {}
|
||||
SDLGLGraphicsContext() {}
|
||||
|
||||
bool InitAPI(void *wnd, std::string *deviceName, std::string *errorMessage) override;
|
||||
void ShutdownAPI() override;
|
||||
|
||||
// Returns 0 on success.
|
||||
// data1 should be a *pointer* to the SDL_Window pointer, data2 is the SDL_WindowFlags.
|
||||
// data1 should be the SDL_Window pointer, data2 is the SDL_WindowFlags.
|
||||
bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) override;
|
||||
void ShutdownSurface() override;
|
||||
|
||||
@@ -43,6 +43,7 @@ private:
|
||||
Draw::DrawContext *draw_ = nullptr;
|
||||
SDL_Window *window_ = nullptr;
|
||||
SDL_GLContext glContext_ = nullptr;
|
||||
int force_gl_version_ = 0;
|
||||
GLRenderManager *renderManager_ = nullptr;
|
||||
};
|
||||
|
||||
SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, int forceGLVersion, SDL_GLContext *glContextOut);
|
||||
+85
-93
@@ -96,8 +96,6 @@ static float g_ForcedDPI = 0.0f; // if this is 0.0f, use g_DesktopDPI
|
||||
static float g_RefreshRate = 60.f;
|
||||
static int g_sampleRate = 44100;
|
||||
|
||||
static bool g_rebootEmuThread = false;
|
||||
|
||||
static SDL_AudioSpec g_retFmt;
|
||||
static int g_audioFramesPerBuffer = 0;
|
||||
|
||||
@@ -1334,6 +1332,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
{
|
||||
INFO_LOG(Log::UI, "SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: %d x %d", event.window.data1, event.window.data2);
|
||||
int new_width = event.window.data1;
|
||||
int new_height = event.window.data2;
|
||||
|
||||
@@ -1342,6 +1341,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
Uint64 window_flags = SDL_GetWindowFlags(window);
|
||||
bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN) != 0;
|
||||
|
||||
// !!! This is the wrong thread!
|
||||
// This one calls NativeResized if the size changed.
|
||||
Native_UpdateScreenScale(new_width, new_height, UIScaleFactorToMultiplier(g_Config.iUIScaleFactor));
|
||||
|
||||
@@ -1408,7 +1408,9 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
#endif
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
{
|
||||
if (event.key.repeat > 0) { break;}
|
||||
if (event.key.repeat > 0) {
|
||||
break;
|
||||
}
|
||||
int k = event.key.key;
|
||||
KeyInput key;
|
||||
key.flags = KeyInputFlags::DOWN;
|
||||
@@ -1420,15 +1422,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
key.deviceId = DEVICE_ID_KEYBOARD;
|
||||
NativeKey(key);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (k == SDLK_F7) {
|
||||
fprintf(stderr, "f7 pressed - rebooting emuthread\n");
|
||||
g_rebootEmuThread = true;
|
||||
}
|
||||
#endif
|
||||
// Convenience subset of what
|
||||
// "Enable standard shortcut keys"
|
||||
// does on Windows.
|
||||
// Convenience subset of what "Enable standard shortcut keys" does on Windows.
|
||||
if (g_Config.bSystemControls) {
|
||||
bool ctrl = bool(event.key.mod & SDL_KMOD_CTRL);
|
||||
if (ctrl && (k == SDLK_W))
|
||||
@@ -1539,6 +1533,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
switch (event.button.button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
{
|
||||
INFO_LOG(Log::UI, "SDL_EVENT_MOUSE_BUTTON_DOWN: %f x %f", event.button.x, event.button.y);
|
||||
// We have to juggle around 3 kinds of "DPI spaces" if a logical DPI is
|
||||
// provided (through --dpi, it is equal to system DPI if unspecified):
|
||||
// - SDL gives us motion events in "system DPI" points
|
||||
@@ -1749,6 +1744,7 @@ void UpdateSDLCursor() {
|
||||
}
|
||||
|
||||
bool DetermineVulkanWindowSystem(SDL_Window *window, WindowSystem *windowSystem, void **data1, void **data2) {
|
||||
_dbg_assert_(window);
|
||||
SDL_PropertiesID windowProps = SDL_GetWindowProperties(window);
|
||||
void *x11Display = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr);
|
||||
if (x11Display != nullptr) {
|
||||
@@ -2035,88 +2031,101 @@ int main(int argc, char *argv[]) {
|
||||
h = g_Config.iWindowHeight;
|
||||
}
|
||||
|
||||
GraphicsContext *graphicsContext = nullptr;
|
||||
SDL_Window *window = nullptr;
|
||||
|
||||
// Switch away from Vulkan if not available.
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN && !vulkanMayBeAvailable) {
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
int fallbackGPUBackend = -1;
|
||||
switch ((GPUBackend)g_Config.iGPUBackend) {
|
||||
case GPUBackend::VULKAN:
|
||||
if (!vulkanMayBeAvailable) {
|
||||
fprintf(stderr, "Vulkan is not available, switching to OpenGL.\n");
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
} else {
|
||||
fallbackGPUBackend = (int)GPUBackend::OPENGL;
|
||||
}
|
||||
break;
|
||||
case GPUBackend::OPENGL:
|
||||
fallbackGPUBackend = (int)GPUBackend::VULKAN;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown GPU backend %d, switching to Vulkan.\n", g_Config.iGPUBackend);
|
||||
g_Config.iGPUBackend = (int)GPUBackend::VULKAN;
|
||||
fallbackGPUBackend = (int)GPUBackend::OPENGL;
|
||||
break;
|
||||
}
|
||||
|
||||
window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode);
|
||||
SDL_Window *window = nullptr;
|
||||
auto initializeBackend = [&](GPUBackend backend, GraphicsContext **graphicsContext, std::string *errorMessage) -> bool {
|
||||
// Surface init params.
|
||||
WindowSystem windowSystem = WINDOWSYSTEM_NONE;
|
||||
void *data1 = nullptr;
|
||||
void *data2 = nullptr;
|
||||
|
||||
// Surface init params. These are set up for OpenGL by default.
|
||||
WindowSystem windowSystem = WINDOWSYSTEM_NONE;
|
||||
void *data1 = &window;
|
||||
void *data2 = nullptr;
|
||||
GraphicsContext *ctx = nullptr;
|
||||
if (backend == GPUBackend::OPENGL) {
|
||||
SDL_GLContext glContext = nullptr;
|
||||
window = CreateSDLGLWindowAndContext(x, y, w, h, mode, cmdLineOptions.force_gl_version, &glContext);
|
||||
|
||||
std::string error_message;
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
|
||||
SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(cmdLineOptions.force_gl_version);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
data1 = (void *)window;
|
||||
data2 = (void *)glContext;
|
||||
|
||||
glctx->InitAPI(nullptr, nullptr, &error_message);
|
||||
if (!glctx->InitSurface(WINDOWSYSTEM_NONE, &window, (void *)(uintptr_t)mode, &error_message)) {
|
||||
// Let's try the fallback once per process run.
|
||||
fprintf(stderr, "GL init error '%s' - falling back to Vulkan\n", error_message.c_str());
|
||||
g_Config.iGPUBackend = (int)GPUBackend::VULKAN;
|
||||
SetGPUBackend((GPUBackend)g_Config.iGPUBackend);
|
||||
delete glctx;
|
||||
ctx = new SDLGLGraphicsContext();
|
||||
} else {
|
||||
mode |= SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN;
|
||||
window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
// Overwrite the surface init params with what we need for Vulkan..
|
||||
if (!DetermineVulkanWindowSystem(window, &windowSystem, &data1, &data2)) {
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE : This should match the lines below in the Vulkan case.
|
||||
VulkanGraphicsContext *vkctx = new VulkanGraphicsContext();
|
||||
vkctx->InitAPI(nullptr, &g_Config.sVulkanDevice, &error_message);
|
||||
ctx = new VulkanGraphicsContext();
|
||||
}
|
||||
|
||||
if (!vkctx->InitSurface(windowSystem, data1, data2, &error_message)) {
|
||||
fprintf(stderr, "Vulkan fallback failed: %s\n", error_message.c_str());
|
||||
if (!ctx->InitAPI(nullptr, &g_Config.sVulkanDevice, errorMessage)) {
|
||||
fprintf(stderr, "Graphics initialization failed: %s\n", errorMessage->c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ctx->InitSurface(windowSystem, data1, data2, errorMessage)) {
|
||||
fprintf(stderr, "Surface creation failed: %s\n", errorMessage->c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
*graphicsContext = ctx;
|
||||
return true;
|
||||
};
|
||||
|
||||
GraphicsContext *graphicsContext = nullptr;
|
||||
std::string error_message;
|
||||
if (!initializeBackend((GPUBackend)g_Config.iGPUBackend, &graphicsContext, &error_message)) {
|
||||
fprintf(stderr, "Failed to initialize graphics backend: %s\n", error_message.c_str());
|
||||
if (fallbackGPUBackend != -1) {
|
||||
fprintf(stderr, "Attempting to fall back to %s...\n", fallbackGPUBackend == (int)GPUBackend::OPENGL ? "OpenGL" : "Vulkan");
|
||||
g_Config.iGPUBackend = fallbackGPUBackend;
|
||||
error_message.clear();
|
||||
if (!initializeBackend((GPUBackend)g_Config.iGPUBackend, &graphicsContext, &error_message)) {
|
||||
fprintf(stderr, "Fallback failed: %s\n", error_message.c_str());
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
graphicsContext = vkctx;
|
||||
} else {
|
||||
graphicsContext = glctx;
|
||||
}
|
||||
#if !PPSSPP_PLATFORM(SWITCH)
|
||||
} else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) {
|
||||
// Overwrite the surface init params with what we need for Vulkan..
|
||||
if (!DetermineVulkanWindowSystem(window, &windowSystem, &data1, &data2)) {
|
||||
fprintf(stderr, "No fallback GPU backend available. Exiting.\n");
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
VulkanGraphicsContext *vkctx = new VulkanGraphicsContext();
|
||||
vkctx->InitAPI(nullptr, &g_Config.sVulkanDevice, &error_message);
|
||||
if (!vkctx->InitSurface(windowSystem, data1, data2, &error_message)) {
|
||||
// Let's try the fallback once per process run.
|
||||
|
||||
fprintf(stderr, "Vulkan init error '%s' - falling back to GL\n", error_message.c_str());
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
SetGPUBackend((GPUBackend)g_Config.iGPUBackend);
|
||||
delete vkctx;
|
||||
|
||||
// NOTE : This should match the three lines above in the OpenGL case.
|
||||
SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(cmdLineOptions.force_gl_version);
|
||||
glctx->InitAPI(nullptr, nullptr, &error_message);
|
||||
if (!glctx->InitSurface(windowSystem, data1, data2, &error_message)) {
|
||||
fprintf(stderr, "GL fallback failed: %s\n", error_message.c_str());
|
||||
return 1;
|
||||
}
|
||||
graphicsContext = glctx;
|
||||
} else {
|
||||
graphicsContext = vkctx;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// At this point, we have a window that we can show finally.
|
||||
SDL_ShowWindow(window);
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
UpdateScreenDPI(window);
|
||||
|
||||
float dpi_scale = 1.0f / (g_ForcedDPI == 0.0f ? g_DesktopDPI : g_ForcedDPI);
|
||||
@@ -2175,6 +2184,7 @@ int main(int argc, char *argv[]) {
|
||||
EnableFZ();
|
||||
|
||||
// We use the emuthread both for OpenGL and Vulkan, but in OpenGL mode we also render from the main thread.
|
||||
_dbg_assert_(graphicsContext);
|
||||
std::thread emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), nullptr);
|
||||
|
||||
InputStateTracker inputTracker{};
|
||||
@@ -2251,24 +2261,6 @@ int main(int argc, char *argv[]) {
|
||||
UpdateWindowState(window);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_rebootEmuThread) {
|
||||
fprintf(stderr, "rebooting emu thread");
|
||||
g_rebootEmuThread = false;
|
||||
EmuThread_Join(graphicsContext, emuThread);
|
||||
graphicsContext->ShutdownSurface();
|
||||
|
||||
fprintf(stderr, "OK, shutdown complete. starting up graphics again.\n");
|
||||
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
|
||||
SDLGLGraphicsContext *ctx = (SDLGLGraphicsContext *)graphicsContext;
|
||||
if (!ctx->InitSurface(windowSystem,data1, data2, &error_message)) {
|
||||
fprintf(stderr, "Failed to reinit graphics.\n");
|
||||
}
|
||||
}
|
||||
|
||||
emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
EmuThread_Join(graphicsContext, emuThread);
|
||||
|
||||
Reference in new issue
Block a user