mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-09-20 02:04:44 +00:00
Fix GLUT redraw timing
Currently the GLUT thread draws the screen too slowly, Ex. The default is supposed to be 60 FPS, but it will always draw a bit slower than 60 FPS. This is because the current logic simply inserts delays for the entire length of a frame, not taking into account how long it took us to render the last frame. The new code uses GetTicks() to measure how much time has passed since the last render, which then lets us calculate the exact amount of delay until the next frame. We additionally then measure how long the delay lasted vs. what we asked for (since any delay we do only has a minimum guarentee, it will ocassionally last a bit longer) and adjust based on that as well. The result is a perfect 60 FPS as long as rendering is quick enough. If the rendering falls behind (Ex. a slow _GL SUB is in the program) then we'll start skipping frames to get back on track. Fixes: #408
This commit is contained in:
parent
786f40193b
commit
cdbfb94c61
2 changed files with 36 additions and 32 deletions
|
@ -27227,49 +27227,61 @@ void GLUT_SPECIAL_FUNC(int key, int x, int y) {
|
|||
}
|
||||
void GLUT_SPECIALUP_FUNC(int key, int x, int y) { GLUT_key_special(key, 0); }
|
||||
|
||||
#ifdef QB64_WINDOWS
|
||||
void GLUT_TIMER_EVENT(int ignore) {
|
||||
libqb_process_glut_queue();
|
||||
static int64_t lastTick = 0;
|
||||
static double deltaTick = 0;
|
||||
|
||||
# ifdef QB64_GLUT
|
||||
glutPostRedisplay();
|
||||
int32 msdelay = 1000.0 / max_fps;
|
||||
Sleep(4);
|
||||
msdelay -= 4; // this forces GLUT to relinquish some CPU time to other threads but still allow for _FPS 100+
|
||||
if (msdelay < 1)
|
||||
msdelay = 1;
|
||||
glutTimerFunc(msdelay, GLUT_TIMER_EVENT, 0);
|
||||
# endif
|
||||
}
|
||||
#else
|
||||
void GLUT_IDLEFUNC() {
|
||||
libqb_process_glut_queue();
|
||||
|
||||
# ifdef QB64_MACOSX
|
||||
# ifdef DEPENDENCY_DEVICEINPUT
|
||||
#ifdef QB64_MACOSX
|
||||
# ifdef DEPENDENCY_DEVICEINPUT
|
||||
// must be in same thread as GLUT for OSX
|
||||
QB64_GAMEPAD_POLL();
|
||||
//[[[[NSApplication sharedApplication] mainWindow] standardWindowButton:NSWindowCloseButton] setEnabled:YES];
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# ifdef QB64_GLUT
|
||||
#ifdef QB64_GLUT
|
||||
|
||||
# ifdef QB64_LINUX
|
||||
if (x11_lock_request) {
|
||||
x11_locked = 1;
|
||||
x11_lock_request = 0;
|
||||
while (x11_locked)
|
||||
Sleep(1);
|
||||
}
|
||||
# endif
|
||||
int64_t curTime = GetTicks();
|
||||
|
||||
// This is how long the frame took to render
|
||||
int64_t elapsed = curTime - lastTick;
|
||||
|
||||
// Calculate out the error between how long the frame was 'supposed' to take vs. how long it actually took.
|
||||
deltaTick += ((double)1000 / max_fps) - (double)elapsed;
|
||||
|
||||
lastTick = curTime;
|
||||
|
||||
// If the error is positive, we sleep for that period of time.
|
||||
if (deltaTick > 0) {
|
||||
int32 msdelay = deltaTick;
|
||||
Sleep(msdelay);
|
||||
|
||||
int64_t sleepTime = GetTicks();
|
||||
|
||||
// Subtract off the time we spent sleeping. This should leave deltaTick at zero or slightly negative.
|
||||
// If it ends up negative, then we'll sleep less next frame to compensate
|
||||
deltaTick -= sleepTime - lastTick;
|
||||
lastTick = sleepTime;
|
||||
} else {
|
||||
// If we fall behind by a full frame or more, then skip to the next one
|
||||
while (deltaTick < -((double)1000 / max_fps))
|
||||
deltaTick += ((double)1000 / max_fps);
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
int32 msdelay = 1000.0 / max_fps;
|
||||
if (msdelay < 1)
|
||||
msdelay = 1;
|
||||
Sleep(msdelay);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef QB64_MACOSX
|
||||
# include <sys/sysctl.h>
|
||||
|
|
|
@ -43,11 +43,7 @@ void GLUT_MOTION_FUNC(int x, int y);
|
|||
void GLUT_PASSIVEMOTION_FUNC(int x, int y);
|
||||
void GLUT_RESHAPE_FUNC(int width, int height);
|
||||
|
||||
#ifdef QB64_WINDOWS
|
||||
void GLUT_TIMER_EVENT(int ignore);
|
||||
#else
|
||||
void GLUT_IDLEFUNC();
|
||||
#endif
|
||||
|
||||
#ifdef CORE_FREEGLUT
|
||||
void GLUT_MOUSEWHEEL_FUNC(int wheel, int direction, int x, int y);
|
||||
|
@ -97,11 +93,7 @@ static void initialize_glut(int argc, char **argv) {
|
|||
|
||||
glutDisplayFunc(GLUT_DISPLAY_REQUEST);
|
||||
|
||||
#ifdef QB64_WINDOWS
|
||||
glutTimerFunc(8, GLUT_TIMER_EVENT, 0);
|
||||
#else
|
||||
glutIdleFunc(GLUT_IDLEFUNC);
|
||||
#endif
|
||||
|
||||
glutKeyboardFunc(GLUT_KEYBOARD_FUNC);
|
||||
glutKeyboardUpFunc(GLUT_KEYBOARDUP_FUNC);
|
||||
|
|
Loading…
Reference in a new issue