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 wipetypepost = -1;
|
||||
|
||||
static void D_Display(void)
|
||||
static boolean D_Display(void)
|
||||
{
|
||||
boolean forcerefresh = false;
|
||||
static boolean wipe = false;
|
||||
INT32 wipedefindex = 0;
|
||||
|
||||
if (dedicated)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (nodrawers)
|
||||
return; // for comparative timing/profiling
|
||||
return false; // for comparative timing/profiling
|
||||
|
||||
// Lactozilla: Switching renderers works by checking
|
||||
// if the game has to do it right when the frame
|
||||
|
@ -681,10 +681,10 @@ static void D_Display(void)
|
|||
M_DrawPerfStats();
|
||||
}
|
||||
|
||||
PS_START_TIMING(ps_swaptime);
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
PS_STOP_TIMING(ps_swaptime);
|
||||
return true; // Do I_FinishUpdate in the main loop
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
@ -701,9 +701,9 @@ void D_SRB2Loop(void)
|
|||
boolean ticked = false;
|
||||
boolean interp = false;
|
||||
boolean doDisplay = false;
|
||||
boolean screenUpdate = false;
|
||||
|
||||
double frameTime = 0.0;
|
||||
double frameElapsed = 0.0;
|
||||
double frameEnd = 0.0;
|
||||
|
||||
if (dedicated)
|
||||
server = true;
|
||||
|
@ -755,9 +755,6 @@ void D_SRB2Loop(void)
|
|||
|
||||
for (;;)
|
||||
{
|
||||
frameTime = I_GetFrameTime();
|
||||
frameElapsed = 0.0;
|
||||
|
||||
if (lastwipetic)
|
||||
{
|
||||
oldentertics = lastwipetic;
|
||||
|
@ -769,8 +766,6 @@ void D_SRB2Loop(void)
|
|||
realtics = entertic - oldentertics;
|
||||
oldentertics = entertic;
|
||||
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
|
||||
if (demoplayback && gamestate == GS_LEVEL)
|
||||
{
|
||||
// Nicer place to put this.
|
||||
|
@ -784,13 +779,15 @@ void D_SRB2Loop(void)
|
|||
#endif
|
||||
|
||||
interp = R_UsingFrameInterpolation();
|
||||
doDisplay = false;
|
||||
doDisplay = screenUpdate = false;
|
||||
ticked = false;
|
||||
|
||||
#ifdef HW3SOUND
|
||||
HW3S_BeginFrameUpdate();
|
||||
#endif
|
||||
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
|
||||
if (realtics > 0 || singletics)
|
||||
{
|
||||
// don't skip more than 10 frames at a time
|
||||
|
@ -879,14 +876,9 @@ void D_SRB2Loop(void)
|
|||
|
||||
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)
|
||||
S_UpdateSounds(); // move positional sounds
|
||||
S_UpdateClosedCaptions();
|
||||
|
@ -897,18 +889,27 @@ void D_SRB2Loop(void)
|
|||
|
||||
LUA_Step();
|
||||
|
||||
// Moved to here from I_FinishUpdate.
|
||||
// It doesn't track fades properly anymore by being here (might be easy fix),
|
||||
// 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;
|
||||
|
||||
// Fully completed frame made.
|
||||
frameEnd = I_GetFrameTime();
|
||||
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
|
||||
*/
|
||||
boolean I_FrameCapSleep(const double elapsed);
|
||||
boolean I_FrameCapSleep(const double frameStart);
|
||||
|
||||
/** \brief Get events
|
||||
|
||||
|
|
|
@ -2222,6 +2222,7 @@ double I_GetFrameTime(void)
|
|||
|
||||
if (cap != frame_rate)
|
||||
{
|
||||
// Maybe do this in a OnChange function for cv_fpscap?
|
||||
I_InitFrameTime(now, cap);
|
||||
}
|
||||
|
||||
|
@ -2260,23 +2261,24 @@ void I_StartupTimer(void)
|
|||
//
|
||||
void I_Sleep(void)
|
||||
{
|
||||
if (cv_sleep.value != -1)
|
||||
if (cv_sleep.value > 0)
|
||||
SDL_Delay(cv_sleep.value);
|
||||
}
|
||||
|
||||
//
|
||||
// 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.
|
||||
// Has a bit extra to be totally safe.
|
||||
const double delayGranularity = 2.1;
|
||||
double frameMS = 0.0;
|
||||
|
||||
double capMS = 0.0;
|
||||
double elapsedMS = 0.0;
|
||||
double waitMS = 0.0;
|
||||
double curTime = 0.0;
|
||||
double destTime = 0.0;
|
||||
double sleepTime = 0.0;
|
||||
|
||||
if (frame_rate == 0)
|
||||
{
|
||||
|
@ -2284,46 +2286,29 @@ boolean I_FrameCapSleep(const double elapsed)
|
|||
return false;
|
||||
}
|
||||
|
||||
capMS = 1000.0 / frame_rate; // Time of 1 frame, in milliseconds
|
||||
elapsedMS = elapsed * capMS; // Convert elapsed from frame time to milliseconds.
|
||||
waitMS = (capMS - elapsedMS); // How many MS to delay by.
|
||||
curTime = I_GetFrameTime();
|
||||
destTime = floor(t) + 1.0;
|
||||
|
||||
if (waitMS <= 0.0)
|
||||
if (curTime >= destTime)
|
||||
{
|
||||
// Too small of a wait, don't delay.
|
||||
// We're already behind schedule.
|
||||
return false;
|
||||
}
|
||||
|
||||
while (waitMS > 0.0)
|
||||
{
|
||||
double sleepStart = I_GetFrameTime();
|
||||
double sleepEnd = sleepStart;
|
||||
double sleepElaspedMS = 0.0;
|
||||
frameMS = frame_rate * 0.001; // 1ms as frame time
|
||||
sleepTime = destTime - (delayGranularity * frameMS);
|
||||
|
||||
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)
|
||||
// until we're close enough.
|
||||
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;
|
||||
}
|
||||
|
||||
waitMS -= sleepElaspedMS;
|
||||
// This part will spin-lock the rest.
|
||||
curTime = I_GetFrameTime();
|
||||
}
|
||||
|
||||
// We took our nap.
|
||||
|
|
|
@ -1214,7 +1214,7 @@ void I_FinishUpdate(void)
|
|||
if (rendermode == render_none)
|
||||
return; //Alam: No software or OpenGl surface
|
||||
|
||||
//SCR_CalculateFPS(); // Moved to main loop
|
||||
SCR_CalculateFPS();
|
||||
|
||||
if (I_SkipFrame())
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue