From 1c0740c4b9b02840fa93bf8bafeb447c00d53f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 3 Aug 2026 14:54:49 +0200 Subject: [PATCH 1/2] SDL: Simplify graphics context fallback --- .vscode/launch-example-wsl.json | 37 +++++++ .vscode/launch-example.json | 24 +++++ Common/System/Display.cpp | 2 + Common/UI/Screen.cpp | 2 +- SDL/SDLGLGraphicsContext.cpp | 6 +- SDL/SDLMain.cpp | 168 +++++++++++++++----------------- 6 files changed, 145 insertions(+), 94 deletions(-) create mode 100644 .vscode/launch-example-wsl.json create mode 100644 .vscode/launch-example.json diff --git a/.vscode/launch-example-wsl.json b/.vscode/launch-example-wsl.json new file mode 100644 index 0000000000..e7559b0393 --- /dev/null +++ b/.vscode/launch-example-wsl.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch PPSSPPSDL (WSL)", + "type": "cppdbg", + "request": "launch", + "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, + "MIMode": "gdb", + "pipeTransport": { + "pipeProgram": "wsl.exe", + "pipeArgs": [ + "-d", + "Ubuntu", + "--" + ], + "pipeCwd": "C:/", + "quoteArgs": false, + "debuggerPath": "/usr/bin/gdb" + } + } + ] +} \ No newline at end of file diff --git a/.vscode/launch-example.json b/.vscode/launch-example.json new file mode 100644 index 0000000000..878ad9851c --- /dev/null +++ b/.vscode/launch-example.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index 096595e360..d80f0a6175 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -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; diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index 903be8a968..3b0ca9ab43 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -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_) { diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index da4ca4e2c1..e0bed058ac 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -286,6 +286,8 @@ 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; @@ -448,10 +450,6 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d }); window_ = window; - - // HACK: Ensure that the swap interval is set after context creation (needed for kmsdrm) - SDL_GL_SetSwapInterval(1); - return true; } diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 4e7267958b..c4f0167ed0 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -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) { @@ -2039,82 +2035,93 @@ int main(int argc, char *argv[]) { 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); + auto initializeBackend = [&](GPUBackend backend, GraphicsContext **graphicsContext, std::string *errorMessage) -> bool { + // Surface init params. + WindowSystem windowSystem = WINDOWSYSTEM_NONE; + void *data1 = &window; + void *data2 = (void *)(uintptr_t)mode; + if (backend == GPUBackend::OPENGL) { + mode |= SDL_WINDOW_OPENGL; + window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode); + if (!window) { + fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); + exit(1); + } - // Surface init params. These are set up for OpenGL by default. - WindowSystem windowSystem = WINDOWSYSTEM_NONE; - void *data1 = &window; - void *data2 = nullptr; + SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(cmdLineOptions.force_gl_version); + *graphicsContext = glctx; - 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); - } - - 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; + glctx->InitAPI(nullptr, nullptr, errorMessage); + if (!glctx->InitSurface(windowSystem, data1, data2, errorMessage)) { + fprintf(stderr, "OpenGL surface creation failed: %s\n", errorMessage->c_str()); + return false; + } + } else { + mode |= SDL_WINDOW_VULKAN; + window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode); + if (!window) { + fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); + exit(1); + } // 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); + if (!vkctx->InitAPI(nullptr, &g_Config.sVulkanDevice, errorMessage)) { + fprintf(stderr, "Vulkan initialization failed: %s\n", errorMessage->c_str()); + return false; + } + if (!vkctx->InitSurface(windowSystem, data1, data2, errorMessage)) { + fprintf(stderr, "Vulkan surface creation failed: %s\n", errorMessage->c_str()); + return false; + } + *graphicsContext = vkctx; + } + return true; + }; - if (!vkctx->InitSurface(windowSystem, data1, data2, &error_message)) { - fprintf(stderr, "Vulkan fallback failed: %s\n", error_message.c_str()); + 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()); 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"); 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 + if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) { + SDL_SetWindowPosition(window, x, y); } UpdateScreenDPI(window); @@ -2175,6 +2182,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 +2259,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); From 0f4f1d7091e2df00872064c78bce452777306094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 3 Aug 2026 17:52:56 +0200 Subject: [PATCH 2/2] More SDL GL context refactor --- .vscode/launch-example-wsl.json | 5 +++ SDL/SDLGLGraphicsContext.cpp | 76 ++++++++++++++------------------- SDL/SDLGLGraphicsContext.h | 7 +-- SDL/SDLMain.cpp | 62 ++++++++++++++------------- 4 files changed, 74 insertions(+), 76 deletions(-) diff --git a/.vscode/launch-example-wsl.json b/.vscode/launch-example-wsl.json index e7559b0393..151a4a70e2 100644 --- a/.vscode/launch-example-wsl.json +++ b/.vscode/launch-example-wsl.json @@ -5,6 +5,7 @@ "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" @@ -20,6 +21,10 @@ }, "environment": [], "externalConsole": false, + "internalConsoleOptions": "openOnSessionStart", + "logging": { + "programOutput": true + }, "MIMode": "gdb", "pipeTransport": { "pipeProgram": "wsl.exe", diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index e0bed058ac..73aecd0c55 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -286,12 +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; @@ -305,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...) @@ -345,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; } @@ -360,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); @@ -368,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) { @@ -411,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) @@ -421,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(); @@ -443,7 +434,6 @@ 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); @@ -459,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; } diff --git a/SDL/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h index 63945da8eb..e2cc6e6fa0 100644 --- a/SDL/SDLGLGraphicsContext.h +++ b/SDL/SDLGLGraphicsContext.h @@ -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); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index c4f0167ed0..e84aa708e3 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -2031,9 +2031,6 @@ int main(int argc, char *argv[]) { h = g_Config.iWindowHeight; } - GraphicsContext *graphicsContext = nullptr; - SDL_Window *window = nullptr; - // Switch away from Vulkan if not available. int fallbackGPUBackend = -1; switch ((GPUBackend)g_Config.iGPUBackend) { @@ -2055,54 +2052,56 @@ int main(int argc, char *argv[]) { break; } + SDL_Window *window = nullptr; auto initializeBackend = [&](GPUBackend backend, GraphicsContext **graphicsContext, std::string *errorMessage) -> bool { // Surface init params. WindowSystem windowSystem = WINDOWSYSTEM_NONE; - void *data1 = &window; - void *data2 = (void *)(uintptr_t)mode; + void *data1 = nullptr; + void *data2 = nullptr; + + GraphicsContext *ctx = nullptr; if (backend == GPUBackend::OPENGL) { - mode |= SDL_WINDOW_OPENGL; - window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode); - if (!window) { - fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); - exit(1); - } + SDL_GLContext glContext = nullptr; + window = CreateSDLGLWindowAndContext(x, y, w, h, mode, cmdLineOptions.force_gl_version, &glContext); - SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(cmdLineOptions.force_gl_version); - *graphicsContext = glctx; + data1 = (void *)window; + data2 = (void *)glContext; - glctx->InitAPI(nullptr, nullptr, errorMessage); - if (!glctx->InitSurface(windowSystem, data1, data2, errorMessage)) { - fprintf(stderr, "OpenGL surface creation failed: %s\n", errorMessage->c_str()); - return false; - } + ctx = new SDLGLGraphicsContext(); } else { - mode |= SDL_WINDOW_VULKAN; + 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 false; } // NOTE : This should match the lines below in the Vulkan case. - VulkanGraphicsContext *vkctx = new VulkanGraphicsContext(); - if (!vkctx->InitAPI(nullptr, &g_Config.sVulkanDevice, errorMessage)) { - fprintf(stderr, "Vulkan initialization failed: %s\n", errorMessage->c_str()); - return false; - } - if (!vkctx->InitSurface(windowSystem, data1, data2, errorMessage)) { - fprintf(stderr, "Vulkan surface creation failed: %s\n", errorMessage->c_str()); - return false; - } - *graphicsContext = vkctx; + ctx = new VulkanGraphicsContext(); } + + 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()); @@ -2112,18 +2111,21 @@ int main(int argc, char *argv[]) { 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; } } else { fprintf(stderr, "No fallback GPU backend available. Exiting.\n"); + SDL_Quit(); return 1; } } + // 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);