1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-05-09 23:10:12 +00:00

Compare commits

...

5 commits

Author SHA1 Message Date
Samuel Gomes 528a51f8bc
Merge 0195500087 into 15f7988101 2024-04-19 08:37:29 +05:30
github-actions[bot] 15f7988101 Automatic update of ./internal/source 2024-04-19 02:11:56 +00:00
Matt Kilgore cc382d433a
Merge pull request #474 from mkilgore/fix-60-fps
Fix GLUT thread to redraw at an accurate 60 FPS.
2024-04-18 21:53:32 -04:00
Matthew Kilgore cdbfb94c61 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
2024-04-17 00:58:30 -04:00
Matthew Kilgore 786f40193b Make Linux GetTicks() start from zero
Since the GetTicks() is visible in the logging, it's useful
to have it start from zero rather than an arbitrary number.
2024-04-17 00:58:30 -04:00
5 changed files with 68 additions and 46 deletions

View file

@ -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>
@ -29468,6 +29480,8 @@ int32 func__scaledheight() { return environment_2d__screen_scaled_height; }
extern void set_dynamic_info();
int main(int argc, char *argv[]) {
clock_init();
#if defined(QB64_LINUX) && defined(X11)
XInitThreads();

View file

@ -4,6 +4,14 @@
#include <stdint.h>
#include "qbs.h"
#ifdef QB64_LINUX
// Initializes the clock returned by 'GetTicks()' so that it starts from zero
// Should be called at the very beginning of the program
void clock_init();
#else
static inline void clock_init() { }
#endif
int64_t GetTicks();
double func_timer(double accuracy, int32_t passed);

View file

@ -37,10 +37,18 @@ static int64_t orwl_gettime(void) {
#endif
#ifdef QB64_LINUX
static int64_t initial_tick = 0;
void clock_init() {
// When GetTicks() is called here initial_tick is zero, so as a result
// GetTicks() returns the original value of the clock.
initial_tick = GetTicks();
}
int64_t GetTicks() {
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
return (tp.tv_sec * 1000 + tp.tv_nsec / 1000000) - initial_tick;
}
#elif defined QB64_MACOSX
int64_t GetTicks() { return orwl_gettime(); }

View file

@ -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);

View file

@ -128636,7 +128636,7 @@ sub__resize( 1 ,NULL);
if(!qbevent)break;evnt(23787,964,"ide_methods.bas");}while(r);
}
S_37650:;
if ((((func__resize()|*_FUNC_IDE2_LONG_FORCERESIZE))&(-(((float)(FUNC_TIMEELAPSEDSINCE(__SINGLE_QB64_UPTIME)))>((float)( 1.5E+0 )))))||is_error_pending()){
if ((((func__resize()|*_FUNC_IDE2_LONG_FORCERESIZE))&(-(FUNC_TIMEELAPSEDSINCE(__SINGLE_QB64_UPTIME)> 1.5E+0 )))||is_error_pending()){
if(qbevent){evnt(23787,966,"ide_methods.bas");if(r)goto S_37650;}
S_37651:;
if ((-(*__LONG_IDESUBWINDOW!= 0 ))||is_error_pending()){
@ -133112,7 +133112,7 @@ qbs_cleanup(qbs_tmp_base,0);
if(!qbevent)break;evnt(23787,2510,"ide_methods.bas");}while(r);
}
S_39247:;
if ((qbs_cleanup(qbs_tmp_base,(-(((double)(*_FUNC_IDE2_DOUBLE_T))>((double)((*__DOUBLE_HELP_SEARCH_TIME+ 1 )))))|(-(((double)(*_FUNC_IDE2_DOUBLE_T))<((double)(*__DOUBLE_HELP_SEARCH_TIME))))|(((-(*_FUNC_IDE2_LONG_K==*_FUNC_IDE2_LONG_OLDK))&(-(__STRING_HELP_SEARCH_STR->len== 1 ))))))||is_error_pending()){
if ((qbs_cleanup(qbs_tmp_base,(-(*_FUNC_IDE2_DOUBLE_T>(*__DOUBLE_HELP_SEARCH_TIME+ 1 )))|(-(*_FUNC_IDE2_DOUBLE_T<*__DOUBLE_HELP_SEARCH_TIME))|(((-(*_FUNC_IDE2_LONG_K==*_FUNC_IDE2_LONG_OLDK))&(-(__STRING_HELP_SEARCH_STR->len== 1 ))))))||is_error_pending()){
if(qbevent){evnt(23787,2511,"ide_methods.bas");if(r)goto S_39247;}
S_39248:;
if ((-(*_FUNC_IDE2_LONG_K==*_FUNC_IDE2_LONG_OLDK))||is_error_pending()){
@ -135301,7 +135301,7 @@ S_39871:;
if (((-(*_FUNC_IDE2_LONG_OLD__ASCII_CHR_046__MX==*__LONG_MX))&(-(*_FUNC_IDE2_LONG_OLD__ASCII_CHR_046__MY==*__LONG_MY)))||is_error_pending()){
if(qbevent){evnt(23787,3076,"ide_methods.bas");if(r)goto S_39871;}
S_39872:;
if ((-(((float)(FUNC_TIMEELAPSEDSINCE(&(pass4460=*_FUNC_IDE2_DOUBLE_LAST__ASCII_CHR_046__TBCLICK))))>((float)( 0.5E+0 ))))||is_error_pending()){
if ((-(FUNC_TIMEELAPSEDSINCE(&(pass4460=*_FUNC_IDE2_DOUBLE_LAST__ASCII_CHR_046__TBCLICK))> 0.5E+0 ))||is_error_pending()){
if(qbevent){evnt(23787,3077,"ide_methods.bas");if(r)goto S_39872;}
do{
goto LABEL_REGULARTEXTBOX_CLICK;
@ -138504,7 +138504,7 @@ do{
*_FUNC_IDE2_SINGLE_CHECK__ASCII_CHR_046__TABSTOP=(*__LONG_IDECX- 1 )/ ((long double)(*_FUNC_IDE2_LONG_X));
if(!qbevent)break;evnt(23787,4132,"ide_methods.bas");}while(r);
S_41009:;
if ((-(((float)(*_FUNC_IDE2_SINGLE_CHECK__ASCII_CHR_046__TABSTOP))==((float)(func_fix_double(*_FUNC_IDE2_SINGLE_CHECK__ASCII_CHR_046__TABSTOP)))))||is_error_pending()){
if ((-(*_FUNC_IDE2_SINGLE_CHECK__ASCII_CHR_046__TABSTOP==func_fix_double(*_FUNC_IDE2_SINGLE_CHECK__ASCII_CHR_046__TABSTOP)))||is_error_pending()){
if(qbevent){evnt(23787,4133,"ide_methods.bas");if(r)goto S_41009;}
S_41010:;
if ((-((*__LONG_IDECX-*_FUNC_IDE2_LONG_X)<( 1 )))||is_error_pending()){
@ -148867,7 +148867,7 @@ do{
*(int8*)(((char*)_SUB_DEBUGMODE_UDT_VWATCHPANEL)+(35))= 1 ;
if(!qbevent)break;evnt(23787,7118,"ide_methods.bas");}while(r);
S_44314:;
if ((-(((float)(FUNC_TIMEELAPSEDSINCE(_SUB_DEBUGMODE_SINGLE_LASTPANELCLICK)))<((float)( 0.3E+0 ))))||is_error_pending()){
if ((-(FUNC_TIMEELAPSEDSINCE(_SUB_DEBUGMODE_SINGLE_LASTPANELCLICK)< 0.3E+0 ))||is_error_pending()){
if(qbevent){evnt(23787,7119,"ide_methods.bas");if(r)goto S_44314;}
do{
*(int8*)(((char*)_SUB_DEBUGMODE_UDT_VWATCHPANEL)+(32))= 0 ;
@ -156791,7 +156791,7 @@ S_46618:;
if ((*__LONG_MCLICK&(-(*_FUNC_IDEVARIABLEWATCHBOX_LONG_FOCUS== 2 )))||is_error_pending()){
if(qbevent){evnt(23787,9272,"ide_methods.bas");if(r)goto S_46618;}
S_46619:;
if (((-(((float)(FUNC_TIMEELAPSEDSINCE(_FUNC_IDEVARIABLEWATCHBOX_SINGLE_LASTCLICK)))<((float)( 0.3E+0 ))))&(-(*_FUNC_IDEVARIABLEWATCHBOX_LONG_CLICKEDITEM==*(int32*)(((char*)_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_O[0])+((array_check((*_FUNC_IDEVARIABLEWATCHBOX_LONG_VARLISTBOX)-_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_O[4],_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_O[5]))*89+64)))))||is_error_pending()){
if (((-(FUNC_TIMEELAPSEDSINCE(_FUNC_IDEVARIABLEWATCHBOX_SINGLE_LASTCLICK)< 0.3E+0 ))&(-(*_FUNC_IDEVARIABLEWATCHBOX_LONG_CLICKEDITEM==*(int32*)(((char*)_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_O[0])+((array_check((*_FUNC_IDEVARIABLEWATCHBOX_LONG_VARLISTBOX)-_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_O[4],_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_O[5]))*89+64)))))||is_error_pending()){
if(qbevent){evnt(23787,9273,"ide_methods.bas");if(r)goto S_46619;}
S_46620:;
if (((-(*_FUNC_IDEVARIABLEWATCHBOX_LONG_DOUBLECLICKTHRESHOLD> 0 ))&(-(*__LONG_MX>=(*(int32*)(((char*)_FUNC_IDEVARIABLEWATCHBOX_UDT_P)+(0))+*_FUNC_IDEVARIABLEWATCHBOX_LONG_DOUBLECLICKTHRESHOLD)))&(-(*__LONG_IDEDEBUGMODE> 0 )))||is_error_pending()){
@ -159324,7 +159324,7 @@ S_47371:;
if ((*__LONG_MCLICK&(-(*_FUNC_IDEELEMENTWATCHBOX_LONG_FOCUS== 1 )))||is_error_pending()){
if(qbevent){evnt(23787,9989,"ide_methods.bas");if(r)goto S_47371;}
S_47372:;
if (((-(((float)(FUNC_TIMEELAPSEDSINCE(_FUNC_IDEELEMENTWATCHBOX_SINGLE_LASTCLICK)))<((float)( 0.3E+0 ))))&(-(*_FUNC_IDEELEMENTWATCHBOX_LONG_CLICKEDITEM==*(int32*)(((char*)_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_O[0])+((array_check((*_FUNC_IDEELEMENTWATCHBOX_LONG_VARLISTBOX)-_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_O[4],_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_O[5]))*89+64)))))||is_error_pending()){
if (((-(FUNC_TIMEELAPSEDSINCE(_FUNC_IDEELEMENTWATCHBOX_SINGLE_LASTCLICK)< 0.3E+0 ))&(-(*_FUNC_IDEELEMENTWATCHBOX_LONG_CLICKEDITEM==*(int32*)(((char*)_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_O[0])+((array_check((*_FUNC_IDEELEMENTWATCHBOX_LONG_VARLISTBOX)-_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_O[4],_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_O[5]))*89+64)))))||is_error_pending()){
if(qbevent){evnt(23787,9990,"ide_methods.bas");if(r)goto S_47372;}
S_47373:;
if ((-(*_FUNC_IDEELEMENTWATCHBOX_LONG_SINGLEELEMENTSELECTION== 0 ))||is_error_pending()){
@ -160891,7 +160891,7 @@ S_47798:;
if ((*__LONG_MCLICK&(-(*_FUNC_IDECALLSTACKBOX_LONG_FOCUS== 1 )))||is_error_pending()){
if(qbevent){evnt(23787,10399,"ide_methods.bas");if(r)goto S_47798;}
S_47799:;
if (((-(((float)(FUNC_TIMEELAPSEDSINCE(_FUNC_IDECALLSTACKBOX_SINGLE_LASTCLICK)))<((float)( 0.3E+0 ))))&(-(*_FUNC_IDECALLSTACKBOX_LONG_CLICKEDITEM==*(int32*)(((char*)_FUNC_IDECALLSTACKBOX_ARRAY_UDT_O[0])+((array_check(( 1 )-_FUNC_IDECALLSTACKBOX_ARRAY_UDT_O[4],_FUNC_IDECALLSTACKBOX_ARRAY_UDT_O[5]))*89+64)))))||is_error_pending()){
if (((-(FUNC_TIMEELAPSEDSINCE(_FUNC_IDECALLSTACKBOX_SINGLE_LASTCLICK)< 0.3E+0 ))&(-(*_FUNC_IDECALLSTACKBOX_LONG_CLICKEDITEM==*(int32*)(((char*)_FUNC_IDECALLSTACKBOX_ARRAY_UDT_O[0])+((array_check(( 1 )-_FUNC_IDECALLSTACKBOX_ARRAY_UDT_O[4],_FUNC_IDECALLSTACKBOX_ARRAY_UDT_O[5]))*89+64)))))||is_error_pending()){
if(qbevent){evnt(23787,10400,"ide_methods.bas");if(r)goto S_47799;}
do{
goto LABEL_SETIDECY;
@ -165980,7 +165980,7 @@ do{
*_FUNC_IDEHBAR_SINGLE_P=(*_FUNC_IDEHBAR_LONG_I- 1 )/ ((long double)((*_FUNC_IDEHBAR_LONG_N- 1 )));
if(!qbevent)break;evnt(23787,11775,"ide_methods.bas");}while(r);
S_49275:;
if ((-(((float)(*_FUNC_IDEHBAR_SINGLE_P))<((float)( 0.5E+0 ))))||is_error_pending()){
if ((-(*_FUNC_IDEHBAR_SINGLE_P< 0.5E+0 ))||is_error_pending()){
if(qbevent){evnt(23787,11776,"ide_methods.bas");if(r)goto S_49275;}
do{
*_FUNC_IDEHBAR_LONG_X2=*_FUNC_IDEHBAR_LONG_X+ 1 ;
@ -169100,7 +169100,7 @@ sf_mem_lock=mem_lock_tmp;
sf_mem_lock->type=3;
if (is_error_pending()) goto exit_subfunc;
S_50106:;
if ((-(((float)(*_FUNC_TIMEELAPSEDSINCE_SINGLE_STARTTIME))>((float)(func_timer(NULL,0)))))||is_error_pending()){
if ((-(*_FUNC_TIMEELAPSEDSINCE_SINGLE_STARTTIME>func_timer(NULL,0)))||is_error_pending()){
if(qbevent){evnt(23787,12549,"ide_methods.bas");if(r)goto S_50106;}
do{
*_FUNC_TIMEELAPSEDSINCE_SINGLE_STARTTIME=*_FUNC_TIMEELAPSEDSINCE_SINGLE_STARTTIME- 86400 ;
@ -177213,7 +177213,7 @@ do{
*_FUNC_IDEVBAR_SINGLE_P=(*_FUNC_IDEVBAR_LONG_I- 1 )/ ((long double)((*_FUNC_IDEVBAR_LONG_N- 1 )));
if(!qbevent)break;evnt(23787,14729,"ide_methods.bas");}while(r);
S_52338:;
if ((-(((float)(*_FUNC_IDEVBAR_SINGLE_P))<((float)( 0.5E+0 ))))||is_error_pending()){
if ((-(*_FUNC_IDEVBAR_SINGLE_P< 0.5E+0 ))||is_error_pending()){
if(qbevent){evnt(23787,14730,"ide_methods.bas");if(r)goto S_52338;}
do{
*_FUNC_IDEVBAR_LONG_Y2=*_FUNC_IDEVBAR_LONG_Y+ 1 ;
@ -194684,7 +194684,7 @@ do{
*_FUNC_IDEASCIIBOX_LONG_FOCUS= 1 ;
if(!qbevent)break;evnt(23787,19199,"ide_methods.bas");}while(r);
S_57244:;
if (((-(((float)(FUNC_TIMEELAPSEDSINCE(_FUNC_IDEASCIIBOX_SINGLE_LASTCLICK)))<=((float)( 0.3E+0 ))))&(-(*_FUNC_IDEASCIIBOX_LONG_LASTCLICKON==*_FUNC_IDEASCIIBOX_LONG_I)))||is_error_pending()){
if (((-(FUNC_TIMEELAPSEDSINCE(_FUNC_IDEASCIIBOX_SINGLE_LASTCLICK)<= 0.3E+0 ))&(-(*_FUNC_IDEASCIIBOX_LONG_LASTCLICKON==*_FUNC_IDEASCIIBOX_LONG_I)))||is_error_pending()){
if(qbevent){evnt(23787,19200,"ide_methods.bas");if(r)goto S_57244;}
do{
*_FUNC_IDEASCIIBOX_LONG_RELAUNCH= -1 ;
@ -203588,7 +203588,7 @@ if(!qbevent)break;evnt(23787,1169,"wiki_methods.bas");}while(r);
}
S_59826:;
dl_continue_6855:;
}while((!(-(((float)((func_timer( 0.001E+0 ,0|1))))>((float)((*_FUNC_WIKIDLPAGE_DOUBLE_ST+*_FUNC_WIKIDLPAGE_DOUBLE_TIO))))))&&(!is_error_pending()));
}while((!(-((func_timer( 0.001E+0 ,0|1))>(*_FUNC_WIKIDLPAGE_DOUBLE_ST+*_FUNC_WIKIDLPAGE_DOUBLE_TIO))))&&(!is_error_pending()));
dl_exit_6855:;
if(qbevent){evnt(23787,1170,"wiki_methods.bas");if(r)goto S_59826;}
}