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:
parent
49bfb6bd84
commit
e78202b0af
@ -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)
|
||||||
@ -169,8 +170,13 @@ CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H)
|
|||||||
CHECK_INCLUDE_FILES(errno.h HAVE_ERRNO_H)
|
CHECK_INCLUDE_FILES(errno.h HAVE_ERRNO_H)
|
||||||
CHECK_INCLUDE_FILES(usbhid.h HAVE_USBHID_H)
|
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.
|
||||||
|
@ -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}
|
||||||
|
@ -123,15 +123,15 @@
|
|||||||
/* Use EGL (implies OpenGL ES) */
|
/* Use EGL (implies OpenGL ES) */
|
||||||
/* TODO: EGL/GLES builds should be more generally defined, possibly by
|
/* TODO: EGL/GLES builds should be more generally defined, possibly by
|
||||||
generating this file dynamically */
|
generating this file dynamically */
|
||||||
#include <EGL/egl.h>
|
# include <EGL/egl.h>
|
||||||
/* TODO: we probably need 2 builds: -lGLESv1 and -lGLESv2 */
|
/* TODO: we probably need 2 builds: -lGLESv1 and -lGLESv2 */
|
||||||
/* #include <GLES/gl.h> */
|
/* #include <GLES/gl.h> */
|
||||||
#include <GLES2/gl2.h>
|
# include <GLES2/gl2.h>
|
||||||
/* TODO: temporary work-around for e.g. glutWireCube */
|
/* TODO: temporary work-around for e.g. glutWireCube */
|
||||||
#define GLdouble GLfloat
|
# define GLdouble GLfloat
|
||||||
#else
|
#else
|
||||||
#include <GL/gl.h>
|
# include <GL/gl.h>
|
||||||
#include <GL/glu.h>
|
# include <GL/glu.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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);
|
||||||
|
@ -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,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
|
* 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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;
|
||||||
|
@ -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" );
|
||||||
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
Reference in New Issue
Block a user