mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-22 09:11:21 +00:00
Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code
This commit is contained in:
parent
f482218913
commit
80cb9994d5
4 changed files with 51 additions and 65 deletions
59
src/d_main.c
59
src/d_main.c
|
@ -297,17 +297,17 @@ gamestate_t wipegamestate = GS_LEVEL;
|
||||||
INT16 wipetypepre = -1;
|
INT16 wipetypepre = -1;
|
||||||
INT16 wipetypepost = -1;
|
INT16 wipetypepost = -1;
|
||||||
|
|
||||||
static void D_Display(void)
|
static boolean D_Display(void)
|
||||||
{
|
{
|
||||||
boolean forcerefresh = false;
|
boolean forcerefresh = false;
|
||||||
static boolean wipe = false;
|
static boolean wipe = false;
|
||||||
INT32 wipedefindex = 0;
|
INT32 wipedefindex = 0;
|
||||||
|
|
||||||
if (dedicated)
|
if (dedicated)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (nodrawers)
|
if (nodrawers)
|
||||||
return; // for comparative timing/profiling
|
return false; // for comparative timing/profiling
|
||||||
|
|
||||||
// Lactozilla: Switching renderers works by checking
|
// Lactozilla: Switching renderers works by checking
|
||||||
// if the game has to do it right when the frame
|
// if the game has to do it right when the frame
|
||||||
|
@ -681,10 +681,10 @@ static void D_Display(void)
|
||||||
M_DrawPerfStats();
|
M_DrawPerfStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
PS_START_TIMING(ps_swaptime);
|
return true; // Do I_FinishUpdate in the main loop
|
||||||
I_FinishUpdate(); // page flip or blit buffer
|
|
||||||
PS_STOP_TIMING(ps_swaptime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
@ -701,9 +701,9 @@ void D_SRB2Loop(void)
|
||||||
boolean ticked = false;
|
boolean ticked = false;
|
||||||
boolean interp = false;
|
boolean interp = false;
|
||||||
boolean doDisplay = false;
|
boolean doDisplay = false;
|
||||||
|
boolean screenUpdate = false;
|
||||||
|
|
||||||
double frameTime = 0.0;
|
double frameEnd = 0.0;
|
||||||
double frameElapsed = 0.0;
|
|
||||||
|
|
||||||
if (dedicated)
|
if (dedicated)
|
||||||
server = true;
|
server = true;
|
||||||
|
@ -755,9 +755,6 @@ void D_SRB2Loop(void)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
frameTime = I_GetFrameTime();
|
|
||||||
frameElapsed = 0.0;
|
|
||||||
|
|
||||||
if (lastwipetic)
|
if (lastwipetic)
|
||||||
{
|
{
|
||||||
oldentertics = lastwipetic;
|
oldentertics = lastwipetic;
|
||||||
|
@ -769,8 +766,6 @@ void D_SRB2Loop(void)
|
||||||
realtics = entertic - oldentertics;
|
realtics = entertic - oldentertics;
|
||||||
oldentertics = entertic;
|
oldentertics = entertic;
|
||||||
|
|
||||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
|
||||||
|
|
||||||
if (demoplayback && gamestate == GS_LEVEL)
|
if (demoplayback && gamestate == GS_LEVEL)
|
||||||
{
|
{
|
||||||
// Nicer place to put this.
|
// Nicer place to put this.
|
||||||
|
@ -784,13 +779,15 @@ void D_SRB2Loop(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
interp = R_UsingFrameInterpolation();
|
interp = R_UsingFrameInterpolation();
|
||||||
doDisplay = false;
|
doDisplay = screenUpdate = false;
|
||||||
ticked = false;
|
ticked = false;
|
||||||
|
|
||||||
#ifdef HW3SOUND
|
#ifdef HW3SOUND
|
||||||
HW3S_BeginFrameUpdate();
|
HW3S_BeginFrameUpdate();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||||
|
|
||||||
if (realtics > 0 || singletics)
|
if (realtics > 0 || singletics)
|
||||||
{
|
{
|
||||||
// don't skip more than 10 frames at a time
|
// don't skip more than 10 frames at a time
|
||||||
|
@ -879,14 +876,9 @@ void D_SRB2Loop(void)
|
||||||
|
|
||||||
if (interp || doDisplay)
|
if (interp || doDisplay)
|
||||||
{
|
{
|
||||||
D_Display();
|
screenUpdate = D_Display();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moviemode)
|
|
||||||
M_SaveFrame();
|
|
||||||
if (takescreenshot) // Only take screenshots after drawing.
|
|
||||||
M_DoScreenShot();
|
|
||||||
|
|
||||||
// consoleplayer -> displayplayer (hear sounds from viewpoint)
|
// consoleplayer -> displayplayer (hear sounds from viewpoint)
|
||||||
S_UpdateSounds(); // move positional sounds
|
S_UpdateSounds(); // move positional sounds
|
||||||
S_UpdateClosedCaptions();
|
S_UpdateClosedCaptions();
|
||||||
|
@ -897,18 +889,27 @@ void D_SRB2Loop(void)
|
||||||
|
|
||||||
LUA_Step();
|
LUA_Step();
|
||||||
|
|
||||||
// Moved to here from I_FinishUpdate.
|
// Fully completed frame made.
|
||||||
// It doesn't track fades properly anymore by being here (might be easy fix),
|
frameEnd = I_GetFrameTime();
|
||||||
// but it's a little more accurate for actual rendering when its here.
|
|
||||||
SCR_CalculateFPS();
|
|
||||||
|
|
||||||
// Fully completed frame made, handle frame cap delay.
|
|
||||||
frameElapsed = I_GetFrameTime() - frameTime;
|
|
||||||
|
|
||||||
if (!singletics)
|
if (!singletics)
|
||||||
{
|
{
|
||||||
I_FrameCapSleep(frameElapsed);
|
I_FrameCapSleep(frameEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I_FinishUpdate is now here instead of D_Display,
|
||||||
|
// because it synchronizes it more closely with the frame counter.
|
||||||
|
if (screenUpdate == true)
|
||||||
|
{
|
||||||
|
PS_START_TIMING(ps_swaptime);
|
||||||
|
I_FinishUpdate(); // page flip or blit buffer
|
||||||
|
PS_STOP_TIMING(ps_swaptime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only take screenshots after drawing.
|
||||||
|
if (moviemode)
|
||||||
|
M_SaveFrame();
|
||||||
|
if (takescreenshot)
|
||||||
|
M_DoScreenShot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ void I_Sleep(void);
|
||||||
|
|
||||||
\return void
|
\return void
|
||||||
*/
|
*/
|
||||||
boolean I_FrameCapSleep(const double elapsed);
|
boolean I_FrameCapSleep(const double frameStart);
|
||||||
|
|
||||||
/** \brief Get events
|
/** \brief Get events
|
||||||
|
|
||||||
|
|
|
@ -2222,6 +2222,7 @@ double I_GetFrameTime(void)
|
||||||
|
|
||||||
if (cap != frame_rate)
|
if (cap != frame_rate)
|
||||||
{
|
{
|
||||||
|
// Maybe do this in a OnChange function for cv_fpscap?
|
||||||
I_InitFrameTime(now, cap);
|
I_InitFrameTime(now, cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2260,23 +2261,24 @@ void I_StartupTimer(void)
|
||||||
//
|
//
|
||||||
void I_Sleep(void)
|
void I_Sleep(void)
|
||||||
{
|
{
|
||||||
if (cv_sleep.value != -1)
|
if (cv_sleep.value > 0)
|
||||||
SDL_Delay(cv_sleep.value);
|
SDL_Delay(cv_sleep.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// I_FrameCapSleep
|
// I_FrameCapSleep
|
||||||
// Sleeps for a variable amount of time, depending on how much time the last frame took.
|
// Sleeps for a variable amount of time, depending on how much time the frame took.
|
||||||
//
|
//
|
||||||
boolean I_FrameCapSleep(const double elapsed)
|
boolean I_FrameCapSleep(const double t)
|
||||||
{
|
{
|
||||||
// SDL_Delay(1) gives me a range of around 1.95ms to 2.05ms.
|
// SDL_Delay(1) gives me a range of around 1.95ms to 2.05ms.
|
||||||
// Has a bit extra to be totally safe.
|
// Has a bit extra to be totally safe.
|
||||||
const double delayGranularity = 2.1;
|
const double delayGranularity = 2.1;
|
||||||
|
double frameMS = 0.0;
|
||||||
|
|
||||||
double capMS = 0.0;
|
double curTime = 0.0;
|
||||||
double elapsedMS = 0.0;
|
double destTime = 0.0;
|
||||||
double waitMS = 0.0;
|
double sleepTime = 0.0;
|
||||||
|
|
||||||
if (frame_rate == 0)
|
if (frame_rate == 0)
|
||||||
{
|
{
|
||||||
|
@ -2284,46 +2286,29 @@ boolean I_FrameCapSleep(const double elapsed)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
capMS = 1000.0 / frame_rate; // Time of 1 frame, in milliseconds
|
curTime = I_GetFrameTime();
|
||||||
elapsedMS = elapsed * capMS; // Convert elapsed from frame time to milliseconds.
|
destTime = floor(t) + 1.0;
|
||||||
waitMS = (capMS - elapsedMS); // How many MS to delay by.
|
|
||||||
|
|
||||||
if (waitMS <= 0.0)
|
if (curTime >= destTime)
|
||||||
{
|
{
|
||||||
// Too small of a wait, don't delay.
|
// We're already behind schedule.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (waitMS > 0.0)
|
frameMS = frame_rate * 0.001; // 1ms as frame time
|
||||||
{
|
sleepTime = destTime - (delayGranularity * frameMS);
|
||||||
double sleepStart = I_GetFrameTime();
|
|
||||||
double sleepEnd = sleepStart;
|
|
||||||
double sleepElaspedMS = 0.0;
|
|
||||||
|
|
||||||
if (waitMS > delayGranularity && cv_sleep.value != -1)
|
while (curTime < destTime)
|
||||||
|
{
|
||||||
|
if (curTime < sleepTime && cv_sleep.value <= 0)
|
||||||
{
|
{
|
||||||
// Wait 1ms at a time (on default settings)
|
// Wait 1ms at a time (on default settings)
|
||||||
// until we're close enough.
|
// until we're close enough.
|
||||||
SDL_Delay(cv_sleep.value);
|
SDL_Delay(cv_sleep.value);
|
||||||
|
|
||||||
sleepEnd = I_GetFrameTime();
|
|
||||||
sleepElaspedMS = (sleepEnd - sleepStart) * capMS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// When we have an extremely fine wait,
|
|
||||||
// we do this to spin-lock the remaining time.
|
|
||||||
|
|
||||||
while (sleepElaspedMS < waitMS)
|
|
||||||
{
|
|
||||||
sleepEnd = I_GetFrameTime();
|
|
||||||
sleepElaspedMS = (sleepEnd - sleepStart) * capMS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
// This part will spin-lock the rest.
|
||||||
}
|
curTime = I_GetFrameTime();
|
||||||
|
|
||||||
waitMS -= sleepElaspedMS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We took our nap.
|
// We took our nap.
|
||||||
|
|
|
@ -1214,7 +1214,7 @@ void I_FinishUpdate(void)
|
||||||
if (rendermode == render_none)
|
if (rendermode == render_none)
|
||||||
return; //Alam: No software or OpenGl surface
|
return; //Alam: No software or OpenGl surface
|
||||||
|
|
||||||
//SCR_CalculateFPS(); // Moved to main loop
|
SCR_CalculateFPS();
|
||||||
|
|
||||||
if (I_SkipFrame())
|
if (I_SkipFrame())
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue