diff options
Diffstat (limited to 'source/3rd-party/SDL2/src/timer')
-rw-r--r-- | source/3rd-party/SDL2/src/timer/SDL_timer.c | 373 | ||||
-rw-r--r-- | source/3rd-party/SDL2/src/timer/SDL_timer_c.h | 40 | ||||
-rw-r--r-- | source/3rd-party/SDL2/src/timer/dummy/SDL_systimer.c | 75 | ||||
-rw-r--r-- | source/3rd-party/SDL2/src/timer/haiku/SDL_systimer.c | 80 | ||||
-rw-r--r-- | source/3rd-party/SDL2/src/timer/psp/SDL_systimer.c | 91 | ||||
-rw-r--r-- | source/3rd-party/SDL2/src/timer/unix/SDL_systimer.c | 232 | ||||
-rw-r--r-- | source/3rd-party/SDL2/src/timer/windows/SDL_systimer.c | 200 |
7 files changed, 1091 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/timer/SDL_timer.c b/source/3rd-party/SDL2/src/timer/SDL_timer.c new file mode 100644 index 0000000..f4a13f4 --- /dev/null +++ b/source/3rd-party/SDL2/src/timer/SDL_timer.c @@ -0,0 +1,373 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../SDL_internal.h" + +#include "SDL_timer.h" +#include "SDL_timer_c.h" +#include "SDL_atomic.h" +#include "SDL_cpuinfo.h" +#include "../thread/SDL_systhread.h" + +/* #define DEBUG_TIMERS */ + +typedef struct _SDL_Timer +{ + int timerID; + SDL_TimerCallback callback; + void *param; + Uint32 interval; + Uint32 scheduled; + SDL_atomic_t canceled; + struct _SDL_Timer *next; +} SDL_Timer; + +typedef struct _SDL_TimerMap +{ + int timerID; + SDL_Timer *timer; + struct _SDL_TimerMap *next; +} SDL_TimerMap; + +/* The timers are kept in a sorted list */ +typedef struct { + /* Data used by the main thread */ + SDL_Thread *thread; + SDL_atomic_t nextID; + SDL_TimerMap *timermap; + SDL_mutex *timermap_lock; + + /* Padding to separate cache lines between threads */ + char cache_pad[SDL_CACHELINE_SIZE]; + + /* Data used to communicate with the timer thread */ + SDL_SpinLock lock; + SDL_sem *sem; + SDL_Timer *pending; + SDL_Timer *freelist; + SDL_atomic_t active; + + /* List of timers - this is only touched by the timer thread */ + SDL_Timer *timers; +} SDL_TimerData; + +static SDL_TimerData SDL_timer_data; + +/* The idea here is that any thread might add a timer, but a single + * thread manages the active timer queue, sorted by scheduling time. + * + * Timers are removed by simply setting a canceled flag + */ + +static void +SDL_AddTimerInternal(SDL_TimerData *data, SDL_Timer *timer) +{ + SDL_Timer *prev, *curr; + + prev = NULL; + for (curr = data->timers; curr; prev = curr, curr = curr->next) { + if ((Sint32)(timer->scheduled-curr->scheduled) < 0) { + break; + } + } + + /* Insert the timer here! */ + if (prev) { + prev->next = timer; + } else { + data->timers = timer; + } + timer->next = curr; +} + +static int SDLCALL +SDL_TimerThread(void *_data) +{ + SDL_TimerData *data = (SDL_TimerData *)_data; + SDL_Timer *pending; + SDL_Timer *current; + SDL_Timer *freelist_head = NULL; + SDL_Timer *freelist_tail = NULL; + Uint32 tick, now, interval, delay; + + /* Threaded timer loop: + * 1. Queue timers added by other threads + * 2. Handle any timers that should dispatch this cycle + * 3. Wait until next dispatch time or new timer arrives + */ + for ( ; ; ) { + /* Pending and freelist maintenance */ + SDL_AtomicLock(&data->lock); + { + /* Get any timers ready to be queued */ + pending = data->pending; + data->pending = NULL; + + /* Make any unused timer structures available */ + if (freelist_head) { + freelist_tail->next = data->freelist; + data->freelist = freelist_head; + } + } + SDL_AtomicUnlock(&data->lock); + + /* Sort the pending timers into our list */ + while (pending) { + current = pending; + pending = pending->next; + SDL_AddTimerInternal(data, current); + } + freelist_head = NULL; + freelist_tail = NULL; + + /* Check to see if we're still running, after maintenance */ + if (!SDL_AtomicGet(&data->active)) { + break; + } + + /* Initial delay if there are no timers */ + delay = SDL_MUTEX_MAXWAIT; + + tick = SDL_GetTicks(); + + /* Process all the pending timers for this tick */ + while (data->timers) { + current = data->timers; + + if ((Sint32)(tick-current->scheduled) < 0) { + /* Scheduled for the future, wait a bit */ + delay = (current->scheduled - tick); + break; + } + + /* We're going to do something with this timer */ + data->timers = current->next; + + if (SDL_AtomicGet(¤t->canceled)) { + interval = 0; + } else { + interval = current->callback(current->interval, current->param); + } + + if (interval > 0) { + /* Reschedule this timer */ + current->interval = interval; + current->scheduled = tick + interval; + SDL_AddTimerInternal(data, current); + } else { + if (!freelist_head) { + freelist_head = current; + } + if (freelist_tail) { + freelist_tail->next = current; + } + freelist_tail = current; + + SDL_AtomicSet(¤t->canceled, 1); + } + } + + /* Adjust the delay based on processing time */ + now = SDL_GetTicks(); + interval = (now - tick); + if (interval > delay) { + delay = 0; + } else { + delay -= interval; + } + + /* Note that each time a timer is added, this will return + immediately, but we process the timers added all at once. + That's okay, it just means we run through the loop a few + extra times. + */ + SDL_SemWaitTimeout(data->sem, delay); + } + return 0; +} + +int +SDL_TimerInit(void) +{ + SDL_TimerData *data = &SDL_timer_data; + + if (!SDL_AtomicGet(&data->active)) { + const char *name = "SDLTimer"; + data->timermap_lock = SDL_CreateMutex(); + if (!data->timermap_lock) { + return -1; + } + + data->sem = SDL_CreateSemaphore(0); + if (!data->sem) { + SDL_DestroyMutex(data->timermap_lock); + return -1; + } + + SDL_AtomicSet(&data->active, 1); + + /* Timer threads use a callback into the app, so we can't set a limited stack size here. */ + data->thread = SDL_CreateThreadInternal(SDL_TimerThread, name, 0, data); + if (!data->thread) { + SDL_TimerQuit(); + return -1; + } + + SDL_AtomicSet(&data->nextID, 1); + } + return 0; +} + +void +SDL_TimerQuit(void) +{ + SDL_TimerData *data = &SDL_timer_data; + SDL_Timer *timer; + SDL_TimerMap *entry; + + if (SDL_AtomicCAS(&data->active, 1, 0)) { /* active? Move to inactive. */ + /* Shutdown the timer thread */ + if (data->thread) { + SDL_SemPost(data->sem); + SDL_WaitThread(data->thread, NULL); + data->thread = NULL; + } + + SDL_DestroySemaphore(data->sem); + data->sem = NULL; + + /* Clean up the timer entries */ + while (data->timers) { + timer = data->timers; + data->timers = timer->next; + SDL_free(timer); + } + while (data->freelist) { + timer = data->freelist; + data->freelist = timer->next; + SDL_free(timer); + } + while (data->timermap) { + entry = data->timermap; + data->timermap = entry->next; + SDL_free(entry); + } + + SDL_DestroyMutex(data->timermap_lock); + data->timermap_lock = NULL; + } +} + +SDL_TimerID +SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param) +{ + SDL_TimerData *data = &SDL_timer_data; + SDL_Timer *timer; + SDL_TimerMap *entry; + + SDL_AtomicLock(&data->lock); + if (!SDL_AtomicGet(&data->active)) { + if (SDL_TimerInit() < 0) { + SDL_AtomicUnlock(&data->lock); + return 0; + } + } + + timer = data->freelist; + if (timer) { + data->freelist = timer->next; + } + SDL_AtomicUnlock(&data->lock); + + if (timer) { + SDL_RemoveTimer(timer->timerID); + } else { + timer = (SDL_Timer *)SDL_malloc(sizeof(*timer)); + if (!timer) { + SDL_OutOfMemory(); + return 0; + } + } + timer->timerID = SDL_AtomicIncRef(&data->nextID); + timer->callback = callback; + timer->param = param; + timer->interval = interval; + timer->scheduled = SDL_GetTicks() + interval; + SDL_AtomicSet(&timer->canceled, 0); + + entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry)); + if (!entry) { + SDL_free(timer); + SDL_OutOfMemory(); + return 0; + } + entry->timer = timer; + entry->timerID = timer->timerID; + + SDL_LockMutex(data->timermap_lock); + entry->next = data->timermap; + data->timermap = entry; + SDL_UnlockMutex(data->timermap_lock); + + /* Add the timer to the pending list for the timer thread */ + SDL_AtomicLock(&data->lock); + timer->next = data->pending; + data->pending = timer; + SDL_AtomicUnlock(&data->lock); + + /* Wake up the timer thread if necessary */ + SDL_SemPost(data->sem); + + return entry->timerID; +} + +SDL_bool +SDL_RemoveTimer(SDL_TimerID id) +{ + SDL_TimerData *data = &SDL_timer_data; + SDL_TimerMap *prev, *entry; + SDL_bool canceled = SDL_FALSE; + + /* Find the timer */ + SDL_LockMutex(data->timermap_lock); + prev = NULL; + for (entry = data->timermap; entry; prev = entry, entry = entry->next) { + if (entry->timerID == id) { + if (prev) { + prev->next = entry->next; + } else { + data->timermap = entry->next; + } + break; + } + } + SDL_UnlockMutex(data->timermap_lock); + + if (entry) { + if (!SDL_AtomicGet(&entry->timer->canceled)) { + SDL_AtomicSet(&entry->timer->canceled, 1); + canceled = SDL_TRUE; + } + SDL_free(entry); + } + return canceled; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/timer/SDL_timer_c.h b/source/3rd-party/SDL2/src/timer/SDL_timer_c.h new file mode 100644 index 0000000..3ea350f --- /dev/null +++ b/source/3rd-party/SDL2/src/timer/SDL_timer_c.h @@ -0,0 +1,40 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_timer_c_h_ +#define SDL_timer_c_h_ + +#include "../SDL_internal.h" + +/* Useful functions and variables from SDL_timer.c */ +#include "SDL_timer.h" + +#define ROUND_RESOLUTION(X) \ + (((X+TIMER_RESOLUTION-1)/TIMER_RESOLUTION)*TIMER_RESOLUTION) + +extern void SDL_TicksInit(void); +extern void SDL_TicksQuit(void); +extern int SDL_TimerInit(void); +extern void SDL_TimerQuit(void); + +#endif /* SDL_timer_c_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/timer/dummy/SDL_systimer.c b/source/3rd-party/SDL2/src/timer/dummy/SDL_systimer.c new file mode 100644 index 0000000..aff145b --- /dev/null +++ b/source/3rd-party/SDL2/src/timer/dummy/SDL_systimer.c @@ -0,0 +1,75 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if defined(SDL_TIMER_DUMMY) || defined(SDL_TIMERS_DISABLED) + +#include "SDL_timer.h" + +static SDL_bool ticks_started = SDL_FALSE; + +void +SDL_TicksInit(void) +{ + if (ticks_started) { + return; + } + ticks_started = SDL_TRUE; +} + +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + +Uint32 +SDL_GetTicks(void) +{ + if (!ticks_started) { + SDL_TicksInit(); + } + + SDL_Unsupported(); + return 0; +} + +Uint64 +SDL_GetPerformanceCounter(void) +{ + return SDL_GetTicks(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return 1000; +} + +void +SDL_Delay(Uint32 ms) +{ + SDL_Unsupported(); +} + +#endif /* SDL_TIMER_DUMMY || SDL_TIMERS_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/timer/haiku/SDL_systimer.c b/source/3rd-party/SDL2/src/timer/haiku/SDL_systimer.c new file mode 100644 index 0000000..16f49c0 --- /dev/null +++ b/source/3rd-party/SDL2/src/timer/haiku/SDL_systimer.c @@ -0,0 +1,80 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_TIMER_HAIKU + +#include <kernel/OS.h> + +#include "SDL_timer.h" + +static bigtime_t start; +static SDL_bool ticks_started = SDL_FALSE; + +void +SDL_TicksInit(void) +{ + if (ticks_started) { + return; + } + ticks_started = SDL_TRUE; + + /* Set first ticks value */ + start = system_time(); +} + +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + +Uint32 +SDL_GetTicks(void) +{ + if (!ticks_started) { + SDL_TicksInit(); + } + + return ((system_time() - start) / 1000); +} + +Uint64 +SDL_GetPerformanceCounter(void) +{ + return system_time(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return 1000000; +} + +void +SDL_Delay(Uint32 ms) +{ + snooze(ms * 1000); +} + +#endif /* SDL_TIMER_HAIKU */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/timer/psp/SDL_systimer.c b/source/3rd-party/SDL2/src/timer/psp/SDL_systimer.c new file mode 100644 index 0000000..e39d800 --- /dev/null +++ b/source/3rd-party/SDL2/src/timer/psp/SDL_systimer.c @@ -0,0 +1,91 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_TIMERS_PSP + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_error.h" +#include "../SDL_timer_c.h" +#include <stdlib.h> +#include <time.h> +#include <sys/time.h> +#include <pspthreadman.h> + +static struct timeval start; +static SDL_bool ticks_started = SDL_FALSE; + +void +SDL_TicksInit(void) +{ + if (ticks_started) { + return; + } + ticks_started = SDL_TRUE; + + gettimeofday(&start, NULL); +} + +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + +Uint32 SDL_GetTicks(void) +{ + if (!ticks_started) { + SDL_TicksInit(); + } + + struct timeval now; + Uint32 ticks; + + gettimeofday(&now, NULL); + ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000; + return(ticks); +} + +Uint64 +SDL_GetPerformanceCounter(void) +{ + return SDL_GetTicks(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return 1000; +} + +void SDL_Delay(Uint32 ms) +{ + const Uint32 max_delay = 0xffffffffUL / 1000; + if(ms > max_delay) + ms = max_delay; + sceKernelDelayThreadCB(ms * 1000); +} + +#endif /* SDL_TIMERS_PSP */ + +/* vim: ts=4 sw=4 + */ diff --git a/source/3rd-party/SDL2/src/timer/unix/SDL_systimer.c b/source/3rd-party/SDL2/src/timer/unix/SDL_systimer.c new file mode 100644 index 0000000..5045996 --- /dev/null +++ b/source/3rd-party/SDL2/src/timer/unix/SDL_systimer.c @@ -0,0 +1,232 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_TIMER_UNIX + +#include <stdio.h> +#include <sys/time.h> +#include <unistd.h> +#include <errno.h> + +#include "SDL_timer.h" +#include "SDL_assert.h" +#include "../SDL_timer_c.h" + +/* The clock_gettime provides monotonous time, so we should use it if + it's available. The clock_gettime function is behind ifdef + for __USE_POSIX199309 + Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005 +*/ +/* Reworked monotonic clock to not assume the current system has one + as not all linux kernels provide a monotonic clock (yeah recent ones + probably do) + Also added OS X Monotonic clock support + Based on work in https://github.com/ThomasHabets/monotonic_clock + */ +#if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME +#include <time.h> +#endif +#ifdef __APPLE__ +#include <mach/mach_time.h> +#endif + +/* Use CLOCK_MONOTONIC_RAW, if available, which is not subject to adjustment by NTP */ +#if HAVE_CLOCK_GETTIME +#ifdef CLOCK_MONOTONIC_RAW +#define SDL_MONOTONIC_CLOCK CLOCK_MONOTONIC_RAW +#else +#define SDL_MONOTONIC_CLOCK CLOCK_MONOTONIC +#endif +#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; +mach_timebase_info_data_t mach_base_info; +#endif +static SDL_bool has_monotonic_time = SDL_FALSE; +static struct timeval start_tv; +static SDL_bool ticks_started = SDL_FALSE; + +void +SDL_TicksInit(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) { + has_monotonic_time = SDL_TRUE; + } else +#elif defined(__APPLE__) + kern_return_t ret = mach_timebase_info(&mach_base_info); + if (ret == 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; +} + +Uint32 +SDL_GetTicks(void) +{ + Uint32 ticks; + if (!ticks_started) { + SDL_TicksInit(); + } + + if (has_monotonic_time) { +#if HAVE_CLOCK_GETTIME + struct timespec now; + clock_gettime(SDL_MONOTONIC_CLOCK, &now); + ticks = (now.tv_sec - start_ts.tv_sec) * 1000 + (now.tv_nsec - + start_ts.tv_nsec) / 1000000; +#elif defined(__APPLE__) + uint64_t now = mach_absolute_time(); + ticks = (Uint32)((((now - start_mach) * mach_base_info.numer) / mach_base_info.denom) / 1000000); +#else + SDL_assert(SDL_FALSE); + ticks = 0; +#endif + } else { + struct timeval now; + + gettimeofday(&now, NULL); + ticks = (Uint32)((now.tv_sec - start_tv.tv_sec) * 1000 + (now.tv_usec - start_tv.tv_usec) / 1000); + } + return (ticks); +} + +Uint64 +SDL_GetPerformanceCounter(void) +{ + Uint64 ticks; + if (!ticks_started) { + SDL_TicksInit(); + } + + if (has_monotonic_time) { +#if HAVE_CLOCK_GETTIME + struct timespec now; + + clock_gettime(SDL_MONOTONIC_CLOCK, &now); + ticks = now.tv_sec; + ticks *= 1000000000; + ticks += now.tv_nsec; +#elif defined(__APPLE__) + ticks = mach_absolute_time(); +#else + SDL_assert(SDL_FALSE); + ticks = 0; +#endif + } else { + struct timeval now; + + gettimeofday(&now, NULL); + ticks = now.tv_sec; + ticks *= 1000000; + ticks += now.tv_usec; + } + return (ticks); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + if (!ticks_started) { + SDL_TicksInit(); + } + + if (has_monotonic_time) { +#if HAVE_CLOCK_GETTIME + return 1000000000; +#elif defined(__APPLE__) + Uint64 freq = mach_base_info.denom; + freq *= 1000000000; + freq /= mach_base_info.numer; + return freq; +#endif + } + + return 1000000; +} + +void +SDL_Delay(Uint32 ms) +{ + int was_error; + +#if HAVE_NANOSLEEP + struct timespec elapsed, tv; +#else + struct timeval tv; + Uint32 then, now, elapsed; +#endif + + /* Set the timeout interval */ +#if HAVE_NANOSLEEP + elapsed.tv_sec = ms / 1000; + elapsed.tv_nsec = (ms % 1000) * 1000000; +#else + then = SDL_GetTicks(); +#endif + do { + errno = 0; + +#if HAVE_NANOSLEEP + tv.tv_sec = elapsed.tv_sec; + tv.tv_nsec = elapsed.tv_nsec; + was_error = nanosleep(&tv, &elapsed); +#else + /* Calculate the time interval left (in case of interrupt) */ + now = SDL_GetTicks(); + elapsed = (now - then); + then = now; + if (elapsed >= ms) { + break; + } + ms -= elapsed; + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * 1000; + + was_error = select(0, NULL, NULL, NULL, &tv); +#endif /* HAVE_NANOSLEEP */ + } while (was_error && (errno == EINTR)); +} + +#endif /* SDL_TIMER_UNIX */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/timer/windows/SDL_systimer.c b/source/3rd-party/SDL2/src/timer/windows/SDL_systimer.c new file mode 100644 index 0000000..3f5413b --- /dev/null +++ b/source/3rd-party/SDL2/src/timer/windows/SDL_systimer.c @@ -0,0 +1,200 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_TIMER_WINDOWS + +#include "../../core/windows/SDL_windows.h" +#include <mmsystem.h> + +#include "SDL_timer.h" +#include "SDL_hints.h" + + +/* The first (low-resolution) ticks value of the application */ +static DWORD start = 0; +static BOOL ticks_started = FALSE; + +/* Store if a high-resolution performance counter exists on the system */ +static BOOL hires_timer_available; +/* The first high-resolution ticks value of the application */ +static LARGE_INTEGER hires_start_ticks; +/* The number of ticks per second of the high-resolution performance counter */ +static LARGE_INTEGER hires_ticks_per_second; + +static void +SDL_SetSystemTimerResolution(const UINT uPeriod) +{ +#ifndef __WINRT__ + 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) +{ + 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 has had problems in the past, but lots of games + use it, so we'll rely on it here. + */ + if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE) { + hires_timer_available = TRUE; + QueryPerformanceCounter(&hires_start_ticks); + } else { + hires_timer_available = FALSE; +#ifndef __WINRT__ + start = timeGetTime(); +#endif /* __WINRT__ */ + } +} + +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; +} + +Uint32 +SDL_GetTicks(void) +{ + DWORD now = 0; + LARGE_INTEGER hires_now; + + if (!ticks_started) { + SDL_TicksInit(); + } + + if (hires_timer_available) { + QueryPerformanceCounter(&hires_now); + + hires_now.QuadPart -= hires_start_ticks.QuadPart; + hires_now.QuadPart *= 1000; + hires_now.QuadPart /= hires_ticks_per_second.QuadPart; + + return (DWORD) hires_now.QuadPart; + } else { +#ifndef __WINRT__ + now = timeGetTime(); +#endif /* __WINRT__ */ + } + + return (now - start); +} + +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) +{ + /* Sleep() is not publicly available to apps in early versions of WinRT. + * + * Visual C++ 2013 Update 4 re-introduced Sleep() for Windows 8.1 and + * Windows Phone 8.1. + * + * Use the compiler version to determine availability. + * + * NOTE #1: _MSC_FULL_VER == 180030723 for Visual C++ 2013 Update 3. + * NOTE #2: Visual C++ 2013, when compiling for Windows 8.0 and + * Windows Phone 8.0, uses the Visual C++ 2012 compiler to build + * apps and libraries. + */ +#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); +#endif +} + +#endif /* SDL_TIMER_WINDOWS */ + +/* vi: set ts=4 sw=4 expandtab: */ |