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: https://svn.code.sf.net/p/freeglut/code/trunk@1110 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
dcnieho 2012-03-11 13:03:14 +00:00
parent 49bfb6bd84
commit e78202b0af
8 changed files with 71 additions and 38 deletions

View File

@ -159,6 +159,7 @@ ENDIF()
INCLUDE(CheckIncludeFiles) INCLUDE(CheckIncludeFiles)
INCLUDE(CheckFunctionExists) INCLUDE(CheckFunctionExists)
INCLUDE(CheckTypeSize)
CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H) CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H)
@ -171,6 +172,11 @@ CHECK_INCLUDE_FILES(usbhid.h HAVE_USBHID_H)
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
CHECK_FUNCTION_EXISTS(vfprintf HAVE_VFPRINTF) CHECK_FUNCTION_EXISTS(vfprintf HAVE_VFPRINTF)
CHECK_FUNCTION_EXISTS(_doprnt HAVE_DOPRNT) 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 # 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. # ensure that all CMake-generated files are kept away from the main source tree.

View File

@ -12,3 +12,6 @@
#cmakedefine HAVE_GETTIMEOFDAY #cmakedefine HAVE_GETTIMEOFDAY
#cmakedefine HAVE_VFPRINTF #cmakedefine HAVE_VFPRINTF
#cmakedefine HAVE_DOPRNT #cmakedefine HAVE_DOPRNT
#cmakedefine HAVE_STDINT_H
#cmakedefine HAVE_INTTYPES_H
#define HAVE_ULONG_LONG ${HAVE_ULONG_LONG}

View File

@ -154,9 +154,21 @@
#endif #endif
/* General defines */ /* General defines */
#define INVALID_MODIFIERS 0xffffffff #define INVALID_MODIFIERS 0xffffffff
/* FreeGLUT internal time type */
#if defined(HAVE_STDINT_H)
# include <stdint.h>
typedef uint64_t fg_time_t;
#elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
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 */ /* Platform-specific includes */
@ -278,7 +290,7 @@ struct tagSFG_State
GLuint SwapCount; /* Count of glutSwapBuffer calls */ GLuint SwapCount; /* Count of glutSwapBuffer calls */
GLuint SwapTime; /* Time of last SwapBuffers */ 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 Timers; /* The freeglut timer hooks */
SFG_List FreeTimers; /* The unused timer hooks */ SFG_List FreeTimers; /* The unused timer hooks */
@ -333,7 +345,7 @@ struct tagSFG_Timer
SFG_Node Node; SFG_Node Node;
int ID; /* The timer ID integer */ int ID; /* The timer ID integer */
FGCBTimer Callback; /* The timer callback */ 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 */ int Cursor; /* The currently selected cursor */
long JoystickPollRate; /* The joystick polling rate */ 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 */ int MouseX, MouseY; /* The most recent mouse position */
@ -925,10 +937,10 @@ void fgDeactivateMenu( SFG_Window *window );
void fgDisplayMenu( void ); void fgDisplayMenu( void );
/* Elapsed time as per glutGet(GLUT_ELAPSED_TIME). */ /* Elapsed time as per glutGet(GLUT_ELAPSED_TIME). */
long fgElapsedTime( void ); fg_time_t fgElapsedTime( void );
/* System time in milliseconds */ /* System time in milliseconds */
long unsigned fgSystemTime(void); fg_time_t fgSystemTime(void);
/* List functions */ /* List functions */
void fgListInit(SFG_List *list); void fgListInit(SFG_List *list);

View File

@ -56,8 +56,8 @@
extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ); extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height );
extern void fgPlatformDisplayWindow ( SFG_Window *window ); extern void fgPlatformDisplayWindow ( SFG_Window *window );
extern unsigned long fgPlatformSystemTime ( void ); extern fg_time_t fgPlatformSystemTime ( void );
extern void fgPlatformSleepForEvents( long msec ); extern void fgPlatformSleepForEvents( fg_time_t msec );
extern void fgPlatformProcessSingleEvent ( void ); extern void fgPlatformProcessSingleEvent ( void );
extern void fgPlatformMainLoopPreliminaryWork ( void ); extern void fgPlatformMainLoopPreliminaryWork ( void );
@ -161,7 +161,7 @@ static void fghDisplayAll( void )
static void fghcbCheckJoystickPolls( SFG_Window *window, static void fghcbCheckJoystickPolls( SFG_Window *window,
SFG_Enumerator *enumerator ) SFG_Enumerator *enumerator )
{ {
long int checkTime = fgElapsedTime( ); fg_time_t checkTime = fgElapsedTime( );
if( window->State.JoystickLastPoll + window->State.JoystickPollRate <= if( window->State.JoystickLastPoll + window->State.JoystickPollRate <=
checkTime ) checkTime )
@ -193,7 +193,7 @@ static void fghCheckJoystickPolls( void )
*/ */
static void fghCheckTimers( void ) static void fghCheckTimers( void )
{ {
long checkTime = fgElapsedTime( ); fg_time_t checkTime = fgElapsedTime( );
while( fgState.Timers.First ) while( fgState.Timers.First )
{ {
@ -210,12 +210,17 @@ 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 * This value wraps every 49.7 days, but integer overflows cancel
* when subtracting an initial start time, unless the total time exceeds * when subtracting an initial start time, unless the total time exceeds
* 32-bit, where the GLUT API return value is also overflowed. * 32-bit, where the GLUT API return value is also overflowed.
*/ */
unsigned long fgSystemTime(void) fg_time_t fgSystemTime(void)
{ {
return fgPlatformSystemTime(); return fgPlatformSystemTime();
} }
@ -223,9 +228,9 @@ unsigned long fgSystemTime(void)
/* /*
* Elapsed Time * 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. * 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; SFG_Timer *timer = fgState.Timers.First;
if( timer ) if( !timer )
ret = timer->TriggerTime - fgElapsedTime(); return INT_MAX;
if( ret < 0 )
ret = 0;
return ret; if( timer->TriggerTime < currentTime )
return 0;
else
return timer->TriggerTime - currentTime;
} }
static void fghSleepForEvents( void ) static void fghSleepForEvents( void )
{ {
long msec; fg_time_t msec;
if( fgState.IdleCallback || fghHavePendingRedisplays( ) ) if( fgState.IdleCallback || fghHavePendingRedisplays( ) )
return; return;

View File

@ -128,7 +128,7 @@ int FGAPIENTRY glutGet( GLenum eWhat )
return fgState.Initialised; return fgState.Initialised;
case GLUT_ELAPSED_TIME: case GLUT_ELAPSED_TIME:
return fgElapsedTime(); return (int) fgElapsedTime();
} }
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" );

View File

@ -122,17 +122,25 @@ void fgPlatformDisplayWindow ( SFG_Window *window )
} }
unsigned long fgPlatformSystemTime ( void ) fg_time_t fgPlatformSystemTime ( void )
{ {
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
return GetTickCount(); return GetTickCount();
#else #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(); return timeGetTime();
#endif #endif
} }
void fgPlatformSleepForEvents( long msec ) void fgPlatformSleepForEvents( fg_time_t msec )
{ {
MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLINPUT ); MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLINPUT );
} }

View File

@ -89,19 +89,17 @@ void fgPlatformDisplayWindow ( SFG_Window *window )
} }
unsigned long fgPlatformSystemTime ( void ) fg_time_t fgPlatformSystemTime ( void )
{ {
#ifdef CLOCK_MONOTONIC #ifdef CLOCK_MONOTONIC
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_nsec/1000000 + now.tv_sec*1000; return now.tv_nsec/1000000 + now.tv_sec*1000;
#else #elif defined(HAVE_GETTIMEOFDAY)
#ifdef HAVE_GETTIMEOFDAY
struct timeval now; struct timeval now;
gettimeofday( &now, NULL ); gettimeofday( &now, NULL );
return now.tv_usec/1000 + now.tv_sec*1000; return now.tv_usec/1000 + now.tv_sec*1000;
#endif #endif
#endif
} }
/* /*
@ -109,7 +107,7 @@ unsigned long fgPlatformSystemTime ( void )
* happens. * happens.
*/ */
void fgPlatformSleepForEvents( long msec ) void fgPlatformSleepForEvents( fg_time_t msec )
{ {
/* /*
* Possibly due to aggressive use of XFlush() and friends, * Possibly due to aggressive use of XFlush() and friends,