summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/VisualC-GDK/tests/testgdk/src
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/VisualC-GDK/tests/testgdk/src
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/VisualC-GDK/tests/testgdk/src')
-rw-r--r--contrib/SDL-3.2.8/VisualC-GDK/tests/testgdk/src/testgdk.cpp462
1 files changed, 462 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/VisualC-GDK/tests/testgdk/src/testgdk.cpp b/contrib/SDL-3.2.8/VisualC-GDK/tests/testgdk/src/testgdk.cpp
new file mode 100644
index 0000000..51fc75b
--- /dev/null
+++ b/contrib/SDL-3.2.8/VisualC-GDK/tests/testgdk/src/testgdk.cpp
@@ -0,0 +1,462 @@
1/*
2 Copyright (C) 1997-2025 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/* testgdk: Basic tests of using task queue/xbl (with simple drawing) in GDK.
13 * NOTE: As of June 2022 GDK, login will only work if MicrosoftGame.config is
14 * configured properly. See README-gdk.md.
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <time.h>
20
21#include <SDL3/SDL_test.h>
22#include <SDL3/SDL_test_common.h>
23#include "../src/core/windows/SDL_windows.h"
24#include <SDL3/SDL_main.h>
25
26extern "C" {
27#include "../test/testutils.h"
28}
29
30#include <XGameRuntime.h>
31
32#define NUM_SPRITES 100
33#define MAX_SPEED 1
34
35static SDLTest_CommonState *state;
36static int num_sprites;
37static SDL_Texture **sprites;
38static bool cycle_color;
39static bool cycle_alpha;
40static int cycle_direction = 1;
41static int current_alpha = 0;
42static int current_color = 0;
43static int sprite_w, sprite_h;
44static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND;
45
46int done;
47
48static struct
49{
50 SDL_AudioSpec spec;
51 Uint8 *sound; /* Pointer to wave data */
52 Uint32 soundlen; /* Length of wave data */
53 int soundpos; /* Current play position */
54} wave;
55
56static SDL_AudioStream *stream;
57
58/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
59static void
60quit(int rc)
61{
62 SDL_free(sprites);
63 SDL_DestroyAudioStream(stream);
64 SDL_free(wave.sound);
65 SDLTest_CommonQuit(state);
66 /* If rc is 0, just let main return normally rather than calling exit.
67 * This allows testing of platforms where SDL_main is required and does meaningful cleanup.
68 */
69 if (rc != 0) {
70 exit(rc);
71 }
72}
73
74static int fillerup(void)
75{
76 const int minimum = (wave.soundlen / SDL_AUDIO_FRAMESIZE(wave.spec)) / 2;
77 if (SDL_GetAudioStreamQueued(stream) < minimum) {
78 SDL_PutAudioStreamData(stream, wave.sound, wave.soundlen);
79 }
80 return 0;
81}
82
83void
84UserLoggedIn(XUserHandle user)
85{
86 HRESULT hr;
87 char gamertag[128];
88 hr = XUserGetGamertag(user, XUserGamertagComponent::UniqueModern, sizeof(gamertag), gamertag, NULL);
89
90 if (SUCCEEDED(hr)) {
91 SDL_Log("User logged in: %s", gamertag);
92 } else {
93 SDL_Log("[GDK] UserLoggedIn -- XUserGetGamertag failed: 0x%08x.", hr);
94 }
95
96 XUserCloseHandle(user);
97}
98
99void
100AddUserUICallback(XAsyncBlock *asyncBlock)
101{
102 HRESULT hr;
103 XUserHandle user = NULL;
104
105 hr = XUserAddResult(asyncBlock, &user);
106 if (SUCCEEDED(hr)) {
107 uint64_t userId;
108
109 hr = XUserGetId(user, &userId);
110 if (FAILED(hr)) {
111 /* If unable to get the user ID, it means the account is banned, etc. */
112 SDL_Log("[GDK] AddUserSilentCallback -- XUserGetId failed: 0x%08x.", hr);
113 XUserCloseHandle(user);
114
115 /* Per the docs, likely should call XUserResolveIssueWithUiAsync here. */
116 } else {
117 UserLoggedIn(user);
118 }
119 } else {
120 SDL_Log("[GDK] AddUserUICallback -- XUserAddAsync failed: 0x%08x.", hr);
121 }
122
123 delete asyncBlock;
124}
125
126void
127AddUserUI()
128{
129 HRESULT hr;
130 XAsyncBlock *asyncBlock = new XAsyncBlock;
131
132 asyncBlock->context = NULL;
133 asyncBlock->queue = NULL; /* A null queue will use the global process task queue */
134 asyncBlock->callback = &AddUserUICallback;
135
136 hr = XUserAddAsync(XUserAddOptions::None, asyncBlock);
137
138 if (FAILED(hr)) {
139 delete asyncBlock;
140 SDL_Log("[GDK] AddUserSilent -- failed: 0x%08x", hr);
141 }
142}
143
144void
145AddUserSilentCallback(XAsyncBlock *asyncBlock)
146{
147 HRESULT hr;
148 XUserHandle user = NULL;
149
150 hr = XUserAddResult(asyncBlock, &user);
151 if (SUCCEEDED(hr)) {
152 uint64_t userId;
153
154 hr = XUserGetId(user, &userId);
155 if (FAILED(hr)) {
156 /* If unable to get the user ID, it means the account is banned, etc. */
157 SDL_Log("[GDK] AddUserSilentCallback -- XUserGetId failed: 0x%08x. Trying with UI.", hr);
158 XUserCloseHandle(user);
159 AddUserUI();
160 } else {
161 UserLoggedIn(user);
162 }
163 } else {
164 SDL_Log("[GDK] AddUserSilentCallback -- XUserAddAsync failed: 0x%08x. Trying with UI.", hr);
165 AddUserUI();
166 }
167
168 delete asyncBlock;
169}
170
171void
172AddUserSilent()
173{
174 HRESULT hr;
175 XAsyncBlock *asyncBlock = new XAsyncBlock;
176
177 asyncBlock->context = NULL;
178 asyncBlock->queue = NULL; /* A null queue will use the global process task queue */
179 asyncBlock->callback = &AddUserSilentCallback;
180
181 hr = XUserAddAsync(XUserAddOptions::AddDefaultUserSilently, asyncBlock);
182
183 if (FAILED(hr)) {
184 delete asyncBlock;
185 SDL_Log("[GDK] AddUserSilent -- failed: 0x%08x", hr);
186 }
187}
188
189int
190LoadSprite(const char *file)
191{
192 int i;
193
194 for (i = 0; i < state->num_windows; ++i) {
195 /* This does the SDL_LoadBMP step repeatedly, but that's OK for test code. */
196 sprites[i] = LoadTexture(state->renderers[i], file, true, &sprite_w, &sprite_h);
197 if (!sprites[i]) {
198 return -1;
199 }
200 if (!SDL_SetTextureBlendMode(sprites[i], blendMode)) {
201 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set blend mode: %s", SDL_GetError());
202 SDL_DestroyTexture(sprites[i]);
203 return -1;
204 }
205 }
206
207 /* We're ready to roll. :) */
208 return 0;
209}
210
211void
212DrawSprites(SDL_Renderer * renderer, SDL_Texture * sprite)
213{
214 SDL_Rect viewport;
215 SDL_FRect temp;
216
217 /* Query the sizes */
218 SDL_GetRenderViewport(renderer, &viewport);
219
220 /* Cycle the color and alpha, if desired */
221 if (cycle_color) {
222 current_color += cycle_direction;
223 if (current_color < 0) {
224 current_color = 0;
225 cycle_direction = -cycle_direction;
226 }
227 if (current_color > 255) {
228 current_color = 255;
229 cycle_direction = -cycle_direction;
230 }
231 SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
232 (Uint8) current_color);
233 }
234 if (cycle_alpha) {
235 current_alpha += cycle_direction;
236 if (current_alpha < 0) {
237 current_alpha = 0;
238 cycle_direction = -cycle_direction;
239 }
240 if (current_alpha > 255) {
241 current_alpha = 255;
242 cycle_direction = -cycle_direction;
243 }
244 SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
245 }
246
247 /* Draw a gray background */
248 SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
249 SDL_RenderClear(renderer);
250
251 /* Test points */
252 SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
253 SDL_RenderPoint(renderer, 0.0f, 0.0f);
254 SDL_RenderPoint(renderer, (float)(viewport.w - 1), 0.0f);
255 SDL_RenderPoint(renderer, 0.0f, (float)(viewport.h - 1));
256 SDL_RenderPoint(renderer, (float)(viewport.w - 1), (float)(viewport.h - 1));
257
258 /* Test horizontal and vertical lines */
259 SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
260 SDL_RenderLine(renderer, 1.0f, 0.0f, (float)(viewport.w - 2), 0.0f);
261 SDL_RenderLine(renderer, 1.0f, (float)(viewport.h - 1), (float)(viewport.w - 2), (float)(viewport.h - 1));
262 SDL_RenderLine(renderer, 0.0f, 1.0f, 0.0f, (float)(viewport.h - 2));
263 SDL_RenderLine(renderer, (float)(viewport.w - 1), 1, (float)(viewport.w - 1), (float)(viewport.h - 2));
264
265 /* Test fill and copy */
266 SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
267 temp.x = 1.0f;
268 temp.y = 1.0f;
269 temp.w = (float)sprite_w;
270 temp.h = (float)sprite_h;
271 SDL_RenderFillRect(renderer, &temp);
272 SDL_RenderTexture(renderer, sprite, NULL, &temp);
273 temp.x = (float)(viewport.w-sprite_w-1);
274 temp.y = 1.0f;
275 temp.w = (float)sprite_w;
276 temp.h = (float)sprite_h;
277 SDL_RenderFillRect(renderer, &temp);
278 SDL_RenderTexture(renderer, sprite, NULL, &temp);
279 temp.x = 1.0f;
280 temp.y = (float)(viewport.h-sprite_h-1);
281 temp.w = (float)sprite_w;
282 temp.h = (float)sprite_h;
283 SDL_RenderFillRect(renderer, &temp);
284 SDL_RenderTexture(renderer, sprite, NULL, &temp);
285 temp.x = (float)(viewport.w-sprite_w-1);
286 temp.y = (float)(viewport.h-sprite_h-1);
287 temp.w = (float)(sprite_w);
288 temp.h = (float)(sprite_h);
289 SDL_RenderFillRect(renderer, &temp);
290 SDL_RenderTexture(renderer, sprite, NULL, &temp);
291
292 /* Test diagonal lines */
293 SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
294 SDL_RenderLine(renderer, (float)sprite_w, (float)sprite_h,
295 (float)(viewport.w-sprite_w-2), (float)(viewport.h-sprite_h-2));
296 SDL_RenderLine(renderer, (float)(viewport.w-sprite_w-2), (float)sprite_h,
297 (float)sprite_w, (float)(viewport.h-sprite_h-2));
298
299 /* Update the screen! */
300 SDL_RenderPresent(renderer);
301}
302
303void
304loop()
305{
306 int i;
307 SDL_Event event;
308
309 /* Check for events */
310 while (SDL_PollEvent(&event)) {
311 if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat) {
312 SDL_Log("Initial SDL_EVENT_KEY_DOWN: %s", SDL_GetScancodeName(event.key.scancode));
313 }
314#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
315 /* On Xbox, ignore the keydown event because the features aren't supported */
316 if (event.type != SDL_EVENT_KEY_DOWN) {
317 SDLTest_CommonEvent(state, &event, &done);
318 }
319#else
320 SDLTest_CommonEvent(state, &event, &done);
321#endif
322 }
323 for (i = 0; i < state->num_windows; ++i) {
324 if (state->windows[i] == NULL) {
325 continue;
326 }
327 DrawSprites(state->renderers[i], sprites[i]);
328 }
329 fillerup();
330}
331
332int
333main(int argc, char *argv[])
334{
335 int i;
336 const char *icon = "icon.bmp";
337 char *soundname = NULL;
338
339 /* Initialize parameters */
340 num_sprites = NUM_SPRITES;
341
342 /* Initialize test framework */
343 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_AUDIO);
344 if (!state) {
345 return 1;
346 }
347
348 for (i = 1; i < argc;) {
349 int consumed;
350
351 consumed = SDLTest_CommonArg(state, i);
352 if (consumed == 0) {
353 consumed = -1;
354 if (SDL_strcasecmp(argv[i], "--blend") == 0) {
355 if (argv[i + 1]) {
356 if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
357 blendMode = SDL_BLENDMODE_NONE;
358 consumed = 2;
359 } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
360 blendMode = SDL_BLENDMODE_BLEND;
361 consumed = 2;
362 } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
363 blendMode = SDL_BLENDMODE_ADD;
364 consumed = 2;
365 } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
366 blendMode = SDL_BLENDMODE_MOD;
367 consumed = 2;
368 } else if (SDL_strcasecmp(argv[i + 1], "sub") == 0) {
369 blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
370 consumed = 2;
371 }
372 }
373 } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
374 cycle_color = true;
375 consumed = 1;
376 } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
377 cycle_alpha = true;
378 consumed = 1;
379 } else if (SDL_isdigit(*argv[i])) {
380 num_sprites = SDL_atoi(argv[i]);
381 consumed = 1;
382 } else if (argv[i][0] != '-') {
383 icon = argv[i];
384 consumed = 1;
385 }
386 }
387 if (consumed < 0) {
388 static const char *options[] = {
389 "[--blend none|blend|add|mod]",
390 "[--cyclecolor]",
391 "[--cyclealpha]",
392 "[num_sprites]",
393 "[icon.bmp]",
394 NULL };
395 SDLTest_CommonLogUsage(state, argv[0], options);
396 quit(1);
397 }
398 i += consumed;
399 }
400 if (!SDLTest_CommonInit(state)) {
401 quit(2);
402 }
403
404 /* Create the windows, initialize the renderers, and load the textures */
405 sprites =
406 (SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites));
407 if (!sprites) {
408 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
409 quit(2);
410 }
411 for (i = 0; i < state->num_windows; ++i) {
412 SDL_Renderer *renderer = state->renderers[i];
413 SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
414 SDL_RenderClear(renderer);
415 }
416 if (LoadSprite(icon) < 0) {
417 quit(2);
418 }
419
420 soundname = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav");
421
422 if (!soundname) {
423 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError());
424 quit(1);
425 }
426
427 /* Load the wave file into memory */
428 if (!SDL_LoadWAV(soundname, &wave.spec, &wave.sound, &wave.soundlen)) {
429 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", soundname, SDL_GetError());
430 quit(1);
431 }
432
433 /* Show the list of available drivers */
434 SDL_Log("Available audio drivers:");
435 for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
436 SDL_Log("%i: %s", i, SDL_GetAudioDriver(i));
437 }
438
439 SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver());
440
441 stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &wave.spec, NULL, NULL);
442 if (!stream) {
443 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s", SDL_GetError());
444 return -1;
445 }
446 SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
447
448 /* Main render loop */
449 done = 0;
450
451 /* Try to add the default user silently */
452 AddUserSilent();
453
454 while (!done) {
455 loop();
456 }
457
458 quit(0);
459
460 SDL_free(soundname);
461 return 0;
462}