mirror of
https://github.com/shadps4-emu/ext-SDL.git
synced 2024-12-11 20:43:39 +00:00
Added SDL_AddTimerNS()
This commit is contained in:
parent
b6360516e4
commit
99599d9236
@ -132,7 +132,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_DelayNS(Uint64 ns);
|
||||
typedef Uint32 SDL_TimerID;
|
||||
|
||||
/**
|
||||
* Function prototype for the timer callback function.
|
||||
* Function prototype for the millisecond timer callback function.
|
||||
*
|
||||
* The callback function is passed the current timer interval and returns the
|
||||
* next timer interval, in milliseconds. If the returned value is the same as
|
||||
@ -187,10 +187,72 @@ typedef Uint32 (SDLCALL *SDL_TimerCallback)(void *userdata, SDL_TimerID timerID,
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*
|
||||
* \sa SDL_AddTimerNS
|
||||
* \sa SDL_RemoveTimer
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *userdata);
|
||||
|
||||
/**
|
||||
* Function prototype for the nanosecond timer callback function.
|
||||
*
|
||||
* The callback function is passed the current timer interval and returns the
|
||||
* next timer interval, in nanoseconds. If the returned value is the same as
|
||||
* the one passed in, the periodic alarm continues, otherwise a new alarm is
|
||||
* scheduled. If the callback returns 0, the periodic alarm is cancelled.
|
||||
*
|
||||
* \param userdata an arbitrary pointer provided by the app through SDL_AddTimer, for its own use.
|
||||
* \param timerID the current timer being processed
|
||||
* \param interval the current callback time interval.
|
||||
* \returns the new callback time interval, or 0 to disable further runs of
|
||||
* the callback.
|
||||
*
|
||||
* \threadsafety SDL may call this callback at any time from a background
|
||||
* thread; the application is responsible for locking resources
|
||||
* the callback touches that need to be protected.
|
||||
*
|
||||
* \since This datatype is available since SDL 3.0.0.
|
||||
*
|
||||
* \sa SDL_AddTimerNS
|
||||
*/
|
||||
typedef Uint64 (SDLCALL *SDL_NSTimerCallback)(void *userdata, SDL_TimerID timerID, Uint64 interval);
|
||||
|
||||
/**
|
||||
* Call a callback function at a future time.
|
||||
*
|
||||
* If you use this function, you must pass `SDL_INIT_TIMER` to SDL_Init().
|
||||
*
|
||||
* The callback function is passed the current timer interval and the user
|
||||
* supplied parameter from the SDL_AddTimerNS() call and should return the next
|
||||
* timer interval. If the value returned from the callback is 0, the timer is
|
||||
* canceled.
|
||||
*
|
||||
* The callback is run on a separate thread.
|
||||
*
|
||||
* Timers take into account the amount of time it took to execute the
|
||||
* callback. For example, if the callback took 250 ns to execute and returned
|
||||
* 1000 (ns), the timer would only wait another 750 ns before its next
|
||||
* iteration.
|
||||
*
|
||||
* Timing may be inexact due to OS scheduling. Be sure to note the current
|
||||
* time with SDL_GetTicksNS() or SDL_GetPerformanceCounter() in case your
|
||||
* callback needs to adjust for variances.
|
||||
*
|
||||
* \param interval the timer delay, in nanoseconds, passed to `callback`
|
||||
* \param callback the SDL_TimerCallback function to call when the specified
|
||||
* `interval` elapses
|
||||
* \param userdata a pointer that is passed to `callback`
|
||||
* \returns a timer ID or 0 if an error occurs; call SDL_GetError() for more
|
||||
* information.
|
||||
*
|
||||
* \threadsafety It is safe to call this function from any thread.
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*
|
||||
* \sa SDL_AddTimer
|
||||
* \sa SDL_RemoveTimer
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_TimerID SDLCALL SDL_AddTimerNS(Uint64 interval, SDL_NSTimerCallback callback, void *userdata);
|
||||
|
||||
/**
|
||||
* Remove a timer created with SDL_AddTimer().
|
||||
*
|
||||
|
@ -9,6 +9,7 @@ SDL3_0.0.0 {
|
||||
SDL_AddGamepadMappingsFromIO;
|
||||
SDL_AddHintCallback;
|
||||
SDL_AddTimer;
|
||||
SDL_AddTimerNS;
|
||||
SDL_AddVulkanRenderSemaphores;
|
||||
SDL_AllocateEventMemory;
|
||||
SDL_AndroidBackButton;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define SDL_AddGamepadMappingsFromIO SDL_AddGamepadMappingsFromIO_REAL
|
||||
#define SDL_AddHintCallback SDL_AddHintCallback_REAL
|
||||
#define SDL_AddTimer SDL_AddTimer_REAL
|
||||
#define SDL_AddTimerNS SDL_AddTimerNS_REAL
|
||||
#define SDL_AddVulkanRenderSemaphores SDL_AddVulkanRenderSemaphores_REAL
|
||||
#define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL
|
||||
#define SDL_AndroidBackButton SDL_AndroidBackButton_REAL
|
||||
|
@ -54,6 +54,7 @@ SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromFile,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromIO,(SDL_IOStream *a, SDL_bool b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(SDL_TimerID,SDL_AddTimer,(Uint32 a, SDL_TimerCallback b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(SDL_TimerID,SDL_AddTimerNS,(Uint64 a, SDL_NSTimerCallback b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_AddVulkanRenderSemaphores,(SDL_Renderer *a, Uint32 b, Sint64 c, Sint64 d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_AndroidBackButton,(void),(),)
|
||||
|
@ -30,7 +30,8 @@
|
||||
typedef struct SDL_Timer
|
||||
{
|
||||
SDL_TimerID timerID;
|
||||
SDL_TimerCallback callback;
|
||||
SDL_TimerCallback callback_ms;
|
||||
SDL_NSTimerCallback callback_ns;
|
||||
void *userdata;
|
||||
Uint64 interval;
|
||||
Uint64 scheduled;
|
||||
@ -160,8 +161,11 @@ static int SDLCALL SDL_TimerThread(void *_data)
|
||||
if (SDL_AtomicGet(¤t->canceled)) {
|
||||
interval = 0;
|
||||
} else {
|
||||
/* FIXME: We could potentially support sub-millisecond timers now */
|
||||
interval = SDL_MS_TO_NS(current->callback(current->userdata, current->timerID, (Uint32)SDL_NS_TO_MS(current->interval)));
|
||||
if (current->callback_ms) {
|
||||
interval = SDL_MS_TO_NS(current->callback_ms(current->userdata, current->timerID, (Uint32)SDL_NS_TO_MS(current->interval)));
|
||||
} else {
|
||||
interval = current->callback_ns(current->userdata, current->timerID, current->interval);
|
||||
}
|
||||
}
|
||||
|
||||
if (interval > 0) {
|
||||
@ -269,7 +273,7 @@ void SDL_QuitTimers(void)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *userdata)
|
||||
static SDL_TimerID SDL_CreateTimer(Uint64 interval, SDL_TimerCallback callback_ms, SDL_NSTimerCallback callback_ns, void *userdata)
|
||||
{
|
||||
SDL_TimerData *data = &SDL_timer_data;
|
||||
SDL_Timer *timer;
|
||||
@ -298,9 +302,10 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *user
|
||||
}
|
||||
}
|
||||
timer->timerID = SDL_GetNextObjectID();
|
||||
timer->callback = callback;
|
||||
timer->callback_ms = callback_ms;
|
||||
timer->callback_ns = callback_ns;
|
||||
timer->userdata = userdata;
|
||||
timer->interval = SDL_MS_TO_NS(interval);
|
||||
timer->interval = interval;
|
||||
timer->scheduled = SDL_GetTicksNS() + timer->interval;
|
||||
SDL_AtomicSet(&timer->canceled, 0);
|
||||
|
||||
@ -329,6 +334,16 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *user
|
||||
return entry->timerID;
|
||||
}
|
||||
|
||||
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *userdata)
|
||||
{
|
||||
return SDL_CreateTimer(SDL_MS_TO_NS(interval), callback, NULL, userdata);
|
||||
}
|
||||
|
||||
SDL_TimerID SDL_AddTimerNS(Uint64 interval, SDL_NSTimerCallback callback, void *userdata)
|
||||
{
|
||||
return SDL_CreateTimer(interval, NULL, callback, userdata);
|
||||
}
|
||||
|
||||
int SDL_RemoveTimer(SDL_TimerID id)
|
||||
{
|
||||
SDL_TimerData *data = &SDL_timer_data;
|
||||
@ -373,8 +388,9 @@ typedef struct SDL_TimerMap
|
||||
{
|
||||
SDL_TimerID timerID;
|
||||
int timeoutID;
|
||||
Uint32 interval;
|
||||
SDL_TimerCallback callback;
|
||||
Uint64 interval;
|
||||
SDL_TimerCallback callback_ms;
|
||||
SDL_NSTimerCallback callback_ns;
|
||||
void *userdata;
|
||||
struct SDL_TimerMap *next;
|
||||
} SDL_TimerMap;
|
||||
@ -389,10 +405,14 @@ static SDL_TimerData SDL_timer_data;
|
||||
static void SDL_Emscripten_TimerHelper(void *userdata)
|
||||
{
|
||||
SDL_TimerMap *entry = (SDL_TimerMap *)userdata;
|
||||
entry->interval = entry->callback(entry->userdata, entry->timerID, entry->interval);
|
||||
if (entry->callback_ms) {
|
||||
entry->interval = SDL_MS_TO_NS(entry->callback_ms(entry->userdata, entry->timerID, (Uint32)SDL_NS_TO_MS(entry->interval)));
|
||||
} else {
|
||||
entry->interval = entry->callback_ns(entry->userdata, entry->timerID, entry->interval);
|
||||
}
|
||||
if (entry->interval > 0) {
|
||||
entry->timeoutID = emscripten_set_timeout(&SDL_Emscripten_TimerHelper,
|
||||
entry->interval,
|
||||
SDL_NS_TO_MS(entry->interval),
|
||||
entry);
|
||||
}
|
||||
}
|
||||
@ -414,7 +434,7 @@ void SDL_QuitTimers(void)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *userdata)
|
||||
static SDL_TimerID SDL_CreateTimer(Uint64 interval, SDL_TimerCallback callback_ms, SDL_NSTimerCallback callback_ns, void *userdata)
|
||||
{
|
||||
SDL_TimerData *data = &SDL_timer_data;
|
||||
SDL_TimerMap *entry;
|
||||
@ -424,12 +444,13 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *user
|
||||
return 0;
|
||||
}
|
||||
entry->timerID = SDL_GetNextObjectID();
|
||||
entry->callback = callback;
|
||||
entry->callback_ms = callback_ms;
|
||||
entry->callback_ns = callback_ns;
|
||||
entry->userdata = userdata;
|
||||
entry->interval = interval;
|
||||
|
||||
entry->timeoutID = emscripten_set_timeout(&SDL_Emscripten_TimerHelper,
|
||||
entry->interval,
|
||||
SDL_NS_TO_MS(entry->interval),
|
||||
entry);
|
||||
|
||||
entry->next = data->timermap;
|
||||
@ -438,6 +459,16 @@ SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *user
|
||||
return entry->timerID;
|
||||
}
|
||||
|
||||
SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *userdata)
|
||||
{
|
||||
return SDL_CreateTimer(SDL_MS_TO_NS(interval), callback, NULL, userdata);
|
||||
}
|
||||
|
||||
SDL_TimerID SDL_AddTimerNS(Uint64 interval, SDL_NSTimerCallback callback, void *userdata)
|
||||
{
|
||||
return SDL_CreateTimer(interval, NULL, callback, userdata);
|
||||
}
|
||||
|
||||
int SDL_RemoveTimer(SDL_TimerID id)
|
||||
{
|
||||
SDL_TimerData *data = &SDL_timer_data;
|
||||
|
@ -56,6 +56,13 @@ ticktock(void *param, SDL_TimerID timerID, Uint32 interval)
|
||||
return interval;
|
||||
}
|
||||
|
||||
static Uint64 SDLCALL
|
||||
ticktockNS(void *param, SDL_TimerID timerID, Uint64 interval)
|
||||
{
|
||||
++ticks;
|
||||
return interval;
|
||||
}
|
||||
|
||||
static Uint32 SDLCALL
|
||||
callback(void *param, SDL_TimerID timerID, Uint32 interval)
|
||||
{
|
||||
@ -136,25 +143,49 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* Start the timer */
|
||||
/* Start the millisecond timer */
|
||||
if (desired < 0) {
|
||||
desired = DEFAULT_RESOLUTION;
|
||||
}
|
||||
ticks = 0;
|
||||
t1 = SDL_AddTimer(desired, ticktock, NULL);
|
||||
|
||||
/* Wait 10 seconds */
|
||||
SDL_Log("Waiting 10 seconds\n");
|
||||
SDL_Delay(10 * 1000);
|
||||
/* Wait 1 seconds */
|
||||
SDL_Log("Waiting 1 seconds for millisecond timer\n");
|
||||
SDL_Delay(1 * 1000);
|
||||
|
||||
/* Stop the timer */
|
||||
SDL_RemoveTimer(t1);
|
||||
|
||||
/* Print the results */
|
||||
if (ticks) {
|
||||
SDL_Log("Timer resolution: desired = %d ms, actual = %f ms\n",
|
||||
SDL_Log("Millisecond timer resolution: desired = %d ms, actual = %f ms\n",
|
||||
desired, (double)(10 * 1000) / ticks);
|
||||
}
|
||||
|
||||
/* Wait for the results to be seen */
|
||||
SDL_Delay(1 * 1000);
|
||||
|
||||
/* Start the nanosecond timer */
|
||||
ticks = 0;
|
||||
t1 = SDL_AddTimerNS(desired, ticktockNS, NULL);
|
||||
|
||||
/* Wait 1 seconds */
|
||||
SDL_Log("Waiting 1 seconds for nanosecond timer\n");
|
||||
SDL_Delay(1 * 1000);
|
||||
|
||||
/* Stop the timer */
|
||||
SDL_RemoveTimer(t1);
|
||||
|
||||
/* Print the results */
|
||||
if (ticks) {
|
||||
SDL_Log("Nanosecond timer resolution: desired = %d ns, actual = %f ns\n",
|
||||
desired, (double)(10 * 1000000) / ticks);
|
||||
}
|
||||
|
||||
/* Wait for the results to be seen */
|
||||
SDL_Delay(1 * 1000);
|
||||
|
||||
/* Test multiple timers */
|
||||
SDL_Log("Testing multiple timers...\n");
|
||||
t1 = SDL_AddTimer(100, callback, (void *)1);
|
||||
@ -170,18 +201,19 @@ int main(int argc, char *argv[])
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 3: %s\n", SDL_GetError());
|
||||
}
|
||||
|
||||
/* Wait 10 seconds */
|
||||
SDL_Log("Waiting 10 seconds\n");
|
||||
SDL_Delay(10 * 1000);
|
||||
/* Wait 3 seconds */
|
||||
SDL_Log("Waiting 3 seconds\n");
|
||||
SDL_Delay(3 * 1000);
|
||||
|
||||
SDL_Log("Removing timer 1 and waiting 5 more seconds\n");
|
||||
SDL_Log("Removing timer 1 and waiting 3 more seconds\n");
|
||||
SDL_RemoveTimer(t1);
|
||||
|
||||
SDL_Delay(5 * 1000);
|
||||
SDL_Delay(3 * 1000);
|
||||
|
||||
SDL_RemoveTimer(t2);
|
||||
SDL_RemoveTimer(t3);
|
||||
|
||||
ticks = 0;
|
||||
start_perf = SDL_GetPerformanceCounter();
|
||||
for (i = 0; i < 1000000; ++i) {
|
||||
ticktock(NULL, 0, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user