sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

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: */