src/SDL.c
changeset 6866 e74a4b282450
parent 6690 9548c8a58103
child 6867 4c899e841091
     1.1 --- a/src/SDL.c	Tue Feb 12 11:47:29 2013 -0800
     1.2 +++ b/src/SDL.c	Tue Feb 12 11:47:31 2013 -0800
     1.3 @@ -23,6 +23,7 @@
     1.4  /* Initialization code for SDL */
     1.5  
     1.6  #include "SDL.h"
     1.7 +#include "SDL_bits.h"
     1.8  #include "SDL_revision.h"
     1.9  #include "SDL_fatal.h"
    1.10  #include "SDL_assert_c.h"
    1.11 @@ -42,134 +43,146 @@
    1.12  
    1.13  
    1.14  /* The initialized subsystems */
    1.15 -static Uint32 SDL_initialized = 0;
    1.16  static Uint32 ticks_started = 0;
    1.17  static SDL_bool SDL_bInMainQuit = SDL_FALSE;
    1.18 -static Uint8 SDL_SubsystemRefCount[ 32 ]; // keep a per subsystem init
    1.19 +static Uint8 SDL_SubsystemRefCount[ 32 ];
    1.20  
    1.21 -/* helper func to return the index of the MSB in an int */
    1.22 -int msb32_idx( Uint32 n)
    1.23 +/* Private helper to increment a subsystem's ref counter. */
    1.24 +static void SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem)
    1.25 +{
    1.26 +    int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    1.27 +    SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
    1.28 +    ++SDL_SubsystemRefCount[subsystem_index];
    1.29 +}
    1.30 +
    1.31 +/* Private helper to decrement a subsystem's ref counter. */
    1.32 +void SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)
    1.33  {
    1.34 -	int b = 0;
    1.35 -	if (!n) return -1;
    1.36 +    int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    1.37 +    if (SDL_SubsystemRefCount[subsystem_index] > 0) {
    1.38 +        --SDL_SubsystemRefCount[subsystem_index];
    1.39 +    }
    1.40 +}
    1.41 +
    1.42 +/* Private helper to check if a system needs init. */
    1.43 +static SDL_bool
    1.44 +SDL_PrivateShouldInitSubsystem(Uint32 flags, Uint32 subsystem)
    1.45 +{
    1.46 +    if ((flags & subsystem) == 0) {
    1.47 +      return SDL_FALSE;
    1.48 +    }
    1.49  
    1.50 -#define step(x) if (n >= ((Uint32)1) << x) b += x, n >>= x
    1.51 -	step(16); step(8); step(4); step(2); step(1);
    1.52 -#undef step
    1.53 -	return b;
    1.54 +    int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    1.55 +    SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
    1.56 +    return (SDL_SubsystemRefCount[subsystem_index] == 0);
    1.57 +}
    1.58 +
    1.59 +/* Private helper to check if a system needs to be quit. */
    1.60 +static SDL_bool
    1.61 +SDL_PrivateShouldQuitSubsystem(Uint32 subsystem) {
    1.62 +    int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
    1.63 +    if (SDL_SubsystemRefCount[subsystem_index] == 0) {
    1.64 +      return SDL_FALSE;
    1.65 +    }
    1.66 +
    1.67 +    /* If we're in SDL_Quit, we shut down every subsystem, even if refcount
    1.68 +     * isn't zero.
    1.69 +     */
    1.70 +    return SDL_SubsystemRefCount[subsystem_index] == 1 || SDL_bInMainQuit;
    1.71  }
    1.72  
    1.73  int
    1.74  SDL_InitSubSystem(Uint32 flags)
    1.75  {
    1.76  #if !SDL_TIMERS_DISABLED
    1.77 -    /* Initialize the timer subsystem */
    1.78      if (!ticks_started) {
    1.79          SDL_StartTicks();
    1.80          ticks_started = 1;
    1.81      }
    1.82 -
    1.83 -    if ((flags & SDL_INIT_TIMER) ){
    1.84 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ]++;
    1.85 -		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ] < 254 );
    1.86 -		if ( !(SDL_initialized & SDL_INIT_TIMER)) {
    1.87 -			if (SDL_TimerInit() < 0) {
    1.88 -				return (-1);
    1.89 -			}
    1.90 -			SDL_initialized |= SDL_INIT_TIMER;
    1.91 -		}
    1.92 -    }
    1.93 -#else
    1.94 -    if (flags & SDL_INIT_TIMER) {
    1.95 -        SDL_SetError("SDL not built with timer support");
    1.96 -        return (-1);
    1.97 -    }
    1.98 -#endif
    1.99 -
   1.100 -#if !SDL_VIDEO_DISABLED
   1.101 -    /* Initialize the video/event subsystem */
   1.102 -    if ((flags & SDL_INIT_VIDEO) ) {
   1.103 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ]++;
   1.104 -		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ] < 254 );
   1.105 -		if ( !(SDL_initialized & SDL_INIT_VIDEO)) {
   1.106 -			if (SDL_VideoInit(NULL) < 0) {
   1.107 -				return (-1);
   1.108 -			}
   1.109 -			SDL_initialized |= SDL_INIT_VIDEO;
   1.110 -		}
   1.111 -    }
   1.112 -#else
   1.113 -    if (flags & SDL_INIT_VIDEO) {
   1.114 -        SDL_SetError("SDL not built with video support");
   1.115 -        return (-1);
   1.116 -    }
   1.117  #endif
   1.118  
   1.119 -#if !SDL_AUDIO_DISABLED
   1.120 -    /* Initialize the audio subsystem */
   1.121 -    if ((flags & SDL_INIT_AUDIO) ) {
   1.122 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ]++;
   1.123 -		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ] < 254 );
   1.124 -		if ( !(SDL_initialized & SDL_INIT_AUDIO)) {
   1.125 -			if (SDL_AudioInit(NULL) < 0) {
   1.126 -				return (-1);
   1.127 -			}
   1.128 -			SDL_initialized |= SDL_INIT_AUDIO;
   1.129 -		}
   1.130 -    }
   1.131 +    /* Initialize the timer subsystem */
   1.132 +    if (SDL_PrivateShouldInitSubsystem(flags, SDL_INIT_TIMER)) {
   1.133 +#if !SDL_TIMERS_DISABLED
   1.134 +        if (SDL_TimerInit() < 0) {
   1.135 +            return (-1);
   1.136 +        }
   1.137 +        SDL_PrivateSubsystemRefCountIncr(SDL_INIT_TIMER);
   1.138  #else
   1.139 -    if (flags & SDL_INIT_AUDIO) {
   1.140 -        SDL_SetError("SDL not built with audio support");
   1.141 +        SDL_SetError("SDL not built with timer support");
   1.142          return (-1);
   1.143 +#endif
   1.144      }
   1.145 -#endif
   1.146  
   1.147 -#if !SDL_JOYSTICK_DISABLED
   1.148 -    /* Initialize the joystick subsystem */
   1.149 -    if ( ( (flags & SDL_INIT_JOYSTICK)  ) || ((flags & SDL_INIT_GAMECONTROLLER) ) ) { // game controller implies joystick
   1.150 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ]++;
   1.151 -		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ] < 254 );
   1.152 -        if ( !(SDL_initialized & SDL_INIT_JOYSTICK) && SDL_JoystickInit() < 0) {
   1.153 +    /* Initialize the video/event subsystem */
   1.154 +    if (SDL_PrivateShouldInitSubsystem(flags, SDL_INIT_VIDEO)) {
   1.155 +#if !SDL_VIDEO_DISABLED
   1.156 +        if (SDL_VideoInit(NULL) < 0) {
   1.157 +            return (-1);
   1.158 +        }
   1.159 +        SDL_PrivateSubsystemRefCountIncr(SDL_INIT_VIDEO);
   1.160 +#else
   1.161 +        SDL_SetError("SDL not built with video support");
   1.162 +        return (-1);
   1.163 +#endif
   1.164 +    }
   1.165 +
   1.166 +    /* Initialize the audio subsystem */
   1.167 +    if (SDL_PrivateShouldInitSubsystem(flags, SDL_INIT_AUDIO)) {
   1.168 +#if !SDL_AUDIO_DISABLED
   1.169 +        if (SDL_AudioInit(NULL) < 0) {
   1.170              return (-1);
   1.171          }
   1.172 +        SDL_PrivateSubsystemRefCountIncr(SDL_INIT_AUDIO);
   1.173 +#else
   1.174 +        SDL_SetError("SDL not built with audio support");
   1.175 +        return (-1);
   1.176 +#endif
   1.177 +    }
   1.178  
   1.179 -		if ((flags & SDL_INIT_GAMECONTROLLER) ) {
   1.180 -			SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ]++;
   1.181 -			SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ] < 254 );
   1.182 -			if ( !(SDL_initialized & SDL_INIT_GAMECONTROLLER)) {
   1.183 -				if (SDL_GameControllerInit() < 0) {
   1.184 -					return (-1);
   1.185 -				}
   1.186 -				SDL_initialized |= SDL_INIT_GAMECONTROLLER;
   1.187 -			}
   1.188 -		}
   1.189 -        SDL_initialized |= SDL_INIT_JOYSTICK;
   1.190 +    if ((flags & SDL_INIT_GAMECONTROLLER)) {
   1.191 +        // Game controller implies Joystick.
   1.192 +        flags |= SDL_INIT_JOYSTICK;
   1.193      }
   1.194 +
   1.195 +    /* Initialize the joystick subsystem */
   1.196 +    if (SDL_PrivateShouldInitSubsystem(flags, SDL_INIT_JOYSTICK)) {
   1.197 +#if !SDL_JOYSTICK_DISABLED
   1.198 +        if (SDL_JoystickInit() < 0) {
   1.199 +            return (-1);
   1.200 +        }
   1.201 +        SDL_PrivateSubsystemRefCountIncr(SDL_INIT_JOYSTICK);
   1.202  #else
   1.203 -    if (flags & SDL_INIT_JOYSTICK) {
   1.204          SDL_SetError("SDL not built with joystick support");
   1.205          return (-1);
   1.206 -    }
   1.207  #endif
   1.208 +    }
   1.209  
   1.210 -#if !SDL_HAPTIC_DISABLED
   1.211 +    if (SDL_PrivateShouldInitSubsystem(flags, SDL_INIT_GAMECONTROLLER)) {
   1.212 +#if !SDL_JOYSTICK_DISABLED
   1.213 +        if (SDL_GameControllerInit() < 0) {
   1.214 +            return (-1);
   1.215 +        }
   1.216 +        SDL_PrivateSubsystemRefCountIncr(SDL_INIT_GAMECONTROLLER);
   1.217 +#else
   1.218 +        SDL_SetError("SDL not built with joystick support");
   1.219 +        return (-1);
   1.220 +#endif
   1.221 +    }
   1.222 +
   1.223      /* Initialize the haptic subsystem */
   1.224 -    if ((flags & SDL_INIT_HAPTIC) ) {
   1.225 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ]++;
   1.226 -		SDL_assert( SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ] < 254 );
   1.227 -		if ( !(SDL_initialized & SDL_INIT_HAPTIC)) {
   1.228 -			if (SDL_HapticInit() < 0) {
   1.229 -				return (-1);
   1.230 -			}
   1.231 -			SDL_initialized |= SDL_INIT_HAPTIC;
   1.232 -		}
   1.233 -    }
   1.234 +    if (SDL_PrivateShouldInitSubsystem(flags, SDL_INIT_HAPTIC)) {
   1.235 +#if !SDL_HAPTIC_DISABLED
   1.236 +        if (SDL_HapticInit() < 0) {
   1.237 +            return (-1);
   1.238 +        }
   1.239 +        SDL_PrivateSubsystemRefCountIncr(SDL_INIT_HAPTIC);
   1.240  #else
   1.241 -    if (flags & SDL_INIT_HAPTIC) {
   1.242          SDL_SetError("SDL not built with haptic (force feedback) support");
   1.243          return (-1);
   1.244 +#endif
   1.245      }
   1.246 -#endif
   1.247 +
   1.248      return (0);
   1.249  }
   1.250  
   1.251 @@ -199,7 +212,6 @@
   1.252          SDL_InstallParachute();
   1.253      }
   1.254  
   1.255 -	SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
   1.256      return (0);
   1.257  }
   1.258  
   1.259 @@ -208,62 +220,57 @@
   1.260  {
   1.261      /* Shut down requested initialized subsystems */
   1.262  #if !SDL_JOYSTICK_DISABLED
   1.263 -    if ((flags & SDL_initialized & SDL_INIT_JOYSTICK) || (flags & SDL_initialized & SDL_INIT_GAMECONTROLLER)) {
   1.264 -		if ( (flags & SDL_initialized & SDL_INIT_GAMECONTROLLER) ) {
   1.265 -			SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ]--;
   1.266 -			if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_GAMECONTROLLER) ] == 0 ) {
   1.267 -				SDL_GameControllerQuit();
   1.268 -				SDL_initialized &= ~SDL_INIT_GAMECONTROLLER;
   1.269 -			}
   1.270 +    if ((flags & SDL_INIT_GAMECONTROLLER)) {
   1.271 +        // Game controller implies Joystick.
   1.272 +        flags |= SDL_INIT_JOYSTICK;
   1.273 +
   1.274 +        if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_GAMECONTROLLER)) {
   1.275 +            SDL_GameControllerQuit();
   1.276  		}
   1.277 +        SDL_PrivateSubsystemRefCountDecr(SDL_INIT_GAMECONTROLLER);
   1.278 +    }
   1.279  
   1.280 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ]--;
   1.281 -		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_JOYSTICK) ] == 0 )
   1.282 -		{
   1.283 +    if ((flags & SDL_INIT_JOYSTICK)) {
   1.284 +        if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
   1.285  			SDL_JoystickQuit();
   1.286 -			SDL_initialized &= ~SDL_INIT_JOYSTICK;
   1.287  		}
   1.288 -
   1.289 +        SDL_PrivateSubsystemRefCountDecr(SDL_INIT_JOYSTICK);
   1.290      }
   1.291  #endif
   1.292 +
   1.293  #if !SDL_HAPTIC_DISABLED
   1.294 -    if ((flags & SDL_initialized & SDL_INIT_HAPTIC)) {
   1.295 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ]--;
   1.296 -		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_HAPTIC) ] == 0 )
   1.297 -		{
   1.298 +    if ((flags & SDL_INIT_HAPTIC)) {
   1.299 +        if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_HAPTIC)) {
   1.300  			SDL_HapticQuit();
   1.301 -			SDL_initialized &= ~SDL_INIT_HAPTIC;
   1.302  		}
   1.303 +        SDL_PrivateSubsystemRefCountDecr(SDL_INIT_HAPTIC);
   1.304      }
   1.305  #endif
   1.306 +
   1.307  #if !SDL_AUDIO_DISABLED
   1.308 -    if ((flags & SDL_initialized & SDL_INIT_AUDIO)) {
   1.309 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ]--;
   1.310 -		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_AUDIO) ] == 0 )
   1.311 -		{
   1.312 +    if ((flags & SDL_INIT_AUDIO)) {
   1.313 +        if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_AUDIO)) {
   1.314  			SDL_AudioQuit();
   1.315 -			SDL_initialized &= ~SDL_INIT_AUDIO;
   1.316  		}
   1.317 +        SDL_PrivateSubsystemRefCountDecr(SDL_INIT_AUDIO);
   1.318      }
   1.319  #endif
   1.320 +
   1.321  #if !SDL_VIDEO_DISABLED
   1.322 -    if ((flags & SDL_initialized & SDL_INIT_VIDEO)) {
   1.323 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ]--;
   1.324 -		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_VIDEO) ] == 0 )
   1.325 -		{
   1.326 +    if ((flags & SDL_INIT_VIDEO)) {
   1.327 +        if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_VIDEO)) {
   1.328  			SDL_VideoQuit();
   1.329 -			SDL_initialized &= ~SDL_INIT_VIDEO;
   1.330  		}
   1.331 +        SDL_PrivateSubsystemRefCountDecr(SDL_INIT_VIDEO);
   1.332      }
   1.333  #endif
   1.334 +
   1.335  #if !SDL_TIMERS_DISABLED
   1.336 -    if ((flags & SDL_initialized & SDL_INIT_TIMER)) {
   1.337 -		SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ]--;
   1.338 -		if ( SDL_bInMainQuit || SDL_SubsystemRefCount[ msb32_idx(SDL_INIT_TIMER) ] == 0 )
   1.339 -		{
   1.340 +    if ((flags & SDL_INIT_TIMER)) {
   1.341 +        if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_TIMER)) {
   1.342  			SDL_TimerQuit();
   1.343 -			SDL_initialized &= ~SDL_INIT_TIMER;
   1.344  		}
   1.345 +        SDL_PrivateSubsystemRefCountDecr(SDL_INIT_TIMER);
   1.346      }
   1.347  #endif
   1.348  }
   1.349 @@ -271,16 +278,33 @@
   1.350  Uint32
   1.351  SDL_WasInit(Uint32 flags)
   1.352  {
   1.353 +    int i;
   1.354 +    int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
   1.355 +    Uint32 initialized = 0;
   1.356 +
   1.357      if (!flags) {
   1.358          flags = SDL_INIT_EVERYTHING;
   1.359      }
   1.360 -    return (SDL_initialized & flags);
   1.361 +
   1.362 +    num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1);
   1.363 +
   1.364 +    /* Iterate over each bit in flags, and check the matching subsystem. */
   1.365 +    for (i = 0; i < num_subsystems; ++i) {
   1.366 +        if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) {
   1.367 +            initialized |= (1 << i);
   1.368 +        }
   1.369 +
   1.370 +        flags >>= 1;
   1.371 +    }
   1.372 +
   1.373 +    return initialized;
   1.374  }
   1.375  
   1.376  void
   1.377  SDL_Quit(void)
   1.378  {
   1.379 -	SDL_bInMainQuit = SDL_TRUE;
   1.380 +    SDL_bInMainQuit = SDL_TRUE;
   1.381 +
   1.382      /* Quit all subsystems */
   1.383  #if defined(__WIN32__)
   1.384      SDL_HelperWindowDestroy();
   1.385 @@ -294,8 +318,12 @@
   1.386      SDL_AssertionsQuit();
   1.387      SDL_LogResetPriorities();
   1.388  
   1.389 -	SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
   1.390 -	SDL_bInMainQuit = SDL_FALSE;
   1.391 +    /* Now that every subsystem has been quit, we reset the subsystem refcount
   1.392 +     * and the list of initialized subsystems.
   1.393 +     */
   1.394 +    SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
   1.395 +
   1.396 +    SDL_bInMainQuit = SDL_FALSE;
   1.397  }
   1.398  
   1.399  /* Get the library version number */