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