Add glfwGetTimerValue and glfwGetTimerFrequency

This adds raw timer access to the public API and builds the
floating-point time functions on top.  It also makes the GLFWuint64 type
public.
This commit is contained in:
Camilla Berglund 2016-03-06 11:38:55 +01:00
parent 8221aadea3
commit 31f67dd3cc
14 changed files with 148 additions and 96 deletions

View File

@ -83,6 +83,8 @@ does not find Doxygen, the documentation will not be generated.
absolute and relative window size limits absolute and relative window size limits
- Added `glfwGetKeyName` for querying the layout-specific name of printable - Added `glfwGetKeyName` for querying the layout-specific name of printable
keys keys
- Added `glfwGetTimerValue` and `glfwGetTimerFrequency` for raw timer access
- Added `GLFWuint64` for platform-independent 64-bit unsigned values
- Added `GLFW_NO_API` for creating window without contexts - Added `GLFW_NO_API` for creating window without contexts
- Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support - Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support
- Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header - Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header

View File

@ -554,6 +554,21 @@ glfwSetTime(4.0);
This sets the timer to the specified time, in seconds. This sets the timer to the specified time, in seconds.
You can also access the raw timer value, in 1 / frequency seconds,
with @ref glfwGetTimerValue.
@code
GLFWuint64 value = glfwGetTimerValue();
@endcode
The frequency of the raw timer varies depending on what time sources are
available on the machine. You can query its frequency, in Hz, with @ref
glfwGetTimerFrequency.
@code
GLFWuint64 freqency = glfwGetTimerFrequency();
@endcode
@section clipboard Clipboard input and output @section clipboard Clipboard input and output

View File

@ -37,6 +37,12 @@ GLFW now supports window maximization with @ref glfwMaximizeWindow and the
GLFW now supports giving windows input focus with @ref glfwFocusWindow. GLFW now supports giving windows input focus with @ref glfwFocusWindow.
@subsection news_32_timer Raw timer access
GLFW now supports raw timer values with @ref glfwGetTimerValue and @ref
glfwGetTimerFrequency.
@section news_31 New features in 3.1 @section news_31 New features in 3.1
These are the release highlights. For a full list of changes see the These are the release highlights. For a full list of changes see the

View File

@ -728,6 +728,19 @@ extern "C" {
* GLFW API types * GLFW API types
*************************************************************************/ *************************************************************************/
/*! @brief 64-bit unsigned integer.
*
* 64-bit unsigned integer.
*
* @since Added in version 3.2.
*/
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef unsigned __int64 GLFWuint64;
#else
#include <stdint.h>
typedef uint64_t GLFWuint64;
#endif
/*! @brief Client API function pointer type. /*! @brief Client API function pointer type.
* *
* Generic function pointer used for returning client API function pointers * Generic function pointer used for returning client API function pointers
@ -3557,6 +3570,47 @@ GLFWAPI double glfwGetTime(void);
*/ */
GLFWAPI void glfwSetTime(double time); GLFWAPI void glfwSetTime(double time);
/*! @brief Returns the current value of the raw timer.
*
* This function returns the current value of the raw timer. To get its
* frequency, call @ref glfwGetTimerFrequency.
*
* @return The value of the timer, or zero if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_VALUE.
*
* @thread_safety This function may be called from any thread.
*
* @sa @ref time
* @sa glfwGetTimerFrequency
*
* @since Added in version 3.2.
*
* @ingroup input
*/
GLFWAPI GLFWuint64 glfwGetTimerValue(void);
/*! @brief Returns the frequency, in Hz, of the raw timer.
*
* @return The frequency of the timer, in Hz, or zero if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_VALUE.
*
* @thread_safety This function may be called from any thread.
*
* @sa @ref time
* @sa glfwGetTimerValue
*
* @since Added in version 3.2.
*
* @ingroup input
*/
GLFWAPI GLFWuint64 glfwGetTimerFrequency(void);
/*! @brief Makes the context of the specified window current for the calling /*! @brief Makes the context of the specified window current for the calling
* thread. * thread.
* *

View File

@ -118,8 +118,7 @@ typedef struct _GLFWcursorNS
// //
typedef struct _GLFWtimeNS typedef struct _GLFWtimeNS
{ {
double base; GLFWuint64 frequency;
double resolution;
} _GLFWtimeNS; } _GLFWtimeNS;

View File

@ -29,14 +29,6 @@
#include <mach/mach_time.h> #include <mach/mach_time.h>
// Return raw time
//
static uint64_t getRawTime(void)
{
return mach_absolute_time();
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -48,8 +40,7 @@ void _glfwInitTimerNS(void)
mach_timebase_info_data_t info; mach_timebase_info_data_t info;
mach_timebase_info(&info); mach_timebase_info(&info);
_glfw.ns_time.resolution = (double) info.numer / (info.denom * 1.0e9); _glfw.ns_time.frequency = (info.denom * 1e9) / info.numer;
_glfw.ns_time.base = getRawTime();
} }
@ -57,15 +48,13 @@ void _glfwInitTimerNS(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void) GLFWuint64 _glfwPlatformGetTimerValue(void)
{ {
return (double) (getRawTime() - _glfw.ns_time.base) * return mach_absolute_time();
_glfw.ns_time.resolution;
} }
void _glfwPlatformSetTime(double time) GLFWuint64 _glfwPlatformGetTimerFrequency(void)
{ {
_glfw.ns_time.base = getRawTime() - return _glfw.ns_time.frequency;
(uint64_t) (time / _glfw.ns_time.resolution);
} }

View File

@ -135,6 +135,8 @@ GLFWAPI int glfwInit(void)
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount); _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
_glfwInitialized = GLFW_TRUE; _glfwInitialized = GLFW_TRUE;
_glfw.timerOffset = _glfwPlatformGetTimerValue();
// Not all window hints have zero as their default value // Not all window hints have zero as their default value
glfwDefaultWindowHints(); glfwDefaultWindowHints();

View File

@ -645,7 +645,8 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
GLFWAPI double glfwGetTime(void) GLFWAPI double glfwGetTime(void)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(0.0); _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
return _glfwPlatformGetTime(); return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
_glfwPlatformGetTimerFrequency();
} }
GLFWAPI void glfwSetTime(double time) GLFWAPI void glfwSetTime(double time)
@ -658,6 +659,19 @@ GLFWAPI void glfwSetTime(double time)
return; return;
} }
_glfwPlatformSetTime(time); _glfw.timerOffset = _glfwPlatformGetTimerValue() -
(GLFWuint64) (time * _glfwPlatformGetTimerFrequency());
}
GLFWAPI GLFWuint64 glfwGetTimerValue(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return _glfwPlatformGetTimerValue();
}
GLFWAPI GLFWuint64 glfwGetTimerFrequency(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return _glfwPlatformGetTimerFrequency();
} }

View File

@ -47,13 +47,6 @@
#define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_NONE
#include "../include/GLFW/glfw3.h" #include "../include/GLFW/glfw3.h"
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef unsigned __int64 GLFWuint64;
#else
#include <stdint.h>
typedef uint64_t GLFWuint64;
#endif
typedef int GLFWbool; typedef int GLFWbool;
typedef struct _GLFWwndconfig _GLFWwndconfig; typedef struct _GLFWwndconfig _GLFWwndconfig;
@ -432,6 +425,8 @@ struct _GLFWlibrary
_GLFWmonitor** monitors; _GLFWmonitor** monitors;
int monitorCount; int monitorCount;
GLFWuint64 timerOffset;
struct { struct {
GLFWbool available; GLFWbool available;
void* handle; void* handle;
@ -596,15 +591,15 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
*/ */
const char* _glfwPlatformGetJoystickName(int joy); const char* _glfwPlatformGetJoystickName(int joy);
/*! @copydoc glfwGetTime /*! @copydoc glfwGetTimerValue
* @ingroup platform * @ingroup platform
*/ */
double _glfwPlatformGetTime(void); GLFWuint64 _glfwPlatformGetTimerValue(void);
/*! @copydoc glfwSetTime /*! @copydoc glfwGetTimerFrequency
* @ingroup platform * @ingroup platform
*/ */
void _glfwPlatformSetTime(double time); GLFWuint64 _glfwPlatformGetTimerFrequency(void);
/*! @ingroup platform /*! @ingroup platform
*/ */

View File

@ -30,28 +30,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
// Return raw time
//
static uint64_t getRawTime(void)
{
#if defined(CLOCK_MONOTONIC)
if (_glfw.posix_time.monotonic)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
}
else
#endif
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -67,15 +45,14 @@ void _glfwInitTimerPOSIX(void)
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
{ {
_glfw.posix_time.monotonic = GLFW_TRUE; _glfw.posix_time.monotonic = GLFW_TRUE;
_glfw.posix_time.resolution = 1e-9; _glfw.posix_time.frequency = 1000000000;
} }
else else
#endif #endif
{ {
_glfw.posix_time.resolution = 1e-6; _glfw.posix_time.monotonic = GLFW_FALSE;
_glfw.posix_time.frequency = 1000000;
} }
_glfw.posix_time.base = getRawTime();
} }
@ -83,15 +60,26 @@ void _glfwInitTimerPOSIX(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void) GLFWuint64 _glfwPlatformGetTimerValue(void)
{ {
return (double) (getRawTime() - _glfw.posix_time.base) * #if defined(CLOCK_MONOTONIC)
_glfw.posix_time.resolution; if (_glfw.posix_time.monotonic)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
}
else
#endif
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
}
} }
void _glfwPlatformSetTime(double time) GLFWuint64 _glfwPlatformGetTimerFrequency(void)
{ {
_glfw.posix_time.base = getRawTime() - return _glfw.posix_time.frequency;
(uint64_t) (time / _glfw.posix_time.resolution);
} }

View File

@ -38,8 +38,7 @@
typedef struct _GLFWtimePOSIX typedef struct _GLFWtimePOSIX
{ {
GLFWbool monotonic; GLFWbool monotonic;
double resolution; GLFWuint64 frequency;
uint64_t base;
} _GLFWtimePOSIX; } _GLFWtimePOSIX;

View File

@ -277,8 +277,7 @@ typedef struct _GLFWcursorWin32
typedef struct _GLFWtimeWin32 typedef struct _GLFWtimeWin32
{ {
GLFWbool hasPC; GLFWbool hasPC;
double resolution; GLFWuint64 frequency;
unsigned __int64 base;
} _GLFWtimeWin32; } _GLFWtimeWin32;

View File

@ -28,21 +28,6 @@
#include "internal.h" #include "internal.h"
// Return raw time
//
static unsigned __int64 getRawTime(void)
{
if (_glfw.win32_time.hasPC)
{
unsigned __int64 time;
QueryPerformanceCounter((LARGE_INTEGER*) &time);
return time;
}
else
return (unsigned __int64) _glfw_timeGetTime();
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -51,20 +36,18 @@ static unsigned __int64 getRawTime(void)
// //
void _glfwInitTimerWin32(void) void _glfwInitTimerWin32(void)
{ {
unsigned __int64 frequency; GLFWuint64 frequency;
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
{ {
_glfw.win32_time.hasPC = GLFW_TRUE; _glfw.win32_time.hasPC = GLFW_TRUE;
_glfw.win32_time.resolution = 1.0 / (double) frequency; _glfw.win32_time.frequency = frequency;
} }
else else
{ {
_glfw.win32_time.hasPC = GLFW_FALSE; _glfw.win32_time.hasPC = GLFW_FALSE;
_glfw.win32_time.resolution = 0.001; // winmm resolution is 1 ms _glfw.win32_time.frequency = 1000;
} }
_glfw.win32_time.base = getRawTime();
} }
@ -72,15 +55,20 @@ void _glfwInitTimerWin32(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void) GLFWuint64 _glfwPlatformGetTimerValue(void)
{ {
return (double) (getRawTime() - _glfw.win32_time.base) * if (_glfw.win32_time.hasPC)
_glfw.win32_time.resolution; {
GLFWuint64 value;
QueryPerformanceCounter((LARGE_INTEGER*) &value);
return value;
}
else
return (GLFWuint64) _glfw_timeGetTime();
} }
void _glfwPlatformSetTime(double time) GLFWuint64 _glfwPlatformGetTimerFrequency(void)
{ {
_glfw.win32_time.base = getRawTime() - return _glfw.win32_time.frequency;
(unsigned __int64) (time / _glfw.win32_time.resolution);
} }

View File

@ -1688,7 +1688,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
if (!_glfwPlatformWindowVisible(window) && if (!_glfwPlatformWindowVisible(window) &&
_glfw.x11.NET_REQUEST_FRAME_EXTENTS) _glfw.x11.NET_REQUEST_FRAME_EXTENTS)
{ {
double base; GLFWuint64 base;
XEvent event; XEvent event;
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to // Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
@ -1696,13 +1696,14 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS, sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
0, 0, 0, 0, 0); 0, 0, 0, 0, 0);
base = _glfwPlatformGetTimerValue();
// HACK: Poll with timeout for the required reply instead of blocking // HACK: Poll with timeout for the required reply instead of blocking
// This is done because some window managers (at least Unity, // This is done because some window managers (at least Unity,
// Fluxbox and Xfwm) failed to send the required reply // Fluxbox and Xfwm) failed to send the required reply
// They have been fixed but broken versions are still in the wild // They have been fixed but broken versions are still in the wild
// If you are affected by this and your window manager is NOT // If you are affected by this and your window manager is NOT
// listed above, PLEASE report it to their and our issue trackers // listed above, PLEASE report it to their and our issue trackers
base = _glfwPlatformGetTime();
while (!XCheckIfEvent(_glfw.x11.display, while (!XCheckIfEvent(_glfw.x11.display,
&event, &event,
isFrameExtentsEvent, isFrameExtentsEvent,
@ -1711,7 +1712,8 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
double remaining; double remaining;
struct timeval timeout; struct timeval timeout;
remaining = 0.5 + base - _glfwPlatformGetTime(); remaining = 0.5 - (_glfwPlatformGetTimerValue() - base) /
(double) _glfwPlatformGetTimerFrequency();
if (remaining <= 0.0) if (remaining <= 0.0)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,