From 01cb78a763e0d8ea31feb6f5754cd99718cbe075 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 25 Mar 2011 14:45:04 -0700 Subject: [PATCH] Added high resolution timing API: SDL_GetPerformanceCounter(), SDL_GetPerformanceFrequency() --- include/SDL_timer.h | 10 +++++++++ src/timer/beos/SDL_systimer.c | 12 +++++++++++ src/timer/dummy/SDL_systimer.c | 12 +++++++++++ src/timer/nds/SDL_systimer.c | 12 +++++++++++ src/timer/unix/SDL_systimer.c | 36 ++++++++++++++++++++++++++++++++ src/timer/wince/SDL_systimer.c | 12 +++++++++++ src/timer/windows/SDL_systimer.c | 22 +++++++++++++++++++ test/testtimer.c | 12 ++++++++++- 8 files changed, 127 insertions(+), 1 deletion(-) diff --git a/include/SDL_timer.h b/include/SDL_timer.h index 9b7ad837b..37e07551d 100644 --- a/include/SDL_timer.h +++ b/include/SDL_timer.h @@ -47,6 +47,16 @@ extern "C" { */ extern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void); +/** + * \brief Get the current value of the high resolution counter + */ +extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void); + +/** + * \brief Get the count per second of the high resolution counter + */ +extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void); + /** * \brief Wait a specified number of milliseconds before returning. */ diff --git a/src/timer/beos/SDL_systimer.c b/src/timer/beos/SDL_systimer.c index af30f4ed2..4809cce48 100644 --- a/src/timer/beos/SDL_systimer.c +++ b/src/timer/beos/SDL_systimer.c @@ -42,6 +42,18 @@ SDL_GetTicks(void) return ((system_time() - start) / 1000); } +Uint64 +SDL_GetPerformanceCounter(void) +{ + return system_time(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return 1000000; +} + void SDL_Delay(Uint32 ms) { diff --git a/src/timer/dummy/SDL_systimer.c b/src/timer/dummy/SDL_systimer.c index f6cf50cb6..bfe798c03 100644 --- a/src/timer/dummy/SDL_systimer.c +++ b/src/timer/dummy/SDL_systimer.c @@ -37,6 +37,18 @@ SDL_GetTicks(void) return 0; } +Uint64 +SDL_GetPerformanceCounter(void) +{ + return SDL_GetTicks(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return 1000; +} + void SDL_Delay(Uint32 ms) { diff --git a/src/timer/nds/SDL_systimer.c b/src/timer/nds/SDL_systimer.c index 8eb453ba9..8b9cfdc9c 100644 --- a/src/timer/nds/SDL_systimer.c +++ b/src/timer/nds/SDL_systimer.c @@ -52,6 +52,18 @@ SDL_GetTicks(void) return timer_ticks; } +Uint64 +SDL_GetPerformanceCounter(void) +{ + return SDL_GetTicks(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return 1000; +} + void SDL_Delay(Uint32 ms) { diff --git a/src/timer/unix/SDL_systimer.c b/src/timer/unix/SDL_systimer.c index 48bc85049..ba40284a3 100644 --- a/src/timer/unix/SDL_systimer.c +++ b/src/timer/unix/SDL_systimer.c @@ -64,6 +64,7 @@ SDL_GetTicks(void) #if HAVE_CLOCK_GETTIME Uint32 ticks; struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); ticks = (now.tv_sec - start.tv_sec) * 1000 + (now.tv_nsec - @@ -72,6 +73,7 @@ SDL_GetTicks(void) #else Uint32 ticks; struct timeval now; + gettimeofday(&now, NULL); ticks = (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - @@ -80,6 +82,40 @@ SDL_GetTicks(void) #endif } +Uint64 +SDL_GetPerformanceCounter(void) +{ +#if HAVE_CLOCK_GETTIME + Uint64 ticks; + struct timespec now; + + clock_gettime(CLOCK_MONOTONIC, &now); + ticks = now.tv_sec; + ticks *= 1000000000; + ticks += now.tv_nsec; + return (ticks); +#else + Uint64 ticks; + struct timeval now; + + gettimeofday(&now, NULL); + ticks = now.tv_sec; + ticks *= 1000000; + ticks += now.tv_usec; + return (ticks); +#endif +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ +#if HAVE_CLOCK_GETTIME + return 1000000000; +#else + return 1000000; +#endif +} + void SDL_Delay(Uint32 ms) { diff --git a/src/timer/wince/SDL_systimer.c b/src/timer/wince/SDL_systimer.c index 35aa46557..33160bbbb 100644 --- a/src/timer/wince/SDL_systimer.c +++ b/src/timer/wince/SDL_systimer.c @@ -87,6 +87,18 @@ SDL_GetTicks() return ((Uint32) wce_rel_ticks()); } +Uint64 +SDL_GetPerformanceCounter(void) +{ + return SDL_GetTicks(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return 1000; +} + /* Give up approx. givem milliseconds to the OS. */ void SDL_Delay(Uint32 ms) diff --git a/src/timer/windows/SDL_systimer.c b/src/timer/windows/SDL_systimer.c index df22ad22b..0f4d8f331 100644 --- a/src/timer/windows/SDL_systimer.c +++ b/src/timer/windows/SDL_systimer.c @@ -99,6 +99,28 @@ SDL_GetTicks(void) return (ticks); } +Uint64 +SDL_GetPerformanceCounter(void) +{ + LARGE_INTEGER counter; + + if (!QueryPerformanceCounter(&counter)) { + return SDL_GetTicks(); + } + return counter.QuadPart; +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + LARGE_INTEGER frequency; + + if (!QueryPerformanceFrequency(&frequency)) { + return 1000; + } + return frequency.QuadPart; +} + void SDL_Delay(Uint32 ms) { diff --git a/test/testtimer.c b/test/testtimer.c index f58efbbda..c2d1573ab 100644 --- a/test/testtimer.c +++ b/test/testtimer.c @@ -29,8 +29,9 @@ callback(Uint32 interval, void *param) int main(int argc, char *argv[]) { - int desired; + int i, desired; SDL_TimerID t1, t2, t3; + Uint64 start, now; if (SDL_Init(SDL_INIT_TIMER) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); @@ -85,6 +86,15 @@ main(int argc, char *argv[]) SDL_RemoveTimer(t2); SDL_RemoveTimer(t3); + start = SDL_GetPerformanceCounter(); + for (i = 0; i < 1000000; ++i) { + ticktock(0); + } + now = SDL_GetPerformanceCounter(); + printf("1 million iterations of ticktock took %f ms\n", (double)((now - start)*1000) / SDL_GetPerformanceFrequency()); + SDL_Quit(); return (0); } + +/* vi: set ts=4 sw=4 expandtab: */