Atlas - SDL.c

Home / ext / SDL / src Lines: 1 | Size: 27689 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#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#ifdef SDL_PLATFORM_EMSCRIPTEN 330 MAIN_THREAD_EM_ASM({ 331 // make sure this generic table to hang SDL-specific Javascript stuff is available at init time. 332 if (typeof(Module['SDL3']) === 'undefined') { 333 Module['SDL3'] = {}; 334 } 335 336 var SDL3 = Module['SDL3']; 337 #if defined(__wasm32__) 338 if (typeof(SDL3.JSVarToCPtr) === 'undefined') { SDL3.JSVarToCPtr = function(v) { return v; }; } 339 if (typeof(SDL3.CPtrToHeap32Index) === 'undefined') { SDL3.CPtrToHeap32Index = function(ptr) { return ptr >>> 2; }; } 340 #elif defined(__wasm64__) 341 if (typeof(SDL3.JSVarToCPtr) === 'undefined') { SDL3.JSVarToCPtr = function(v) { return BigInt(v); }; } 342 if (typeof(SDL3.CPtrToHeap32Index) === 'undefined') { SDL3.CPtrToHeap32Index = function(ptr) { return Number(ptr / 4n); }; } 343 #else 344 #error Please define your platform. 345 #endif 346 }); 347#endif 348 349 SDL_InitMainThread(); 350 351#ifdef SDL_USE_LIBDBUS 352 SDL_DBus_Init(); 353#endif 354 355#ifdef SDL_PLATFORM_WINDOWS 356 if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) { 357 if (!SDL_HelperWindowCreate()) { 358 goto quit_and_error; 359 } 360 } 361#endif 362 363 // Initialize the event subsystem 364 if (flags & SDL_INIT_EVENTS) { 365 if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) { 366 SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS); 367 368 // Note which thread initialized events 369 // This is the thread which should be pumping events 370 SDL_EventsThreadID = SDL_GetCurrentThreadID(); 371 372 if (!SDL_InitEvents()) { 373 SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS); 374 goto quit_and_error; 375 } 376 } else { 377 SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS); 378 } 379 flags_initialized |= SDL_INIT_EVENTS; 380 } 381 382 // Initialize the video subsystem 383 if (flags & SDL_INIT_VIDEO) { 384#ifndef SDL_VIDEO_DISABLED 385 if (SDL_ShouldInitSubsystem(SDL_INIT_VIDEO)) { 386 // video implies events 387 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 388 goto quit_and_error; 389 } 390 391 SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO); 392 393 // We initialize video on the main thread 394 // On Apple platforms this is a requirement. 395 // On other platforms, this is the definition. 396 SDL_VideoThreadID = SDL_GetCurrentThreadID(); 397#ifdef SDL_PLATFORM_APPLE 398 SDL_assert(SDL_VideoThreadID == SDL_MainThreadID); 399#endif 400 401 if (!SDL_VideoInit(NULL)) { 402 SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); 403 SDL_PushError(); 404 SDL_QuitSubSystem(SDL_INIT_EVENTS); 405 SDL_PopError(); 406 goto quit_and_error; 407 } 408 } else { 409 SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO); 410 } 411 flags_initialized |= SDL_INIT_VIDEO; 412#else 413 SDL_SetError("SDL not built with video support"); 414 goto quit_and_error; 415#endif 416 } 417 418 // Initialize the audio subsystem 419 if (flags & SDL_INIT_AUDIO) { 420#ifndef SDL_AUDIO_DISABLED 421 if (SDL_ShouldInitSubsystem(SDL_INIT_AUDIO)) { 422 // audio implies events 423 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 424 goto quit_and_error; 425 } 426 427 SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO); 428 if (!SDL_InitAudio(NULL)) { 429 SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); 430 SDL_PushError(); 431 SDL_QuitSubSystem(SDL_INIT_EVENTS); 432 SDL_PopError(); 433 goto quit_and_error; 434 } 435 } else { 436 SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO); 437 } 438 flags_initialized |= SDL_INIT_AUDIO; 439#else 440 SDL_SetError("SDL not built with audio support"); 441 goto quit_and_error; 442#endif 443 } 444 445 // Initialize the joystick subsystem 446 if (flags & SDL_INIT_JOYSTICK) { 447#ifndef SDL_JOYSTICK_DISABLED 448 if (SDL_ShouldInitSubsystem(SDL_INIT_JOYSTICK)) { 449 // joystick implies events 450 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 451 goto quit_and_error; 452 } 453 454 SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK); 455 if (!SDL_InitJoysticks()) { 456 SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); 457 SDL_PushError(); 458 SDL_QuitSubSystem(SDL_INIT_EVENTS); 459 SDL_PopError(); 460 goto quit_and_error; 461 } 462 } else { 463 SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK); 464 } 465 flags_initialized |= SDL_INIT_JOYSTICK; 466#else 467 SDL_SetError("SDL not built with joystick support"); 468 goto quit_and_error; 469#endif 470 } 471 472 if (flags & SDL_INIT_GAMEPAD) { 473#ifndef SDL_JOYSTICK_DISABLED 474 if (SDL_ShouldInitSubsystem(SDL_INIT_GAMEPAD)) { 475 // game controller implies joystick 476 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_JOYSTICK)) { 477 goto quit_and_error; 478 } 479 480 SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD); 481 if (!SDL_InitGamepads()) { 482 SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); 483 SDL_PushError(); 484 SDL_QuitSubSystem(SDL_INIT_JOYSTICK); 485 SDL_PopError(); 486 goto quit_and_error; 487 } 488 } else { 489 SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD); 490 } 491 flags_initialized |= SDL_INIT_GAMEPAD; 492#else 493 SDL_SetError("SDL not built with joystick support"); 494 goto quit_and_error; 495#endif 496 } 497 498 // Initialize the haptic subsystem 499 if (flags & SDL_INIT_HAPTIC) { 500#ifndef SDL_HAPTIC_DISABLED 501 if (SDL_ShouldInitSubsystem(SDL_INIT_HAPTIC)) { 502 SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC); 503 if (!SDL_InitHaptics()) { 504 SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC); 505 goto quit_and_error; 506 } 507 } else { 508 SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC); 509 } 510 flags_initialized |= SDL_INIT_HAPTIC; 511#else 512 SDL_SetError("SDL not built with haptic (force feedback) support"); 513 goto quit_and_error; 514#endif 515 } 516 517 // Initialize the sensor subsystem 518 if (flags & SDL_INIT_SENSOR) { 519#ifndef SDL_SENSOR_DISABLED 520 if (SDL_ShouldInitSubsystem(SDL_INIT_SENSOR)) { 521 SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR); 522 if (!SDL_InitSensors()) { 523 SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR); 524 goto quit_and_error; 525 } 526 } else { 527 SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR); 528 } 529 flags_initialized |= SDL_INIT_SENSOR; 530#else 531 SDL_SetError("SDL not built with sensor support"); 532 goto quit_and_error; 533#endif 534 } 535 536 // Initialize the camera subsystem 537 if (flags & SDL_INIT_CAMERA) { 538#ifndef SDL_CAMERA_DISABLED 539 if (SDL_ShouldInitSubsystem(SDL_INIT_CAMERA)) { 540 // camera implies events 541 if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { 542 goto quit_and_error; 543 } 544 545 SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); 546 if (!SDL_CameraInit(NULL)) { 547 SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); 548 SDL_PushError(); 549 SDL_QuitSubSystem(SDL_INIT_EVENTS); 550 SDL_PopError(); 551 goto quit_and_error; 552 } 553 } else { 554 SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); 555 } 556 flags_initialized |= SDL_INIT_CAMERA; 557#else 558 SDL_SetError("SDL not built with camera support"); 559 goto quit_and_error; 560#endif 561 } 562 563 (void)flags_initialized; // make static analysis happy, since this only gets used in error cases. 564 565 return SDL_ClearError(); 566 567quit_and_error: 568 { 569 SDL_PushError(); 570 SDL_QuitSubSystem(flags_initialized); 571 SDL_PopError(); 572 } 573 return false; 574} 575 576bool SDL_Init(SDL_InitFlags flags) 577{ 578 return SDL_InitSubSystem(flags); 579} 580 581void SDL_QuitSubSystem(SDL_InitFlags flags) 582{ 583 // Shut down requested initialized subsystems 584 585#ifndef SDL_CAMERA_DISABLED 586 if (flags & SDL_INIT_CAMERA) { 587 if (SDL_ShouldQuitSubsystem(SDL_INIT_CAMERA)) { 588 SDL_QuitCamera(); 589 // camera implies events 590 SDL_QuitSubSystem(SDL_INIT_EVENTS); 591 } 592 SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); 593 } 594#endif 595 596#ifndef SDL_SENSOR_DISABLED 597 if (flags & SDL_INIT_SENSOR) { 598 if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) { 599 SDL_QuitSensors(); 600 } 601 SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR); 602 } 603#endif 604 605#ifndef SDL_JOYSTICK_DISABLED 606 if (flags & SDL_INIT_GAMEPAD) { 607 if (SDL_ShouldQuitSubsystem(SDL_INIT_GAMEPAD)) { 608 SDL_QuitGamepads(); 609 // game controller implies joystick 610 SDL_QuitSubSystem(SDL_INIT_JOYSTICK); 611 } 612 SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); 613 } 614 615 if (flags & SDL_INIT_JOYSTICK) { 616 if (SDL_ShouldQuitSubsystem(SDL_INIT_JOYSTICK)) { 617 SDL_QuitJoysticks(); 618 // joystick implies events 619 SDL_QuitSubSystem(SDL_INIT_EVENTS); 620 } 621 SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); 622 } 623#endif 624 625#ifndef SDL_HAPTIC_DISABLED 626 if (flags & SDL_INIT_HAPTIC) { 627 if (SDL_ShouldQuitSubsystem(SDL_INIT_HAPTIC)) { 628 SDL_QuitHaptics(); 629 } 630 SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC); 631 } 632#endif 633 634#ifndef SDL_AUDIO_DISABLED 635 if (flags & SDL_INIT_AUDIO) { 636 if (SDL_ShouldQuitSubsystem(SDL_INIT_AUDIO)) { 637 SDL_QuitAudio(); 638 // audio implies events 639 SDL_QuitSubSystem(SDL_INIT_EVENTS); 640 } 641 SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); 642 } 643#endif 644 645#ifndef SDL_VIDEO_DISABLED 646 if (flags & SDL_INIT_VIDEO) { 647 if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) { 648 SDL_QuitRender(); 649 SDL_VideoQuit(); 650 SDL_VideoThreadID = 0; 651 // video implies events 652 SDL_QuitSubSystem(SDL_INIT_EVENTS); 653 } 654 SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); 655 } 656#endif 657 658 if (flags & SDL_INIT_EVENTS) { 659 if (SDL_ShouldQuitSubsystem(SDL_INIT_EVENTS)) { 660 SDL_QuitEvents(); 661 SDL_EventsThreadID = 0; 662 } 663 SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS); 664 } 665} 666 667Uint32 SDL_WasInit(SDL_InitFlags flags) 668{ 669 int i; 670 int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount); 671 Uint32 initialized = 0; 672 673 // Fast path for checking one flag 674 if (SDL_HasExactlyOneBitSet32(flags)) { 675 int subsystem_index = SDL_MostSignificantBitIndex32(flags); 676 return SDL_SubsystemRefCount[subsystem_index] ? flags : 0; 677 } 678 679 if (!flags) { 680 flags = SDL_INIT_EVERYTHING; 681 } 682 683 num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1); 684 685 // Iterate over each bit in flags, and check the matching subsystem. 686 for (i = 0; i < num_subsystems; ++i) { 687 if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) { 688 initialized |= (1 << i); 689 } 690 691 flags >>= 1; 692 } 693 694 return initialized; 695} 696 697void SDL_Quit(void) 698{ 699 SDL_bInMainQuit = true; 700 701 // Quit all subsystems 702#ifdef SDL_PLATFORM_WINDOWS 703 SDL_HelperWindowDestroy(); 704#endif 705 SDL_QuitSubSystem(SDL_INIT_EVERYTHING); 706 SDL_CleanupTrays(); 707 708#ifdef SDL_USE_LIBDBUS 709 SDL_DBus_Quit(); 710#endif 711 712#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) && !defined(SDL_PLATFORM_EMSCRIPTEN) && !defined(SDL_PLATFORM_PRIVATE) 713 SDL_Gtk_Quit(); 714#endif 715 716 SDL_QuitTimers(); 717 SDL_QuitAsyncIO(); 718 719 SDL_SetObjectsInvalid(); 720 SDL_AssertionsQuit(); 721 722 SDL_QuitPixelFormatDetails(); 723 724 SDL_QuitCPUInfo(); 725 726 /* Now that every subsystem has been quit, we reset the subsystem refcount 727 * and the list of initialized subsystems. 728 */ 729 SDL_zeroa(SDL_SubsystemRefCount); 730 731 SDL_QuitLog(); 732 SDL_QuitHints(); 733 SDL_QuitProperties(); 734 735 SDL_QuitMainThread(); 736 737 SDL_bInMainQuit = false; 738} 739 740// Get the library version number 741int SDL_GetVersion(void) 742{ 743 return SDL_VERSION; 744} 745 746// Get the library source revision 747const char *SDL_GetRevision(void) 748{ 749 return SDL_REVISION; 750} 751 752// Get the name of the platform 753const char *SDL_GetPlatform(void) 754{ 755#if defined(SDL_PLATFORM_PRIVATE) 756 return SDL_PLATFORM_PRIVATE_NAME; 757#elif defined(SDL_PLATFORM_AIX) 758 return "AIX"; 759#elif defined(SDL_PLATFORM_ANDROID) 760 return "Android"; 761#elif defined(SDL_PLATFORM_BSDI) 762 return "BSDI"; 763#elif defined(SDL_PLATFORM_EMSCRIPTEN) 764 return "Emscripten"; 765#elif defined(SDL_PLATFORM_FREEBSD) 766 return "FreeBSD"; 767#elif defined(SDL_PLATFORM_HAIKU) 768 return "Haiku"; 769#elif defined(SDL_PLATFORM_HPUX) 770 return "HP-UX"; 771#elif defined(SDL_PLATFORM_IRIX) 772 return "Irix"; 773#elif defined(SDL_PLATFORM_LINUX) 774 return "Linux"; 775#elif defined(__MINT__) 776 return "Atari MiNT"; 777#elif defined(SDL_PLATFORM_MACOS) 778 return "macOS"; 779#elif defined(SDL_PLATFORM_NETBSD) 780 return "NetBSD"; 781#elif defined(SDL_PLATFORM_NGAGE) 782 return "Nokia N-Gage"; 783#elif defined(SDL_PLATFORM_OPENBSD) 784 return "OpenBSD"; 785#elif defined(SDL_PLATFORM_OS2) 786 return "OS/2"; 787#elif defined(SDL_PLATFORM_OSF) 788 return "OSF/1"; 789#elif defined(SDL_PLATFORM_QNXNTO) 790 return "QNX Neutrino"; 791#elif defined(SDL_PLATFORM_RISCOS) 792 return "RISC OS"; 793#elif defined(SDL_PLATFORM_SOLARIS) 794 return "Solaris"; 795#elif defined(SDL_PLATFORM_WIN32) 796 return "Windows"; 797#elif defined(SDL_PLATFORM_WINGDK) 798 return "WinGDK"; 799#elif defined(SDL_PLATFORM_XBOXONE) 800 return "Xbox One"; 801#elif defined(SDL_PLATFORM_XBOXSERIES) 802 return "Xbox Series X|S"; 803#elif defined(SDL_PLATFORM_VISIONOS) 804 return "visionOS"; 805#elif defined(SDL_PLATFORM_IOS) 806 return "iOS"; 807#elif defined(SDL_PLATFORM_TVOS) 808 return "tvOS"; 809#elif defined(SDL_PLATFORM_PS2) 810 return "PlayStation 2"; 811#elif defined(SDL_PLATFORM_PSP) 812 return "PlayStation Portable"; 813#elif defined(SDL_PLATFORM_VITA) 814 return "PlayStation Vita"; 815#elif defined(SDL_PLATFORM_3DS) 816 return "Nintendo 3DS"; 817#elif defined(SDL_PLATFORM_HURD) 818 return "GNU/Hurd"; 819#elif defined(__managarm__) 820 return "Managarm"; 821#else 822 return "Unknown (see SDL_platform.h)"; 823#endif 824} 825 826bool SDL_IsTablet(void) 827{ 828#ifdef SDL_PLATFORM_ANDROID 829 return SDL_IsAndroidTablet(); 830#elif defined(SDL_PLATFORM_IOS) 831 extern bool SDL_IsIPad(void); 832 return SDL_IsIPad(); 833#else 834 return false; 835#endif 836} 837 838bool SDL_IsTV(void) 839{ 840#ifdef SDL_PLATFORM_ANDROID 841 return SDL_IsAndroidTV(); 842#elif defined(SDL_PLATFORM_IOS) 843 extern bool SDL_IsAppleTV(void); 844 return SDL_IsAppleTV(); 845#else 846 return false; 847#endif 848} 849 850static SDL_Sandbox SDL_DetectSandbox(void) 851{ 852#if defined(SDL_PLATFORM_LINUX) 853 if (access("/.flatpak-info", F_OK) == 0) { 854 return SDL_SANDBOX_FLATPAK; 855 } 856 857 /* For Snap, we check multiple variables because they might be set for 858 * unrelated reasons. This is the same thing WebKitGTK does. */ 859 if (SDL_getenv("SNAP") && SDL_getenv("SNAP_NAME") && SDL_getenv("SNAP_REVISION")) { 860 return SDL_SANDBOX_SNAP; 861 } 862 863 if (access("/run/host/container-manager", F_OK) == 0) { 864 return SDL_SANDBOX_UNKNOWN_CONTAINER; 865 } 866 867#elif defined(SDL_PLATFORM_MACOS) 868 if (SDL_getenv("APP_SANDBOX_CONTAINER_ID")) { 869 return SDL_SANDBOX_MACOS; 870 } 871#endif 872 873 return SDL_SANDBOX_NONE; 874} 875 876SDL_Sandbox SDL_GetSandbox(void) 877{ 878 static SDL_Sandbox sandbox; 879 static bool sandbox_initialized; 880 881 if (!sandbox_initialized) { 882 sandbox = SDL_DetectSandbox(); 883 sandbox_initialized = true; 884 } 885 return sandbox; 886} 887 888#ifdef SDL_PLATFORM_WIN32 889 890#if !defined(HAVE_LIBC) && !defined(SDL_STATIC_LIB) 891BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 892{ 893 switch (ul_reason_for_call) { 894 case DLL_PROCESS_ATTACH: 895 case DLL_THREAD_ATTACH: 896 case DLL_THREAD_DETACH: 897 case DLL_PROCESS_DETACH: 898 break; 899 } 900 return TRUE; 901} 902#endif // Building DLL 903 904#endif // defined(SDL_PLATFORM_WIN32) 905
[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.