mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-09 01:14:24 +02:00
Convert ticks to 64-bit, added nanosecond precision to the API
Fixes https://github.com/libsdl-org/SDL/issues/5512 Fixes https://github.com/libsdl-org/SDL/issues/6731
This commit is contained in:
@@ -23,99 +23,7 @@
|
||||
#ifdef SDL_TIMER_WINDOWS
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include <mmsystem.h>
|
||||
|
||||
/* The first (low-resolution) ticks value of the application */
|
||||
static DWORD start = 0;
|
||||
static BOOL ticks_started = FALSE;
|
||||
|
||||
/* The first high-resolution ticks value of the application */
|
||||
static LARGE_INTEGER start_ticks;
|
||||
/* The number of ticks per second of the high-resolution performance counter */
|
||||
static LARGE_INTEGER ticks_per_second;
|
||||
|
||||
static void SDL_SetSystemTimerResolution(const UINT uPeriod)
|
||||
{
|
||||
#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
|
||||
static UINT timer_period = 0;
|
||||
|
||||
if (uPeriod != timer_period) {
|
||||
if (timer_period) {
|
||||
timeEndPeriod(timer_period);
|
||||
}
|
||||
|
||||
timer_period = uPeriod;
|
||||
|
||||
if (timer_period) {
|
||||
timeBeginPeriod(timer_period);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_TimerResolutionChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
UINT uPeriod;
|
||||
|
||||
/* Unless the hint says otherwise, let's have good sleep precision */
|
||||
if (hint && *hint) {
|
||||
uPeriod = SDL_atoi(hint);
|
||||
} else {
|
||||
uPeriod = 1;
|
||||
}
|
||||
if (uPeriod || oldValue != hint) {
|
||||
SDL_SetSystemTimerResolution(uPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_TicksInit(void)
|
||||
{
|
||||
BOOL rc;
|
||||
|
||||
if (ticks_started) {
|
||||
return;
|
||||
}
|
||||
ticks_started = SDL_TRUE;
|
||||
|
||||
/* if we didn't set a precision, set it high. This affects lots of things
|
||||
on Windows besides the SDL timers, like audio callbacks, etc. */
|
||||
SDL_AddHintCallback(SDL_HINT_TIMER_RESOLUTION,
|
||||
SDL_TimerResolutionChanged, NULL);
|
||||
|
||||
/* Set first ticks value */
|
||||
/* QueryPerformanceCounter allegedly is always available and reliable as of WinXP,
|
||||
so we'll rely on it here.
|
||||
*/
|
||||
rc = QueryPerformanceFrequency(&ticks_per_second);
|
||||
SDL_assert(rc != 0); /* this should _never_ fail if you're on XP or later. */
|
||||
QueryPerformanceCounter(&start_ticks);
|
||||
}
|
||||
|
||||
void SDL_TicksQuit(void)
|
||||
{
|
||||
SDL_DelHintCallback(SDL_HINT_TIMER_RESOLUTION,
|
||||
SDL_TimerResolutionChanged, NULL);
|
||||
|
||||
SDL_SetSystemTimerResolution(0); /* always release our timer resolution request. */
|
||||
|
||||
start = 0;
|
||||
ticks_started = SDL_FALSE;
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_GetTicks64(void)
|
||||
{
|
||||
LARGE_INTEGER now;
|
||||
BOOL rc;
|
||||
|
||||
if (!ticks_started) {
|
||||
SDL_TicksInit();
|
||||
}
|
||||
|
||||
rc = QueryPerformanceCounter(&now);
|
||||
SDL_assert(rc != 0); /* this should _never_ fail if you're on XP or later. */
|
||||
return (Uint64)(((now.QuadPart - start_ticks.QuadPart) * 1000) / ticks_per_second.QuadPart);
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_GetPerformanceCounter(void)
|
||||
@@ -135,7 +43,7 @@ SDL_GetPerformanceFrequency(void)
|
||||
return (Uint64)frequency.QuadPart;
|
||||
}
|
||||
|
||||
void SDL_Delay(Uint32 ms)
|
||||
void SDL_DelayNS(Uint64 ns)
|
||||
{
|
||||
/* CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag was added in Windows 10 version 1803.
|
||||
*
|
||||
@@ -155,7 +63,7 @@ void SDL_Delay(Uint32 ms)
|
||||
HANDLE timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
||||
if (timer) {
|
||||
LARGE_INTEGER due_time;
|
||||
due_time.QuadPart = -(ms * 10000LL);
|
||||
due_time.QuadPart = -((LONGLONG)ns / 100);
|
||||
if (SetWaitableTimerEx(timer, &due_time, 0, NULL, NULL, NULL, 0)) {
|
||||
WaitForSingleObject(timer, INFINITE);
|
||||
}
|
||||
@@ -163,19 +71,23 @@ void SDL_Delay(Uint32 ms)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723)
|
||||
static HANDLE mutex = 0;
|
||||
if (!mutex) {
|
||||
mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS);
|
||||
}
|
||||
WaitForSingleObjectEx(mutex, ms, FALSE);
|
||||
#else
|
||||
if (!ticks_started) {
|
||||
SDL_TicksInit();
|
||||
}
|
||||
|
||||
Sleep(ms);
|
||||
{
|
||||
const Uint64 max_delay = 0xffffffff * SDL_NS_PER_MS;
|
||||
if (ns > max_delay) {
|
||||
ns = max_delay;
|
||||
}
|
||||
|
||||
#if defined(__WINRT__) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723)
|
||||
static HANDLE mutex = 0;
|
||||
if (!mutex) {
|
||||
mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS);
|
||||
}
|
||||
WaitForSingleObjectEx(mutex, (DWORD)SDL_NS_TO_MS(ns), FALSE);
|
||||
#else
|
||||
Sleep((DWORD)SDL_NS_TO_MS(ns));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_WINDOWS */
|
||||
|
||||
Reference in New Issue
Block a user