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