src/SDL.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 07 Aug 2013 12:17:33 -0700
changeset 7591 56550c03824b
parent 7590 5706d7fc10d0
child 7592 063a932a264f
permissions -rw-r--r--
Whoops, forgot to commit this piece.
     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     SDL_ClearHints();
   353     SDL_AssertionsQuit();
   354     SDL_LogResetPriorities();
   355 
   356     /* Now that every subsystem has been quit, we reset the subsystem refcount
   357      * and the list of initialized subsystems.
   358      */
   359     SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
   360 
   361     SDL_bInMainQuit = SDL_FALSE;
   362 }
   363 
   364 /* Get the library version number */
   365 void
   366 SDL_GetVersion(SDL_version * ver)
   367 {
   368     SDL_VERSION(ver);
   369 }
   370 
   371 /* Get the library source revision */
   372 const char *
   373 SDL_GetRevision(void)
   374 {
   375     return SDL_REVISION;
   376 }
   377 
   378 /* Get the library source revision number */
   379 int
   380 SDL_GetRevisionNumber(void)
   381 {
   382     return SDL_REVISION_NUMBER;
   383 }
   384 
   385 /* Get the name of the platform */
   386 const char *
   387 SDL_GetPlatform()
   388 {
   389 #if __AIX__
   390     return "AIX";
   391 #elif __ANDROID__
   392     return "Android";
   393 #elif __BEOS__
   394     return "BeOS";
   395 #elif __BSDI__
   396     return "BSDI";
   397 #elif __DREAMCAST__
   398     return "Dreamcast";
   399 #elif __FREEBSD__
   400     return "FreeBSD";
   401 #elif __HAIKU__
   402     return "Haiku";
   403 #elif __HPUX__
   404     return "HP-UX";
   405 #elif __IRIX__
   406     return "Irix";
   407 #elif __LINUX__
   408     return "Linux";
   409 #elif __MINT__
   410     return "Atari MiNT";
   411 #elif __MACOS__
   412     return "MacOS Classic";
   413 #elif __MACOSX__
   414     return "Mac OS X";
   415 #elif __NETBSD__
   416     return "NetBSD";
   417 #elif __OPENBSD__
   418     return "OpenBSD";
   419 #elif __OS2__
   420     return "OS/2";
   421 #elif __OSF__
   422     return "OSF/1";
   423 #elif __QNXNTO__
   424     return "QNX Neutrino";
   425 #elif __RISCOS__
   426     return "RISC OS";
   427 #elif __SOLARIS__
   428     return "Solaris";
   429 #elif __WIN32__
   430     return "Windows";
   431 #elif __IPHONEOS__
   432     return "iPhone OS";
   433 #elif __PSP__
   434     return "PlayStation Portable";
   435 #else
   436     return "Unknown (see SDL_platform.h)";
   437 #endif
   438 }
   439 
   440 #if defined(__WIN32__)
   441 
   442 #if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL))
   443 /* Need to include DllMain() on Watcom C for some reason.. */
   444 #include "core/windows/SDL_windows.h"
   445 
   446 BOOL APIENTRY
   447 _DllMainCRTStartup(HANDLE hModule,
   448                    DWORD ul_reason_for_call, LPVOID lpReserved)
   449 {
   450     switch (ul_reason_for_call) {
   451     case DLL_PROCESS_ATTACH:
   452     case DLL_THREAD_ATTACH:
   453     case DLL_THREAD_DETACH:
   454     case DLL_PROCESS_DETACH:
   455         break;
   456     }
   457     return TRUE;
   458 }
   459 #endif /* building DLL with Watcom C */
   460 
   461 #endif /* __WIN32__ */
   462 
   463 /* vi: set sts=4 ts=4 sw=4 expandtab: */