SDL

Форк
0
/
testtimer.c 
267 строк · 8.2 Кб
1
/*
2
  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
3

4
  This software is provided 'as-is', without any express or implied
5
  warranty.  In no event will the authors be held liable for any damages
6
  arising from the use of this software.
7

8
  Permission is granted to anyone to use this software for any purpose,
9
  including commercial applications, and to alter it and redistribute it
10
  freely.
11
*/
12

13
/* Test program to check the resolution of the SDL timer on the current
14
   platform
15
*/
16
#include <SDL3/SDL.h>
17
#include <SDL3/SDL_main.h>
18
#include <SDL3/SDL_test.h>
19

20
#define DEFAULT_RESOLUTION 1
21

22
static int test_sdl_delay_within_bounds(void) {
23
    const int testDelay = 100;
24
    const int marginOfError = 25;
25
    Uint64 result;
26
    Uint64 result2;
27
    Sint64 difference;
28

29
    SDLTest_ResetAssertSummary();
30

31
    /* Get ticks count - should be non-zero by now */
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);
35

36
    /* Delay a bit longer and measure ticks and verify difference */
37
    SDL_Delay(testDelay);
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);
44
    /* Disabled because this might fail on non-interactive systems. */
45
    SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%d, got: %" SDL_PRIu64, testDelay + marginOfError, difference);
46

47
    return SDLTest_AssertSummaryToTestResult() == TEST_RESULT_PASSED ? 0 : 1;
48
}
49

50
static int ticks = 0;
51

52
static Uint32 SDLCALL
53
ticktock(void *param, SDL_TimerID timerID, Uint32 interval)
54
{
55
    ++ticks;
56
    return interval;
57
}
58

59
static Uint64 SDLCALL
60
ticktockNS(void *param, SDL_TimerID timerID, Uint64 interval)
61
{
62
    ++ticks;
63
    return interval;
64
}
65

66
static Uint32 SDLCALL
67
callback(void *param, SDL_TimerID timerID, Uint32 interval)
68
{
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);
72
    return interval;
73
}
74

75
int main(int argc, char *argv[])
76
{
77
    int i;
78
    int desired = -1;
79
    SDL_TimerID t1, t2, t3;
80
    Uint64 start, now;
81
    Uint64 start_perf, now_perf;
82
    SDLTest_CommonState  *state;
83
    SDL_bool run_interactive_tests = SDL_TRUE;
84
    int return_code = 0;
85

86
    /* Initialize test framework */
87
    state = SDLTest_CommonCreateState(argv, 0);
88
    if (!state) {
89
        return 1;
90
    }
91

92
    /* Enable standard application logging */
93
    SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
94

95
    /* Parse commandline */
96
    for (i = 1; i < argc;) {
97
        int consumed;
98

99
        consumed = SDLTest_CommonArg(state, i);
100
        if (!consumed) {
101
            if (SDL_strcmp(argv[i], "--no-interactive") == 0) {
102
                run_interactive_tests = SDL_FALSE;
103
                consumed = 1;
104
            } else if (desired < 0) {
105
                char *endptr;
106

107
                desired = SDL_strtoul(argv[i], &endptr, 0);
108
                if (desired != 0 && endptr != argv[i] && *endptr == '\0') {
109
                    consumed = 1;
110
                }
111
            }
112
        }
113
        if (consumed <= 0) {
114
            static const char *options[] = { "[--no-interactive]", "[interval]", NULL };
115
            SDLTest_CommonLogUsage(state, argv[0], options);
116
            return 1;
117
        }
118

119
        i += consumed;
120
    }
121

122
    if (SDL_Init(SDL_INIT_TIMER) < 0) {
123
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
124
        return 1;
125
    }
126

127
    if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
128
        SDL_Log("Not running slower tests");
129
        SDL_Quit();
130
        return 0;
131
    }
132

133
    /* Verify SDL_GetTicks* acts monotonically increasing, and not erratic. */
134
    SDL_Log("Sanity-checking GetTicks\n");
135
    for (i = 0; i < 1000; ++i) {
136
        start = SDL_GetTicks();
137
        SDL_Delay(1);
138
        now = SDL_GetTicks() - start;
139
        if (now > 100) {
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);
141
            SDL_Quit();
142
            return 1;
143
        }
144
    }
145

146
    /* Start the millisecond timer */
147
    if (desired < 0) {
148
        desired = DEFAULT_RESOLUTION;
149
    }
150
    ticks = 0;
151
    t1 = SDL_AddTimer(desired, ticktock, NULL);
152

153
    /* Wait 1 seconds */
154
    SDL_Log("Waiting 1 seconds for millisecond timer\n");
155
    SDL_Delay(1 * 1000);
156

157
    /* Stop the timer */
158
    SDL_RemoveTimer(t1);
159

160
    /* Print the results */
161
    if (ticks) {
162
        SDL_Log("Millisecond timer resolution: desired = %d ms, actual = %f ms\n",
163
                desired, (double)(10 * 1000) / ticks);
164
    }
165

166
    /* Wait for the results to be seen */
167
    SDL_Delay(1 * 1000);
168

169
    /* Start the nanosecond timer */
170
    ticks = 0;
171
    t1 = SDL_AddTimerNS(desired, ticktockNS, NULL);
172

173
    /* Wait 1 seconds */
174
    SDL_Log("Waiting 1 seconds for nanosecond timer\n");
175
    SDL_Delay(1 * 1000);
176

177
    /* Stop the timer */
178
    SDL_RemoveTimer(t1);
179

180
    /* Print the results */
181
    if (ticks) {
182
        SDL_Log("Nanosecond timer resolution: desired = %d ns, actual = %f ns\n",
183
                desired, (double)(10 * 1000000) / ticks);
184
    }
185

186
    /* Wait for the results to be seen */
187
    SDL_Delay(1 * 1000);
188

189
    /* Check accuracy of precise delay */
190
    {
191
        Uint64 desired_delay = SDL_NS_PER_SECOND / 60;
192
        Uint64 actual_delay;
193
        Uint64 total_overslept = 0;
194

195
        start = SDL_GetTicksNS();
196
        SDL_DelayNS(1);
197
        now = SDL_GetTicksNS();
198
        actual_delay = (now - start);
199
        SDL_Log("Minimum precise delay: %" SDL_PRIu64 " ns\n", actual_delay);
200

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);
209
            }
210
        }
211
        SDL_Log("Overslept %.2f ms\n", (double)total_overslept / SDL_NS_PER_MS);
212
    }
213

214
    /* Wait for the results to be seen */
215
    SDL_Delay(1 * 1000);
216

217
    /* Test multiple timers */
218
    SDL_Log("Testing multiple timers...\n");
219
    t1 = SDL_AddTimer(100, callback, (void *)1);
220
    if (!t1) {
221
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 1: %s\n", SDL_GetError());
222
    }
223
    t2 = SDL_AddTimer(50, callback, (void *)2);
224
    if (!t2) {
225
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 2: %s\n", SDL_GetError());
226
    }
227
    t3 = SDL_AddTimer(233, callback, (void *)3);
228
    if (!t3) {
229
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 3: %s\n", SDL_GetError());
230
    }
231

232
    /* Wait 3 seconds */
233
    SDL_Log("Waiting 3 seconds\n");
234
    SDL_Delay(3 * 1000);
235

236
    SDL_Log("Removing timer 1 and waiting 3 more seconds\n");
237
    SDL_RemoveTimer(t1);
238

239
    SDL_Delay(3 * 1000);
240

241
    SDL_RemoveTimer(t2);
242
    SDL_RemoveTimer(t3);
243

244
    ticks = 0;
245
    start_perf = SDL_GetPerformanceCounter();
246
    for (i = 0; i < 1000000; ++i) {
247
        ticktock(NULL, 0, 0);
248
    }
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());
251

252
    SDL_Log("Performance counter frequency: %" SDL_PRIu64 "\n", SDL_GetPerformanceFrequency());
253
    start = SDL_GetTicks();
254
    start_perf = SDL_GetPerformanceCounter();
255
    SDL_Delay(1000);
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());
259

260
    if (run_interactive_tests) {
261
        return_code = test_sdl_delay_within_bounds();
262
    }
263

264
    SDL_Quit();
265
    SDLTest_CommonDestroyState(state);
266
    return return_code;
267
}
268

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.