fgCreateStructure( );
- /* Get start time */
- fgState.Time = fgSystemTime();
-
fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
/*
/* 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
+ * which means you 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.
*/
fg_time_t fgSystemTime(void)
{
case GLUT_INIT_STATE:
return fgState.Initialised;
+ /* Although internally the time store is 64bits wide, the return value
+ * here still wraps every 49.7 days. Integer overflows cancel however
+ * when subtracting an initial start time, unless the total time exceeds
+ * 32-bit, so you can still work with this.
+ * XXX: a glutGet64 to return the time might be an idea...
+ */
case GLUT_ELAPSED_TIME:
return (int) fgElapsedTime();
}
extern LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam );
+extern void fgPlatformInitSystemTime();
/*
}
/* Set the timer granularity to 1 ms */
timeBeginPeriod ( 1 );
+ /* Init setup to deal with timer wrap, can't query system time before this is done */
+ fgPlatformInitSystemTime();
+ /* Get start time */
+ fgState.Time = fgSystemTime();
fgState.Initialised = GL_TRUE;
}
+/* Get system time, taking special precautions against 32bit timer wrap.
+ We use timeGetTime and not GetTickCount because of its better stability,
+ and because we can increase its granularity (to 1 ms in
+ fgPlatformInitialize). For that reason we can't use GetTickCount64 which
+ wouldn't have the wrap issue.
+ Credit: this is based on code in glibc (https://mail.gnome.org/archives/commits-list/2011-November/msg04588.html)
+ */
+static fg_time_t lastTime32 = 0;
+static fg_time_t timeEpoch = 0;
+void fgPlatformInitSystemTime()
+{
+#if defined(_WIN32_WCE)
+ lastTime32 = GetTickCount();
+#else
+ lastTime32 = timeGetTime();
+#endif
+}
fg_time_t fgPlatformSystemTime ( void )
{
+ fg_time_t currTime32;
#if defined(_WIN32_WCE)
- return GetTickCount();
+ currTime32 = 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();
+ currTime32 = timeGetTime();
#endif
+ /* Check if we just wrapped */
+ if (currTime32 < lastTime32)
+ timeEpoch++;
+
+ lastTime32 = currTime32;
+
+ return currTime32 | timeEpoch << 32;
}
}
}
+ /* Get start time */
+ fgState.Time = fgSystemTime();
+
fgState.Initialised = GL_TRUE;