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