timers internally now use 64bit unsigned int, if available
authorDiederick Niehorster <dcnieho@gmail.com>
Sun, 11 Mar 2012 13:03:14 +0000 (13:03 +0000)
committerDiederick Niehorster <dcnieho@gmail.com>
Sun, 11 Mar 2012 13:03:14 +0000 (13:03 +0000)
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
config.h.in
include/GL/freeglut_std.h
src/Common/freeglut_internal.h
src/Common/freeglut_main.c
src/Common/freeglut_state.c
src/mswin/freeglut_main_mswin.c
src/x11/freeglut_main_x11.c

index f422a9b..8b9d568 100644 (file)
@@ -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.
index c1467bc..588f15a 100644 (file)
@@ -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}
index d1cd23f..573243a 100644 (file)
 /* Use EGL (implies OpenGL ES) */
 /* TODO: EGL/GLES builds should be more generally defined, possibly by
    generating this file dynamically */
-#include <EGL/egl.h>
+#   include <EGL/egl.h>
 /* TODO: we probably need 2 builds: -lGLESv1 and -lGLESv2 */
 /* #include <GLES/gl.h> */
-#include <GLES2/gl2.h>
+#   include <GLES2/gl2.h>
 /* TODO: temporary work-around for e.g. glutWireCube */
-#define GLdouble     GLfloat
+#   define GLdouble     GLfloat
 #else
-#include <GL/gl.h>
-#include <GL/glu.h>
+#   include <GL/gl.h>
+#   include <GL/glu.h>
 #endif
 
 /*
index aab598f..9a3ef7b 100644 (file)
 #endif
 
 /* General defines */
-
 #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 */
@@ -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);
index ee40496..8aa02b2 100644 (file)
@@ -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;
index 84e2ccd..d310b70 100644 (file)
@@ -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" );
index 127a090..8a13a84 100644 (file)
@@ -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 );
 }
index 75bc54c..710535a 100644 (file)
@@ -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,