Atlas - SDL.c

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