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