From 6e4f23cef6740b129e5086a8c625dc49854158a0 Mon Sep 17 00:00:00 2001 From: themuffinator Date: Wed, 26 Aug 2026 21:07:13 +0100 Subject: [PATCH] Restore SDL context before VSync updates --- docs/dev/release-completion.md | 1 + docs/dev/releases/v0.12.0.md | 1 + src/renderer/OpenGL/gl_ContextSDL3.cpp | 3 +++ tools/tests/linux_vsync_support.py | 7 +++++++ tools/tests/macos_sdl3_backend_guard.py | 8 ++++++++ 5 files changed, 20 insertions(+) diff --git a/docs/dev/release-completion.md b/docs/dev/release-completion.md index e05f104c..ca77752c 100644 --- a/docs/dev/release-completion.md +++ b/docs/dev/release-completion.md @@ -549,6 +549,7 @@ is `docs/dev/macos-moltenvk-decision.md`. - [x] Linux SDL3 mouse capture now recovers reliably after opening or closing the pull-down console: POSIX frame event generation applies SDL input-frame state like Windows, and console routing is treated as the topmost mouse target before returning control to gameplay or menus. - [x] Linux and experimental macOS SDL3 single-player loading screens now pump SDL window events while the displayed "press any key to continue" prompt is active and honor normal keyboard and printable character input, matching the expected Windows behavior after a level finishes loading. Mouse clicks now also dismiss the prompt on all SDL3 platforms: the continue gate raises a loading-input flag so the backend queues mouse-button key events even though the mouse is neither captured nor menu-routed during loading, and `tools/tests/loading_continue_input.py` locks the whole path in CI. - [x] Linux VSync support is more consistent: SDL3 now applies and reports the requested swap interval during startup, display-mode changes, and live `r_swapInterval` edits, while the native GLX fallback now honors the same cvar through EXT/MESA/SGI swap-control extensions when available. +- [x] Native Wayland now restores SDL's OpenGL context before every swap-interval update, so initial window setup can no longer leave `r_swapInterval` unapplied with a `No OpenGL context has been made current` error. - [x] Linux SDL3 native Wayland startup is more robust: bundled GLEW now initializes through SDL's current OpenGL proc-address path and skips GLX-only extension probing on the SDL3 backend, preventing the post-context `Init Glew...` crash reported on CachyOS while preserving the native GLX comparison backend. - [x] Startup language selection is more predictable: after `default.cfg`, user config, and `autoexec.cfg` run, command-line `+set sys_lang ...` is restored before the final language dictionary reload, so launch scripts can override stale archived language settings. - [x] First-run language selection now respects installed retail language packs: openQ4 discovers available `q4base/zpak_.pk4` packs, follows the OS language preference when multiple packs are present, uses the only available pack when appropriate, and repairs stale `sys_lang` values that point at missing localization media. diff --git a/docs/dev/releases/v0.12.0.md b/docs/dev/releases/v0.12.0.md index f03d4971..ceab9fe4 100644 --- a/docs/dev/releases/v0.12.0.md +++ b/docs/dev/releases/v0.12.0.md @@ -74,6 +74,7 @@ - Allowed the intended active free-for-all recipients through competitive match disclosure policy. - Restored the stock F1/F2/F3/F6/F7 impulse bindings, aligned the controls menu's vote/ready rows, routed the throttled ready toggle through the reliable operation, kept the two-line readiness prompt inside its authored HUD bounds, narrowly migrated only the exact historical openQ4 defaults, and normalized no-time-limit casual matches to sudden-death overtime with a zero period. - Corrected `s_muteUnfocused` transitions so returning to the game cannot leave audio muted for the rest of the level. +- Restored the SDL OpenGL context before applying startup or live swap-interval changes, keeping `r_swapInterval` effective when native Wayland window setup temporarily detaches the context. - Initialized engine-side triangle-surface allocators for `dmap` and related geometry tools. - Restored clean, fixed-size manual save-game previews at widescreen resolutions and prevented renderer row padding from leaking into narrow captures. - Replaced plaintext-by-default remote console authentication with bounded `rcon2`, redacted private password CVars throughout console and persistence paths, restricted server-originated CVar dictionaries to their declared userinfo/network-sync authority with all-or-nothing decoding, constrained server package URLs to bounded HTTP/HTTPS with syntax-checked hosts, and retired executable download/launch behavior from the legacy updater. Standard packages keep direct PK4 transfer disabled; separately integrated curl-enabled builds add time-limited, no-redirect transfer containment. diff --git a/src/renderer/OpenGL/gl_ContextSDL3.cpp b/src/renderer/OpenGL/gl_ContextSDL3.cpp index 46276ecb..2ff31f8e 100644 --- a/src/renderer/OpenGL/gl_ContextSDL3.cpp +++ b/src/renderer/OpenGL/gl_ContextSDL3.cpp @@ -120,6 +120,9 @@ static bool SDL3_ApplySwapInterval(void) { if (!s_glWindow || !s_glContext) { return false; } + if (!SDL3_EnsureGLContextCurrent("swap interval update")) { + return false; + } const int requestedInterval = R_GetEffectiveSwapInterval(); if (!s_glWindowServices->SetGLSwapInterval(requestedInterval)) { diff --git a/tools/tests/linux_vsync_support.py b/tools/tests/linux_vsync_support.py index ceb719ee..e1b98b42 100644 --- a/tools/tests/linux_vsync_support.py +++ b/tools/tests/linux_vsync_support.py @@ -63,6 +63,13 @@ def validate_sdl3_swap_interval() -> None: require(apply_swap, "SetGLSwapInterval(requestedInterval)", "SDL3 swap interval helper") require(apply_swap, "GetGLSwapInterval(&actualInterval)", "SDL3 swap interval helper") require(apply_swap, "requested swap interval", "SDL3 swap interval diagnostics") + require(apply_swap, 'SDL3_EnsureGLContextCurrent("swap interval update")', "SDL3 swap interval context guard") + require_order( + apply_swap, + 'SDL3_EnsureGLContextCurrent("swap interval update")', + "SetGLSwapInterval(requestedInterval)", + "SDL3 swap interval context guard", + ) require(backend_set, "SDL_GL_SetSwapInterval(interval)", "SDL3 swap interval seam implementation") require(backend_get, "SDL_GL_GetSwapInterval(outInterval)", "SDL3 swap interval seam implementation") diff --git a/tools/tests/macos_sdl3_backend_guard.py b/tools/tests/macos_sdl3_backend_guard.py index d1132b94..e52f921f 100644 --- a/tools/tests/macos_sdl3_backend_guard.py +++ b/tools/tests/macos_sdl3_backend_guard.py @@ -138,6 +138,7 @@ def validate_sdl3_context_teardown_guards() -> None: # compiled into the SDL3 backend until the module split (Phase B8) source = read("src/renderer/OpenGL/gl_ContextSDL3.cpp") ensure_current = function_body(source, "static bool SDL3_EnsureGLContextCurrent(const char *operation) {") + apply_swap = function_body(source, "static bool SDL3_ApplySwapInterval(void) {") screen_parms = function_body(source, "bool GLimp_SetScreenParms(glimpParms_t parms) {") shutdown = function_body(source, "void GLimp_Shutdown(void) {") swap = function_body(source, "void GLimp_SwapBuffers(void) {") @@ -157,6 +158,13 @@ def validate_sdl3_context_teardown_guards() -> None: ): require(ensure_current, token, "SDL3 current-context helper") + require(apply_swap, 'SDL3_EnsureGLContextCurrent("swap interval update")', "SDL3 swap-interval current-context guard") + require_before( + apply_swap, + 'SDL3_EnsureGLContextCurrent("swap interval update")', + "SetGLSwapInterval(requestedInterval)", + "SDL3 swap-interval current-context guard", + ) require(screen_parms, 'SDL3_EnsureGLContextCurrent("screen parm change")', "SDL3 screen-parm current-context guard") require(shutdown, "if (s_glWindow) {\n\t\t\t(void)windowServices->MakeGLContextCurrent(NULL);", "SDL3 shutdown context detach guard") reject(shutdown, "(void)windowServices->MakeGLContextCurrent(NULL);\n\t\twindowServices->DestroyGLContext", "SDL3 shutdown unguarded context detach")