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
- Added `glfwGetKeyName` for querying the layout-specific name of printable
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_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support
- 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.
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

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.
@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
These are the release highlights. For a full list of changes see the

View File

@ -728,6 +728,19 @@ extern "C" {
* 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.
*
* Generic function pointer used for returning client API function pointers
@ -3557,6 +3570,47 @@ GLFWAPI double glfwGetTime(void);
*/
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
* thread.
*

View File

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

View File

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

View File

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

View File

@ -645,7 +645,8 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
GLFWAPI double glfwGetTime(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
return _glfwPlatformGetTime();
return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
_glfwPlatformGetTimerFrequency();
}
GLFWAPI void glfwSetTime(double time)
@ -658,6 +659,19 @@ GLFWAPI void glfwSetTime(double time)
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
#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 struct _GLFWwndconfig _GLFWwndconfig;
@ -432,6 +425,8 @@ struct _GLFWlibrary
_GLFWmonitor** monitors;
int monitorCount;
GLFWuint64 timerOffset;
struct {
GLFWbool available;
void* handle;
@ -596,15 +591,15 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
*/
const char* _glfwPlatformGetJoystickName(int joy);
/*! @copydoc glfwGetTime
/*! @copydoc glfwGetTimerValue
* @ingroup platform
*/
double _glfwPlatformGetTime(void);
GLFWuint64 _glfwPlatformGetTimerValue(void);
/*! @copydoc glfwSetTime
/*! @copydoc glfwGetTimerFrequency
* @ingroup platform
*/
void _glfwPlatformSetTime(double time);
GLFWuint64 _glfwPlatformGetTimerFrequency(void);
/*! @ingroup platform
*/

View File

@ -30,28 +30,6 @@
#include <sys/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 //////
@ -67,15 +45,14 @@ void _glfwInitTimerPOSIX(void)
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
{
_glfw.posix_time.monotonic = GLFW_TRUE;
_glfw.posix_time.resolution = 1e-9;
_glfw.posix_time.frequency = 1000000000;
}
else
#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 //////
//////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void)
GLFWuint64 _glfwPlatformGetTimerValue(void)
{
return (double) (getRawTime() - _glfw.posix_time.base) *
_glfw.posix_time.resolution;
#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;
}
}
void _glfwPlatformSetTime(double time)
GLFWuint64 _glfwPlatformGetTimerFrequency(void)
{
_glfw.posix_time.base = getRawTime() -
(uint64_t) (time / _glfw.posix_time.resolution);
return _glfw.posix_time.frequency;
}

View File

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

View File

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

View File

@ -28,21 +28,6 @@
#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 //////
//////////////////////////////////////////////////////////////////////////
@ -51,20 +36,18 @@ static unsigned __int64 getRawTime(void)
//
void _glfwInitTimerWin32(void)
{
unsigned __int64 frequency;
GLFWuint64 frequency;
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
{
_glfw.win32_time.hasPC = GLFW_TRUE;
_glfw.win32_time.resolution = 1.0 / (double) frequency;
_glfw.win32_time.frequency = frequency;
}
else
{
_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 //////
//////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void)
GLFWuint64 _glfwPlatformGetTimerValue(void)
{
return (double) (getRawTime() - _glfw.win32_time.base) *
_glfw.win32_time.resolution;
if (_glfw.win32_time.hasPC)
{
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() -
(unsigned __int64) (time / _glfw.win32_time.resolution);
return _glfw.win32_time.frequency;
}

View File

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