diff --git a/internal/c/libqb.cpp b/internal/c/libqb.cpp index bc8cfbff0..209f000e6 100644 --- a/internal/c/libqb.cpp +++ b/internal/c/libqb.cpp @@ -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 @@ -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(); diff --git a/internal/c/libqb/include/datetime.h b/internal/c/libqb/include/datetime.h index b4c4a6c9e..c8223e614 100644 --- a/internal/c/libqb/include/datetime.h +++ b/internal/c/libqb/include/datetime.h @@ -4,6 +4,14 @@ #include #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); diff --git a/internal/c/libqb/src/datetime.cpp b/internal/c/libqb/src/datetime.cpp index f7ca516de..bab6234e0 100644 --- a/internal/c/libqb/src/datetime.cpp +++ b/internal/c/libqb/src/datetime.cpp @@ -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(); } diff --git a/internal/c/libqb/src/glut-main-thread.cpp b/internal/c/libqb/src/glut-main-thread.cpp index 0efb40aa8..0b2233bf3 100644 --- a/internal/c/libqb/src/glut-main-thread.cpp +++ b/internal/c/libqb/src/glut-main-thread.cpp @@ -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); diff --git a/internal/source/main.txt b/internal/source/main.txt index 98233b720..0f0ffc569 100644 --- a/internal/source/main.txt +++ b/internal/source/main.txt @@ -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;} }