17
#include <SDL3/SDL_main.h>
18
#include <SDL3/SDL_test.h>
20
#define DEFAULT_RESOLUTION 1
22
static int test_sdl_delay_within_bounds(void) {
23
const int testDelay = 100;
24
const int marginOfError = 25;
29
SDLTest_ResetAssertSummary();
32
result = SDL_GetTicks();
33
SDLTest_AssertPass("Call to SDL_GetTicks()");
34
SDLTest_AssertCheck(result > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result);
38
SDLTest_AssertPass("Call to SDL_Delay(%d)", testDelay);
39
result2 = SDL_GetTicks();
40
SDLTest_AssertPass("Call to SDL_GetTicks()");
41
SDLTest_AssertCheck(result2 > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result2);
42
difference = result2 - result;
43
SDLTest_AssertCheck(difference > (testDelay - marginOfError), "Check difference, expected: >%d, got: %" SDL_PRIu64, testDelay - marginOfError, difference);
45
SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%d, got: %" SDL_PRIu64, testDelay + marginOfError, difference);
47
return SDLTest_AssertSummaryToTestResult() == TEST_RESULT_PASSED ? 0 : 1;
53
ticktock(void *param, SDL_TimerID timerID, Uint32 interval)
60
ticktockNS(void *param, SDL_TimerID timerID, Uint64 interval)
67
callback(void *param, SDL_TimerID timerID, Uint32 interval)
69
int value = (int)(uintptr_t)param;
70
SDL_assert( value == 1 || value == 2 || value == 3 );
71
SDL_Log("Timer %" SDL_PRIu32 " : param = %d\n", interval, value);
75
int main(int argc, char *argv[])
79
SDL_TimerID t1, t2, t3;
81
Uint64 start_perf, now_perf;
82
SDLTest_CommonState *state;
83
SDL_bool run_interactive_tests = SDL_TRUE;
87
state = SDLTest_CommonCreateState(argv, 0);
93
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
96
for (i = 1; i < argc;) {
99
consumed = SDLTest_CommonArg(state, i);
101
if (SDL_strcmp(argv[i], "--no-interactive") == 0) {
102
run_interactive_tests = SDL_FALSE;
104
} else if (desired < 0) {
107
desired = SDL_strtoul(argv[i], &endptr, 0);
108
if (desired != 0 && endptr != argv[i] && *endptr == '\0') {
114
static const char *options[] = { "[--no-interactive]", "[interval]", NULL };
115
SDLTest_CommonLogUsage(state, argv[0], options);
122
if (SDL_Init(SDL_INIT_TIMER) < 0) {
123
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
127
if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
128
SDL_Log("Not running slower tests");
134
SDL_Log("Sanity-checking GetTicks\n");
135
for (i = 0; i < 1000; ++i) {
136
start = SDL_GetTicks();
138
now = SDL_GetTicks() - start;
140
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "testtimer.c: Delta time erratic at iter %d. Delay 1ms = %d ms in ticks\n", i, (int)now);
148
desired = DEFAULT_RESOLUTION;
151
t1 = SDL_AddTimer(desired, ticktock, NULL);
154
SDL_Log("Waiting 1 seconds for millisecond timer\n");
162
SDL_Log("Millisecond timer resolution: desired = %d ms, actual = %f ms\n",
163
desired, (double)(10 * 1000) / ticks);
171
t1 = SDL_AddTimerNS(desired, ticktockNS, NULL);
174
SDL_Log("Waiting 1 seconds for nanosecond timer\n");
182
SDL_Log("Nanosecond timer resolution: desired = %d ns, actual = %f ns\n",
183
desired, (double)(10 * 1000000) / ticks);
191
Uint64 desired_delay = SDL_NS_PER_SECOND / 60;
193
Uint64 total_overslept = 0;
195
start = SDL_GetTicksNS();
197
now = SDL_GetTicksNS();
198
actual_delay = (now - start);
199
SDL_Log("Minimum precise delay: %" SDL_PRIu64 " ns\n", actual_delay);
201
SDL_Log("Timing 100 frames at 60 FPS\n");
202
for (i = 0; i < 100; ++i) {
203
start = SDL_GetTicksNS();
204
SDL_DelayNS(desired_delay);
205
now = SDL_GetTicksNS();
206
actual_delay = (now - start);
207
if (actual_delay > desired_delay) {
208
total_overslept += (actual_delay - desired_delay);
211
SDL_Log("Overslept %.2f ms\n", (double)total_overslept / SDL_NS_PER_MS);
218
SDL_Log("Testing multiple timers...\n");
219
t1 = SDL_AddTimer(100, callback, (void *)1);
221
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 1: %s\n", SDL_GetError());
223
t2 = SDL_AddTimer(50, callback, (void *)2);
225
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 2: %s\n", SDL_GetError());
227
t3 = SDL_AddTimer(233, callback, (void *)3);
229
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 3: %s\n", SDL_GetError());
233
SDL_Log("Waiting 3 seconds\n");
236
SDL_Log("Removing timer 1 and waiting 3 more seconds\n");
245
start_perf = SDL_GetPerformanceCounter();
246
for (i = 0; i < 1000000; ++i) {
247
ticktock(NULL, 0, 0);
249
now_perf = SDL_GetPerformanceCounter();
250
SDL_Log("1 million iterations of ticktock took %f ms\n", (double)((now_perf - start_perf) * 1000) / SDL_GetPerformanceFrequency());
252
SDL_Log("Performance counter frequency: %" SDL_PRIu64 "\n", SDL_GetPerformanceFrequency());
253
start = SDL_GetTicks();
254
start_perf = SDL_GetPerformanceCounter();
256
now_perf = SDL_GetPerformanceCounter();
257
now = SDL_GetTicks();
258
SDL_Log("Delay 1 second = %d ms in ticks, %f ms according to performance counter\n", (int)(now - start), (double)((now_perf - start_perf) * 1000) / SDL_GetPerformanceFrequency());
260
if (run_interactive_tests) {
261
return_code = test_sdl_delay_within_bounds();
265
SDLTest_CommonDestroyState(state);