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] 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);