From 1ede9f68f98e29ddd07bd466310967e716bfac92 Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 11 Mar 2012 13:03:14 +0000 Subject: [PATCH] timers internally now use 64bit unsigned int, if available External timer info (glutGet) unchanged. Some work to do to improve Windows timers beyond what it is now... git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1110 7f0cb862-5218-0410-a997-914c9d46530a --- CMakeLists.txt | 10 ++++++++-- config.h.in | 3 +++ include/GL/freeglut_std.h | 10 +++++----- src/Common/freeglut_internal.h | 24 +++++++++++++++++------ src/Common/freeglut_main.c | 40 ++++++++++++++++++++++----------------- src/Common/freeglut_state.c | 2 +- src/mswin/freeglut_main_mswin.c | 12 ++++++++++-- src/x11/freeglut_main_x11.c | 8 +++----- 8 files changed, 71 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f422a9b..8b9d568 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,6 +159,7 @@ ENDIF() INCLUDE(CheckIncludeFiles) INCLUDE(CheckFunctionExists) +INCLUDE(CheckTypeSize) CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H) CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) @@ -169,8 +170,13 @@ CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H) CHECK_INCLUDE_FILES(errno.h HAVE_ERRNO_H) CHECK_INCLUDE_FILES(usbhid.h HAVE_USBHID_H) CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) -CHECK_FUNCTION_EXISTS(vfprintf HAVE_VFPRINTF) -CHECK_FUNCTION_EXISTS(_doprnt HAVE_DOPRNT) +CHECK_FUNCTION_EXISTS(vfprintf HAVE_VFPRINTF) +CHECK_FUNCTION_EXISTS(_doprnt HAVE_DOPRNT) +# decide on suitable type for internal time keeping, 64-bit if possible +CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H) +CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H) +CHECK_TYPE_SIZE("unsigned long long" ULONG_LONG BUILTIN_TYPES_ONLY) + # The generated config.h is placed in the project's build directory, just to # ensure that all CMake-generated files are kept away from the main source tree. diff --git a/config.h.in b/config.h.in index c1467bc..588f15a 100644 --- a/config.h.in +++ b/config.h.in @@ -12,3 +12,6 @@ #cmakedefine HAVE_GETTIMEOFDAY #cmakedefine HAVE_VFPRINTF #cmakedefine HAVE_DOPRNT +#cmakedefine HAVE_STDINT_H +#cmakedefine HAVE_INTTYPES_H +#define HAVE_ULONG_LONG ${HAVE_ULONG_LONG} diff --git a/include/GL/freeglut_std.h b/include/GL/freeglut_std.h index d1cd23f..573243a 100644 --- a/include/GL/freeglut_std.h +++ b/include/GL/freeglut_std.h @@ -123,15 +123,15 @@ /* Use EGL (implies OpenGL ES) */ /* TODO: EGL/GLES builds should be more generally defined, possibly by generating this file dynamically */ -#include +# include /* TODO: we probably need 2 builds: -lGLESv1 and -lGLESv2 */ /* #include */ -#include +# include /* TODO: temporary work-around for e.g. glutWireCube */ -#define GLdouble GLfloat +# define GLdouble GLfloat #else -#include -#include +# include +# include #endif /* diff --git a/src/Common/freeglut_internal.h b/src/Common/freeglut_internal.h index aab598f..9a3ef7b 100644 --- a/src/Common/freeglut_internal.h +++ b/src/Common/freeglut_internal.h @@ -154,9 +154,21 @@ #endif /* General defines */ - #define INVALID_MODIFIERS 0xffffffff +/* FreeGLUT internal time type */ +#if defined(HAVE_STDINT_H) +# include + typedef uint64_t fg_time_t; +#elif defined(HAVE_INTTYPES_H) +# include + typedef uint64_t fg_time_t; +#elif defined(HAVE_ULONG_LONG) + typedef unsigned long long fg_time_t; +#else + typedef unsigned long fg_time_t; +#endif + /* Platform-specific includes */ @@ -278,7 +290,7 @@ struct tagSFG_State GLuint SwapCount; /* Count of glutSwapBuffer calls */ GLuint SwapTime; /* Time of last SwapBuffers */ - unsigned long Time; /* Time that glutInit was called */ + fg_time_t Time; /* Time that glutInit was called */ SFG_List Timers; /* The freeglut timer hooks */ SFG_List FreeTimers; /* The unused timer hooks */ @@ -333,7 +345,7 @@ struct tagSFG_Timer SFG_Node Node; int ID; /* The timer ID integer */ FGCBTimer Callback; /* The timer callback */ - long TriggerTime; /* The timer trigger time */ + fg_time_t TriggerTime; /* The timer trigger time */ }; /* @@ -367,7 +379,7 @@ struct tagSFG_WindowState int Cursor; /* The currently selected cursor */ long JoystickPollRate; /* The joystick polling rate */ - long JoystickLastPoll; /* When the last poll happened */ + fg_time_t JoystickLastPoll; /* When the last poll happened */ int MouseX, MouseY; /* The most recent mouse position */ @@ -925,10 +937,10 @@ void fgDeactivateMenu( SFG_Window *window ); void fgDisplayMenu( void ); /* Elapsed time as per glutGet(GLUT_ELAPSED_TIME). */ -long fgElapsedTime( void ); +fg_time_t fgElapsedTime( void ); /* System time in milliseconds */ -long unsigned fgSystemTime(void); +fg_time_t fgSystemTime(void); /* List functions */ void fgListInit(SFG_List *list); diff --git a/src/Common/freeglut_main.c b/src/Common/freeglut_main.c index ee40496..8aa02b2 100644 --- a/src/Common/freeglut_main.c +++ b/src/Common/freeglut_main.c @@ -56,8 +56,8 @@ extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ); extern void fgPlatformDisplayWindow ( SFG_Window *window ); -extern unsigned long fgPlatformSystemTime ( void ); -extern void fgPlatformSleepForEvents( long msec ); +extern fg_time_t fgPlatformSystemTime ( void ); +extern void fgPlatformSleepForEvents( fg_time_t msec ); extern void fgPlatformProcessSingleEvent ( void ); extern void fgPlatformMainLoopPreliminaryWork ( void ); @@ -161,7 +161,7 @@ static void fghDisplayAll( void ) static void fghcbCheckJoystickPolls( SFG_Window *window, SFG_Enumerator *enumerator ) { - long int checkTime = fgElapsedTime( ); + fg_time_t checkTime = fgElapsedTime( ); if( window->State.JoystickLastPoll + window->State.JoystickPollRate <= checkTime ) @@ -193,7 +193,7 @@ static void fghCheckJoystickPolls( void ) */ static void fghCheckTimers( void ) { - long checkTime = fgElapsedTime( ); + fg_time_t checkTime = fgElapsedTime( ); while( fgState.Timers.First ) { @@ -210,22 +210,27 @@ static void fghCheckTimers( void ) } -/* Platform-dependent time in milliseconds, as an unsigned 32-bit integer. +/* Platform-dependent time in milliseconds, as an unsigned 64-bit integer. + * This doesn't overflow in any reasonable time, so no need to worry about + * that. The GLUT API return value will however overflow after 49.7 days, + * and on Windows we (currently) do not have access to a 64-bit timestamp, + * which means internal time will still get in trouble when running the + * application for more than 49.7 days. * This value wraps every 49.7 days, but integer overflows cancel * when subtracting an initial start time, unless the total time exceeds * 32-bit, where the GLUT API return value is also overflowed. */ -unsigned long fgSystemTime(void) +fg_time_t fgSystemTime(void) { - return fgPlatformSystemTime (); + return fgPlatformSystemTime(); } /* * Elapsed Time */ -long fgElapsedTime( void ) +fg_time_t fgElapsedTime( void ) { - return (long) (fgSystemTime() - fgState.Time); + return fgSystemTime() - fgState.Time; } /* @@ -342,22 +347,23 @@ static int fghHavePendingRedisplays (void) /* * Returns the number of GLUT ticks (milliseconds) till the next timer event. */ -static long fghNextTimer( void ) +static fg_time_t fghNextTimer( void ) { - long ret = INT_MAX; + fg_time_t currentTime = fgElapsedTime(); SFG_Timer *timer = fgState.Timers.First; - if( timer ) - ret = timer->TriggerTime - fgElapsedTime(); - if( ret < 0 ) - ret = 0; + if( !timer ) + return INT_MAX; - return ret; + if( timer->TriggerTime < currentTime ) + return 0; + else + return timer->TriggerTime - currentTime; } static void fghSleepForEvents( void ) { - long msec; + fg_time_t msec; if( fgState.IdleCallback || fghHavePendingRedisplays( ) ) return; diff --git a/src/Common/freeglut_state.c b/src/Common/freeglut_state.c index 84e2ccd..d310b70 100644 --- a/src/Common/freeglut_state.c +++ b/src/Common/freeglut_state.c @@ -128,7 +128,7 @@ int FGAPIENTRY glutGet( GLenum eWhat ) return fgState.Initialised; case GLUT_ELAPSED_TIME: - return fgElapsedTime(); + return (int) fgElapsedTime(); } FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" ); diff --git a/src/mswin/freeglut_main_mswin.c b/src/mswin/freeglut_main_mswin.c index 127a090..8a13a84 100644 --- a/src/mswin/freeglut_main_mswin.c +++ b/src/mswin/freeglut_main_mswin.c @@ -122,17 +122,25 @@ void fgPlatformDisplayWindow ( SFG_Window *window ) } -unsigned long fgPlatformSystemTime ( void ) +fg_time_t fgPlatformSystemTime ( void ) { #if defined(_WIN32_WCE) return GetTickCount(); #else + /* TODO: do this with QueryPerformanceCounter as timeGetTime has + * insufficient resolution (only about 5 ms on system under low load). + * See: + * http://msdn.microsoft.com/en-us/library/windows/desktop/dd757629(v=vs.85).aspx + * Or maybe QueryPerformanceCounter is not a good idea either, see + * http://old.nabble.com/Re%3A-glutTimerFunc-does-not-detect-if-system-time-moved-backward-p33479674.html + * for some other ideas (at bottom)... + */ return timeGetTime(); #endif } -void fgPlatformSleepForEvents( long msec ) +void fgPlatformSleepForEvents( fg_time_t msec ) { MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLINPUT ); } diff --git a/src/x11/freeglut_main_x11.c b/src/x11/freeglut_main_x11.c index 75bc54c..710535a 100644 --- a/src/x11/freeglut_main_x11.c +++ b/src/x11/freeglut_main_x11.c @@ -89,19 +89,17 @@ void fgPlatformDisplayWindow ( SFG_Window *window ) } -unsigned long fgPlatformSystemTime ( void ) +fg_time_t fgPlatformSystemTime ( void ) { #ifdef CLOCK_MONOTONIC struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); return now.tv_nsec/1000000 + now.tv_sec*1000; -#else -#ifdef HAVE_GETTIMEOFDAY +#elif defined(HAVE_GETTIMEOFDAY) struct timeval now; gettimeofday( &now, NULL ); return now.tv_usec/1000 + now.tv_sec*1000; #endif -#endif } /* @@ -109,7 +107,7 @@ unsigned long fgPlatformSystemTime ( void ) * happens. */ -void fgPlatformSleepForEvents( long msec ) +void fgPlatformSleepForEvents( fg_time_t msec ) { /* * Possibly due to aggressive use of XFlush() and friends, -- 1.7.10.4