Atlas - testgdk.cpp
Home / ext / SDL / VisualC-GDK / tests / testgdk / src Lines: 1 | Size: 14090 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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 quit(int rc) 60{ 61 SDL_free(sprites); 62 SDL_DestroyAudioStream(stream); 63 SDL_free(wave.sound); 64 SDLTest_CommonQuit(state); 65 /* If rc is 0, just let main return normally rather than calling exit. 66 * This allows testing of platforms where SDL_main is required and does meaningful cleanup. 67 */ 68 if (rc != 0) { 69 exit(rc); 70 } 71} 72 73static int fillerup(void) 74{ 75 const int minimum = (wave.soundlen / SDL_AUDIO_FRAMESIZE(wave.spec)) / 2; 76 if (SDL_GetAudioStreamQueued(stream) < minimum) { 77 SDL_PutAudioStreamData(stream, wave.sound, wave.soundlen); 78 } 79 return 0; 80} 81 82static void UserLoggedIn(XUserHandle user) 83{ 84 HRESULT hr; 85 char gamertag[128]; 86 hr = XUserGetGamertag(user, XUserGamertagComponent::UniqueModern, sizeof(gamertag), gamertag, NULL); 87 88 if (SUCCEEDED(hr)) { 89 SDL_Log("User logged in: %s", gamertag); 90 } else { 91 SDL_Log("[GDK] UserLoggedIn -- XUserGetGamertag failed: 0x%08x.", hr); 92 } 93 94 XUserCloseHandle(user); 95} 96 97static void AddUserUICallback(XAsyncBlock *asyncBlock) 98{ 99 HRESULT hr; 100 XUserHandle user = NULL; 101 102 hr = XUserAddResult(asyncBlock, &user); 103 if (SUCCEEDED(hr)) { 104 uint64_t userId; 105 106 hr = XUserGetId(user, &userId); 107 if (FAILED(hr)) { 108 /* If unable to get the user ID, it means the account is banned, etc. */ 109 SDL_Log("[GDK] AddUserSilentCallback -- XUserGetId failed: 0x%08x.", hr); 110 XUserCloseHandle(user); 111 112 /* Per the docs, likely should call XUserResolveIssueWithUiAsync here. */ 113 } else { 114 UserLoggedIn(user); 115 } 116 } else { 117 SDL_Log("[GDK] AddUserUICallback -- XUserAddAsync failed: 0x%08x.", hr); 118 } 119 120 delete asyncBlock; 121} 122 123static void AddUserUI() 124{ 125 HRESULT hr; 126 XAsyncBlock *asyncBlock = new XAsyncBlock; 127 128 asyncBlock->context = NULL; 129 asyncBlock->queue = NULL; /* A null queue will use the global process task queue */ 130 asyncBlock->callback = &AddUserUICallback; 131 132 hr = XUserAddAsync(XUserAddOptions::None, asyncBlock); 133 134 if (FAILED(hr)) { 135 delete asyncBlock; 136 SDL_Log("[GDK] AddUserSilent -- failed: 0x%08x", hr); 137 } 138} 139 140static void AddUserSilentCallback(XAsyncBlock *asyncBlock) 141{ 142 HRESULT hr; 143 XUserHandle user = NULL; 144 145 hr = XUserAddResult(asyncBlock, &user); 146 if (SUCCEEDED(hr)) { 147 uint64_t userId; 148 149 hr = XUserGetId(user, &userId); 150 if (FAILED(hr)) { 151 /* If unable to get the user ID, it means the account is banned, etc. */ 152 SDL_Log("[GDK] AddUserSilentCallback -- XUserGetId failed: 0x%08x. Trying with UI.", hr); 153 XUserCloseHandle(user); 154 AddUserUI(); 155 } else { 156 UserLoggedIn(user); 157 } 158 } else { 159 SDL_Log("[GDK] AddUserSilentCallback -- XUserAddAsync failed: 0x%08x. Trying with UI.", hr); 160 AddUserUI(); 161 } 162 163 delete asyncBlock; 164} 165 166static void AddUserSilent() 167{ 168 HRESULT hr; 169 XAsyncBlock *asyncBlock = new XAsyncBlock; 170 171 asyncBlock->context = NULL; 172 asyncBlock->queue = NULL; /* A null queue will use the global process task queue */ 173 asyncBlock->callback = &AddUserSilentCallback; 174 175 hr = XUserAddAsync(XUserAddOptions::AddDefaultUserSilently, asyncBlock); 176 177 if (FAILED(hr)) { 178 delete asyncBlock; 179 SDL_Log("[GDK] AddUserSilent -- failed: 0x%08x", hr); 180 } 181} 182 183static bool LoadSprite(const char *file) 184{ 185 int i; 186 187 for (i = 0; i < state->num_windows; ++i) { 188 /* This does the SDL_LoadBMP step repeatedly, but that's OK for test code. */ 189 sprites[i] = LoadTexture(state->renderers[i], file, true); 190 if (!sprites[i]) { 191 return false; 192 } 193 sprite_w = sprites[i]->w; 194 sprite_h = sprites[i]->h; 195 196 SDL_SetTextureBlendMode(sprites[i], blendMode); 197 } 198 199 /* We're ready to roll. :) */ 200 return true; 201} 202 203static void DrawSprites(SDL_Renderer * renderer, SDL_Texture * sprite) 204{ 205 SDL_Rect viewport; 206 SDL_FRect temp; 207 208 /* Query the sizes */ 209 SDL_GetRenderViewport(renderer, &viewport); 210 211 /* Cycle the color and alpha, if desired */ 212 if (cycle_color) { 213 current_color += cycle_direction; 214 if (current_color < 0) { 215 current_color = 0; 216 cycle_direction = -cycle_direction; 217 } 218 if (current_color > 255) { 219 current_color = 255; 220 cycle_direction = -cycle_direction; 221 } 222 SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color, 223 (Uint8) current_color); 224 } 225 if (cycle_alpha) { 226 current_alpha += cycle_direction; 227 if (current_alpha < 0) { 228 current_alpha = 0; 229 cycle_direction = -cycle_direction; 230 } 231 if (current_alpha > 255) { 232 current_alpha = 255; 233 cycle_direction = -cycle_direction; 234 } 235 SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha); 236 } 237 238 /* Draw a gray background */ 239 SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); 240 SDL_RenderClear(renderer); 241 242 /* Test points */ 243 SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF); 244 SDL_RenderPoint(renderer, 0.0f, 0.0f); 245 SDL_RenderPoint(renderer, (float)(viewport.w - 1), 0.0f); 246 SDL_RenderPoint(renderer, 0.0f, (float)(viewport.h - 1)); 247 SDL_RenderPoint(renderer, (float)(viewport.w - 1), (float)(viewport.h - 1)); 248 249 /* Test horizontal and vertical lines */ 250 SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF); 251 SDL_RenderLine(renderer, 1.0f, 0.0f, (float)(viewport.w - 2), 0.0f); 252 SDL_RenderLine(renderer, 1.0f, (float)(viewport.h - 1), (float)(viewport.w - 2), (float)(viewport.h - 1)); 253 SDL_RenderLine(renderer, 0.0f, 1.0f, 0.0f, (float)(viewport.h - 2)); 254 SDL_RenderLine(renderer, (float)(viewport.w - 1), 1, (float)(viewport.w - 1), (float)(viewport.h - 2)); 255 256 /* Test fill and copy */ 257 SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); 258 temp.x = 1.0f; 259 temp.y = 1.0f; 260 temp.w = (float)sprite_w; 261 temp.h = (float)sprite_h; 262 SDL_RenderFillRect(renderer, &temp); 263 SDL_RenderTexture(renderer, sprite, NULL, &temp); 264 temp.x = (float)(viewport.w-sprite_w-1); 265 temp.y = 1.0f; 266 temp.w = (float)sprite_w; 267 temp.h = (float)sprite_h; 268 SDL_RenderFillRect(renderer, &temp); 269 SDL_RenderTexture(renderer, sprite, NULL, &temp); 270 temp.x = 1.0f; 271 temp.y = (float)(viewport.h-sprite_h-1); 272 temp.w = (float)sprite_w; 273 temp.h = (float)sprite_h; 274 SDL_RenderFillRect(renderer, &temp); 275 SDL_RenderTexture(renderer, sprite, NULL, &temp); 276 temp.x = (float)(viewport.w-sprite_w-1); 277 temp.y = (float)(viewport.h-sprite_h-1); 278 temp.w = (float)(sprite_w); 279 temp.h = (float)(sprite_h); 280 SDL_RenderFillRect(renderer, &temp); 281 SDL_RenderTexture(renderer, sprite, NULL, &temp); 282 283 /* Test diagonal lines */ 284 SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF); 285 SDL_RenderLine(renderer, (float)sprite_w, (float)sprite_h, 286 (float)(viewport.w-sprite_w-2), (float)(viewport.h-sprite_h-2)); 287 SDL_RenderLine(renderer, (float)(viewport.w-sprite_w-2), (float)sprite_h, 288 (float)sprite_w, (float)(viewport.h-sprite_h-2)); 289 290 /* Update the screen! */ 291 SDL_RenderPresent(renderer); 292} 293 294static void loop() 295{ 296 int i; 297 SDL_Event event; 298 299 /* Check for events */ 300 while (SDL_PollEvent(&event)) { 301 if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat) { 302 SDL_Log("Initial SDL_EVENT_KEY_DOWN: %s", SDL_GetScancodeName(event.key.scancode)); 303 } 304#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) 305 /* On Xbox, ignore the keydown event because the features aren't supported */ 306 if (event.type != SDL_EVENT_KEY_DOWN) { 307 SDLTest_CommonEvent(state, &event, &done); 308 } 309#else 310 SDLTest_CommonEvent(state, &event, &done); 311#endif 312 } 313 for (i = 0; i < state->num_windows; ++i) { 314 if (state->windows[i] == NULL) { 315 continue; 316 } 317 DrawSprites(state->renderers[i], sprites[i]); 318 } 319 fillerup(); 320} 321 322int main(int argc, char *argv[]) 323{ 324 int i; 325 const char *icon = "icon.bmp"; 326 char *soundname = NULL; 327 328 /* Initialize parameters */ 329 num_sprites = NUM_SPRITES; 330 331 /* Initialize test framework */ 332 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO | SDL_INIT_AUDIO); 333 if (!state) { 334 return 1; 335 } 336 337 for (i = 1; i < argc;) { 338 int consumed; 339 340 consumed = SDLTest_CommonArg(state, i); 341 if (consumed == 0) { 342 consumed = -1; 343 if (SDL_strcasecmp(argv[i], "--blend") == 0) { 344 if (argv[i + 1]) { 345 if (SDL_strcasecmp(argv[i + 1], "none") == 0) { 346 blendMode = SDL_BLENDMODE_NONE; 347 consumed = 2; 348 } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) { 349 blendMode = SDL_BLENDMODE_BLEND; 350 consumed = 2; 351 } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) { 352 blendMode = SDL_BLENDMODE_ADD; 353 consumed = 2; 354 } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) { 355 blendMode = SDL_BLENDMODE_MOD; 356 consumed = 2; 357 } else if (SDL_strcasecmp(argv[i + 1], "sub") == 0) { 358 blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT); 359 consumed = 2; 360 } 361 } 362 } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) { 363 cycle_color = true; 364 consumed = 1; 365 } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) { 366 cycle_alpha = true; 367 consumed = 1; 368 } else if (SDL_isdigit(*argv[i])) { 369 num_sprites = SDL_atoi(argv[i]); 370 consumed = 1; 371 } else if (argv[i][0] != '-') { 372 icon = argv[i]; 373 consumed = 1; 374 } 375 } 376 if (consumed < 0) { 377 static const char *options[] = { 378 "[--blend none|blend|add|mod]", 379 "[--cyclecolor]", 380 "[--cyclealpha]", 381 "[num_sprites]", 382 "[icon.bmp]", 383 NULL }; 384 SDLTest_CommonLogUsage(state, argv[0], options); 385 quit(1); 386 } 387 i += consumed; 388 } 389 if (!SDLTest_CommonInit(state)) { 390 quit(2); 391 } 392 393 /* Create the windows, initialize the renderers, and load the textures */ 394 sprites = 395 (SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites)); 396 if (!sprites) { 397 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); 398 quit(2); 399 } 400 for (i = 0; i < state->num_windows; ++i) { 401 SDL_Renderer *renderer = state->renderers[i]; 402 SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); 403 SDL_RenderClear(renderer); 404 } 405 if (!LoadSprite(icon)) { 406 quit(2); 407 } 408 409 soundname = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav"); 410 411 if (!soundname) { 412 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError()); 413 quit(1); 414 } 415 416 /* Load the wave file into memory */ 417 if (!SDL_LoadWAV(soundname, &wave.spec, &wave.sound, &wave.soundlen)) { 418 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", soundname, SDL_GetError()); 419 quit(1); 420 } 421 422 /* Show the list of available drivers */ 423 SDL_Log("Available audio drivers:"); 424 for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) { 425 SDL_Log("%i: %s", i, SDL_GetAudioDriver(i)); 426 } 427 428 SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver()); 429 430 stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &wave.spec, NULL, NULL); 431 if (!stream) { 432 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s", SDL_GetError()); 433 return -1; 434 } 435 SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream)); 436 437 /* Main render loop */ 438 done = 0; 439 440 /* Try to add the default user silently */ 441 AddUserSilent(); 442 443 while (!done) { 444 loop(); 445 } 446 447 quit(0); 448 449 SDL_free(soundname); 450 return 0; 451} 452[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.