src/SDL.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 05 Jun 2013 21:23:59 -0700
changeset 7281 cd5516b9263d
parent 7191 75360622e65f
child 7346 ff228f955a48
permissions -rw-r--r--
Added some extra protection to notify the developer if they haven't initialized the application properly.

This will help reduce issues like that reported in bug 1819:

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