src/SDL.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 07 Aug 2013 11:14:16 -0700
changeset 7590 5706d7fc10d0
parent 7589 e9a7333d86f0
child 7591 56550c03824b
permissions -rw-r--r--
SDL_Init() is now just a wrapper around SDL_InitSubSystem().
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_config.h"
    22 
    23 /* Initialization code for SDL */
    24 
    25 #include "SDL.h"
    26 #include "SDL_bits.h"
    27 #include "SDL_revision.h"
    28 #include "SDL_assert_c.h"
    29 #include "events/SDL_events_c.h"
    30 #include "haptic/SDL_haptic_c.h"
    31 #include "joystick/SDL_joystick_c.h"
    32 
    33 /* Initialization/Cleanup routines */
    34 #if !SDL_TIMERS_DISABLED
    35 extern int SDL_TimerInit(void);
    36 extern void SDL_TimerQuit(void);
    37 extern void SDL_InitTicks(void);
    38 #endif
    39 #if SDL_VIDEO_DRIVER_WINDOWS
    40 extern int SDL_HelperWindowCreate(void);
    41 extern int SDL_HelperWindowDestroy(void);
    42 #endif
    43 
    44 
    45 /* The initialized subsystems */
    46 #ifdef SDL_MAIN_NEEDED
    47 static SDL_bool SDL_MainIsReady = SDL_FALSE;
    48 #else
    49 static SDL_bool SDL_MainIsReady = SDL_TRUE;
    50 #endif
    51 static SDL_bool SDL_bInMainQuit = SDL_FALSE;
    52 static Uint8 SDL_SubsystemRefCount[ 32 ];
    53 
    54 /* Private helper to increment a subsystem's ref counter. */
    55 static void
    56 SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem)
    57 {
    58     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    59     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
    60     ++SDL_SubsystemRefCount[subsystem_index];
    61 }
    62 
    63 /* Private helper to decrement a subsystem's ref counter. */
    64 static void
    65 SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)
    66 {
    67     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    68     if (SDL_SubsystemRefCount[subsystem_index] > 0) {
    69         --SDL_SubsystemRefCount[subsystem_index];
    70     }
    71 }
    72 
    73 /* Private helper to check if a system needs init. */
    74 static SDL_bool
    75 SDL_PrivateShouldInitSubsystem(Uint32 subsystem)
    76 {
    77     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    78     SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
    79     return (SDL_SubsystemRefCount[subsystem_index] == 0);
    80 }
    81 
    82 /* Private helper to check if a system needs to be quit. */
    83 static SDL_bool
    84 SDL_PrivateShouldQuitSubsystem(Uint32 subsystem) {
    85     int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    86     if (SDL_SubsystemRefCount[subsystem_index] == 0) {
    87       return SDL_FALSE;
    88     }
    89 
    90     /* If we're in SDL_Quit, we shut down every subsystem, even if refcount
    91      * isn't zero.
    92      */
    93     return SDL_SubsystemRefCount[subsystem_index] == 1 || SDL_bInMainQuit;
    94 }
    95 
    96 void
    97 SDL_SetMainReady(void)
    98 {
    99     SDL_MainIsReady = SDL_TRUE;
   100 }
   101 
   102 int
   103 SDL_InitSubSystem(Uint32 flags)
   104 {
   105     if (!SDL_MainIsReady) {
   106         SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?");
   107         return -1;
   108     }
   109 
   110     /* Clear the error message */
   111     SDL_ClearError();
   112 
   113 #if SDL_VIDEO_DRIVER_WINDOWS
   114     if (SDL_HelperWindowCreate() < 0) {
   115         return -1;
   116     }
   117 #endif
   118 
   119 #if !SDL_TIMERS_DISABLED
   120     SDL_InitTicks();
   121 #endif
   122 
   123     if ((flags & SDL_INIT_GAMECONTROLLER)) {
   124         /* game controller implies joystick */
   125         flags |= SDL_INIT_JOYSTICK;
   126     }
   127 
   128     if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
   129         /* video or joystick implies events */
   130         flags |= SDL_INIT_EVENTS;
   131     }
   132 
   133     /* Initialize the event subsystem */
   134     if ((flags & SDL_INIT_EVENTS)) {
   135 #if !SDL_EVENTS_DISABLED
   136         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) {
   137             if (SDL_StartEventLoop() < 0) {
   138                 return (-1);
   139             }
   140             SDL_QuitInit();
   141         }
   142         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS);
   143 #else
   144         return SDL_SetError("SDL not built with events support");
   145 #endif
   146     }
   147 
   148     /* Initialize the timer subsystem */
   149     if ((flags & SDL_INIT_TIMER)){
   150 #if !SDL_TIMERS_DISABLED
   151         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_TIMER)) {
   152             if (SDL_TimerInit() < 0) {
   153                 return (-1);
   154             }
   155         }
   156         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_TIMER);
   157 #else
   158         return SDL_SetError("SDL not built with timer support");
   159 #endif
   160     }
   161 
   162     /* Initialize the video subsystem */
   163     if ((flags & SDL_INIT_VIDEO)){
   164 #if !SDL_VIDEO_DISABLED
   165         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_VIDEO)) {
   166             if (SDL_VideoInit(NULL) < 0) {
   167                 return (-1);
   168             }
   169         }
   170         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_VIDEO);
   171 #else
   172         return SDL_SetError("SDL not built with video support");
   173 #endif
   174     }
   175 
   176     /* Initialize the audio subsystem */
   177     if ((flags & SDL_INIT_AUDIO)){
   178 #if !SDL_AUDIO_DISABLED
   179         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_AUDIO)) {
   180             if (SDL_AudioInit(NULL) < 0) {
   181                 return (-1);
   182             }
   183         }
   184         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_AUDIO);
   185 #else
   186         return SDL_SetError("SDL not built with audio support");
   187 #endif
   188     }
   189 
   190     /* Initialize the joystick subsystem */
   191     if ((flags & SDL_INIT_JOYSTICK)){
   192 #if !SDL_JOYSTICK_DISABLED
   193         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
   194            if (SDL_JoystickInit() < 0) {
   195                return (-1);
   196            }
   197         }
   198         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_JOYSTICK);
   199 #else
   200         return SDL_SetError("SDL not built with joystick support");
   201 #endif
   202     }
   203 
   204     if ((flags & SDL_INIT_GAMECONTROLLER)){
   205 #if !SDL_JOYSTICK_DISABLED
   206         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_GAMECONTROLLER)) {
   207             if (SDL_GameControllerInit() < 0) {
   208                 return (-1);
   209             }
   210         }
   211         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_GAMECONTROLLER);
   212 #else
   213         return SDL_SetError("SDL not built with joystick support");
   214 #endif
   215     }
   216 
   217     /* Initialize the haptic subsystem */
   218     if ((flags & SDL_INIT_HAPTIC)){
   219 #if !SDL_HAPTIC_DISABLED
   220         if (SDL_PrivateShouldInitSubsystem(SDL_INIT_HAPTIC)) {
   221             if (SDL_HapticInit() < 0) {
   222                 return (-1);
   223             }
   224         }
   225         SDL_PrivateSubsystemRefCountIncr(SDL_INIT_HAPTIC);
   226 #else
   227         return SDL_SetError("SDL not built with haptic (force feedback) support");
   228 #endif
   229     }
   230 
   231     return (0);
   232 }
   233 
   234 int
   235 SDL_Init(Uint32 flags)
   236 {
   237     return SDL_InitSubSystem(flags);
   238 }
   239 
   240 void
   241 SDL_QuitSubSystem(Uint32 flags)
   242 {
   243     /* Shut down requested initialized subsystems */
   244 #if !SDL_JOYSTICK_DISABLED
   245     if ((flags & SDL_INIT_GAMECONTROLLER)) {
   246         /* game controller implies joystick */
   247         flags |= SDL_INIT_JOYSTICK;
   248 
   249         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_GAMECONTROLLER)) {
   250             SDL_GameControllerQuit();
   251         }
   252         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_GAMECONTROLLER);
   253     }
   254 
   255     if ((flags & SDL_INIT_JOYSTICK)) {
   256         /* joystick implies events */
   257         flags |= SDL_INIT_EVENTS;
   258 
   259         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
   260             SDL_JoystickQuit();
   261         }
   262         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_JOYSTICK);
   263     }
   264 #endif
   265 
   266 #if !SDL_HAPTIC_DISABLED
   267     if ((flags & SDL_INIT_HAPTIC)) {
   268         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_HAPTIC)) {
   269             SDL_HapticQuit();
   270         }
   271         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_HAPTIC);
   272     }
   273 #endif
   274 
   275 #if !SDL_AUDIO_DISABLED
   276     if ((flags & SDL_INIT_AUDIO)) {
   277         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_AUDIO)) {
   278             SDL_AudioQuit();
   279         }
   280         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_AUDIO);
   281     }
   282 #endif
   283 
   284 #if !SDL_VIDEO_DISABLED
   285     if ((flags & SDL_INIT_VIDEO)) {
   286         /* video implies events */
   287         flags |= SDL_INIT_EVENTS;
   288 
   289         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_VIDEO)) {
   290             SDL_VideoQuit();
   291         }
   292         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_VIDEO);
   293     }
   294 #endif
   295 
   296 #if !SDL_TIMERS_DISABLED
   297     if ((flags & SDL_INIT_TIMER)) {
   298         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_TIMER)) {
   299             SDL_TimerQuit();
   300         }
   301         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_TIMER);
   302     }
   303 #endif
   304 
   305 #if !SDL_EVENTS_DISABLED
   306     if ((flags & SDL_INIT_EVENTS)) {
   307         if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) {
   308             SDL_QuitQuit();
   309             SDL_StopEventLoop();
   310         }
   311         SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS);
   312     }
   313 #endif
   314 }
   315 
   316 Uint32
   317 SDL_WasInit(Uint32 flags)
   318 {
   319     int i;
   320     int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
   321     Uint32 initialized = 0;
   322 
   323     if (!flags) {
   324         flags = SDL_INIT_EVERYTHING;
   325     }
   326 
   327     num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1);
   328 
   329     /* Iterate over each bit in flags, and check the matching subsystem. */
   330     for (i = 0; i < num_subsystems; ++i) {
   331         if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) {
   332             initialized |= (1 << i);
   333         }
   334 
   335         flags >>= 1;
   336     }
   337 
   338     return initialized;
   339 }
   340 
   341 void
   342 SDL_Quit(void)
   343 {
   344     SDL_bInMainQuit = SDL_TRUE;
   345 
   346     /* Quit all subsystems */
   347 #if SDL_VIDEO_DRIVER_WINDOWS
   348     SDL_HelperWindowDestroy();
   349 #endif
   350     SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
   351 
   352     /* Uninstall any parachute signal handlers */
   353     SDL_UninstallParachute();
   354 
   355     SDL_ClearHints();
   356     SDL_AssertionsQuit();
   357     SDL_LogResetPriorities();
   358 
   359     /* Now that every subsystem has been quit, we reset the subsystem refcount
   360      * and the list of initialized subsystems.
   361      */
   362     SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
   363 
   364     SDL_bInMainQuit = SDL_FALSE;
   365 }
   366 
   367 /* Get the library version number */
   368 void
   369 SDL_GetVersion(SDL_version * ver)
   370 {
   371     SDL_VERSION(ver);
   372 }
   373 
   374 /* Get the library source revision */
   375 const char *
   376 SDL_GetRevision(void)
   377 {
   378     return SDL_REVISION;
   379 }
   380 
   381 /* Get the library source revision number */
   382 int
   383 SDL_GetRevisionNumber(void)
   384 {
   385     return SDL_REVISION_NUMBER;
   386 }
   387 
   388 /* Get the name of the platform */
   389 const char *
   390 SDL_GetPlatform()
   391 {
   392 #if __AIX__
   393     return "AIX";
   394 #elif __ANDROID__
   395     return "Android";
   396 #elif __BEOS__
   397     return "BeOS";
   398 #elif __BSDI__
   399     return "BSDI";
   400 #elif __DREAMCAST__
   401     return "Dreamcast";
   402 #elif __FREEBSD__
   403     return "FreeBSD";
   404 #elif __HAIKU__
   405     return "Haiku";
   406 #elif __HPUX__
   407     return "HP-UX";
   408 #elif __IRIX__
   409     return "Irix";
   410 #elif __LINUX__
   411     return "Linux";
   412 #elif __MINT__
   413     return "Atari MiNT";
   414 #elif __MACOS__
   415     return "MacOS Classic";
   416 #elif __MACOSX__
   417     return "Mac OS X";
   418 #elif __NETBSD__
   419     return "NetBSD";
   420 #elif __OPENBSD__
   421     return "OpenBSD";
   422 #elif __OS2__
   423     return "OS/2";
   424 #elif __OSF__
   425     return "OSF/1";
   426 #elif __QNXNTO__
   427     return "QNX Neutrino";
   428 #elif __RISCOS__
   429     return "RISC OS";
   430 #elif __SOLARIS__
   431     return "Solaris";
   432 #elif __WIN32__
   433     return "Windows";
   434 #elif __IPHONEOS__
   435     return "iPhone OS";
   436 #elif __PSP__
   437     return "PlayStation Portable";
   438 #else
   439     return "Unknown (see SDL_platform.h)";
   440 #endif
   441 }
   442 
   443 #if defined(__WIN32__)
   444 
   445 #if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL))
   446 /* Need to include DllMain() on Watcom C for some reason.. */
   447 #include "core/windows/SDL_windows.h"
   448 
   449 BOOL APIENTRY
   450 _DllMainCRTStartup(HANDLE hModule,
   451                    DWORD ul_reason_for_call, LPVOID lpReserved)
   452 {
   453     switch (ul_reason_for_call) {
   454     case DLL_PROCESS_ATTACH:
   455     case DLL_THREAD_ATTACH:
   456     case DLL_THREAD_DETACH:
   457     case DLL_PROCESS_DETACH:
   458         break;
   459     }
   460     return TRUE;
   461 }
   462 #endif /* building DLL with Watcom C */
   463 
   464 #endif /* __WIN32__ */
   465 
   466 /* vi: set sts=4 ts=4 sw=4 expandtab: */