Atlas - SDL.c

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