mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-05 16:47:04 +00: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:
@@ -61,76 +61,34 @@
|
||||
#endif
|
||||
|
||||
/* The first ticks value of the application */
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
static struct timespec start_ts;
|
||||
#elif defined(__APPLE__)
|
||||
static uint64_t start_mach;
|
||||
#if !defined(HAVE_CLOCK_GETTIME) && defined(__APPLE__)
|
||||
mach_timebase_info_data_t mach_base_info;
|
||||
#endif
|
||||
static SDL_bool checked_monotonic_time = SDL_FALSE;
|
||||
static SDL_bool has_monotonic_time = SDL_FALSE;
|
||||
static struct timeval start_tv;
|
||||
static SDL_bool ticks_started = SDL_FALSE;
|
||||
|
||||
void SDL_TicksInit(void)
|
||||
static void CheckMonotonicTime(void)
|
||||
{
|
||||
if (ticks_started) {
|
||||
return;
|
||||
}
|
||||
ticks_started = SDL_TRUE;
|
||||
|
||||
/* Set first ticks value */
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
if (clock_gettime(SDL_MONOTONIC_CLOCK, &start_ts) == 0) {
|
||||
struct timespec value;
|
||||
if (clock_gettime(SDL_MONOTONIC_CLOCK, &value) == 0) {
|
||||
has_monotonic_time = SDL_TRUE;
|
||||
} else
|
||||
#elif defined(__APPLE__)
|
||||
if (mach_timebase_info(&mach_base_info) == 0) {
|
||||
has_monotonic_time = SDL_TRUE;
|
||||
start_mach = mach_absolute_time();
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
{
|
||||
gettimeofday(&start_tv, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_TicksQuit(void)
|
||||
{
|
||||
ticks_started = SDL_FALSE;
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_GetTicks64(void)
|
||||
{
|
||||
if (!ticks_started) {
|
||||
SDL_TicksInit();
|
||||
}
|
||||
|
||||
if (has_monotonic_time) {
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
struct timespec now;
|
||||
clock_gettime(SDL_MONOTONIC_CLOCK, &now);
|
||||
return (Uint64)(((Sint64)(now.tv_sec - start_ts.tv_sec) * 1000) + ((now.tv_nsec - start_ts.tv_nsec) / 1000000));
|
||||
#elif defined(__APPLE__)
|
||||
const uint64_t now = mach_absolute_time();
|
||||
return (((now - start_mach) * mach_base_info.numer) / mach_base_info.denom) / 1000000;
|
||||
#else
|
||||
SDL_assert(SDL_FALSE);
|
||||
return 0;
|
||||
#endif
|
||||
} else {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return (Uint64)(((Sint64)(now.tv_sec - start_tv.tv_sec) * 1000) + ((now.tv_usec - start_tv.tv_usec) / 1000));
|
||||
}
|
||||
checked_monotonic_time = SDL_TRUE;
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_GetPerformanceCounter(void)
|
||||
{
|
||||
Uint64 ticks;
|
||||
if (!ticks_started) {
|
||||
SDL_TicksInit();
|
||||
|
||||
if (!checked_monotonic_time) {
|
||||
CheckMonotonicTime();
|
||||
}
|
||||
|
||||
if (has_monotonic_time) {
|
||||
@@ -139,7 +97,7 @@ SDL_GetPerformanceCounter(void)
|
||||
|
||||
clock_gettime(SDL_MONOTONIC_CLOCK, &now);
|
||||
ticks = now.tv_sec;
|
||||
ticks *= 1000000000;
|
||||
ticks *= SDL_NS_PER_SECOND;
|
||||
ticks += now.tv_nsec;
|
||||
#elif defined(__APPLE__)
|
||||
ticks = mach_absolute_time();
|
||||
@@ -152,7 +110,7 @@ SDL_GetPerformanceCounter(void)
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
ticks = now.tv_sec;
|
||||
ticks *= 1000000;
|
||||
ticks *= SDL_US_PER_SECOND;
|
||||
ticks += now.tv_usec;
|
||||
}
|
||||
return ticks;
|
||||
@@ -161,30 +119,30 @@ SDL_GetPerformanceCounter(void)
|
||||
Uint64
|
||||
SDL_GetPerformanceFrequency(void)
|
||||
{
|
||||
if (!ticks_started) {
|
||||
SDL_TicksInit();
|
||||
if (!checked_monotonic_time) {
|
||||
CheckMonotonicTime();
|
||||
}
|
||||
|
||||
if (has_monotonic_time) {
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
return 1000000000;
|
||||
return SDL_NS_PER_SECOND;
|
||||
#elif defined(__APPLE__)
|
||||
Uint64 freq = mach_base_info.denom;
|
||||
freq *= 1000000000;
|
||||
freq *= SDL_NS_PER_SECOND;
|
||||
freq /= mach_base_info.numer;
|
||||
return freq;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1000000;
|
||||
return SDL_US_PER_SECOND;
|
||||
}
|
||||
|
||||
void SDL_Delay(Uint32 ms)
|
||||
void SDL_DelayNS(Uint64 ns)
|
||||
{
|
||||
int was_error;
|
||||
|
||||
#if HAVE_NANOSLEEP
|
||||
struct timespec elapsed, tv;
|
||||
struct timespec tv, remaining;
|
||||
#else
|
||||
struct timeval tv;
|
||||
Uint64 then, now, elapsed;
|
||||
@@ -193,36 +151,36 @@ void SDL_Delay(Uint32 ms)
|
||||
#ifdef __EMSCRIPTEN__
|
||||
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
|
||||
/* pseudo-synchronous pause, used directly or through e.g. SDL_WaitEvent */
|
||||
emscripten_sleep(ms);
|
||||
emscripten_sleep(ns / SDL_NS_PER_MS);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set the timeout interval */
|
||||
#if HAVE_NANOSLEEP
|
||||
elapsed.tv_sec = ms / 1000;
|
||||
elapsed.tv_nsec = (ms % 1000) * 1000000;
|
||||
remaining.tv_sec = (ns / SDL_NS_PER_SECOND);
|
||||
remaining.tv_nsec = (ns % SDL_NS_PER_SECOND);
|
||||
#else
|
||||
then = SDL_GetTicks64();
|
||||
then = SDL_GetTicksNS();
|
||||
#endif
|
||||
do {
|
||||
errno = 0;
|
||||
|
||||
#if HAVE_NANOSLEEP
|
||||
tv.tv_sec = elapsed.tv_sec;
|
||||
tv.tv_nsec = elapsed.tv_nsec;
|
||||
was_error = nanosleep(&tv, &elapsed);
|
||||
tv.tv_sec = remaining.tv_sec;
|
||||
tv.tv_nsec = remaining.tv_nsec;
|
||||
was_error = nanosleep(&tv, &remaining);
|
||||
#else
|
||||
/* Calculate the time interval left (in case of interrupt) */
|
||||
now = SDL_GetTicks64();
|
||||
now = SDL_GetTicksNS();
|
||||
elapsed = (now - then);
|
||||
then = now;
|
||||
if (elapsed >= ((Uint64)ms)) {
|
||||
if (elapsed >= ns) {
|
||||
break;
|
||||
}
|
||||
ms -= (Uint32)elapsed;
|
||||
tv.tv_sec = ms / 1000;
|
||||
tv.tv_usec = (ms % 1000) * 1000;
|
||||
ns -= elapsed;
|
||||
tv.tv_sec = (ns / SDL_NS_PER_SECOND)
|
||||
tv.tv_usec = SDL_NS_TO_US(ns % SDL_NS_PER_SECOND);
|
||||
|
||||
was_error = select(0, NULL, NULL, NULL, &tv);
|
||||
#endif /* HAVE_NANOSLEEP */
|
||||
|
||||
Reference in New Issue
Block a user