Faster fades when changing to/from/between fullscreen modes on Mac OS X. Also,
authorRyan C. Gordon
Tue, 07 Feb 2006 11:18:21 +0000
changeset 134058b114ef50e7
parent 1339 62802d9d7c87
child 1341 d02b552e5304
Faster fades when changing to/from/between fullscreen modes on Mac OS X. Also,
it doesn't show the desktop between modes anymore.

Fixes Bugzilla #100.

--ryan.
src/video/quartz/SDL_QuartzVideo.m
     1.1 --- a/src/video/quartz/SDL_QuartzVideo.m	Tue Feb 07 10:40:14 2006 +0000
     1.2 +++ b/src/video/quartz/SDL_QuartzVideo.m	Tue Feb 07 11:18:21 2006 +0000
     1.3 @@ -67,7 +67,7 @@
     1.4  
     1.5  static SDL_Rect**   QZ_ListModes        (_THIS, SDL_PixelFormat *format,
     1.6                                           Uint32 flags);
     1.7 -static void         QZ_UnsetVideoMode   (_THIS);
     1.8 +static void         QZ_UnsetVideoMode   (_THIS, BOOL to_desktop);
     1.9  
    1.10  static SDL_Surface* QZ_SetVideoMode     (_THIS, SDL_Surface *current,
    1.11                                           int width, int height, int bpp,
    1.12 @@ -345,97 +345,7 @@
    1.13      return SDL_FALSE;
    1.14  }
    1.15  
    1.16 -/* 
    1.17 -    Gamma functions to try to hide the flash from a rez switch
    1.18 -    Fade the display from normal to black
    1.19 -    Save gamma tables for fade back to normal
    1.20 -*/
    1.21 -static UInt32 QZ_FadeGammaOut (_THIS, SDL_QuartzGammaTable *table) {
    1.22 -
    1.23 -    CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
    1.24 -    greenTable[QZ_GAMMA_TABLE_SIZE],
    1.25 -    blueTable[QZ_GAMMA_TABLE_SIZE];
    1.26 -
    1.27 -    float percent;
    1.28 -    int j;
    1.29 -    int actual;
    1.30 -
    1.31 -    if ( (CGDisplayNoErr != CGGetDisplayTransferByTable
    1.32 -          (display_id, QZ_GAMMA_TABLE_SIZE,
    1.33 -           table->red, table->green, table->blue, &actual)) ||
    1.34 -         actual != QZ_GAMMA_TABLE_SIZE) {
    1.35 -
    1.36 -        return 1;
    1.37 -    }
    1.38 -
    1.39 -    memcpy (redTable, table->red, sizeof(redTable));
    1.40 -    memcpy (greenTable, table->green, sizeof(greenTable));
    1.41 -    memcpy (blueTable, table->blue, sizeof(greenTable));
    1.42 -
    1.43 -    for (percent = 1.0; percent >= 0.0; percent -= 0.01) {
    1.44 -
    1.45 -        for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
    1.46 -
    1.47 -            redTable[j]   = redTable[j]   * percent;
    1.48 -            greenTable[j] = greenTable[j] * percent;
    1.49 -            blueTable[j]  = blueTable[j]  * percent;
    1.50 -        }
    1.51 -
    1.52 -        if (CGDisplayNoErr != CGSetDisplayTransferByTable
    1.53 -            (display_id, QZ_GAMMA_TABLE_SIZE,
    1.54 -             redTable, greenTable, blueTable)) {
    1.55 -
    1.56 -            CGDisplayRestoreColorSyncSettings();
    1.57 -            return 1;
    1.58 -        }
    1.59 -
    1.60 -        SDL_Delay (10);
    1.61 -    }
    1.62 -
    1.63 -    return 0;
    1.64 -}
    1.65 -
    1.66 -/* 
    1.67 -    Fade the display from black to normal
    1.68 -    Restore previously saved gamma values
    1.69 -*/
    1.70 -static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) {
    1.71 -
    1.72 -    CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
    1.73 -    greenTable[QZ_GAMMA_TABLE_SIZE],
    1.74 -    blueTable[QZ_GAMMA_TABLE_SIZE];
    1.75 -
    1.76 -    float percent;
    1.77 -    int j;
    1.78 -
    1.79 -    memset (redTable, 0, sizeof(redTable));
    1.80 -    memset (greenTable, 0, sizeof(greenTable));
    1.81 -    memset (blueTable, 0, sizeof(greenTable));
    1.82 -
    1.83 -    for (percent = 0.0; percent <= 1.0; percent += 0.01) {
    1.84 -
    1.85 -        for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
    1.86 -
    1.87 -            redTable[j]   = table->red[j]   * percent;
    1.88 -            greenTable[j] = table->green[j] * percent;
    1.89 -            blueTable[j]  = table->blue[j]  * percent;
    1.90 -        }
    1.91 -
    1.92 -        if (CGDisplayNoErr != CGSetDisplayTransferByTable
    1.93 -            (display_id, QZ_GAMMA_TABLE_SIZE,
    1.94 -             redTable, greenTable, blueTable)) {
    1.95 -
    1.96 -            CGDisplayRestoreColorSyncSettings();
    1.97 -            return 1;
    1.98 -        }
    1.99 -
   1.100 -        SDL_Delay (10);
   1.101 -    }
   1.102 -
   1.103 -    return 0;
   1.104 -}
   1.105 -
   1.106 -static void QZ_UnsetVideoMode (_THIS) {
   1.107 +static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) {
   1.108  
   1.109      /* Reset values that may change between switches */
   1.110      this->info.blit_fill  = 0;
   1.111 @@ -447,12 +357,8 @@
   1.112      /* Release fullscreen resources */
   1.113      if ( mode_flags & SDL_FULLSCREEN ) {
   1.114  
   1.115 -        SDL_QuartzGammaTable gamma_table;
   1.116 -        int gamma_error;
   1.117          NSRect screen_rect;
   1.118          
   1.119 -        gamma_error = QZ_FadeGammaOut (this, &gamma_table);
   1.120 -
   1.121          /*  Release double buffer stuff */
   1.122          if ( mode_flags & SDL_DOUBLEBUF) {
   1.123              quit_thread = YES;
   1.124 @@ -472,20 +378,18 @@
   1.125              QZ_TearDownOpenGL (this);
   1.126              CGLSetFullScreen (NULL);
   1.127          }
   1.128 -        
   1.129 -        /* Restore original screen resolution/bpp */
   1.130 -        CGDisplaySwitchToMode (display_id, save_mode);
   1.131 -        CGReleaseAllDisplays ();
   1.132 -        ShowMenuBar ();
   1.133 -        /* 
   1.134 -            Reset the main screen's rectangle
   1.135 -            See comment in QZ_SetVideoFullscreen for why we do this
   1.136 -        */
   1.137 -        screen_rect = NSMakeRect(0,0,device_width,device_height);
   1.138 -        [ [ NSScreen mainScreen ] setFrame:screen_rect ];
   1.139 -        
   1.140 -        if (! gamma_error)
   1.141 -            QZ_FadeGammaIn (this, &gamma_table);
   1.142 +        if (to_desktop) {
   1.143 +            /* Restore original screen resolution/bpp */
   1.144 +            CGDisplaySwitchToMode (display_id, save_mode);
   1.145 +            CGReleaseAllDisplays ();
   1.146 +            ShowMenuBar ();
   1.147 +            /* 
   1.148 +                Reset the main screen's rectangle
   1.149 +                See comment in QZ_SetVideoFullscreen for why we do this
   1.150 +            */
   1.151 +            screen_rect = NSMakeRect(0,0,device_width,device_height);
   1.152 +            [ [ NSScreen mainScreen ] setFrame:screen_rect ];
   1.153 +        }
   1.154      }
   1.155      /* Release window mode resources */
   1.156      else {
   1.157 @@ -507,14 +411,19 @@
   1.158  static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width,
   1.159                                             int height, int bpp, Uint32 flags) {
   1.160      boolean_t exact_match = 0;
   1.161 -    int gamma_error;
   1.162 -    SDL_QuartzGammaTable gamma_table;
   1.163      NSRect screen_rect;
   1.164      CGError error;
   1.165 +    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
   1.166 +    
   1.167 +    /* Fade to black to hide resolution-switching flicker (and garbage
   1.168 +       that is displayed by a destroyed OpenGL context, if applicable) */
   1.169 +    if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) {
   1.170 +        CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
   1.171 +    }
   1.172      
   1.173      /* Destroy any previous mode */
   1.174      if (video_set == SDL_TRUE)
   1.175 -        QZ_UnsetVideoMode (this);
   1.176 +        QZ_UnsetVideoMode (this, FALSE);
   1.177  
   1.178      /* See if requested mode exists */
   1.179      mode = CGDisplayBestModeForParameters (display_id, bpp, width,
   1.180 @@ -526,9 +435,6 @@
   1.181          goto ERR_NO_MATCH;
   1.182      }
   1.183  
   1.184 -    /* Fade display to zero gamma */
   1.185 -    gamma_error = QZ_FadeGammaOut (this, &gamma_table);
   1.186 -
   1.187      /* Put up the blanking window (a window above all other windows) */
   1.188      if (getenv ("SDL_SINGLEDISPLAY"))
   1.189          error = CGDisplayCapture (display_id);
   1.190 @@ -629,9 +535,11 @@
   1.191      /* If we don't hide menu bar, it will get events and interrupt the program */
   1.192      HideMenuBar ();
   1.193  
   1.194 -    /* Fade the display to original gamma */
   1.195 -    if (! gamma_error )
   1.196 -        QZ_FadeGammaIn (this, &gamma_table);
   1.197 +    /* Fade in again (asynchronously) */
   1.198 +    if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
   1.199 +        CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
   1.200 +        CGReleaseDisplayFadeReservation(fade_token);
   1.201 +    }
   1.202  
   1.203      /* 
   1.204          There is a bug in Cocoa where NSScreen doesn't synchronize
   1.205 @@ -655,8 +563,12 @@
   1.206  ERR_NO_GL:      
   1.207  ERR_DOUBLEBUF:  CGDisplaySwitchToMode (display_id, save_mode);
   1.208  ERR_NO_SWITCH:  CGReleaseAllDisplays ();
   1.209 -ERR_NO_CAPTURE: if (!gamma_error) { QZ_FadeGammaIn (this, &gamma_table); }
   1.210 -ERR_NO_MATCH:   return NULL;
   1.211 +ERR_NO_CAPTURE:
   1.212 +ERR_NO_MATCH:   if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
   1.213 +                    CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
   1.214 +                    CGReleaseDisplayFadeReservation (fade_token);
   1.215 +                }
   1.216 +                return NULL;
   1.217  }
   1.218  
   1.219  static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
   1.220 @@ -666,6 +578,7 @@
   1.221      BOOL isCustom = NO;
   1.222      int center_window = 1;
   1.223      int origin_x, origin_y;
   1.224 +    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
   1.225  
   1.226      current->flags = 0;
   1.227      current->w = width;
   1.228 @@ -680,12 +593,21 @@
   1.229          - If it is OpenGL (since gl attributes could be different)
   1.230          - If new mode is OpenGL, but previous mode wasn't
   1.231      */
   1.232 -    if (video_set == SDL_TRUE)
   1.233 -        if ( (mode_flags & SDL_FULLSCREEN) ||
   1.234 -             ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) ||
   1.235 -             (mode_flags & SDL_OPENGL) || 
   1.236 -             (flags & SDL_OPENGL) )
   1.237 -            QZ_UnsetVideoMode (this);
   1.238 +    if (video_set == SDL_TRUE) {
   1.239 +        if (mode_flags & SDL_FULLSCREEN) {
   1.240 +            /* Fade to black to hide resolution-switching flicker (and garbage
   1.241 +               that is displayed by a destroyed OpenGL context, if applicable) */
   1.242 +            if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
   1.243 +                CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
   1.244 +            }
   1.245 +            QZ_UnsetVideoMode (this, TRUE);
   1.246 +        }
   1.247 +        else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) ||
   1.248 +                  (mode_flags & SDL_OPENGL) || 
   1.249 +                  (flags & SDL_OPENGL) ) {
   1.250 +            QZ_UnsetVideoMode (this, TRUE);
   1.251 +        }
   1.252 +    }
   1.253      
   1.254      /* Check for user-specified window and view */
   1.255      {
   1.256 @@ -752,6 +674,10 @@
   1.257                            
   1.258          if (qz_window == nil) {
   1.259              SDL_SetError ("Could not create the Cocoa window");
   1.260 +            if (fade_token != kCGDisplayFadeReservationInvalidToken) {
   1.261 +                CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
   1.262 +                CGReleaseDisplayFadeReservation (fade_token);
   1.263 +            }
   1.264              return NULL;
   1.265          }
   1.266      
   1.267 @@ -779,6 +705,10 @@
   1.268      if ( flags & SDL_OPENGL ) {
   1.269  
   1.270          if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) {
   1.271 +            if (fade_token != kCGDisplayFadeReservationInvalidToken) {
   1.272 +                CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
   1.273 +                CGReleaseDisplayFadeReservation (fade_token);
   1.274 +            }
   1.275              return NULL;
   1.276          }
   1.277  
   1.278 @@ -838,6 +768,12 @@
   1.279      /* Save flags to ensure correct teardown */
   1.280      mode_flags = current->flags;
   1.281  
   1.282 +    /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */
   1.283 +    if (fade_token != kCGDisplayFadeReservationInvalidToken) {
   1.284 +        CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
   1.285 +        CGReleaseDisplayFadeReservation (fade_token);
   1.286 +    }
   1.287 +
   1.288      return current;
   1.289  }
   1.290  
   1.291 @@ -1495,6 +1431,8 @@
   1.292  
   1.293  static void QZ_VideoQuit (_THIS) {
   1.294  
   1.295 +    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
   1.296 +
   1.297      /* Restore gamma settings */
   1.298      CGDisplayRestoreColorSyncSettings ();
   1.299  
   1.300 @@ -1502,7 +1440,21 @@
   1.301      CGDisplayShowCursor (display_id);
   1.302      CGAssociateMouseAndMouseCursorPosition (1);
   1.303      
   1.304 -    QZ_UnsetVideoMode (this);
   1.305 +    if (mode_flags & SDL_FULLSCREEN) {
   1.306 +        /* Fade to black to hide resolution-switching flicker (and garbage
   1.307 +           that is displayed by a destroyed OpenGL context, if applicable) */
   1.308 +        if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
   1.309 +            CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
   1.310 +        }
   1.311 +        QZ_UnsetVideoMode (this, TRUE);
   1.312 +        if (fade_token != kCGDisplayFadeReservationInvalidToken) {
   1.313 +            CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
   1.314 +            CGReleaseDisplayFadeReservation (fade_token);
   1.315 +        }
   1.316 +    }
   1.317 +    else
   1.318 +        QZ_UnsetVideoMode (this, TRUE);
   1.319 +    
   1.320      CGPaletteRelease (palette);
   1.321  
   1.322      if (opengl_library) {