Commit dd8d77d9 authored by Ryan C. Gordon's avatar Ryan C. Gordon

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.

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401344
parent c5c8f944
...@@ -67,7 +67,7 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format); ...@@ -67,7 +67,7 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format);
static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format,
Uint32 flags); Uint32 flags);
static void QZ_UnsetVideoMode (_THIS); static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop);
static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current,
int width, int height, int bpp, int width, int height, int bpp,
...@@ -345,97 +345,7 @@ static SDL_bool QZ_WindowPosition(_THIS, int *x, int *y) ...@@ -345,97 +345,7 @@ static SDL_bool QZ_WindowPosition(_THIS, int *x, int *y)
return SDL_FALSE; return SDL_FALSE;
} }
/* static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) {
Gamma functions to try to hide the flash from a rez switch
Fade the display from normal to black
Save gamma tables for fade back to normal
*/
static UInt32 QZ_FadeGammaOut (_THIS, SDL_QuartzGammaTable *table) {
CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
greenTable[QZ_GAMMA_TABLE_SIZE],
blueTable[QZ_GAMMA_TABLE_SIZE];
float percent;
int j;
int actual;
if ( (CGDisplayNoErr != CGGetDisplayTransferByTable
(display_id, QZ_GAMMA_TABLE_SIZE,
table->red, table->green, table->blue, &actual)) ||
actual != QZ_GAMMA_TABLE_SIZE) {
return 1;
}
memcpy (redTable, table->red, sizeof(redTable));
memcpy (greenTable, table->green, sizeof(greenTable));
memcpy (blueTable, table->blue, sizeof(greenTable));
for (percent = 1.0; percent >= 0.0; percent -= 0.01) {
for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
redTable[j] = redTable[j] * percent;
greenTable[j] = greenTable[j] * percent;
blueTable[j] = blueTable[j] * percent;
}
if (CGDisplayNoErr != CGSetDisplayTransferByTable
(display_id, QZ_GAMMA_TABLE_SIZE,
redTable, greenTable, blueTable)) {
CGDisplayRestoreColorSyncSettings();
return 1;
}
SDL_Delay (10);
}
return 0;
}
/*
Fade the display from black to normal
Restore previously saved gamma values
*/
static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) {
CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
greenTable[QZ_GAMMA_TABLE_SIZE],
blueTable[QZ_GAMMA_TABLE_SIZE];
float percent;
int j;
memset (redTable, 0, sizeof(redTable));
memset (greenTable, 0, sizeof(greenTable));
memset (blueTable, 0, sizeof(greenTable));
for (percent = 0.0; percent <= 1.0; percent += 0.01) {
for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
redTable[j] = table->red[j] * percent;
greenTable[j] = table->green[j] * percent;
blueTable[j] = table->blue[j] * percent;
}
if (CGDisplayNoErr != CGSetDisplayTransferByTable
(display_id, QZ_GAMMA_TABLE_SIZE,
redTable, greenTable, blueTable)) {
CGDisplayRestoreColorSyncSettings();
return 1;
}
SDL_Delay (10);
}
return 0;
}
static void QZ_UnsetVideoMode (_THIS) {
/* Reset values that may change between switches */ /* Reset values that may change between switches */
this->info.blit_fill = 0; this->info.blit_fill = 0;
...@@ -447,12 +357,8 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -447,12 +357,8 @@ static void QZ_UnsetVideoMode (_THIS) {
/* Release fullscreen resources */ /* Release fullscreen resources */
if ( mode_flags & SDL_FULLSCREEN ) { if ( mode_flags & SDL_FULLSCREEN ) {
SDL_QuartzGammaTable gamma_table;
int gamma_error;
NSRect screen_rect; NSRect screen_rect;
gamma_error = QZ_FadeGammaOut (this, &gamma_table);
/* Release double buffer stuff */ /* Release double buffer stuff */
if ( mode_flags & SDL_DOUBLEBUF) { if ( mode_flags & SDL_DOUBLEBUF) {
quit_thread = YES; quit_thread = YES;
...@@ -472,20 +378,18 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -472,20 +378,18 @@ static void QZ_UnsetVideoMode (_THIS) {
QZ_TearDownOpenGL (this); QZ_TearDownOpenGL (this);
CGLSetFullScreen (NULL); CGLSetFullScreen (NULL);
} }
if (to_desktop) {
/* Restore original screen resolution/bpp */ /* Restore original screen resolution/bpp */
CGDisplaySwitchToMode (display_id, save_mode); CGDisplaySwitchToMode (display_id, save_mode);
CGReleaseAllDisplays (); CGReleaseAllDisplays ();
ShowMenuBar (); ShowMenuBar ();
/* /*
Reset the main screen's rectangle Reset the main screen's rectangle
See comment in QZ_SetVideoFullscreen for why we do this See comment in QZ_SetVideoFullscreen for why we do this
*/ */
screen_rect = NSMakeRect(0,0,device_width,device_height); screen_rect = NSMakeRect(0,0,device_width,device_height);
[ [ NSScreen mainScreen ] setFrame:screen_rect ]; [ [ NSScreen mainScreen ] setFrame:screen_rect ];
}
if (! gamma_error)
QZ_FadeGammaIn (this, &gamma_table);
} }
/* Release window mode resources */ /* Release window mode resources */
else { else {
...@@ -507,14 +411,19 @@ static void QZ_UnsetVideoMode (_THIS) { ...@@ -507,14 +411,19 @@ static void QZ_UnsetVideoMode (_THIS) {
static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width,
int height, int bpp, Uint32 flags) { int height, int bpp, Uint32 flags) {
boolean_t exact_match = 0; boolean_t exact_match = 0;
int gamma_error;
SDL_QuartzGammaTable gamma_table;
NSRect screen_rect; NSRect screen_rect;
CGError error; CGError error;
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
/* Fade to black to hide resolution-switching flicker (and garbage
that is displayed by a destroyed OpenGL context, if applicable) */
if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) {
CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
}
/* Destroy any previous mode */ /* Destroy any previous mode */
if (video_set == SDL_TRUE) if (video_set == SDL_TRUE)
QZ_UnsetVideoMode (this); QZ_UnsetVideoMode (this, FALSE);
/* See if requested mode exists */ /* See if requested mode exists */
mode = CGDisplayBestModeForParameters (display_id, bpp, width, mode = CGDisplayBestModeForParameters (display_id, bpp, width,
...@@ -526,9 +435,6 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -526,9 +435,6 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
goto ERR_NO_MATCH; goto ERR_NO_MATCH;
} }
/* Fade display to zero gamma */
gamma_error = QZ_FadeGammaOut (this, &gamma_table);
/* Put up the blanking window (a window above all other windows) */ /* Put up the blanking window (a window above all other windows) */
if (getenv ("SDL_SINGLEDISPLAY")) if (getenv ("SDL_SINGLEDISPLAY"))
error = CGDisplayCapture (display_id); error = CGDisplayCapture (display_id);
...@@ -629,9 +535,11 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -629,9 +535,11 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
/* If we don't hide menu bar, it will get events and interrupt the program */ /* If we don't hide menu bar, it will get events and interrupt the program */
HideMenuBar (); HideMenuBar ();
/* Fade the display to original gamma */ /* Fade in again (asynchronously) */
if (! gamma_error ) if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
QZ_FadeGammaIn (this, &gamma_table); CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
CGReleaseDisplayFadeReservation(fade_token);
}
/* /*
There is a bug in Cocoa where NSScreen doesn't synchronize There is a bug in Cocoa where NSScreen doesn't synchronize
...@@ -655,8 +563,12 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -655,8 +563,12 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
ERR_NO_GL: ERR_NO_GL:
ERR_DOUBLEBUF: CGDisplaySwitchToMode (display_id, save_mode); ERR_DOUBLEBUF: CGDisplaySwitchToMode (display_id, save_mode);
ERR_NO_SWITCH: CGReleaseAllDisplays (); ERR_NO_SWITCH: CGReleaseAllDisplays ();
ERR_NO_CAPTURE: if (!gamma_error) { QZ_FadeGammaIn (this, &gamma_table); } ERR_NO_CAPTURE:
ERR_NO_MATCH: return NULL; ERR_NO_MATCH: if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
CGReleaseDisplayFadeReservation (fade_token);
}
return NULL;
} }
static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
...@@ -666,6 +578,7 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -666,6 +578,7 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
BOOL isCustom = NO; BOOL isCustom = NO;
int center_window = 1; int center_window = 1;
int origin_x, origin_y; int origin_x, origin_y;
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
current->flags = 0; current->flags = 0;
current->w = width; current->w = width;
...@@ -680,12 +593,21 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -680,12 +593,21 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
- If it is OpenGL (since gl attributes could be different) - If it is OpenGL (since gl attributes could be different)
- If new mode is OpenGL, but previous mode wasn't - If new mode is OpenGL, but previous mode wasn't
*/ */
if (video_set == SDL_TRUE) if (video_set == SDL_TRUE) {
if ( (mode_flags & SDL_FULLSCREEN) || if (mode_flags & SDL_FULLSCREEN) {
((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) || /* Fade to black to hide resolution-switching flicker (and garbage
(mode_flags & SDL_OPENGL) || that is displayed by a destroyed OpenGL context, if applicable) */
(flags & SDL_OPENGL) ) if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
QZ_UnsetVideoMode (this); CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
}
QZ_UnsetVideoMode (this, TRUE);
}
else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) ||
(mode_flags & SDL_OPENGL) ||
(flags & SDL_OPENGL) ) {
QZ_UnsetVideoMode (this, TRUE);
}
}
/* Check for user-specified window and view */ /* Check for user-specified window and view */
{ {
...@@ -752,6 +674,10 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -752,6 +674,10 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
if (qz_window == nil) { if (qz_window == nil) {
SDL_SetError ("Could not create the Cocoa window"); SDL_SetError ("Could not create the Cocoa window");
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
CGReleaseDisplayFadeReservation (fade_token);
}
return NULL; return NULL;
} }
...@@ -779,6 +705,10 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -779,6 +705,10 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
if ( flags & SDL_OPENGL ) { if ( flags & SDL_OPENGL ) {
if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) { if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) {
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
CGReleaseDisplayFadeReservation (fade_token);
}
return NULL; return NULL;
} }
...@@ -838,6 +768,12 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -838,6 +768,12 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
/* Save flags to ensure correct teardown */ /* Save flags to ensure correct teardown */
mode_flags = current->flags; mode_flags = current->flags;
/* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
CGReleaseDisplayFadeReservation (fade_token);
}
return current; return current;
} }
...@@ -1495,6 +1431,8 @@ static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { ...@@ -1495,6 +1431,8 @@ static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) {
static void QZ_VideoQuit (_THIS) { static void QZ_VideoQuit (_THIS) {
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
/* Restore gamma settings */ /* Restore gamma settings */
CGDisplayRestoreColorSyncSettings (); CGDisplayRestoreColorSyncSettings ();
...@@ -1502,7 +1440,21 @@ static void QZ_VideoQuit (_THIS) { ...@@ -1502,7 +1440,21 @@ static void QZ_VideoQuit (_THIS) {
CGDisplayShowCursor (display_id); CGDisplayShowCursor (display_id);
CGAssociateMouseAndMouseCursorPosition (1); CGAssociateMouseAndMouseCursorPosition (1);
QZ_UnsetVideoMode (this); if (mode_flags & SDL_FULLSCREEN) {
/* Fade to black to hide resolution-switching flicker (and garbage
that is displayed by a destroyed OpenGL context, if applicable) */
if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
}
QZ_UnsetVideoMode (this, TRUE);
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
CGReleaseDisplayFadeReservation (fade_token);
}
}
else
QZ_UnsetVideoMode (this, TRUE);
CGPaletteRelease (palette); CGPaletteRelease (palette);
if (opengl_library) { if (opengl_library) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment