Atlas - SDL.c
Home / ext / SDL / src Lines: 1 | Size: 26768 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22#include "SDL3/SDL_revision.h" 23 24#if defined(SDL_PLATFORM_WINDOWS) 25#include "core/windows/SDL_windows.h" 26#else 27#include <unistd.h> // _exit(), etc. 28#endif 29 30// this checks for HAVE_DBUS_DBUS_H internally. 31#include "core/linux/SDL_dbus.h" 32 33#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) 34#include "core/unix/SDL_gtk.h" 35#endif 36 37#ifdef SDL_PLATFORM_EMSCRIPTEN 38#include <emscripten.h> 39#endif 40 41// Initialization code for SDL 42 43#include "SDL_assert_c.h" 44#include "SDL_hints_c.h" 45#include "SDL_log_c.h" 46#include "SDL_properties_c.h" 47#include "audio/SDL_sysaudio.h" 48#include "camera/SDL_camera_c.h" 49#include "cpuinfo/SDL_cpuinfo_c.h" 50#include "events/SDL_events_c.h" 51#include "haptic/SDL_haptic_c.h" 52#include "joystick/SDL_gamepad_c.h" 53#include "joystick/SDL_joystick_c.h" 54#include "render/SDL_sysrender.h" 55#include "sensor/SDL_sensor_c.h" 56#include "stdlib/SDL_getenv_c.h" 57#include "thread/SDL_thread_c.h" 58#include "tray/SDL_tray_utils.h" 59#include "video/SDL_pixels_c.h" 60#include "video/SDL_surface_c.h" 61#include "video/SDL_video_c.h" 62#include "filesystem/SDL_filesystem_c.h" 63#include "io/SDL_asyncio_c.h" 64#ifdef SDL_PLATFORM_ANDROID 65#include "core/android/SDL_android.h" 66#endif 67 68#define SDL_INIT_EVERYTHING ~0U 69 70// Initialization/Cleanup routines 71#include "timer/SDL_timer_c.h" 72#ifdef SDL_PLATFORM_WINDOWS 73extern bool SDL_HelperWindowCreate(void); 74extern void SDL_HelperWindowDestroy(void); 75#endif 76 77#ifdef SDL_BUILD_MAJOR_VERSION 78SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MAJOR_VERSION, 79 SDL_MAJOR_VERSION == SDL_BUILD_MAJOR_VERSION); 80SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MINOR_VERSION, 81 SDL_MINOR_VERSION == SDL_BUILD_MINOR_VERSION); 82SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MICRO_VERSION, 83 SDL_MICRO_VERSION == SDL_BUILD_MICRO_VERSION); 84#endif 85 86// Limited by its encoding in SDL_VERSIONNUM 87SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_min, SDL_MAJOR_VERSION >= 0); 88SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_max, SDL_MAJOR_VERSION <= 10); 89SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_min, SDL_MINOR_VERSION >= 0); 90SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_max, SDL_MINOR_VERSION <= 999); 91SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_min, SDL_MICRO_VERSION >= 0); 92SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_max, SDL_MICRO_VERSION <= 999); 93 94/* This is not declared in any header, although it is shared between some 95 parts of SDL, because we don't want anything calling it without an 96 extremely good reason. */ 97extern SDL_NORETURN void SDL_ExitProcess(int exitcode); 98SDL_NORETURN void SDL_ExitProcess(int exitcode) 99{ 100#if defined(SDL_PLATFORM_WINDOWS) 101 /* "if you do not know the state of all threads in your process, it is 102 better to call TerminateProcess than ExitProcess" 103 https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */ 104 TerminateProcess(GetCurrentProcess(), exitcode); 105 /* MingW doesn't have TerminateProcess marked as noreturn, so add an 106 ExitProcess here that will never be reached but make MingW happy. */ 107 ExitProcess(exitcode); 108#elif defined(SDL_PLATFORM_EMSCRIPTEN) 109 emscripten_cancel_main_loop(); // this should "kill" the app. 110 emscripten_force_exit(exitcode); // this should "kill" the app. 111 exit(exitcode); 112#elif defined(SDL_PLATFORM_HAIKU) // Haiku has _Exit, but it's not marked noreturn. 113 _exit(exitcode); 114#elif defined(HAVE__EXIT) // Upper case _Exit() 115 _Exit(exitcode); 116#else 117 _exit(exitcode); 118#endif 119} 120 121// App metadata 122 123bool SDL_SetAppMetadata(const char *appname, const char *appversion, const char *appidentifier) 124{ 125 SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, appname); 126 SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, appversion); 127 SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, appidentifier); 128 return true; 129} 130 131static bool SDL_ValidMetadataProperty(const char *name) 132{ 133 if (!name || !*name) { 134 return false; 135 } 136 137 if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0 || 138 SDL_strcmp(name, SDL_PROP_APP_METADATA_VERSION_STRING) == 0 || 139 SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0 || 140 SDL_strcmp(name, SDL_PROP_APP_METADATA_CREATOR_STRING) == 0 || 141 SDL_strcmp(name, SDL_PROP_APP_METADATA_COPYRIGHT_STRING) == 0 || 142 SDL_strcmp(name, SDL_PROP_APP_METADATA_URL_STRING) == 0 || 143 SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) { 144 return true; 145 } 146 return false; 147} 148 149bool SDL_SetAppMetadataProperty(const char *name, const char *value) 150{ 151 CHECK_PARAM(!SDL_ValidMetadataProperty(name)) { 152 return SDL_InvalidParamError("name"); 153 } 154 155 return SDL_SetStringProperty(SDL_GetGlobalProperties(), name, value); 156} 157 158const char *SDL_GetAppMetadataProperty(const char *name) 159{ 160 CHECK_PARAM(!SDL_ValidMetadataProperty(name)) { 161 SDL_InvalidParamError("name"); 162 return NULL; 163 } 164 165 const char *value = NULL; 166 if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) { 167 value = SDL_GetHint(SDL_HINT_APP_NAME); 168 } else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0) { 169 value = SDL_GetHint(SDL_HINT_APP_ID); 170 } 171 if (!value || !*value) { 172 value = SDL_GetStringProperty(SDL_GetGlobalProperties(), name, NULL); 173 } 174 if (!value || !*value) { 175 if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) { 176 value = "SDL Application"; 177 } else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) { 178 value = "application"; 179 } 180 } 181 return value; 182} 183 184 185// The initialized subsystems 186#ifdef SDL_MAIN_NEEDED 187static bool SDL_MainIsReady = false; 188#else 189static bool SDL_MainIsReady = true; 190#endif 191static SDL_ThreadID SDL_MainThreadID = 0; 192static SDL_ThreadID SDL_EventsThreadID = 0; 193static SDL_ThreadID SDL_VideoThreadID = 0; 194static bool SDL_bInMainQuit = false; 195static Uint8 SDL_SubsystemRefCount[32]; 196 197// Private helper to increment a subsystem's ref counter. 198static void SDL_IncrementSubsystemRefCount(Uint32 subsystem) 199{ 200 const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 201 SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255)); 202 if (subsystem_index >= 0) { 203 ++SDL_SubsystemRefCount[subsystem_index]; 204 } 205} 206 207// Private helper to decrement a subsystem's ref counter. 208static void SDL_DecrementSubsystemRefCount(Uint32 subsystem) 209{ 210 const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 211 if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] > 0)) { 212 if (SDL_bInMainQuit) { 213 SDL_SubsystemRefCount[subsystem_index] = 0; 214 } else { 215 --SDL_SubsystemRefCount[subsystem_index]; 216 } 217 } 218} 219 220// Private helper to check if a system needs init. 221static bool SDL_ShouldInitSubsystem(Uint32 subsystem) 222{ 223 const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 224 SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255)); 225 return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)); 226} 227 228// Private helper to check if a system needs to be quit. 229static bool SDL_ShouldQuitSubsystem(Uint32 subsystem) 230{ 231 const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 232 if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)) { 233 return false; 234 } 235 236 /* If we're in SDL_Quit, we shut down every subsystem, even if refcount 237 * isn't zero. 238 */ 239 return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit); 240} 241 242#if !defined(SDL_VIDEO_DISABLED) || !defined(SDL_AUDIO_DISABLED) || !defined(SDL_JOYSTICK_DISABLED) 243/* Private helper to either increment's existing ref counter, 244 * or fully init a new subsystem. */ 245static bool SDL_InitOrIncrementSubsystem(Uint32 subsystem) 246{ 247 int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 248 SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255)); 249 if (subsystem_index < 0) { 250 return false; 251 } 252 if (SDL_SubsystemRefCount[subsystem_index] > 0) { 253 ++SDL_SubsystemRefCount[subsystem_index]; 254 return true; 255 } 256 return SDL_InitSubSystem(subsystem); 257} 258#endif // !SDL_VIDEO_DISABLED || !SDL_AUDIO_DISABLED || !SDL_JOYSTICK_DISABLED 259 260void SDL_SetMainReady(void) 261{ 262 SDL_MainIsReady = true; 263 264 if (SDL_MainThreadID == 0) { 265 SDL_MainThreadID = SDL_GetCurrentThreadID(); 266 } 267} 268 269bool SDL_IsMainThread(void) 270{ 271 if (SDL_VideoThreadID) { 272 return (SDL_GetCurrentThreadID() == SDL_VideoThreadID); 273 } 274 if (SDL_EventsThreadID) { 275 return (SDL_GetCurrentThreadID() == SDL_EventsThreadID); 276 } 277 if (SDL_MainThreadID) { 278 return (SDL_GetCurrentThreadID() == SDL_MainThreadID); 279 } 280 return true; 281} 282 283// Initialize all the subsystems that require initialization before threads start 284void SDL_InitMainThread(void) 285{ 286 static bool done_info = false; 287 288 // If we haven't done it by now, mark this as the main thread 289 if (SDL_MainThreadID == 0) { 290 SDL_MainThreadID = SDL_GetCurrentThreadID(); 291 } 292 293 SDL_InitTLSData(); 294 SDL_InitEnvironment(); 295 SDL_InitTicks(); 296 SDL_InitFilesystem(); 297 298 if (!done_info) { 299 const char *value; 300 301 value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING); 302 SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App name: %s", value ? value : "<unspecified>"); 303 value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING); 304 SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App version: %s", value ? value : "<unspecified>"); 305 value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING); 306 SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App ID: %s", value ? value : "<unspecified>"); 307 SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "SDL revision: %s", SDL_REVISION); 308 309 done_info = true; 310 } 311} 312 313static void SDL_QuitMainThread(void) 314{ 315 SDL_QuitFilesystem(); 316 SDL_QuitTicks(); 317 SDL_QuitEnvironment(); 318 SDL_QuitTLSData(); 319} 320 321bool SDL_InitSubSystem(SDL_InitFlags flags) 322{ 323 Uint32 flags_initialized = 0; 324 325 if (!SDL_MainIsReady) { 326 return SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?"); 327 } 328 329 SDL_InitMainThread(); 330 331#ifdef SDL_USE_LIBDBUS 332 SDL_DBus_Init(); 333#endif 334 335#ifdef SDL_PLATFORM_WINDOWS 336 if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) { 337 if (!SDL_HelperWindowCreate()) { 338 goto quit_and_error; 339 } 340 } 341#endif 342 343 // Initialize the event subsystem 344 if (flags & SDL_INIT_EVENTS) { 345 if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) { 346 SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS); 347 348 // Note which thread initialized events 349 // This is the thread which should be pumping events 350 SDL_EventsThreadID = SDL_GetCurrentThreadID(); 351 352 if (!SDL_InitEvents()) { 353 SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS); 354 goto quit_and_error; 355 } 356 } else { 357 SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS); 358 } 359 flags_initialized |= SDL_INIT_EVENTS; 360 } 361 362 // Initialize the video subsystem 363 if (flags & SDL_INIT_VIDEO) { 364#ifndef SDL_VIDEO_DISABLED 365 if (SDL_ShouldInitSubsystem(SDL_INIT_VIDEO)) { 366 // video implies events 367 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 368 goto quit_and_error; 369 } 370 371 SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO); 372 373 // We initialize video on the main thread 374 // On Apple platforms this is a requirement. 375 // On other platforms, this is the definition. 376 SDL_VideoThreadID = SDL_GetCurrentThreadID(); 377#ifdef SDL_PLATFORM_APPLE 378 SDL_assert(SDL_VideoThreadID == SDL_MainThreadID); 379#endif 380 381 if (!SDL_VideoInit(NULL)) { 382 SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); 383 SDL_PushError(); 384 SDL_QuitSubSystem(SDL_INIT_EVENTS); 385 SDL_PopError(); 386 goto quit_and_error; 387 } 388 } else { 389 SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO); 390 } 391 flags_initialized |= SDL_INIT_VIDEO; 392#else 393 SDL_SetError("SDL not built with video support"); 394 goto quit_and_error; 395#endif 396 } 397 398 // Initialize the audio subsystem 399 if (flags & SDL_INIT_AUDIO) { 400#ifndef SDL_AUDIO_DISABLED 401 if (SDL_ShouldInitSubsystem(SDL_INIT_AUDIO)) { 402 // audio implies events 403 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 404 goto quit_and_error; 405 } 406 407 SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO); 408 if (!SDL_InitAudio(NULL)) { 409 SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); 410 SDL_PushError(); 411 SDL_QuitSubSystem(SDL_INIT_EVENTS); 412 SDL_PopError(); 413 goto quit_and_error; 414 } 415 } else { 416 SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO); 417 } 418 flags_initialized |= SDL_INIT_AUDIO; 419#else 420 SDL_SetError("SDL not built with audio support"); 421 goto quit_and_error; 422#endif 423 } 424 425 // Initialize the joystick subsystem 426 if (flags & SDL_INIT_JOYSTICK) { 427#ifndef SDL_JOYSTICK_DISABLED 428 if (SDL_ShouldInitSubsystem(SDL_INIT_JOYSTICK)) { 429 // joystick implies events 430 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 431 goto quit_and_error; 432 } 433 434 SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK); 435 if (!SDL_InitJoysticks()) { 436 SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); 437 SDL_PushError(); 438 SDL_QuitSubSystem(SDL_INIT_EVENTS); 439 SDL_PopError(); 440 goto quit_and_error; 441 } 442 } else { 443 SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK); 444 } 445 flags_initialized |= SDL_INIT_JOYSTICK; 446#else 447 SDL_SetError("SDL not built with joystick support"); 448 goto quit_and_error; 449#endif 450 } 451 452 if (flags & SDL_INIT_GAMEPAD) { 453#ifndef SDL_JOYSTICK_DISABLED 454 if (SDL_ShouldInitSubsystem(SDL_INIT_GAMEPAD)) { 455 // game controller implies joystick 456 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_JOYSTICK)) { 457 goto quit_and_error; 458 } 459 460 SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD); 461 if (!SDL_InitGamepads()) { 462 SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); 463 SDL_PushError(); 464 SDL_QuitSubSystem(SDL_INIT_JOYSTICK); 465 SDL_PopError(); 466 goto quit_and_error; 467 } 468 } else { 469 SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD); 470 } 471 flags_initialized |= SDL_INIT_GAMEPAD; 472#else 473 SDL_SetError("SDL not built with joystick support"); 474 goto quit_and_error; 475#endif 476 } 477 478 // Initialize the haptic subsystem 479 if (flags & SDL_INIT_HAPTIC) { 480#ifndef SDL_HAPTIC_DISABLED 481 if (SDL_ShouldInitSubsystem(SDL_INIT_HAPTIC)) { 482 SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC); 483 if (!SDL_InitHaptics()) { 484 SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC); 485 goto quit_and_error; 486 } 487 } else { 488 SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC); 489 } 490 flags_initialized |= SDL_INIT_HAPTIC; 491#else 492 SDL_SetError("SDL not built with haptic (force feedback) support"); 493 goto quit_and_error; 494#endif 495 } 496 497 // Initialize the sensor subsystem 498 if (flags & SDL_INIT_SENSOR) { 499#ifndef SDL_SENSOR_DISABLED 500 if (SDL_ShouldInitSubsystem(SDL_INIT_SENSOR)) { 501 SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR); 502 if (!SDL_InitSensors()) { 503 SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR); 504 goto quit_and_error; 505 } 506 } else { 507 SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR); 508 } 509 flags_initialized |= SDL_INIT_SENSOR; 510#else 511 SDL_SetError("SDL not built with sensor support"); 512 goto quit_and_error; 513#endif 514 } 515 516 // Initialize the camera subsystem 517 if (flags & SDL_INIT_CAMERA) { 518#ifndef SDL_CAMERA_DISABLED 519 if (SDL_ShouldInitSubsystem(SDL_INIT_CAMERA)) { 520 // camera implies events 521 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 522 goto quit_and_error; 523 } 524 525 SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); 526 if (!SDL_CameraInit(NULL)) { 527 SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); 528 SDL_PushError(); 529 SDL_QuitSubSystem(SDL_INIT_EVENTS); 530 SDL_PopError(); 531 goto quit_and_error; 532 } 533 } else { 534 SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); 535 } 536 flags_initialized |= SDL_INIT_CAMERA; 537#else 538 SDL_SetError("SDL not built with camera support"); 539 goto quit_and_error; 540#endif 541 } 542 543 (void)flags_initialized; // make static analysis happy, since this only gets used in error cases. 544 545 return SDL_ClearError(); 546 547quit_and_error: 548 { 549 SDL_PushError(); 550 SDL_QuitSubSystem(flags_initialized); 551 SDL_PopError(); 552 } 553 return false; 554} 555 556bool SDL_Init(SDL_InitFlags flags) 557{ 558 return SDL_InitSubSystem(flags); 559} 560 561void SDL_QuitSubSystem(SDL_InitFlags flags) 562{ 563 // Shut down requested initialized subsystems 564 565#ifndef SDL_CAMERA_DISABLED 566 if (flags & SDL_INIT_CAMERA) { 567 if (SDL_ShouldQuitSubsystem(SDL_INIT_CAMERA)) { 568 SDL_QuitCamera(); 569 // camera implies events 570 SDL_QuitSubSystem(SDL_INIT_EVENTS); 571 } 572 SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); 573 } 574#endif 575 576#ifndef SDL_SENSOR_DISABLED 577 if (flags & SDL_INIT_SENSOR) { 578 if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) { 579 SDL_QuitSensors(); 580 } 581 SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR); 582 } 583#endif 584 585#ifndef SDL_JOYSTICK_DISABLED 586 if (flags & SDL_INIT_GAMEPAD) { 587 if (SDL_ShouldQuitSubsystem(SDL_INIT_GAMEPAD)) { 588 SDL_QuitGamepads(); 589 // game controller implies joystick 590 SDL_QuitSubSystem(SDL_INIT_JOYSTICK); 591 } 592 SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); 593 } 594 595 if (flags & SDL_INIT_JOYSTICK) { 596 if (SDL_ShouldQuitSubsystem(SDL_INIT_JOYSTICK)) { 597 SDL_QuitJoysticks(); 598 // joystick implies events 599 SDL_QuitSubSystem(SDL_INIT_EVENTS); 600 } 601 SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); 602 } 603#endif 604 605#ifndef SDL_HAPTIC_DISABLED 606 if (flags & SDL_INIT_HAPTIC) { 607 if (SDL_ShouldQuitSubsystem(SDL_INIT_HAPTIC)) { 608 SDL_QuitHaptics(); 609 } 610 SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC); 611 } 612#endif 613 614#ifndef SDL_AUDIO_DISABLED 615 if (flags & SDL_INIT_AUDIO) { 616 if (SDL_ShouldQuitSubsystem(SDL_INIT_AUDIO)) { 617 SDL_QuitAudio(); 618 // audio implies events 619 SDL_QuitSubSystem(SDL_INIT_EVENTS); 620 } 621 SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); 622 } 623#endif 624 625#ifndef SDL_VIDEO_DISABLED 626 if (flags & SDL_INIT_VIDEO) { 627 if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) { 628 SDL_QuitRender(); 629 SDL_VideoQuit(); 630 SDL_VideoThreadID = 0; 631 // video implies events 632 SDL_QuitSubSystem(SDL_INIT_EVENTS); 633 } 634 SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); 635 } 636#endif 637 638 if (flags & SDL_INIT_EVENTS) { 639 if (SDL_ShouldQuitSubsystem(SDL_INIT_EVENTS)) { 640 SDL_QuitEvents(); 641 SDL_EventsThreadID = 0; 642 } 643 SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS); 644 } 645} 646 647Uint32 SDL_WasInit(SDL_InitFlags flags) 648{ 649 int i; 650 int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount); 651 Uint32 initialized = 0; 652 653 // Fast path for checking one flag 654 if (SDL_HasExactlyOneBitSet32(flags)) { 655 int subsystem_index = SDL_MostSignificantBitIndex32(flags); 656 return SDL_SubsystemRefCount[subsystem_index] ? flags : 0; 657 } 658 659 if (!flags) { 660 flags = SDL_INIT_EVERYTHING; 661 } 662 663 num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1); 664 665 // Iterate over each bit in flags, and check the matching subsystem. 666 for (i = 0; i < num_subsystems; ++i) { 667 if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) { 668 initialized |= (1 << i); 669 } 670 671 flags >>= 1; 672 } 673 674 return initialized; 675} 676 677void SDL_Quit(void) 678{ 679 SDL_bInMainQuit = true; 680 681 // Quit all subsystems 682#ifdef SDL_PLATFORM_WINDOWS 683 SDL_HelperWindowDestroy(); 684#endif 685 SDL_QuitSubSystem(SDL_INIT_EVERYTHING); 686 SDL_CleanupTrays(); 687 688#ifdef SDL_USE_LIBDBUS 689 SDL_DBus_Quit(); 690#endif 691 692#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) && !defined(SDL_PLATFORM_EMSCRIPTEN) 693 SDL_Gtk_Quit(); 694#endif 695 696 SDL_QuitTimers(); 697 SDL_QuitAsyncIO(); 698 699 SDL_SetObjectsInvalid(); 700 SDL_AssertionsQuit(); 701 702 SDL_QuitPixelFormatDetails(); 703 704 SDL_QuitCPUInfo(); 705 706 /* Now that every subsystem has been quit, we reset the subsystem refcount 707 * and the list of initialized subsystems. 708 */ 709 SDL_memset(SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount)); 710 711 SDL_QuitLog(); 712 SDL_QuitHints(); 713 SDL_QuitProperties(); 714 715 SDL_QuitMainThread(); 716 717 SDL_bInMainQuit = false; 718} 719 720// Get the library version number 721int SDL_GetVersion(void) 722{ 723 return SDL_VERSION; 724} 725 726// Get the library source revision 727const char *SDL_GetRevision(void) 728{ 729 return SDL_REVISION; 730} 731 732// Get the name of the platform 733const char *SDL_GetPlatform(void) 734{ 735#if defined(SDL_PLATFORM_PRIVATE) 736 return SDL_PLATFORM_PRIVATE_NAME; 737#elif defined(SDL_PLATFORM_AIX) 738 return "AIX"; 739#elif defined(SDL_PLATFORM_ANDROID) 740 return "Android"; 741#elif defined(SDL_PLATFORM_BSDI) 742 return "BSDI"; 743#elif defined(SDL_PLATFORM_EMSCRIPTEN) 744 return "Emscripten"; 745#elif defined(SDL_PLATFORM_FREEBSD) 746 return "FreeBSD"; 747#elif defined(SDL_PLATFORM_HAIKU) 748 return "Haiku"; 749#elif defined(SDL_PLATFORM_HPUX) 750 return "HP-UX"; 751#elif defined(SDL_PLATFORM_IRIX) 752 return "Irix"; 753#elif defined(SDL_PLATFORM_LINUX) 754 return "Linux"; 755#elif defined(__MINT__) 756 return "Atari MiNT"; 757#elif defined(SDL_PLATFORM_MACOS) 758 return "macOS"; 759#elif defined(SDL_PLATFORM_NETBSD) 760 return "NetBSD"; 761#elif defined(SDL_PLATFORM_NGAGE) 762 return "Nokia N-Gage"; 763#elif defined(SDL_PLATFORM_OPENBSD) 764 return "OpenBSD"; 765#elif defined(SDL_PLATFORM_OS2) 766 return "OS/2"; 767#elif defined(SDL_PLATFORM_OSF) 768 return "OSF/1"; 769#elif defined(SDL_PLATFORM_QNXNTO) 770 return "QNX Neutrino"; 771#elif defined(SDL_PLATFORM_RISCOS) 772 return "RISC OS"; 773#elif defined(SDL_PLATFORM_SOLARIS) 774 return "Solaris"; 775#elif defined(SDL_PLATFORM_WIN32) 776 return "Windows"; 777#elif defined(SDL_PLATFORM_WINGDK) 778 return "WinGDK"; 779#elif defined(SDL_PLATFORM_XBOXONE) 780 return "Xbox One"; 781#elif defined(SDL_PLATFORM_XBOXSERIES) 782 return "Xbox Series X|S"; 783#elif defined(SDL_PLATFORM_VISIONOS) 784 return "visionOS"; 785#elif defined(SDL_PLATFORM_IOS) 786 return "iOS"; 787#elif defined(SDL_PLATFORM_TVOS) 788 return "tvOS"; 789#elif defined(SDL_PLATFORM_PS2) 790 return "PlayStation 2"; 791#elif defined(SDL_PLATFORM_PSP) 792 return "PlayStation Portable"; 793#elif defined(SDL_PLATFORM_VITA) 794 return "PlayStation Vita"; 795#elif defined(SDL_PLATFORM_3DS) 796 return "Nintendo 3DS"; 797#elif defined(SDL_PLATFORM_HURD) 798 return "GNU/Hurd"; 799#elif defined(__managarm__) 800 return "Managarm"; 801#else 802 return "Unknown (see SDL_platform.h)"; 803#endif 804} 805 806bool SDL_IsTablet(void) 807{ 808#ifdef SDL_PLATFORM_ANDROID 809 return SDL_IsAndroidTablet(); 810#elif defined(SDL_PLATFORM_IOS) 811 extern bool SDL_IsIPad(void); 812 return SDL_IsIPad(); 813#else 814 return false; 815#endif 816} 817 818bool SDL_IsTV(void) 819{ 820#ifdef SDL_PLATFORM_ANDROID 821 return SDL_IsAndroidTV(); 822#elif defined(SDL_PLATFORM_IOS) 823 extern bool SDL_IsAppleTV(void); 824 return SDL_IsAppleTV(); 825#else 826 return false; 827#endif 828} 829 830static SDL_Sandbox SDL_DetectSandbox(void) 831{ 832#if defined(SDL_PLATFORM_LINUX) 833 if (access("/.flatpak-info", F_OK) == 0) { 834 return SDL_SANDBOX_FLATPAK; 835 } 836 837 /* For Snap, we check multiple variables because they might be set for 838 * unrelated reasons. This is the same thing WebKitGTK does. */ 839 if (SDL_getenv("SNAP") && SDL_getenv("SNAP_NAME") && SDL_getenv("SNAP_REVISION")) { 840 return SDL_SANDBOX_SNAP; 841 } 842 843 if (access("/run/host/container-manager", F_OK) == 0) { 844 return SDL_SANDBOX_UNKNOWN_CONTAINER; 845 } 846 847#elif defined(SDL_PLATFORM_MACOS) 848 if (SDL_getenv("APP_SANDBOX_CONTAINER_ID")) { 849 return SDL_SANDBOX_MACOS; 850 } 851#endif 852 853 return SDL_SANDBOX_NONE; 854} 855 856SDL_Sandbox SDL_GetSandbox(void) 857{ 858 static SDL_Sandbox sandbox; 859 static bool sandbox_initialized; 860 861 if (!sandbox_initialized) { 862 sandbox = SDL_DetectSandbox(); 863 sandbox_initialized = true; 864 } 865 return sandbox; 866} 867 868#ifdef SDL_PLATFORM_WIN32 869 870#if !defined(HAVE_LIBC) && !defined(SDL_STATIC_LIB) 871BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 872{ 873 switch (ul_reason_for_call) { 874 case DLL_PROCESS_ATTACH: 875 case DLL_THREAD_ATTACH: 876 case DLL_THREAD_DETACH: 877 case DLL_PROCESS_DETACH: 878 break; 879 } 880 return TRUE; 881} 882#endif // Building DLL 883 884#endif // defined(SDL_PLATFORM_WIN32) 885[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.