Allow switching VSync on/off without vid_restart (for SDL2)

This commit is contained in:
Daniel Gibson 2017-03-04 16:31:34 +01:00
parent 6b21811af8
commit 18bfa35f9b
11 changed files with 103 additions and 51 deletions

View File

@ -447,3 +447,13 @@ R_EndFrame(void)
re.EndFrame();
}
}
qboolean
R_IsVSyncActive(void)
{
if(ref_active)
{
return re.IsVSyncActive();
}
return false;
}

View File

@ -296,6 +296,8 @@ IN_TranslateSDLtoQ2Key(unsigned int keysym)
/* ------------------------------------------------------------------ */
extern int glimp_refreshRate;
/*
* Updates the input queue state. Called every
* frame by the client and does nearly all the
@ -430,6 +432,12 @@ IN_Update(void)
{
Key_MarkAllUp();
}
else if(event.window.event == SDL_WINDOWEVENT_MOVED)
{
// make sure GLimp_GetRefreshRate() will query from SDL again - the window might
// be on another display now!
glimp_refreshRate = -1;
}
#else /* SDL1.2 */
case SDL_ACTIVEEVENT:

View File

@ -52,8 +52,6 @@ static SDL_Surface* window = NULL;
#endif
qboolean vsync_active;
#if SDL_VERSION_ATLEAST(2, 0, 0)
// some compatibility defines
#define SDL_SRCCOLORKEY SDL_TRUE
@ -340,11 +338,6 @@ GLimp_InitGraphics(qboolean fullscreen, int *pwidth, int *pheight)
return false;
}
// VSync is really set in the renderer dll, but we want vsync_active here
// so just get it from the Cvar here, even though it's a bit ugly
cvar_t* gl_swapinterval = Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE);
vsync_active = gl_swapinterval->value ? true : false;
/* Note: window title is now set in re.InitContext() to include renderer name */
#if SDL_VERSION_ATLEAST(2, 0, 0)
/* Set the window icon - For SDL2, this must be done after creating the window */
@ -377,13 +370,7 @@ void GLimp_GrabInput(qboolean grab)
#endif
}
/*
* Returns the VSync state.
*/
qboolean GLimp_VsyncEnabled(void)
{
return vsync_active;
}
int glimp_refreshRate = -1;
/*
* Returns the current display refresh rate.
@ -391,17 +378,26 @@ qboolean GLimp_VsyncEnabled(void)
int GLimp_GetRefreshRate(void)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
int i;
int refresh = 0;
SDL_DisplayMode mode;
for (i = 0; i < SDL_GetNumVideoDisplays(); ++i)
// do this only once, assuming people don't change their display settings
// or plug in new displays while the game is running
if (glimp_refreshRate == -1)
{
SDL_GetCurrentDisplayMode(i, &mode);
refresh = refresh < mode.refresh_rate ? mode.refresh_rate : refresh;
SDL_DisplayMode mode;
// TODO: probably refreshRate should be reset to -1 if window is moved
int i = SDL_GetWindowDisplayIndex(window);
if(i >= 0 && SDL_GetCurrentDisplayMode(i, &mode) == 0)
{
glimp_refreshRate = mode.refresh_rate;
}
if (glimp_refreshRate <= 0)
{
glimp_refreshRate = 60; // apparently the stuff above failed, use default
}
}
return refresh;
return glimp_refreshRate;
#else
// Asume 60hz.
return 60
@ -427,6 +423,8 @@ VID_ShutdownWindow(void)
}
window = NULL;
// make sure that after vid_restart the refreshrate will be queried from SDL2 again.
glimp_refreshRate = -1;
if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_VIDEO)
{

View File

@ -711,8 +711,8 @@ CL_UpdateWindowedMouse(void)
}
}
qboolean GLimp_VsyncEnabled(void);
int GLimp_GetRefreshRate(void);
qboolean R_IsVSyncActive(void);
void
CL_Frame(int msec)
@ -736,7 +736,7 @@ CL_Frame(int msec)
}
// Target render frame rate
if (GLimp_VsyncEnabled())
if (R_IsVSyncActive())
{
rfps = GLimp_GetRefreshRate();
@ -830,7 +830,7 @@ CL_Frame(int msec)
double frametime = (1000.0 / cl_maxfps->value - packetdelta) <= (1000.0 / gl_maxfps->value - renderdelta) ?
(1000.0 / cl_maxfps->value - packetdelta) : (1000.0 / gl_maxfps->value - renderdelta);
if (frametime > 1)
if (frametime > 1) // FIXME: why > ??
{
Sys_Sleep(1);
}

View File

@ -148,6 +148,9 @@ typedef struct
// VID_ShutdownWindow() to shut down window as well, if !contextOnly
void (EXPORT *ShutdownWindow)(qboolean contextOnly);
// returns true if vsync is active, else false
qboolean (EXPORT *IsVSyncActive)(void);
// All data that will be used in a level should be
// registered before rendering any frames to prevent disk hits,
// but they can still be registered at a later time

View File

@ -1574,6 +1574,7 @@ RI_Shutdown(void)
}
extern void UpdateHardwareGamma();
extern void RI_SetSwapInterval(void);
void
RI_BeginFrame(float camera_separation)
@ -1700,6 +1701,12 @@ RI_BeginFrame(float camera_separation)
gl_texturesolidmode->modified = false;
}
if (gl_swapinterval->modified)
{
gl_swapinterval->modified = false;
RI_SetSwapInterval();
}
/* clear screen if desired */
R_Clear();
}
@ -1852,6 +1859,7 @@ extern void RDraw_FadeScreen(void);
extern void RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
extern void RI_SetPalette(const unsigned char *palette);
extern qboolean RI_IsVSyncActive(void);
extern void RI_EndFrame(void);
Q2_DLL_EXPORTED refexport_t
@ -1868,6 +1876,7 @@ GetRefAPI(refimport_t imp)
re.PrepareForWindow = RI_PrepareForWindow;
re.InitContext = RI_InitContext;
re.ShutdownWindow = RI_ShutdownWindow;
re.IsVSyncActive = RI_IsVSyncActive;
re.BeginRegistration = RI_BeginRegistration;
re.RegisterModel = RI_RegisterModel;
re.RegisterSkin = RI_RegisterSkin;

View File

@ -63,6 +63,7 @@ static SDL_Surface* window = NULL;
#endif
qboolean have_stencil = false;
static qboolean vsyncActive = false;
/*
* Returns the adress of a GL function
@ -370,6 +371,17 @@ int RI_PrepareForWindow(void)
return flags;
}
void RI_SetSwapInterval(void)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
/* Set vsync - TODO: -1 could be set for "late swap tearing" */
SDL_GL_SetSwapInterval(gl_swapinterval->value ? 1 : 0);
vsyncActive = SDL_GL_GetSwapInterval() != 0;
#else
R_Printf(PRINT_ALL, "SDL1.2 requires a vid_restart to apply changes to gl_swapinterval (vsync)!\n");
#endif
}
int RI_InitContext(void* win)
{
int msaa_samples = 0, stencil_bits = 0;
@ -400,8 +412,9 @@ int RI_InitContext(void* win)
#if SDL_VERSION_ATLEAST(2, 0, 0)
/* For SDL2, this must be done after creating the window */
/* Set vsync - TODO: -1 could be set for "late swap tearing" */
SDL_GL_SetSwapInterval(gl_swapinterval->value ? 1 : 0);
RI_SetSwapInterval();
#else // SDL1.2 - set vsyncActive to whatever is configured, hoping it was actually set
vsyncActive = gl_swapinterval->value ? 1 : 0;
#endif
/* Initialize the stencil buffer */
@ -429,6 +442,11 @@ int RI_InitContext(void* win)
return true;
}
qboolean RI_IsVSyncActive(void)
{
return vsyncActive;
}
/*
* Swaps the buffers to show the new frame
*/

View File

@ -1638,6 +1638,12 @@ GL3_BeginFrame(float camera_separation)
gl_anisotropic->modified = false;
}
if(gl_swapinterval->modified)
{
gl_swapinterval->modified = false;
GL3_SetSwapInterval();
}
STUB_ONCE("TODO: texture-alpha/solid-mode stuff??")
#if 0
if (gl_texturealphamode->modified)
@ -1703,6 +1709,7 @@ GetRefAPI(refimport_t imp)
re.PrepareForWindow = GL3_PrepareForWindow;
re.InitContext = GL3_InitContext;
re.ShutdownWindow = GL3_ShutdownWindow;
re.IsVSyncActive = GL3_IsVsyncActive;
re.BeginRegistration = GL3_BeginRegistration;
re.RegisterModel = GL3_RegisterModel;

View File

@ -68,29 +68,6 @@ GL3_SetDefaultState(void)
STUB("need replacement for R_TexEnv(GL_REPLACE);");
STUB("Apparently the GL_POINT stuff works differently in OpenGL3 core");
#if 0
{
// TODO: are we gonna use glPointParameter?
float attenuations[3] = {0.01f, 0.0f, 0.01f};
/*
attenuations[0] = gl_particle_att_a->value;
attenuations[1] = gl_particle_att_b->value;
attenuations[2] = gl_particle_att_c->value;
*/
STUB("gl_particle_att_[abc], gl_particle_min/max_size ??");
/* GL_POINT_SMOOTH is not implemented by some OpenGL
drivers, especially the crappy Mesa3D backends like
i915.so. That the points are squares and not circles
is not a problem by Quake II! */
glEnable(GL_POINT_SMOOTH);
glPointParameterf(GL_POINT_SIZE_MIN_EXT, 2.0f); // TODO was gl_particle_min_size->value);
glPointParameterf(GL_POINT_SIZE_MAX_EXT, 40.0f); // TODO was gl_particle_max_size->value);
glPointParameterf(GL_DISTANCE_ATTENUATION_EXT, attenuations);
}
#endif // 0
if (gl_msaa_samples->value)
{
glEnable(GL_MULTISAMPLE);

View File

@ -47,6 +47,7 @@
#endif
qboolean have_stencil = false;
static qboolean vsyncActive = false;
// called by GLimp_InitGraphics() before creating window,
// returns flags for SDL window creation, -1 on error
@ -199,8 +200,9 @@ int GL3_InitContext(void* win)
#if SDL_VERSION_ATLEAST(2, 0, 0)
/* For SDL2, this must be done after creating the window */
/* Set vsync - TODO: -1 could be set for "late swap tearing" */
SDL_GL_SetSwapInterval(gl_swapinterval->value ? 1 : 0);
GL3_SetSwapInterval();
#else // SDL1.2 - set vsyncActive to whatever is configured, hoping it was actually set
vsyncActive = gl_swapinterval->value ? 1 : 0;
#endif
/* Initialize the stencil buffer */
@ -251,6 +253,24 @@ int GL3_InitContext(void* win)
return true;
}
void GL3_SetSwapInterval(void)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
/* Set vsync - TODO: -1 could be set for "late swap tearing" */
SDL_GL_SetSwapInterval(gl_swapinterval->value ? 1 : 0);
vsyncActive = SDL_GL_GetSwapInterval() != 0;
#else
R_Printf(PRINT_ALL, "SDL1.2 requires a vid_restart to apply changes to gl_swapinterval (vsync)!\n");
#endif
}
qboolean GL3_IsVsyncActive(void)
{
return vsyncActive;
}
/*
* Swaps the buffers to show the new frame
*/

View File

@ -329,6 +329,8 @@ extern qboolean have_stencil;
extern int GL3_PrepareForWindow(void);
extern int GL3_InitContext(void* win);
extern void GL3_SetSwapInterval(void);
extern qboolean GL3_IsVsyncActive(void);
extern void GL3_EndFrame(void);
extern void GL3_ShutdownWindow(qboolean contextOnly);