Refactor refreshrate handling from int to float.

With SDL 2 the refreshrate handling was rather limited by SDL 2 only
supporting integer refreshrates, making it impossible to represent the
common 59.95hz and other non-integer refreshrates. Quake II works around
this by assuming a refreshrate of 2hz higher than returned by SDL.

SDL 3 finally supports float refreshrates. Refactor the internal API to
also use floats.

This should be a no-op since the 'refreshrate * 1.02' logic stayes in
place for the time being. This can be reevaluated at a later time for
the SDL 3 build, but needs testing.

As a nice side effect fix the `vid_displayrefreshrate` cvar. It was
broken in both SDL 2 and 3 since it was always overwritten with the
actual display refresh rate.
This commit is contained in:
Yamagi 2024-03-31 09:26:37 +02:00
parent 5d30c5913b
commit 5a21397761
7 changed files with 16 additions and 51 deletions

View File

@ -701,7 +701,7 @@ IN_Update(void)
{
// make sure GLimp_GetRefreshRate() will query from SDL again - the window might
// be on another display now!
glimp_refreshRate = -1;
glimp_refreshRate = -1.0f;
}
else if (event.window.event == SDL_WINDOWEVENT_SHOWN)
{

View File

@ -701,7 +701,7 @@ IN_Update(void)
{
// make sure GLimp_GetRefreshRate() will query from SDL again - the window might
// be on another display now!
glimp_refreshRate = -1;
glimp_refreshRate = -1.0;
}
else if (event.window.event == SDL_WINDOWEVENT_SHOWN)
{

View File

@ -27,7 +27,6 @@
* =======================================================================
*/
#include "SDL3/SDL_video.h"
#include "header/local.h"
#ifdef USE_SDL3

View File

@ -33,7 +33,7 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_video.h>
int glimp_refreshRate = -1;
float glimp_refreshRate = -1.0f;
static cvar_t *vid_displayrefreshrate;
static cvar_t *vid_displayindex;
@ -733,35 +733,19 @@ GLimp_GrabInput(qboolean grab)
}
/*
* Returns the current display refresh rate. There're 2 limitations:
*
* * The timing code in frame.c only understands full integers, so
* values given by vid_displayrefreshrate are always round up. For
* example 59.95 become 60. Rounding up is the better choice for
* most users because assuming a too high display refresh rate
* avoids micro stuttering caused by missed frames if the vsync
* is enabled. The price are small and hard to notice timing
* problems.
*
* * SDL returns only full integers. In most cases they're rounded
* up, but in some cases - likely depending on the GPU driver -
* they're rounded down. If the value is rounded up, we'll see
* some small and nard to notice timing problems. If the value
* is rounded down frames will be missed. Both is only relevant
* if the vsync is enabled.
* Returns the current display refresh rate.
*/
int
float
GLimp_GetRefreshRate(void)
{
if (vid_displayrefreshrate->value > -1 ||
vid_displayrefreshrate->modified)
{
glimp_refreshRate = ceil(vid_displayrefreshrate->value);
glimp_refreshRate = vid_displayrefreshrate->value;
vid_displayrefreshrate->modified = false;
}
if (glimp_refreshRate == -1)
else if (glimp_refreshRate == -1)
{
SDL_DisplayMode mode;

View File

@ -41,7 +41,7 @@
#include <SDL3/SDL.h>
int glimp_refreshRate = -1;
float glimp_refreshRate = -1.0f;
static cvar_t *vid_displayrefreshrate;
static cvar_t *vid_displayindex;
@ -795,37 +795,19 @@ GLimp_GrabInput(qboolean grab)
}
/*
* Returns the current display refresh rate. There're 2 limitations:
*
* * The timing code in frame.c only understands full integers, so
* values given by vid_displayrefreshrate are always round up. For
* example 59.95 become 60. Rounding up is the better choice for
* most users because assuming a too high display refresh rate
* avoids micro stuttering caused by missed frames if the vsync
* is enabled. The price are small and hard to notice timing
* problems.
*
* * SDL returns only full integers. In most cases they're rounded
* up, but in some cases - likely depending on the GPU driver -
* they're rounded down. If the value is rounded up, we'll see
* some small and nard to notice timing problems. If the value
* is rounded down frames will be missed. Both is only relevant
* if the vsync is enabled.
*
* TODO SDL 3: Refactor this to floats?
* Returns the current display refresh rate.
*/
int
float
GLimp_GetRefreshRate(void)
{
if (vid_displayrefreshrate->value > -1 ||
vid_displayrefreshrate->modified)
{
glimp_refreshRate = ceil(vid_displayrefreshrate->value);
glimp_refreshRate = vid_displayrefreshrate->value;
vid_displayrefreshrate->modified = false;
}
if (glimp_refreshRate == -1)
else if (glimp_refreshRate == -1)
{
const SDL_DisplayMode *mode;
int curdisplay;

View File

@ -54,7 +54,7 @@ void VID_MenuDraw(void);
const char *VID_MenuKey(int);
// Stuff provided by platform backend.
extern int glimp_refreshRate;
extern float glimp_refreshRate;
const char **GLimp_GetDisplayIndices(void);
int GLimp_GetWindowDisplayIndex(void);
@ -64,7 +64,7 @@ void GLimp_Shutdown(void);
qboolean GLimp_InitGraphics(int fullscreen, int *pwidth, int *pheight);
void GLimp_ShutdownGraphics(void);
void GLimp_GrabInput(qboolean grab);
int GLimp_GetRefreshRate(void);
float GLimp_GetRefreshRate(void);
qboolean GLimp_GetDesktopMode(int *pwidth, int *pheight);
#endif

View File

@ -53,7 +53,7 @@ cvar_t *showtrace;
// Forward declarations
#ifndef DEDICATED_ONLY
int GLimp_GetRefreshRate(void);
float GLimp_GetRefreshRate(void);
qboolean R_IsVSyncActive(void);
#endif
@ -556,7 +556,7 @@ Qcommon_Frame(int usec)
// Calculate target and renderframerate.
if (R_IsVSyncActive())
{
int refreshrate = GLimp_GetRefreshRate();
float refreshrate = GLimp_GetRefreshRate();
// using refreshRate - 2, because targeting a value slightly below the
// (possibly not 100% correctly reported) refreshRate would introduce jittering, so only