From 0b02091d9a19d2a37744309eea401cf7663742a2 Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Wed, 4 Oct 2023 03:24:44 +1000 Subject: [PATCH] vid_vsync: fully support adaptive, remove polling, print better errors Adaptive vsync was partially supported: it worked if set before window creation but not if toggled on afterwards, and wasn't mentioned in the cvar description. The immediate application of `vid_vsync` cvar changes was implented by polling, which was ok for one cvar but I'll be making more vid_ cvars apply immediately (no vid_restart needed), and don't want to poll for things that rarely change every frame. SDL is now queried for the current state of vsync instead of storing what we believe to be the current state. If the setting can't be applied the reason (as reported by SDL) is now printed. Signed-off-by: bones_was_here --- cl_demo.c | 6 ++++++ cl_main.c | 4 ++-- vid_sdl.c | 33 +++++++++++++++++++-------------- vid_shared.c | 2 +- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/cl_demo.c b/cl_demo.c index 927e85b5..b1f2e685 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -585,6 +585,9 @@ static void CL_FinishTimeDemo (void) else host.state = host_shutdown; } + + // Might need to re-enable vsync + Cvar_Callback(&vid_vsync); } /* @@ -617,6 +620,9 @@ void CL_TimeDemo_f(cmd_state_t *cmd) cls.timedemo = host.restless = true; cls.td_frames = -2; // skip the first frame cls.demonum = -1; // stop demo loop + + // Might need to disable vsync + Cvar_Callback(&vid_vsync); } /* diff --git a/cl_main.c b/cl_main.c index 01ce5e6d..b7d4f148 100644 --- a/cl_main.c +++ b/cl_main.c @@ -454,9 +454,9 @@ void CL_DisconnectEx(qbool kicked, const char *fmt, ... ) } cls.state = ca_disconnected; cl.islocalgame = false; - - cls.demoplayback = cls.timedemo = host.restless = false; cls.signon = 0; + cls.demoplayback = cls.timedemo = host.restless = false; + Cvar_Callback(&vid_vsync); // might need to re-enable vsync Cvar_Callback(&cl_netport); diff --git a/vid_sdl.c b/vid_sdl.c index 12e45f8a..1a6756aa 100644 --- a/vid_sdl.c +++ b/vid_sdl.c @@ -72,7 +72,6 @@ static qbool vid_usingmouse = false; static qbool vid_usingmouse_relativeworks = false; // SDL2 workaround for unimplemented RelativeMouse mode static qbool vid_usinghidecursor = false; static qbool vid_hasfocus = false; -static qbool vid_usingvsync = false; static SDL_Joystick *vid_sdljoystick = NULL; static SDL_GameController *vid_sdlgamecontroller = NULL; static cvar_t joy_sdl2_trigger_deadzone = {CF_ARCHIVE | CF_CLIENT, "joy_sdl2_trigger_deadzone", "0.5", "deadzone for triggers to be registered as key presses"}; @@ -1320,6 +1319,21 @@ qbool GL_ExtensionSupported(const char *name) return SDL_GL_ExtensionSupported(name); } +static void VID_SetVsync_c(cvar_t *var) +{ + signed char vsyncwanted = cls.timedemo ? 0 : bound(-1, vid_vsync.integer, 1); + + if (!context) + return; + if (SDL_GL_GetSwapInterval() == vsyncwanted) + return; + + if (SDL_GL_SetSwapInterval(vsyncwanted) >= 0) + Con_DPrintf("Vsync %s\n", vsyncwanted ? "activated" : "deactivated"); + else + Con_Printf(CON_ERROR "ERROR: can't %s vsync because %s\n", vsyncwanted ? "activate" : "deactivate", SDL_GetError()); +} + void VID_Init (void) { #ifndef __IPHONEOS__ @@ -1336,6 +1350,8 @@ void VID_Init (void) R_RegisterModule("SDL", sdl_start, sdl_shutdown, sdl_newmap, NULL, NULL); #endif + Cvar_RegisterCallback(&vid_vsync, VID_SetVsync_c); + if (SDL_Init(SDL_INIT_VIDEO) < 0) Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError()); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) @@ -1606,8 +1622,8 @@ static qbool VID_InitModeGL(viddef_mode_t *mode) } #endif - SDL_GL_SetSwapInterval(bound(-1, vid_vsync.integer, 1)); - vid_usingvsync = (vid_vsync.integer != 0); + // apply vid_vsync + Cvar_Callback(&vid_vsync); vid_hidden = false; vid_activewindow = true; @@ -1658,7 +1674,6 @@ void VID_Shutdown (void) void VID_Finish (void) { - qbool vid_usevsync; vid_activewindow = !vid_hidden && vid_hasfocus; VID_UpdateGamma(); @@ -1672,16 +1687,6 @@ void VID_Finish (void) CHECKGLERROR if (r_speeds.integer == 2 || gl_finish.integer) GL_Finish(); - - vid_usevsync = (vid_vsync.integer && !cls.timedemo); - if (vid_usingvsync != vid_usevsync) - { - vid_usingvsync = vid_usevsync; - if (SDL_GL_SetSwapInterval(vid_usevsync != 0) >= 0) - Con_DPrintf("Vsync %s\n", vid_usevsync ? "activated" : "deactivated"); - else - Con_DPrintf("ERROR: can't %s vsync\n", vid_usevsync ? "activate" : "deactivate"); - } SDL_GL_SwapWindow(window); break; } diff --git a/vid_shared.c b/vid_shared.c index 2532d8e4..aa3bdb1f 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -147,7 +147,7 @@ cvar_t vid_touchscreen_density = {CF_CLIENT, "vid_touchscreen_density", "2.0", " cvar_t vid_touchscreen_xdpi = {CF_CLIENT, "vid_touchscreen_xdpi", "300", "Horizontal DPI of the screen (only valid on Android currently)"}; cvar_t vid_touchscreen_ydpi = {CF_CLIENT, "vid_touchscreen_ydpi", "300", "Vertical DPI of the screen (only valid on Android currently)"}; -cvar_t vid_vsync = {CF_CLIENT | CF_ARCHIVE, "vid_vsync", "0", "sync to vertical blank, prevents 'tearing' (seeing part of one frame and part of another on the screen at the same time), automatically disabled when doing timedemo benchmarks"}; +cvar_t vid_vsync = {CF_CLIENT | CF_ARCHIVE, "vid_vsync", "0", "sync to vertical blank, prevents 'tearing' (seeing part of one frame and part of another on the screen at the same time) at the cost of latency, 1 always syncs and -1 is adaptive (stops syncing if the framerate drops, unsupported by some platforms), automatically disabled when doing timedemo benchmarks"}; cvar_t vid_mouse = {CF_CLIENT | CF_ARCHIVE, "vid_mouse", "1", "whether to use the mouse in windowed mode (fullscreen always does)"}; cvar_t vid_mouse_clickthrough = {CF_CLIENT | CF_ARCHIVE, "vid_mouse_clickthrough", "0", "mouse behavior in windowed mode: 0 = click to focus, 1 = allow interaction even if the window is not focused (click-through behaviour, can be useful when using third-party game overlays)"}; cvar_t vid_grabkeyboard = {CF_CLIENT | CF_ARCHIVE, "vid_grabkeyboard", "0", "whether to grab the keyboard when mouse is active (prevents use of volume control keys, music player keys, etc on some keyboards)"}; -- 2.39.2