19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL - Simple DirectMedia Layer
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Copyright (C) 1997-2012  Sam Lantinga
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is free software; you can redistribute it and/or
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    modify it under the terms of the GNU Library General Public
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License as published by the Free Software Foundation; either
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    version 2 of the License, or (at your option) any later version.
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is distributed in the hope that it will be useful,
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    but WITHOUT ANY WARRANTY; without even the implied warranty of
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Library General Public License for more details.
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    You should have received a copy of the GNU Library General Public
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License along with this library; if not, write to the Free
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Sam Lantinga
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    slouken@libsdl.org
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_config.h"
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_QuartzVideo.h"
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_QuartzWindow.h"
26e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall#include "SDL_QuartzWM.h"
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* These APIs aren't just deprecated; they're gone from the headers in the
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   10.7 SDK. If we're using a >= 10.7 SDK, but targeting < 10.7, then we
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   force these function declarations. */
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if ((MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070))
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCG_EXTERN void *CGDisplayBaseAddress(CGDirectDisplayID display)
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6,
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    __IPHONE_NA, __IPHONE_NA);
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCG_EXTERN size_t CGDisplayBytesPerRow(CGDirectDisplayID display)
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6,
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    __IPHONE_NA, __IPHONE_NA);
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline BOOL IS_LION_OR_LATER(_THIS)
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return (system_version >= 0x1070);
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline BOOL IS_SNOW_LEOPARD_OR_LATER(_THIS)
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return (system_version >= 0x1060);
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) && !defined(__LP64__)  /* Fixed in Snow Leopard */
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Add methods to get at private members of NSScreen.
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Since there is a bug in Apple's screen switching code
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    that does not update this variable when switching
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    to fullscreen, we'll set it manually (but only for the
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    main screen).
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@interface NSScreen (NSScreenAccess)
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall- (void) setFrame:(NSRect)frame;
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@end
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@implementation NSScreen (NSScreenAccess)
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall- (void) setFrame:(NSRect)frame;
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    _frame = frame;
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@end
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame)
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!IS_SNOW_LEOPARD_OR_LATER(this)) {
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [nsscreen setFrame:frame];
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame)
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@interface SDLTranslatorResponder : NSTextView
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall- (void) doCommandBySelector:(SEL)myselector;
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@end
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@implementation SDLTranslatorResponder
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall- (void) doCommandBySelector:(SEL) myselector {}
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall@end
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* absent in 10.3.9.  */
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Bootstrap functions */
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int              QZ_Available ();
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_VideoDevice* QZ_CreateDevice (int device_index);
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void             QZ_DeleteDevice (SDL_VideoDevice *device);
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Initialization, Query, Setup, and Redrawing functions */
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int          QZ_VideoInit        (_THIS, SDL_PixelFormat *video_format);
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Rect**   QZ_ListModes        (_THIS, SDL_PixelFormat *format,
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                         Uint32 flags);
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void         QZ_UnsetVideoMode   (_THIS, BOOL to_desktop, BOOL save_gl);
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface* QZ_SetVideoMode     (_THIS, SDL_Surface *current,
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                         int width, int height, int bpp,
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                         Uint32 flags);
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int          QZ_ToggleFullScreen (_THIS, int on);
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int          QZ_SetColors        (_THIS, int first_color,
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                         int num_colors, SDL_Color *colors);
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int          QZ_LockDoubleBuffer   (_THIS, SDL_Surface *surface);
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void         QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface);
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int          QZ_ThreadFlip         (_THIS);
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int          QZ_FlipDoubleBuffer   (_THIS, SDL_Surface *surface);
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void         QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects);
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void         QZ_DirectUpdate     (_THIS, int num_rects, SDL_Rect *rects);
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void         QZ_UpdateRects      (_THIS, int num_rects, SDL_Rect *rects);
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void         QZ_VideoQuit        (_THIS);
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int  QZ_LockHWSurface(_THIS, SDL_Surface *surface);
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface);
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_AllocHWSurface(_THIS, SDL_Surface *surface);
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_FreeHWSurface (_THIS, SDL_Surface *surface);
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Bootstrap binding, enables entry point into the driver */
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallVideoBootStrap QZ_bootstrap = {
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Disable compiler warnings we can't avoid. */
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (defined(__GNUC__) && (__GNUC__ >= 4))
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#  if (MAC_OS_X_VERSION_MAX_ALLOWED <= 1070)
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#    pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#  endif
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_ReleaseDisplayMode(_THIS, const void *moderef)
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* we only own these references in the 10.6+ API. */
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (use_new_mode_apis) {
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGDisplayModeRelease((CGDisplayModeRef) moderef);
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_ReleaseDisplayModeList(_THIS, CFArrayRef mode_list)
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* we only own these references in the 10.6+ API. */
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (use_new_mode_apis) {
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFRelease(mode_list);
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Bootstrap functions */
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_Available ()
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 1;
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_VideoDevice* QZ_CreateDevice (int device_index)
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#pragma unused (device_index)
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_VideoDevice *device;
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_PrivateVideoData *hidden;
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device = (SDL_VideoDevice*) SDL_malloc (sizeof (*device) );
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    hidden = (SDL_PrivateVideoData*) SDL_malloc (sizeof (*hidden) );
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (device == NULL || hidden == NULL)
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_OutOfMemory ();
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_memset (device, 0, sizeof (*device) );
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_memset (hidden, 0, sizeof (*hidden) );
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->hidden = hidden;
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->VideoInit        = QZ_VideoInit;
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->ListModes        = QZ_ListModes;
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->SetVideoMode     = QZ_SetVideoMode;
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->ToggleFullScreen = QZ_ToggleFullScreen;
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->UpdateMouse      = QZ_UpdateMouse;
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->SetColors        = QZ_SetColors;
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* device->UpdateRects      = QZ_UpdateRects; this is determined by SetVideoMode() */
1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->VideoQuit        = QZ_VideoQuit;
1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->LockHWSurface   = QZ_LockHWSurface;
1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->UnlockHWSurface = QZ_UnlockHWSurface;
1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->AllocHWSurface   = QZ_AllocHWSurface;
1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->FreeHWSurface   = QZ_FreeHWSurface;
2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->SetGamma     = QZ_SetGamma;
2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GetGamma     = QZ_GetGamma;
2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->SetGammaRamp = QZ_SetGammaRamp;
2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GetGammaRamp = QZ_GetGammaRamp;
2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GL_GetProcAddress = QZ_GL_GetProcAddress;
2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GL_GetAttribute   = QZ_GL_GetAttribute;
2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GL_MakeCurrent    = QZ_GL_MakeCurrent;
2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GL_SwapBuffers    = QZ_GL_SwapBuffers;
2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GL_LoadLibrary    = QZ_GL_LoadLibrary;
2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->FreeWMCursor   = QZ_FreeWMCursor;
2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->CreateWMCursor = QZ_CreateWMCursor;
2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->ShowWMCursor   = QZ_ShowWMCursor;
2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->WarpWMCursor   = QZ_WarpWMCursor;
2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->MoveWMCursor   = QZ_MoveWMCursor;
2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->CheckMouseMode = QZ_CheckMouseMode;
2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->InitOSKeymap   = QZ_InitOSKeymap;
2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->PumpEvents     = QZ_PumpEvents;
2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->SetCaption    = QZ_SetCaption;
2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->SetIcon       = QZ_SetIcon;
2239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->IconifyWindow = QZ_IconifyWindow;
224e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall    device->SetWindowPos  = QZ_SetWindowPos;
225e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall    device->GetWindowPos  = QZ_GetWindowPos;
226e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall    device->IsWindowVisible = QZ_IsWindowVisible;
227e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall    device->GetMonitorDPI = QZ_GetMonitorDPI;
228e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall    device->GetMonitorRect = QZ_GetMonitorRect;
229e4c5d95ed37611acc6a186522315195b4ebfb9efJesse Hall    device->GetWMInfo     = QZ_GetWMInfo;
2309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->GrabInput     = QZ_GrabInput;
2319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*
2339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * This is a big hassle, needing QuickDraw and QuickTime on older
2349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     *  systems, and god knows what on 10.6, so we immediately fail here,
2359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     *  which causes SDL to make an RGB surface and manage the YUV overlay
2369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     *  in software. Sorry. Use SDL 1.3 if you want YUV rendering in a pixel
2379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     *  shader.  :)
2389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
2399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*device->CreateYUVOverlay = QZ_CreateYUVOverlay;*/
2409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    device->free             = QZ_DeleteDevice;
2429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return device;
2449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_DeleteDevice (SDL_VideoDevice *device)
2479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    _THIS = device;
2499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_ReleaseDisplayMode(this, save_mode);
2509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_ReleaseDisplayMode(this, mode);
2519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_free (device->hidden);
2529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_free (device);
2539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_GetModeInfo(_THIS, const void *_mode, Uint32 *w, Uint32 *h, Uint32 *bpp)
2569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    *w = *h = *bpp = 0;
2589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (_mode == NULL) {
2599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return;
2609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
2619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
2639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (use_new_mode_apis) {
2649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGDisplayModeRef vidmode = (CGDisplayModeRef) _mode;
2659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
2669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        *w = (Uint32) CGDisplayModeGetWidth(vidmode);
2689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        *h = (Uint32) CGDisplayModeGetHeight(vidmode);
2699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* we only care about the 32-bit modes... */
2719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
2729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                            kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
2739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            *bpp = 32;
2749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
2759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFRelease(fmt);
2779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
2789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
2819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!use_new_mode_apis) {
2829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFDictionaryRef vidmode = (CFDictionaryRef) _mode;
2839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFNumberGetValue (
2849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CFDictionaryGetValue (vidmode, kCGDisplayBitsPerPixel),
2859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            kCFNumberSInt32Type, bpp);
2869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFNumberGetValue (
2889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CFDictionaryGetValue (vidmode, kCGDisplayWidth),
2899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            kCFNumberSInt32Type, w);
2909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFNumberGetValue (
2929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CFDictionaryGetValue (vidmode, kCGDisplayHeight),
2939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            kCFNumberSInt32Type, h);
2949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
2959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* we only care about the 32-bit modes... */
2989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (*bpp != 32) {
2999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        *bpp = 0;
3009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format)
3049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
3059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    NSRect r = NSMakeRect(0.0, 0.0, 0.0, 0.0);
3069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const char *env = NULL;
3079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( Gestalt(gestaltSystemVersion, &system_version) != noErr )
3099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        system_version = 0;
3109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    use_new_mode_apis = NO;
3129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
3149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    use_new_mode_apis = IS_SNOW_LEOPARD_OR_LATER(this);
3159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Initialize the video settings; this data persists between mode switches */
3189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    display_id = kCGDirectMainDisplay;
3199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if 0 /* The mouse event code needs to take this into account... */
3219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    env = getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
3229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( env ) {
3239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int monitor = SDL_atoi(env);
3249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CGDirectDisplayID activeDspys [3];
3259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CGDisplayCount dspyCnt;
3269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CGGetActiveDisplayList (3, activeDspys, &dspyCnt);
3279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( monitor >= 0 && monitor < dspyCnt ) {
3289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	    display_id = activeDspys[monitor];
3299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
3309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
3349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (use_new_mode_apis) {
3359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        save_mode = CGDisplayCopyDisplayMode(display_id);
3369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
3409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!use_new_mode_apis) {
3419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        save_mode = CGDisplayCurrentMode(display_id);
3429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
3469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!IS_LION_OR_LATER(this)) {
3479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        palette = CGPaletteCreateDefaultColorPalette();
3489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (save_mode == NULL) {
3529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SetError("Couldn't figure out current display mode.");
3539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return -1;
3549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Allow environment override of screensaver disable. */
3579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
3589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( env ) {
3599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        allow_screensaver = SDL_atoi(env);
3609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    } else {
3619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef SDL_VIDEO_DISABLE_SCREENSAVER
3629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        allow_screensaver = 0;
3639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
3649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        allow_screensaver = 1;
3659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Gather some information that is useful to know about the display */
3699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_GetModeInfo(this, save_mode, &device_width, &device_height, &device_bpp);
3709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (device_bpp == 0) {
3719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_ReleaseDisplayMode(this, save_mode);
3729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        save_mode = NULL;
3739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SetError("Unsupported display mode");
3749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return -1;
3759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
3769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Determine the current screen size */
3789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->info.current_w = device_width;
3799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->info.current_h = device_height;
3809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Determine the default screen depth */
3829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    video_format->BitsPerPixel = device_bpp;
3839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Set misc globals */
3859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current_grab_mode = SDL_GRAB_OFF;
3869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    cursor_should_be_visible    = YES;
3879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    cursor_visible              = YES;
3889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current_mods = 0;
3899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    field_edit =  [[SDLTranslatorResponder alloc] initWithFrame:r];
3909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */
3929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_RegisterForSleepNotifications (this);
3939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Fill in some window manager capabilities */
3959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->info.wm_available = 1;
3969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
3989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags)
4019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CFArrayRef mode_list = NULL;          /* list of available fullscreen modes */
4039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CFIndex num_modes;
4049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CFIndex i;
4059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int list_size = 0;
4079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Any windowed mode is acceptable */
4099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( (flags & SDL_FULLSCREEN) == 0 )
4109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return (SDL_Rect**)-1;
4119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Free memory from previous call, if any */
4139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( client_mode_list != NULL ) {
4149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int i;
4159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        for (i = 0; client_mode_list[i] != NULL; i++)
4179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_free (client_mode_list[i]);
4189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_free (client_mode_list);
4209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        client_mode_list = NULL;
4219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
4229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
4249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (use_new_mode_apis) {
4259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL);
4269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
4279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
4289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
4309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!use_new_mode_apis) {
4319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        mode_list = CGDisplayAvailableModes(display_id);
4329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
4339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
4349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    num_modes = CFArrayGetCount (mode_list);
4369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Build list of modes with the requested bpp */
4389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i = 0; i < num_modes; i++) {
4399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Uint32 width, height, bpp;
4409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        const void *onemode = CFArrayGetValueAtIndex(mode_list, i);
4419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_GetModeInfo(this, onemode, &width, &height, &bpp);
4439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (bpp && (bpp == format->BitsPerPixel)) {
4459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            int hasMode = SDL_FALSE;
4469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            int i;
4479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Check if mode is already in the list */
4499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            for (i = 0; i < list_size; i++) {
4509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if (client_mode_list[i]->w == width &&
4519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    client_mode_list[i]->h == height) {
4529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        hasMode = SDL_TRUE;
4539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        break;
4549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
4559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
4569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Grow the list and add mode to the list */
4589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( ! hasMode ) {
4599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                SDL_Rect *rect;
4609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                list_size++;
4629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if (client_mode_list == NULL)
4649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    client_mode_list = (SDL_Rect**)
4659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        SDL_malloc (sizeof(*client_mode_list) * (list_size+1) );
4669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                else {
4679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    /* !!! FIXME: this leaks memory if SDL_realloc() fails! */
4689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    client_mode_list = (SDL_Rect**)
4699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        SDL_realloc (client_mode_list, sizeof(*client_mode_list) * (list_size+1));
4709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
4719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                rect = (SDL_Rect*) SDL_malloc (sizeof(**client_mode_list));
4739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if (client_mode_list == NULL || rect == NULL) {
4759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    QZ_ReleaseDisplayModeList(this, mode_list);
4769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    SDL_OutOfMemory ();
4779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    return NULL;
4789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
4799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                rect->x = rect->y = 0;
4819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                rect->w = width;
4829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                rect->h = height;
4839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                client_mode_list[list_size-1] = rect;
4859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                client_mode_list[list_size]   = NULL;
4869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
4879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
4889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
4899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_ReleaseDisplayModeList(this, mode_list);
4919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Sort list largest to smallest (by area) */
4939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
4949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int i, j;
4959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        for (i = 0; i < list_size; i++) {
4969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            for (j = 0; j < list_size-1; j++) {
4979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                int area1, area2;
4999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                area1 = client_mode_list[j]->w * client_mode_list[j]->h;
5009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                area2 = client_mode_list[j+1]->w * client_mode_list[j+1]->h;
5019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if (area1 < area2) {
5039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    SDL_Rect *tmp = client_mode_list[j];
5049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    client_mode_list[j] = client_mode_list[j+1];
5059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    client_mode_list[j+1] = tmp;
5069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
5079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
5089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
5099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
5109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return client_mode_list;
5129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_bool QZ_WindowPosition(_THIS, int *x, int *y)
5159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const char *window = getenv("SDL_VIDEO_WINDOW_POS");
5179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( window ) {
5189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( sscanf(window, "%d,%d", x, y) == 2 ) {
5199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return SDL_TRUE;
5209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
5219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
5229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return SDL_FALSE;
5239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic CGError QZ_SetDisplayMode(_THIS, const void *vidmode)
5269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
5289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (use_new_mode_apis) {
5299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return CGDisplaySetDisplayMode(display_id, (CGDisplayModeRef) vidmode, NULL);
5309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
5319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
5329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
5349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!use_new_mode_apis) {
5359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return CGDisplaySwitchToMode(display_id, (CFDictionaryRef) vidmode);
5369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
5379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
5389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return kCGErrorFailure;
5409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline CGError QZ_RestoreDisplayMode(_THIS)
5439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return QZ_SetDisplayMode(this, save_mode);
5459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl)
5489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Reset values that may change between switches */
5509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->info.blit_fill  = 0;
5519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->FillHWRect      = NULL;
5529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->UpdateRects     = NULL;
5539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->LockHWSurface   = NULL;
5549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->UnlockHWSurface = NULL;
5559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (cg_context) {
5579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGContextFlush (cg_context);
5589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGContextRelease (cg_context);
5599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        cg_context = nil;
5609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
5619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Release fullscreen resources */
5639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( mode_flags & SDL_FULLSCREEN ) {
5649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        NSRect screen_rect;
5669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /*  Release double buffer stuff */
5689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
5699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( !IS_LION_OR_LATER(this) && (mode_flags & SDL_DOUBLEBUF) ) {
5709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            quit_thread = YES;
5719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_SemPost (sem1);
5729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_WaitThread (thread, NULL);
5739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_DestroySemaphore (sem1);
5749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_DestroySemaphore (sem2);
5759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_free (sw_buffers[0]);
5769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
5779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
5789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* If we still have a valid window, close it. */
5809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( qz_window ) {
5819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */
5829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */
5839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            qz_window = nil;
5849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            window_view = nil;
5859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
5869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /*
5879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            Release the OpenGL context
5889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            Do this first to avoid trash on the display before fade
5899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        */
5909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( mode_flags & SDL_OPENGL ) {
5919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (!save_gl) {
5929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                QZ_TearDownOpenGL (this);
5939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
5949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            #ifdef __powerpc__  /* we only use this for pre-10.3 compatibility. */
5969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGLSetFullScreen (NULL);
5979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            #endif
5989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
5999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (to_desktop) {
6009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* !!! FIXME: keep an eye on this.
6019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall             * This API is officially unavailable for 64-bit binaries.
6029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall             *  It happens to work, as of 10.7, but we're going to see if
6039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall             *  we can just simply do without it on newer OSes...
6049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall             */
6059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
6069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( !IS_LION_OR_LATER(this) ) {
6079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                ShowMenuBar ();
6089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
6099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            #endif
6109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Restore original screen resolution/bpp */
6129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            QZ_RestoreDisplayMode (this);
6139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGReleaseAllDisplays ();
6149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /*
6159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                Reset the main screen's rectangle
6169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                See comment in QZ_SetVideoFullscreen for why we do this
6179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            */
6189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            screen_rect = NSMakeRect(0,0,device_width,device_height);
6199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect);
6209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
6219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
6229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Release window mode resources */
6239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
6249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        id delegate = [ qz_window delegate ];
6259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */
6269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (delegate != nil) [ delegate release ];
6279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        qz_window = nil;
6289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        window_view = nil;
6299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Release the OpenGL context */
6319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( mode_flags & SDL_OPENGL ) {
6329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (!save_gl) {
6339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                QZ_TearDownOpenGL (this);
6349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
6359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
6369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
6379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Signal successful teardown */
6399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    video_set = SDL_FALSE;
6409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
6419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const void *QZ_BestMode(_THIS, const int bpp, const int w, const int h)
6439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
6449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const void *best = NULL;
6459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (bpp == 0) {
6479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return NULL;
6489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
6499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
6519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (use_new_mode_apis) {
6529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* apparently, we have to roll our own now. :/ */
6539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CFArrayRef mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL);
6549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (mode_list != NULL) {
6559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            const CFIndex num_modes = CFArrayGetCount(mode_list);
6569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CFIndex i;
6579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            for (i = 0; i < num_modes; i++) {
6589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                const void *vidmode = CFArrayGetValueAtIndex(mode_list, i);
6599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                Uint32 thisw, thish, thisbpp;
6609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                QZ_GetModeInfo(this, vidmode, &thisw, &thish, &thisbpp);
6619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                /* We only care about exact matches, apparently. */
6639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if ((thisbpp == bpp) && (thisw == w) && (thish == h)) {
6649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    best = vidmode;
6659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    break;  /* got it! */
6669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
6679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
6689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGDisplayModeRetain((CGDisplayModeRef) best);  /* NULL is ok */
6699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CFRelease(mode_list);
6709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
6719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
6729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
6759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!use_new_mode_apis) {
6769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        boolean_t exact = 0;
6779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        best = CGDisplayBestModeForParameters(display_id, bpp, w, h, &exact);
6789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (!exact) {
6799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            best = NULL;
6809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
6819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
6829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return best;
6859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
6869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width,
6889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                           int height, int bpp, Uint32 flags,
6899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                           const BOOL save_gl)
6909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
6919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const BOOL isLion = IS_LION_OR_LATER(this);
6929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    NSRect screen_rect;
6939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGError error;
6949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    NSRect contentRect;
6959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
6969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->flags = SDL_FULLSCREEN;
6989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->w = width;
6999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->h = height;
7009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    contentRect = NSMakeRect (0, 0, width, height);
7029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Fade to black to hide resolution-switching flicker (and garbage
7049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall       that is displayed by a destroyed OpenGL context, if applicable) */
7059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) {
7069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
7079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
7089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Destroy any previous mode */
7109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (video_set == SDL_TRUE)
7119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_UnsetVideoMode (this, FALSE, save_gl);
7129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Sorry, QuickDraw was ripped out. */
7149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) {
7159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SetError ("Embedded QuickDraw windows are no longer supported");
7169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto ERR_NO_MATCH;
7179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
7189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_ReleaseDisplayMode(this, mode);  /* NULL is okay. */
7209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* See if requested mode exists */
7229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mode = QZ_BestMode(this, bpp, width, height);
7239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Require an exact match to the requested mode */
7259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( mode == NULL ) {
7269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp);
7279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto ERR_NO_MATCH;
7289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
7299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Put up the blanking window (a window above all other windows) */
7319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (getenv ("SDL_SINGLEDISPLAY"))
7329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        error = CGDisplayCapture (display_id);
7339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
7349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        error = CGCaptureAllDisplays ();
7359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( CGDisplayNoErr != error ) {
7379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SetError ("Failed capturing display");
7389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto ERR_NO_CAPTURE;
7399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
7409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Do the physical switch */
7429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( CGDisplayNoErr != QZ_SetDisplayMode(this, mode) ) {
7439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SetError ("Failed switching display resolution");
7449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        goto ERR_NO_SWITCH;
7459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
7469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
7489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( !isLion ) {
7499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->pixels = (Uint32*) CGDisplayBaseAddress (display_id);
7509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->pitch  = CGDisplayBytesPerRow (display_id);
7519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_HWSURFACE;
7539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_PREALLOC;
7549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */
7559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->UpdateRects     = QZ_DirectUpdate;
7579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->LockHWSurface   = QZ_LockHWSurface;
7589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->UnlockHWSurface = QZ_UnlockHWSurface;
7599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Setup double-buffer emulation */
7619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( flags & SDL_DOUBLEBUF ) {
7629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /*
7649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            Setup a software backing store for reasonable results when
7659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            double buffering is requested (since a single-buffered hardware
7669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            surface looks hideous).
7679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            The actual screen blit occurs in a separate thread to allow
7699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            other blitting while waiting on the VBL (and hence results in higher framerates).
7709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            */
7719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this->LockHWSurface = NULL;
7729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this->UnlockHWSurface = NULL;
7739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this->UpdateRects = NULL;
7749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF);
7769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this->UpdateRects = QZ_DoubleBufferUpdate;
7779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this->LockHWSurface = QZ_LockDoubleBuffer;
7789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this->UnlockHWSurface = QZ_UnlockDoubleBuffer;
7799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            this->FlipHWSurface = QZ_FlipDoubleBuffer;
7809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            current->pixels = SDL_malloc (current->pitch * current->h * 2);
7829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (current->pixels == NULL) {
7839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                SDL_OutOfMemory ();
7849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto ERR_DOUBLEBUF;
7859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
7869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            sw_buffers[0] = current->pixels;
7889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h;
7899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            quit_thread = NO;
7919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            sem1 = SDL_CreateSemaphore (0);
7929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            sem2 = SDL_CreateSemaphore (1);
7939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this);
7949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
7959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( CGDisplayCanSetPalette (display_id) )
7979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            current->flags |= SDL_HWPALETTE;
7989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
7999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
8009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Check if we should recreate the window */
8029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (qz_window == nil) {
8039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Manually create a window, avoids having a nib file resource */
8049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        qz_window = [ [ SDL_QuartzWindow alloc ]
8059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            initWithContentRect:contentRect
8069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                styleMask:(isLion ? NSBorderlessWindowMask : 0)
8079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    backing:NSBackingStoreBuffered
8089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        defer:NO ];
8099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (qz_window != nil) {
8119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window setAcceptsMouseMovedEvents:YES ];
8129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window setViewsNeedDisplay:NO ];
8139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (isLion) {
8149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ];
8159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
8169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
8179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
8189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* We already have a window, just change its size */
8199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
8209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setContentSize:contentRect.size ];
8219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
8229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ window_view setFrameSize:contentRect.size ];
8239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
8249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Setup OpenGL for a fullscreen context */
8269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (flags & SDL_OPENGL) {
8279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( ! save_gl ) {
8299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
8309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto ERR_NO_GL;
8319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
8329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
8339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Initialize the NSView and add it to our window.  The presence of a valid window and
8359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           view allow the cursor to be changed whilst in fullscreen.*/
8369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
8379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( isLion ) {
8399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
8409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
8419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ [ qz_window contentView ] addSubview:window_view ];
8439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Apparently Lion checks some version flag set by the linker
8459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           and changes API behavior. Annoying. */
8469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( isLion ) {
8479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window setLevel:CGShieldingWindowLevel() ];
8489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ gl_context setView: window_view ];
8499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            //[ gl_context setFullScreen ];
8509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ gl_context update ];
8519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
8529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
8549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( !isLion ) {
8559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGLError err;
8569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGLContextObj ctx;
8579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window setLevel:NSNormalWindowLevel ];
8599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            ctx = QZ_GetCGLContextObj (gl_context);
8609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            err = CGLSetFullScreen (ctx);
8619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (err) {
8639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err));
8649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto ERR_NO_GL;
8659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
8669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
8679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
8689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ window_view release ];
8709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ gl_context makeCurrentContext];
8719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        glClear (GL_COLOR_BUFFER_BIT);
8739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ gl_context flushBuffer ];
8759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_OPENGL;
8779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    } else if (isLion) {  /* For 2D, we build a CGBitmapContext */
8789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGColorSpaceRef cgColorspace;
8799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Only recreate the view if it doesn't already exist */
8819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (window_view == nil) {
8829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
8839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
8849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ [ qz_window contentView ] addSubview:window_view ];
8859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ window_view release ];
8869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
8879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        cgColorspace = CGColorSpaceCreateDeviceRGB();
8899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->pitch = 4 * current->w;
8909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->pixels = SDL_malloc (current->h * current->pitch);
8919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h,
8939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        8, current->pitch, cgColorspace,
8949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        kCGImageAlphaNoneSkipFirst);
8959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGColorSpaceRelease (cgColorspace);
8969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_SWSURFACE;
8989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_ASYNCBLIT;
8999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->hwdata = (void *) cg_context;
9009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Force this window to draw above _everything_. */
9029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setLevel:CGShieldingWindowLevel() ];
9039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->UpdateRects     = QZ_UpdateRects;
9059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->LockHWSurface   = QZ_LockHWSurface;
9069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->UnlockHWSurface = QZ_UnlockHWSurface;
9079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
9089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (isLion) {
9109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setHasShadow:NO];
9119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setOpaque:YES];
9129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window makeKeyAndOrderFront:nil ];
9139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
9149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* !!! FIXME: keep an eye on this.
9169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     * This API is officially unavailable for 64-bit binaries.
9179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     *  It happens to work, as of 10.7, but we're going to see if
9189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     *  we can just simply do without it on newer OSes...
9199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall     */
9209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
9219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( !isLion ) {
9229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* If we don't hide menu bar, it will get events and interrupt the program */
9239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        HideMenuBar ();
9249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
9259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #endif
9269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Fade in again (asynchronously) */
9289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
9299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
9309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGReleaseDisplayFadeReservation(fade_token);
9319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
9329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*
9349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        There is a bug in Cocoa where NSScreen doesn't synchronize
9359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        with CGDirectDisplay, so the main screen's frame is wrong.
9369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        As a result, coordinate translation produces incorrect results.
9379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        We can hack around this bug by setting the screen rect
9389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ourselves. This hack should be removed if/when the bug is fixed.
9399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    */
9409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    screen_rect = NSMakeRect(0,0,width,height);
9419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect);
9429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Save the flags to ensure correct tear-down */
9449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mode_flags = current->flags;
9459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Set app state, hide cursor if necessary, ... */
9479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    QZ_DoActivate(this);
9489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return current;
9509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
9529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallERR_NO_GL:      goto ERR_DOUBLEBUF;  /* this goto is to stop a compiler warning on newer SDKs. */
9539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallERR_DOUBLEBUF:  QZ_RestoreDisplayMode(this);
9549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallERR_NO_SWITCH:  CGReleaseAllDisplays ();
9559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallERR_NO_CAPTURE:
9569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallERR_NO_MATCH:   if ( fade_token != kCGDisplayFadeReservationInvalidToken ) {
9579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
9589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    CGReleaseDisplayFadeReservation (fade_token);
9599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
9609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                return NULL;
9619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
9649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                         int height, int *bpp, Uint32 flags,
9659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                         const BOOL save_gl)
9669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    unsigned int style;
9689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    NSRect contentRect;
9699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int center_window = 1;
9709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int origin_x, origin_y;
9719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
9729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->flags = 0;
9749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->w = width;
9759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->h = height;
9769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    contentRect = NSMakeRect (0, 0, width, height);
9789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*
9809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Check if we should completely destroy the previous mode
9819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        - If it is fullscreen
9829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        - If it has different noframe or resizable attribute
9839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        - If it is OpenGL (since gl attributes could be different)
9849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        - If new mode is OpenGL, but previous mode wasn't
9859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    */
9869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (video_set == SDL_TRUE) {
9879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (mode_flags & SDL_FULLSCREEN) {
9889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Fade to black to hide resolution-switching flicker (and garbage
9899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall               that is displayed by a destroyed OpenGL context, if applicable) */
9909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
9919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
9929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
9939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            QZ_UnsetVideoMode (this, TRUE, save_gl);
9949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
9959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) ||
9969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                  (mode_flags & SDL_OPENGL) ||
9979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                  (flags & SDL_OPENGL) ) {
9989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            QZ_UnsetVideoMode (this, TRUE, save_gl);
9999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
10009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
10019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Sorry, QuickDraw was ripped out. */
10039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) {
10049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SetError ("Embedded QuickDraw windows are no longer supported");
10059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (fade_token != kCGDisplayFadeReservationInvalidToken) {
10069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
10079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGReleaseDisplayFadeReservation (fade_token);
10089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
10099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return NULL;
10109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
10119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Check if we should recreate the window */
10139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (qz_window == nil) {
10149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Set the window style based on input flags */
10169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( flags & SDL_NOFRAME ) {
10179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            style = NSBorderlessWindowMask;
10189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            current->flags |= SDL_NOFRAME;
10199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } else {
10209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            style = NSTitledWindowMask;
10219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
10229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( flags & SDL_RESIZABLE ) {
10239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                style |= NSResizableWindowMask;
10249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                current->flags |= SDL_RESIZABLE;
10259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
10269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
10279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Manually create a window, avoids having a nib file resource */
10299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        qz_window = [ [ SDL_QuartzWindow alloc ]
10309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            initWithContentRect:contentRect
10319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                styleMask:style
10329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    backing:NSBackingStoreBuffered
10336f5e132ea50c752390095001aa2d1d9a805fa92dJesse Hall                        defer:YES ];
10349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (qz_window == nil) {
10369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_SetError ("Could not create the Cocoa window");
10379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (fade_token != kCGDisplayFadeReservationInvalidToken) {
10389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
10399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                CGReleaseDisplayFadeReservation (fade_token);
10409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
10419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return NULL;
10429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
10439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /*[ qz_window setReleasedWhenClosed:YES ];*/ /* no need to set this as it's the default for NSWindows */
10459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_SetCaption(this, this->wm_title, this->wm_icon);
10469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setAcceptsMouseMovedEvents:YES ];
10479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setViewsNeedDisplay:NO ];
10489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( QZ_WindowPosition(this, &origin_x, &origin_y) ) {
10509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* have to flip the Y value (NSPoint is lower left corner origin) */
10519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window setFrameTopLeftPoint:NSMakePoint((float) origin_x, (float) (this->info.current_h - origin_y))];
10529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            center_window = 0;
10539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        } else if ( center_window ) {
10549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window center ];
10559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
10569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setDelegate:
10589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ [ SDL_QuartzWindowDelegate alloc ] init ] ];
10599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ];
10609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
10619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* We already have a window, just change its size */
10629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
10639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window setContentSize:contentRect.size ];
10649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags;
10659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ window_view setFrameSize:contentRect.size ];
10669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
10679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* For OpenGL, we bind the context to a subview */
10699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( flags & SDL_OPENGL ) {
10709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( ! save_gl ) {
10729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) {
10739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if (fade_token != kCGDisplayFadeReservationInvalidToken) {
10749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
10759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    CGReleaseDisplayFadeReservation (fade_token);
10769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
10779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                return NULL;
10789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
10799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
10809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
10829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
10839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ [ qz_window contentView ] addSubview:window_view ];
10849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ gl_context setView: window_view ];
10859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ window_view release ];
10869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ gl_context makeCurrentContext];
10879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [ qz_window makeKeyAndOrderFront:nil ];
10889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_OPENGL;
10899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
10909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* For 2D, we build a CGBitmapContext */
10919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
10929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGColorSpaceRef cgColorspace;
10939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Only recreate the view if it doesn't already exist */
10959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (window_view == nil) {
10969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
10989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
10999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ [ qz_window contentView ] addSubview:window_view ];
11009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ window_view release ];
11019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [ qz_window makeKeyAndOrderFront:nil ];
11029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
11039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        cgColorspace = CGColorSpaceCreateDeviceRGB();
11059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->pitch = 4 * current->w;
11069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->pixels = SDL_malloc (current->h * current->pitch);
11079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h,
11099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        8, current->pitch, cgColorspace,
11109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                        kCGImageAlphaNoneSkipFirst);
11119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGColorSpaceRelease (cgColorspace);
11129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_SWSURFACE;
11149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->flags |= SDL_ASYNCBLIT;
11159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current->hwdata = (void *) cg_context;
11169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->UpdateRects     = QZ_UpdateRects;
11189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->LockHWSurface   = QZ_LockHWSurface;
11199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        this->UnlockHWSurface = QZ_UnlockHWSurface;
11209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
11219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Save flags to ensure correct teardown */
11239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mode_flags = current->flags;
11249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */
11269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (fade_token != kCGDisplayFadeReservationInvalidToken) {
11279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
11289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGReleaseDisplayFadeReservation (fade_token);
11299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
11309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return current;
11329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
11339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface* QZ_SetVideoModeInternal (_THIS, SDL_Surface *current,
11369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                             int width, int height, int bpp,
11379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                             Uint32 flags, BOOL save_gl)
11389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
11399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const BOOL isLion = IS_LION_OR_LATER(this);
11409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->flags = 0;
11429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current->pixels = NULL;
11439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Setup full screen video */
11459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( flags & SDL_FULLSCREEN ) {
11469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( isLion ) {
11479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            bpp = 32;
11489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
11499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags, save_gl );
11509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (current == NULL)
11519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return NULL;
11529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
11539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Setup windowed video */
11549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
11559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Force bpp to 32 */
11569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        bpp = 32;
11579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags, save_gl );
11589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (current == NULL)
11599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return NULL;
11609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
11619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (qz_window != nil) {
11639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        nsgfx_context = [NSGraphicsContext graphicsContextWithWindow:qz_window];
11649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [NSGraphicsContext setCurrentContext:nsgfx_context];
11659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
11669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Setup the new pixel format */
11689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
11699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int amask = 0,
11709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        rmask = 0,
11719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        gmask = 0,
11729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        bmask = 0;
11739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        switch (bpp) {
11759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            case 16:   /* (1)-5-5-5 RGB */
11769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                amask = 0;
11779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                rmask = 0x7C00;
11789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                gmask = 0x03E0;
11799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                bmask = 0x001F;
11809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                break;
11819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            case 24:
11829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                SDL_SetError ("24bpp is not available");
11839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                return NULL;
11849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            case 32:   /* (8)-8-8-8 ARGB */
11859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                amask = 0x00000000;
11869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                if ( (!isLion) && (flags & SDL_FULLSCREEN) ) {
11879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    rmask = 0x00FF0000;
11889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    gmask = 0x0000FF00;
11899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    bmask = 0x000000FF;
11909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                } else {
11919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if SDL_BYTEORDER == SDL_LIL_ENDIAN
11929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    rmask = 0x0000FF00;
11939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    gmask = 0x00FF0000;
11949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    bmask = 0xFF000000;
11959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
11969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    rmask = 0x00FF0000;
11979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    gmask = 0x0000FF00;
11989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    bmask = 0x000000FF;
11999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
12009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    break;
12019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                }
12029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
12039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if ( ! SDL_ReallocFormat (current, bpp,
12059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                  rmask, gmask, bmask, amask ) ) {
12069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_SetError ("Couldn't reallocate pixel format");
12079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return NULL;
12089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
12099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
12109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Signal successful completion (used internally) */
12129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    video_set = SDL_TRUE;
12139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return current;
12159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface* QZ_SetVideoMode(_THIS, SDL_Surface *current,
12189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                    int width, int height, int bpp,
12199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                                    Uint32 flags)
12209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Don't throw away the GL context if we can just resize the current one. */
12229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if 0  /* !!! FIXME: half-finished side project. Reenable this if you ever debug the corner cases. */
12239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const BOOL save_gl = ( (video_set == SDL_TRUE) && ((flags & SDL_OPENGL) == (current->flags & SDL_OPENGL)) && (bpp == current->format->BitsPerPixel) );
12249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
12259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const BOOL save_gl = NO;
12269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
12279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    NSOpenGLContext *glctx = gl_context;
12299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Surface* retval = NULL;
12309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (save_gl) {
12329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [glctx retain];  /* just so we don't lose this when killing old views, etc */
12339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
12349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    retval = QZ_SetVideoModeInternal (this, current, width, height, bpp, flags, save_gl);
12369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (save_gl) {
12389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [glctx release];  /* something else should own this now, or we legitimately release it. */
12399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
12409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return retval;
12429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_ToggleFullScreen (_THIS, int on)
12469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
12489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_SetColors (_THIS, int first_color, int num_colors,
12519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                         SDL_Color *colors)
12529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
12549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* we shouldn't have an 8-bit mode on Lion! */
12559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!IS_LION_OR_LATER(this)) {
12569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGTableCount  index;
12579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGDeviceColor color;
12589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        for (index = first_color; index < first_color+num_colors; index++) {
12609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Clamp colors between 0.0 and 1.0 */
12629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            color.red   = colors->r / 255.0;
12639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            color.blue  = colors->b / 255.0;
12649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            color.green = colors->g / 255.0;
12659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            colors++;
12679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGPaletteSetColorAtIndex (palette, color, index);
12699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
12709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return ( CGDisplayNoErr == CGDisplaySetPalette (display_id, palette) );
12729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
12739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
12749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
12769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
12799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface)
12809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 1;
12829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface)
12859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */
12899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic AbsoluteTime QZ_SecondsToAbsolute ( double seconds )
12909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    union
12929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
12939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        UInt64 i;
12949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Nanoseconds ns;
12959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    } temp;
12969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    temp.i = seconds * 1000000000.0;
12989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return NanosecondsToAbsolute ( temp.ns );
13009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_ThreadFlip (_THIS)
13039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
13049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Uint8 *src, *dst;
13059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int skip, len, h;
13069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /*
13089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        Give this thread the highest scheduling priority possible,
13099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        in the hopes that it will immediately run after the VBL delay
13109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    */
13119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
13129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        pthread_t current_thread;
13139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int policy;
13149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        struct sched_param param;
13159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        current_thread = pthread_self ();
13179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        pthread_getschedparam (current_thread, &policy, &param);
13189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        policy = SCHED_RR;
13199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        param.sched_priority = sched_get_priority_max (policy);
13209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        pthread_setschedparam (current_thread, policy, &param);
13219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
13229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    while (1) {
13249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SemWait (sem1);
13269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (quit_thread)
13279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            return 0;
13289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /*
13309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         * We have to add SDL_VideoSurface->offset here, since we might be a
13319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         *  smaller surface in the center of the framebuffer (you asked for
13329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         *  a fullscreen resolution smaller than the hardware could supply
13339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         *  so SDL is centering it in a bigger resolution)...
13349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         */
13359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        dst = ((Uint8 *)((size_t)CGDisplayBaseAddress (display_id))) + SDL_VideoSurface->offset;
13369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        src = current_buffer + SDL_VideoSurface->offset;
13379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel;
13389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        h = SDL_VideoSurface->h;
13399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        skip = SDL_VideoSurface->pitch;
13409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */
13429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        {
13439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */
13459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            double refreshRate;
13469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            double linesPerSecond;
13479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            double target;
13489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            double position;
13499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            double adjustment;
13509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            AbsoluteTime nextTime;
13519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CFNumberRef refreshRateCFNumber;
13529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate);
13549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( NULL == refreshRateCFNumber ) {
13559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                SDL_SetError ("Mode has no refresh rate");
13569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto ERROR;
13579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
13589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) {
13609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                SDL_SetError ("Error getting refresh rate");
13619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                goto ERROR;
13629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
13639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if ( 0 == refreshRate ) {
13659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall               SDL_SetError ("Display has no refresh rate, using 60hz");
13679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                /* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */
13699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                refreshRate = 60.0;
13709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            }
13719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            linesPerSecond = refreshRate * h;
13739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            target = h;
13749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            /* Figure out the first delay so we start off about right */
13769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            position = CGDisplayBeamPosition (display_id);
13779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (position > target)
13789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                position = 0;
13799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            adjustment = (target - position) / linesPerSecond;
13819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment));
13839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            MPDelayUntil (&nextTime);
13859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
13869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* On error, skip VBL delay */
13899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ERROR:
13909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* TODO: use CGContextDrawImage here too!  Create two CGContextRefs the same way we
13929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           create two buffers, replace current_buffer with current_context and set it
13939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           appropriately in QZ_FlipDoubleBuffer.  */
13949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        while ( h-- ) {
13959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_memcpy (dst, src, len);
13979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            src += skip;
13989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            dst += skip;
13999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
14009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* signal flip completion */
14029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_SemPost (sem2);
14039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
14049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
14069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface)
14099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
14109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* wait for previous flip to complete */
14119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SemWait (sem2);
14129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    current_buffer = surface->pixels;
14149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (surface->pixels == sw_buffers[0])
14169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        surface->pixels = sw_buffers[1];
14179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
14189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        surface->pixels = sw_buffers[0];
14199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* signal worker thread to do the flip */
14219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_SemPost (sem1);
14229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
14249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects)
14279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
14289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* perform a flip if someone calls updaterects on a doublebuferred surface */
14299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->FlipHWSurface (this, SDL_VideoSurface);
14309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects)
14339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
14349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#pragma unused(this,num_rects,rects)
14359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
14379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Resize icon, BMP format */
14399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const unsigned char QZ_ResizeIcon[] = {
14409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00,
14419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00,
14429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00,
14439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
14469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,
14479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
14489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87,
14499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,
14509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
14519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8,
14529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,
14539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,
14559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
14569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,
14579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,
14589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,
14609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
14619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc,
14639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,
14659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff,
14669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8,
14689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff,
14719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc,
14739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b
14769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
14779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_DrawResizeIcon (_THIS)
14799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
14809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Check if we should draw the resize icon */
14819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (SDL_VideoSurface->flags & SDL_RESIZABLE) {
14829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_Rect icon_rect;
14849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Create the icon image */
14869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (resize_icon == NULL) {
14879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_RWops *rw;
14899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_Surface *tmp;
14909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon));
14929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            tmp = SDL_LoadBMP_RW (rw, SDL_TRUE);
14939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY);
14959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF);
14969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            SDL_FreeSurface (tmp);
14989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
14999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        icon_rect.x = SDL_VideoSurface->w - 13;
15019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        icon_rect.y = SDL_VideoSurface->h - 13;
15029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        icon_rect.w = 13;
15039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        icon_rect.h = 13;
15049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect);
15069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects)
15109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
15119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
15129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_GL_SwapBuffers (this);
15139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else if ( [ qz_window isMiniaturized ] ) {
15159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Do nothing if miniaturized */
15179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
15209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
15219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */
15229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            [NSGraphicsContext setCurrentContext:nsgfx_context];
15239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            ctx = nsgfx_context;
15249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
15259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGContextRef cgc = (CGContextRef) [ctx graphicsPort];
15269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_DrawResizeIcon (this);
15279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGContextFlush (cg_context);
15289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGImageRef image = CGBitmapContextCreateImage (cg_context);
15299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height);
15309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGContextDrawImage (cgc, rectangle, image);
15329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGImageRelease(image);
15339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGContextFlush (cgc);
15349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_VideoQuit (_THIS)
15389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
15399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
15409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Restore gamma settings */
15429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGDisplayRestoreColorSyncSettings ();
15439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Ensure the cursor will be visible and working when we quit */
15459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGDisplayShowCursor (display_id);
15469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGAssociateMouseAndMouseCursorPosition (1);
15479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (mode_flags & SDL_FULLSCREEN) {
15499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        /* Fade to black to hide resolution-switching flicker (and garbage
15509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall           that is displayed by a destroyed OpenGL context, if applicable) */
15519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) {
15529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
15539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
15549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_UnsetVideoMode (this, TRUE, FALSE);
15559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (fade_token != kCGDisplayFadeReservationInvalidToken) {
15569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
15579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            CGReleaseDisplayFadeReservation (fade_token);
15589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
15599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
15619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        QZ_UnsetVideoMode (this, TRUE, FALSE);
15629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
15649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (!IS_LION_OR_LATER(this)) {
15659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        CGPaletteRelease(palette);
15669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
15689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (opengl_library) {
15709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_UnloadObject(opengl_library);
15719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        opengl_library = NULL;
15729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    this->gl_config.driver_loaded = 0;
15749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (field_edit) {
15769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        [field_edit release];
15779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        field_edit = NULL;
15789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
15799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int  QZ_LockHWSurface(_THIS, SDL_Surface *surface)
15829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
15839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 1;
15849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface)
15879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
15889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int QZ_AllocHWSurface(_THIS, SDL_Surface *surface)
15919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
15929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return(-1); /* unallowed (no HWSURFACE support here). */
15939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void QZ_FreeHWSurface (_THIS, SDL_Surface *surface)
15969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
15979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
15989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
15999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Gamma functions */
16009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint QZ_SetGamma (_THIS, float red, float green, float blue)
16019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
16029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const CGGammaValue min = 0.0, max = 1.0;
16039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (red == 0.0)
16059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        red = FLT_MAX;
16069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
16079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        red = 1.0 / red;
16089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (green == 0.0)
16109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        green = FLT_MAX;
16119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
16129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        green = 1.0 / green;
16139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (blue == 0.0)
16159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        blue = FLT_MAX;
16169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
16179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        blue  = 1.0 / blue;
16189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( CGDisplayNoErr == CGSetDisplayTransferByFormula
16209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         (display_id, min, max, red, min, max, green, min, max, blue) ) {
16219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return 0;
16239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
16249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else {
16259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return -1;
16279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
16289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
16299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint QZ_GetGamma (_THIS, float *red, float *green, float *blue)
16319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
16329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGGammaValue dummy;
16339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( CGDisplayNoErr == CGGetDisplayTransferByFormula
16349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         (display_id, &dummy, &dummy, red,
16359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall          &dummy, &dummy, green, &dummy, &dummy, blue) )
16369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return 0;
16389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
16399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return -1;
16409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
16419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint QZ_SetGammaRamp (_THIS, Uint16 *ramp)
16439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
16449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const uint32_t tableSize = 255;
16459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGGammaValue redTable[tableSize];
16469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGGammaValue greenTable[tableSize];
16479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGGammaValue blueTable[tableSize];
16489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int i;
16509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
16529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i = 0; i < 256; i++)
16539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        redTable[i % 256] = ramp[i] / 65535.0;
16549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i=256; i < 512; i++)
16569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        greenTable[i % 256] = ramp[i] / 65535.0;
16579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i=512; i < 768; i++)
16599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        blueTable[i % 256] = ramp[i] / 65535.0;
16609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( CGDisplayNoErr == CGSetDisplayTransferByTable
16629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         (display_id, tableSize, redTable, greenTable, blueTable) )
16639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return 0;
16649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    else
16659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return -1;
16669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
16679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint QZ_GetGammaRamp (_THIS, Uint16 *ramp)
16699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
16709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    const uint32_t tableSize = 255;
16719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGGammaValue redTable[tableSize];
16729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGGammaValue greenTable[tableSize];
16739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CGGammaValue blueTable[tableSize];
16749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    uint32_t actual;
16759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int i;
16769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if ( CGDisplayNoErr != CGGetDisplayTransferByTable
16789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         (display_id, tableSize, redTable, greenTable, blueTable, &actual) ||
16799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall         actual != tableSize)
16809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return -1;
16829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    /* Pack tables into one array, with values from 0 to 65535 */
16849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i = 0; i < 256; i++)
16859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ramp[i] = redTable[i % 256] * 65535.0;
16869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i=256; i < 512; i++)
16889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ramp[i] = greenTable[i % 256] * 65535.0;
16899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i=512; i < 768; i++)
16919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        ramp[i] = blueTable[i % 256] * 65535.0;
16929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
16939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
16949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
16959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1696