SDL.c (14905B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> 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 23 #if defined(__WIN32__) 24 #include "core/windows/SDL_windows.h" 25 #elif defined(__OS2__) 26 #include <stdlib.h> /* For _exit() */ 27 #elif !defined(__WINRT__) 28 #include <unistd.h> /* For _exit(), etc. */ 29 #endif 30 #if defined(__OS2__) 31 #include "core/os2/SDL_os2.h" 32 #endif 33 #if SDL_THREAD_OS2 34 #include "thread/os2/SDL_systls_c.h" 35 #endif 36 37 #if defined(__EMSCRIPTEN__) 38 #include <emscripten.h> 39 #endif 40 41 /* Initialization code for SDL */ 42 43 #include "SDL.h" 44 #include "SDL_bits.h" 45 #include "SDL_revision.h" 46 #include "SDL_assert_c.h" 47 #include "events/SDL_events_c.h" 48 #include "haptic/SDL_haptic_c.h" 49 #include "joystick/SDL_joystick_c.h" 50 #include "sensor/SDL_sensor_c.h" 51 52 /* Initialization/Cleanup routines */ 53 #if !SDL_TIMERS_DISABLED 54 # include "timer/SDL_timer_c.h" 55 #endif 56 #if SDL_VIDEO_DRIVER_WINDOWS 57 extern int SDL_HelperWindowCreate(void); 58 extern int SDL_HelperWindowDestroy(void); 59 #endif 60 61 62 /* This is not declared in any header, although it is shared between some 63 parts of SDL, because we don't want anything calling it without an 64 extremely good reason. */ 65 extern SDL_NORETURN void SDL_ExitProcess(int exitcode); 66 SDL_NORETURN void SDL_ExitProcess(int exitcode) 67 { 68 #ifdef __WIN32__ 69 /* "if you do not know the state of all threads in your process, it is 70 better to call TerminateProcess than ExitProcess" 71 https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */ 72 TerminateProcess(GetCurrentProcess(), exitcode); 73 /* MingW doesn't have TerminateProcess marked as noreturn, so add an 74 ExitProcess here that will never be reached but make MingW happy. */ 75 ExitProcess(exitcode); 76 #elif defined(__EMSCRIPTEN__) 77 emscripten_cancel_main_loop(); /* this should "kill" the app. */ 78 emscripten_force_exit(exitcode); /* this should "kill" the app. */ 79 exit(exitcode); 80 #elif defined(__HAIKU__) /* Haiku has _Exit, but it's not marked noreturn. */ 81 _exit(exitcode); 82 #elif defined(HAVE__EXIT) /* Upper case _Exit() */ 83 _Exit(exitcode); 84 #else 85 _exit(exitcode); 86 #endif 87 } 88 89 90 /* The initialized subsystems */ 91 #ifdef SDL_MAIN_NEEDED 92 static SDL_bool SDL_MainIsReady = SDL_FALSE; 93 #else 94 static SDL_bool SDL_MainIsReady = SDL_TRUE; 95 #endif 96 static SDL_bool SDL_bInMainQuit = SDL_FALSE; 97 static Uint8 SDL_SubsystemRefCount[ 32 ]; 98 99 /* Private helper to increment a subsystem's ref counter. */ 100 static void 101 SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem) 102 { 103 int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 104 SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255); 105 ++SDL_SubsystemRefCount[subsystem_index]; 106 } 107 108 /* Private helper to decrement a subsystem's ref counter. */ 109 static void 110 SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem) 111 { 112 int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 113 if (SDL_SubsystemRefCount[subsystem_index] > 0) { 114 --SDL_SubsystemRefCount[subsystem_index]; 115 } 116 } 117 118 /* Private helper to check if a system needs init. */ 119 static SDL_bool 120 SDL_PrivateShouldInitSubsystem(Uint32 subsystem) 121 { 122 int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 123 SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255); 124 return (SDL_SubsystemRefCount[subsystem_index] == 0) ? SDL_TRUE : SDL_FALSE; 125 } 126 127 /* Private helper to check if a system needs to be quit. */ 128 static SDL_bool 129 SDL_PrivateShouldQuitSubsystem(Uint32 subsystem) { 130 int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); 131 if (SDL_SubsystemRefCount[subsystem_index] == 0) { 132 return SDL_FALSE; 133 } 134 135 /* If we're in SDL_Quit, we shut down every subsystem, even if refcount 136 * isn't zero. 137 */ 138 return (SDL_SubsystemRefCount[subsystem_index] == 1 || SDL_bInMainQuit) ? SDL_TRUE : SDL_FALSE; 139 } 140 141 void 142 SDL_SetMainReady(void) 143 { 144 SDL_MainIsReady = SDL_TRUE; 145 } 146 147 int 148 SDL_InitSubSystem(Uint32 flags) 149 { 150 if (!SDL_MainIsReady) { 151 SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?"); 152 return -1; 153 } 154 155 /* Clear the error message */ 156 SDL_ClearError(); 157 158 if ((flags & SDL_INIT_GAMECONTROLLER)) { 159 /* game controller implies joystick */ 160 flags |= SDL_INIT_JOYSTICK; 161 } 162 163 if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) { 164 /* video or joystick implies events */ 165 flags |= SDL_INIT_EVENTS; 166 } 167 168 #if SDL_THREAD_OS2 169 SDL_OS2TLSAlloc(); /* thread/os2/SDL_systls.c */ 170 #endif 171 172 #if SDL_VIDEO_DRIVER_WINDOWS 173 if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) { 174 if (SDL_HelperWindowCreate() < 0) { 175 return -1; 176 } 177 } 178 #endif 179 180 #if !SDL_TIMERS_DISABLED 181 SDL_TicksInit(); 182 #endif 183 184 /* Initialize the event subsystem */ 185 if ((flags & SDL_INIT_EVENTS)) { 186 #if !SDL_EVENTS_DISABLED 187 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) { 188 if (SDL_EventsInit() < 0) { 189 return (-1); 190 } 191 } 192 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS); 193 #else 194 return SDL_SetError("SDL not built with events support"); 195 #endif 196 } 197 198 /* Initialize the timer subsystem */ 199 if ((flags & SDL_INIT_TIMER)){ 200 #if !SDL_TIMERS_DISABLED 201 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_TIMER)) { 202 if (SDL_TimerInit() < 0) { 203 return (-1); 204 } 205 } 206 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_TIMER); 207 #else 208 return SDL_SetError("SDL not built with timer support"); 209 #endif 210 } 211 212 /* Initialize the video subsystem */ 213 if ((flags & SDL_INIT_VIDEO)){ 214 #if !SDL_VIDEO_DISABLED 215 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_VIDEO)) { 216 if (SDL_VideoInit(NULL) < 0) { 217 return (-1); 218 } 219 } 220 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_VIDEO); 221 #else 222 return SDL_SetError("SDL not built with video support"); 223 #endif 224 } 225 226 /* Initialize the audio subsystem */ 227 if ((flags & SDL_INIT_AUDIO)){ 228 #if !SDL_AUDIO_DISABLED 229 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_AUDIO)) { 230 if (SDL_AudioInit(NULL) < 0) { 231 return (-1); 232 } 233 } 234 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_AUDIO); 235 #else 236 return SDL_SetError("SDL not built with audio support"); 237 #endif 238 } 239 240 /* Initialize the joystick subsystem */ 241 if ((flags & SDL_INIT_JOYSTICK)){ 242 #if !SDL_JOYSTICK_DISABLED 243 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_JOYSTICK)) { 244 if (SDL_JoystickInit() < 0) { 245 return (-1); 246 } 247 } 248 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_JOYSTICK); 249 #else 250 return SDL_SetError("SDL not built with joystick support"); 251 #endif 252 } 253 254 if ((flags & SDL_INIT_GAMECONTROLLER)){ 255 #if !SDL_JOYSTICK_DISABLED 256 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_GAMECONTROLLER)) { 257 if (SDL_GameControllerInit() < 0) { 258 return (-1); 259 } 260 } 261 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_GAMECONTROLLER); 262 #else 263 return SDL_SetError("SDL not built with joystick support"); 264 #endif 265 } 266 267 /* Initialize the haptic subsystem */ 268 if ((flags & SDL_INIT_HAPTIC)){ 269 #if !SDL_HAPTIC_DISABLED 270 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_HAPTIC)) { 271 if (SDL_HapticInit() < 0) { 272 return (-1); 273 } 274 } 275 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_HAPTIC); 276 #else 277 return SDL_SetError("SDL not built with haptic (force feedback) support"); 278 #endif 279 } 280 281 /* Initialize the sensor subsystem */ 282 if ((flags & SDL_INIT_SENSOR)){ 283 #if !SDL_SENSOR_DISABLED 284 if (SDL_PrivateShouldInitSubsystem(SDL_INIT_SENSOR)) { 285 if (SDL_SensorInit() < 0) { 286 return (-1); 287 } 288 } 289 SDL_PrivateSubsystemRefCountIncr(SDL_INIT_SENSOR); 290 #else 291 return SDL_SetError("SDL not built with sensor support"); 292 #endif 293 } 294 295 return (0); 296 } 297 298 int 299 SDL_Init(Uint32 flags) 300 { 301 return SDL_InitSubSystem(flags); 302 } 303 304 void 305 SDL_QuitSubSystem(Uint32 flags) 306 { 307 #if SDL_THREAD_OS2 308 SDL_OS2TLSFree(); /* thread/os2/SDL_systls.c */ 309 #endif 310 #if defined(__OS2__) 311 SDL_OS2Quit(); 312 #endif 313 314 /* Shut down requested initialized subsystems */ 315 #if !SDL_SENSOR_DISABLED 316 if ((flags & SDL_INIT_SENSOR)) { 317 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_SENSOR)) { 318 SDL_SensorQuit(); 319 } 320 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_SENSOR); 321 } 322 #endif 323 324 #if !SDL_JOYSTICK_DISABLED 325 if ((flags & SDL_INIT_GAMECONTROLLER)) { 326 /* game controller implies joystick */ 327 flags |= SDL_INIT_JOYSTICK; 328 329 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_GAMECONTROLLER)) { 330 SDL_GameControllerQuit(); 331 } 332 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_GAMECONTROLLER); 333 } 334 335 if ((flags & SDL_INIT_JOYSTICK)) { 336 /* joystick implies events */ 337 flags |= SDL_INIT_EVENTS; 338 339 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_JOYSTICK)) { 340 SDL_JoystickQuit(); 341 } 342 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_JOYSTICK); 343 } 344 #endif 345 346 #if !SDL_HAPTIC_DISABLED 347 if ((flags & SDL_INIT_HAPTIC)) { 348 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_HAPTIC)) { 349 SDL_HapticQuit(); 350 } 351 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_HAPTIC); 352 } 353 #endif 354 355 #if !SDL_AUDIO_DISABLED 356 if ((flags & SDL_INIT_AUDIO)) { 357 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_AUDIO)) { 358 SDL_AudioQuit(); 359 } 360 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_AUDIO); 361 } 362 #endif 363 364 #if !SDL_VIDEO_DISABLED 365 if ((flags & SDL_INIT_VIDEO)) { 366 /* video implies events */ 367 flags |= SDL_INIT_EVENTS; 368 369 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_VIDEO)) { 370 SDL_VideoQuit(); 371 } 372 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_VIDEO); 373 } 374 #endif 375 376 #if !SDL_TIMERS_DISABLED 377 if ((flags & SDL_INIT_TIMER)) { 378 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_TIMER)) { 379 SDL_TimerQuit(); 380 } 381 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_TIMER); 382 } 383 #endif 384 385 #if !SDL_EVENTS_DISABLED 386 if ((flags & SDL_INIT_EVENTS)) { 387 if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) { 388 SDL_EventsQuit(); 389 } 390 SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS); 391 } 392 #endif 393 } 394 395 Uint32 396 SDL_WasInit(Uint32 flags) 397 { 398 int i; 399 int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount); 400 Uint32 initialized = 0; 401 402 /* Fast path for checking one flag */ 403 if (SDL_HasExactlyOneBitSet32(flags)) { 404 int subsystem_index = SDL_MostSignificantBitIndex32(flags); 405 return SDL_SubsystemRefCount[subsystem_index] ? flags : 0; 406 } 407 408 if (!flags) { 409 flags = SDL_INIT_EVERYTHING; 410 } 411 412 num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1); 413 414 /* Iterate over each bit in flags, and check the matching subsystem. */ 415 for (i = 0; i < num_subsystems; ++i) { 416 if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) { 417 initialized |= (1 << i); 418 } 419 420 flags >>= 1; 421 } 422 423 return initialized; 424 } 425 426 void 427 SDL_Quit(void) 428 { 429 SDL_bInMainQuit = SDL_TRUE; 430 431 /* Quit all subsystems */ 432 #if SDL_VIDEO_DRIVER_WINDOWS 433 SDL_HelperWindowDestroy(); 434 #endif 435 SDL_QuitSubSystem(SDL_INIT_EVERYTHING); 436 437 #if !SDL_TIMERS_DISABLED 438 SDL_TicksQuit(); 439 #endif 440 441 SDL_ClearHints(); 442 SDL_AssertionsQuit(); 443 SDL_LogResetPriorities(); 444 445 /* Now that every subsystem has been quit, we reset the subsystem refcount 446 * and the list of initialized subsystems. 447 */ 448 SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) ); 449 450 SDL_bInMainQuit = SDL_FALSE; 451 } 452 453 /* Get the library version number */ 454 void 455 SDL_GetVersion(SDL_version * ver) 456 { 457 SDL_VERSION(ver); 458 } 459 460 /* Get the library source revision */ 461 const char * 462 SDL_GetRevision(void) 463 { 464 return SDL_REVISION; 465 } 466 467 /* Get the library source revision number */ 468 int 469 SDL_GetRevisionNumber(void) 470 { 471 return SDL_REVISION_NUMBER; 472 } 473 474 /* Get the name of the platform */ 475 const char * 476 SDL_GetPlatform() 477 { 478 #if __AIX__ 479 return "AIX"; 480 #elif __ANDROID__ 481 return "Android"; 482 #elif __BSDI__ 483 return "BSDI"; 484 #elif __DREAMCAST__ 485 return "Dreamcast"; 486 #elif __EMSCRIPTEN__ 487 return "Emscripten"; 488 #elif __FREEBSD__ 489 return "FreeBSD"; 490 #elif __HAIKU__ 491 return "Haiku"; 492 #elif __HPUX__ 493 return "HP-UX"; 494 #elif __IRIX__ 495 return "Irix"; 496 #elif __LINUX__ 497 return "Linux"; 498 #elif __MINT__ 499 return "Atari MiNT"; 500 #elif __MACOS__ 501 return "MacOS Classic"; 502 #elif __MACOSX__ 503 return "Mac OS X"; 504 #elif __NACL__ 505 return "NaCl"; 506 #elif __NETBSD__ 507 return "NetBSD"; 508 #elif __OPENBSD__ 509 return "OpenBSD"; 510 #elif __OS2__ 511 return "OS/2"; 512 #elif __OSF__ 513 return "OSF/1"; 514 #elif __QNXNTO__ 515 return "QNX Neutrino"; 516 #elif __RISCOS__ 517 return "RISC OS"; 518 #elif __SOLARIS__ 519 return "Solaris"; 520 #elif __WIN32__ 521 return "Windows"; 522 #elif __WINRT__ 523 return "WinRT"; 524 #elif __TVOS__ 525 return "tvOS"; 526 #elif __IPHONEOS__ 527 return "iOS"; 528 #elif __PSP__ 529 return "PlayStation Portable"; 530 #else 531 return "Unknown (see SDL_platform.h)"; 532 #endif 533 } 534 535 SDL_bool 536 SDL_IsTablet() 537 { 538 #if __ANDROID__ 539 extern SDL_bool SDL_IsAndroidTablet(void); 540 return SDL_IsAndroidTablet(); 541 #elif __IPHONEOS__ 542 extern SDL_bool SDL_IsIPad(void); 543 return SDL_IsIPad(); 544 #else 545 return SDL_FALSE; 546 #endif 547 } 548 549 #if defined(__WIN32__) 550 551 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB) 552 /* Need to include DllMain() on Watcom C for some reason.. */ 553 554 BOOL APIENTRY 555 _DllMainCRTStartup(HANDLE hModule, 556 DWORD ul_reason_for_call, LPVOID lpReserved) 557 { 558 switch (ul_reason_for_call) { 559 case DLL_PROCESS_ATTACH: 560 case DLL_THREAD_ATTACH: 561 case DLL_THREAD_DETACH: 562 case DLL_PROCESS_DETACH: 563 break; 564 } 565 return TRUE; 566 } 567 #endif /* Building DLL */ 568 569 #endif /* __WIN32__ */ 570 571 /* vi: set sts=4 ts=4 sw=4 expandtab: */