src/video/quartz/SDL_QuartzVideo.h
author Sam Lantinga
Sat, 01 Feb 2003 19:59:23 +0000
changeset 588 2c6510c0a304
parent 563 04dcaf3da918
child 615 7ec821f3cbd0
permissions -rw-r--r--
Darrell added support for emulated SDL_DOUBLEBUF on MacOSX
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 /*    
    24     @file   SDL_QuartzVideo.h
    25     @author Darrell Walisser, Max Horn, et al.
    26     
    27     @abstract SDL video driver for Mac OS X.
    28     
    29     @discussion
    30     
    31     TODO
    32         - Hardware Cursor support with NSCursor instead of Carbon
    33         - Keyboard repeat/mouse speed adjust (if needed)
    34         - Multiple monitor support (currently only main display)
    35         - Accelerated blitting support
    36         - Fix white OpenGL window on minimize (fixed) (update: broken again on 10.2)
    37         - Find out what events should be sent/ignored if window is minimized
    38         - Find a way to deal with external resolution/depth switch while app is running
    39         - Resizeable windows (done)
    40         - Check accuracy of QZ_SetGamma()
    41     Problems:
    42         - OGL not working in full screen with software renderer
    43         - SetColors sets palette correctly but clears framebuffer
    44         - Crash in CG after several mode switches (I think this has been fixed)
    45         - Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows)
    46         - Cursor in 8 bit modes is screwy (might just be Radeon PCI bug) (update: not just Radeon)
    47         - Warping cursor delays mouse events for a fraction of a second,
    48           there is a hack around this that helps a bit
    49 */
    50 
    51 #include <Cocoa/Cocoa.h>
    52 #include <OpenGL/OpenGL.h>
    53 #include <Carbon/Carbon.h>
    54 #include <QuickTime/QuickTime.h>
    55 #include <IOKit/IOKitLib.h>	/* For powersave handling */
    56 #include <pthread.h>
    57 
    58 #include "SDL_thread.h"
    59 #include "SDL_video.h"
    60 #include "SDL_error.h"
    61 #include "SDL_timer.h"
    62 #include "SDL_syswm.h"
    63 #include "SDL_sysvideo.h"
    64 #include "SDL_pixels_c.h"
    65 #include "SDL_events_c.h"
    66 
    67 /* 
    68     Add methods to get at private members of NSScreen. 
    69     Since there is a bug in Apple's screen switching code
    70     that does not update this variable when switching
    71     to fullscreen, we'll set it manually (but only for the
    72     main screen).
    73 */
    74 @interface NSScreen (NSScreenAccess)
    75 - (void) setFrame:(NSRect)frame;
    76 @end
    77 
    78 @implementation NSScreen (NSScreenAccess)
    79 - (void) setFrame:(NSRect)frame;
    80 {
    81     _frame = frame;
    82 }
    83 @end
    84 
    85 /* 
    86     This is a workaround to directly access NSOpenGLContext's CGL context
    87     We need this to check for errors NSOpenGLContext doesn't support
    88 */
    89 @interface NSOpenGLContext (CGLContextAccess)
    90 - (CGLContextObj) cglContext;
    91 @end
    92 
    93 @implementation NSOpenGLContext (CGLContextAccess)
    94 - (CGLContextObj) cglContext;
    95 {
    96     return _contextAuxiliary;
    97 }
    98 @end
    99 
   100 /* 
   101     Structure for rez switch gamma fades
   102     We can hide the monitor flicker by setting the gamma tables to 0
   103 */
   104 #define QZ_GAMMA_TABLE_SIZE 256
   105 
   106 typedef struct {
   107 
   108     CGGammaValue red[QZ_GAMMA_TABLE_SIZE];
   109     CGGammaValue green[QZ_GAMMA_TABLE_SIZE];
   110     CGGammaValue blue[QZ_GAMMA_TABLE_SIZE];
   111 
   112 } SDL_QuartzGammaTable;
   113 
   114 /* Main driver structure to store required state information */
   115 typedef struct SDL_PrivateVideoData {
   116 
   117     CGDirectDisplayID  display;            /* 0 == main display (only support single display) */
   118     CFDictionaryRef    mode;               /* current mode of the display */
   119     CFDictionaryRef    save_mode;          /* original mode of the display */
   120     CFArrayRef         mode_list;          /* list of available fullscreen modes */
   121     CGDirectPaletteRef palette;            /* palette of an 8-bit display */
   122     NSOpenGLContext    *gl_context;        /* OpenGL rendering context */
   123     Uint32             width, height, bpp; /* frequently used data about the display */
   124     Uint32             flags;              /* flags for current mode, for teardown purposes */
   125     Uint32             video_set;          /* boolean; indicates if video was set correctly */
   126     Uint32             warp_flag;          /* boolean; notify to event loop that a warp just occured */
   127     Uint32             warp_ticks;         /* timestamp when the warp occured */
   128     NSWindow           *window;            /* Cocoa window to implement the SDL window */
   129     NSQuickDrawView    *view;              /* the window's view; draw 2D and OpenGL into this view */
   130     SDL_Surface        *resize_icon;       /* icon for the resize badge, we have to draw it by hand */
   131     SDL_GrabMode       current_grab_mode;  /* default value is SDL_GRAB_OFF */
   132     BOOL               in_foreground;      /* boolean; indicate if app is in foreground or not */
   133     SDL_Rect           **client_mode_list; /* resolution list to pass back to client */
   134     SDLKey             keymap[256];        /* Mac OS X to SDL key mapping */
   135     Uint32             current_mods;       /* current keyboard modifiers, to track modifier state */
   136     Uint32             last_virtual_button;/* last virtual mouse button pressed */
   137     io_connect_t       power_connection;   /* used with IOKit to detect wake from sleep */
   138     Uint8              expect_mouse_up;    /* used to determine when to send mouse up events */
   139     Uint8              grab_state;         /* used to manage grab behavior */
   140     NSPoint            cursor_loc;         /* saved cursor coords, for activate/deactivate when grabbed */
   141     BOOL          	   cursor_visible;     /* tells if cursor was hidden or not */
   142     Uint8*             sw_buffers[2];      /* pointers to the two software buffers for double-buffer emulation */
   143     SDL_Thread         *thread;            /* thread for async updates to the screen */
   144     SDL_sem            *sem1, *sem2;       /* synchronization for async screen updates */
   145     Uint8              *current_buffer;    /* the buffer being copied to the screen */
   146     BOOL               quit_thread;        /* used to quit the async blitting thread */
   147     
   148     ImageDescriptionHandle yuv_idh;
   149     MatrixRecordPtr        yuv_matrix;
   150     DecompressorComponent  yuv_codec;
   151     ImageSequence          yuv_seq;
   152     PlanarPixmapInfoYUV420 *yuv_pixmap;
   153     Sint16                  yuv_width, yuv_height;
   154     CGrafPtr                yuv_port;
   155 
   156 } SDL_PrivateVideoData ;
   157 
   158 #define _THIS    SDL_VideoDevice *this
   159 #define display_id (this->hidden->display)
   160 #define mode (this->hidden->mode)
   161 #define save_mode (this->hidden->save_mode)
   162 #define mode_list (this->hidden->mode_list)
   163 #define palette (this->hidden->palette)
   164 #define gl_context (this->hidden->gl_context)
   165 #define device_width (this->hidden->width)
   166 #define device_height (this->hidden->height)
   167 #define device_bpp (this->hidden->bpp)
   168 #define mode_flags (this->hidden->flags)
   169 #define qz_window (this->hidden->window)
   170 #define window_view (this->hidden->view)
   171 #define video_set (this->hidden->video_set)
   172 #define warp_ticks (this->hidden->warp_ticks)
   173 #define warp_flag (this->hidden->warp_flag)
   174 #define resize_icon (this->hidden->resize_icon)
   175 #define current_grab_mode (this->hidden->current_grab_mode)
   176 #define in_foreground (this->hidden->in_foreground)
   177 #define client_mode_list (this->hidden->client_mode_list)
   178 #define keymap (this->hidden->keymap)
   179 #define current_mods (this->hidden->current_mods)
   180 #define last_virtual_button (this->hidden->last_virtual_button)
   181 #define power_connection (this->hidden->power_connection)
   182 #define expect_mouse_up (this->hidden->expect_mouse_up)
   183 #define grab_state (this->hidden->grab_state)
   184 #define cursor_loc (this->hidden->cursor_loc)
   185 #define cursor_visible (this->hidden->cursor_visible)
   186 #define sw_buffers (this->hidden->sw_buffers)
   187 #define thread (this->hidden->thread)
   188 #define sem1 (this->hidden->sem1)
   189 #define sem2 (this->hidden->sem2)
   190 #define current_buffer (this->hidden->current_buffer)
   191 #define quit_thread (this->hidden->quit_thread)
   192 
   193 #define yuv_idh (this->hidden->yuv_idh)
   194 #define yuv_matrix (this->hidden->yuv_matrix)
   195 #define yuv_codec (this->hidden->yuv_codec)
   196 #define yuv_seq (this->hidden->yuv_seq)
   197 #define yuv_pixmap (this->hidden->yuv_pixmap)
   198 #define yuv_data (this->hidden->yuv_data)
   199 #define yuv_width (this->hidden->yuv_width)
   200 #define yuv_height (this->hidden->yuv_height)
   201 #define yuv_port (this->hidden->yuv_port)
   202 
   203 
   204 /* grab states - the input is in one of these states */
   205 enum {
   206     QZ_UNGRABBED = 0,
   207     QZ_VISIBLE_GRAB,
   208     QZ_INVISIBLE_GRAB
   209 };
   210 
   211 /* grab actions - these can change the grabbed state */
   212 enum {
   213     QZ_ENABLE_GRAB = 0,
   214     QZ_DISABLE_GRAB,
   215     QZ_HIDECURSOR,
   216     QZ_SHOWCURSOR
   217 };
   218 
   219 /* 
   220     Obscuring code: maximum number of windows above ours (inclusive) 
   221     
   222     Note: this doesn't work too well in practice and should be
   223     phased out when we add OpenGL 2D acceleration. It was never
   224     enabled in the first place, so this shouldn't be a problem ;-)
   225 */
   226 #define kMaxWindows 256
   227 
   228 /* Some of the Core Graphics Server API for obscuring code */
   229 #define kCGSWindowLevelTop          2147483632
   230 #define kCGSWindowLevelDockIconDrag 500
   231 #define kCGSWindowLevelDockMenu     101
   232 #define kCGSWindowLevelMenuIgnore    21
   233 #define kCGSWindowLevelMenu          20
   234 #define kCGSWindowLevelDockLabel     12
   235 #define kCGSWindowLevelDockIcon      11
   236 #define kCGSWindowLevelDock          10
   237 #define kCGSWindowLevelUtility        3
   238 #define kCGSWindowLevelNormal         0
   239 
   240 /* 
   241     For completeness; We never use these window levels, they are always below us
   242     #define kCGSWindowLevelMBarShadow -20
   243     #define kCGSWindowLevelDesktopPicture -2147483647
   244     #define kCGSWindowLevelDesktop        -2147483648
   245 */
   246 
   247 typedef CGError       CGSError;
   248 typedef long          CGSWindowCount;
   249 typedef void *        CGSConnectionID;
   250 typedef int           CGSWindowID;
   251 typedef CGSWindowID*  CGSWindowIDList;
   252 typedef CGWindowLevel CGSWindowLevel;
   253 typedef NSRect        CGSRect;
   254 
   255 extern CGSConnectionID _CGSDefaultConnection ();
   256 
   257 extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid,
   258                                           CGSConnectionID owner,
   259                                           CGSWindowCount listCapacity,
   260                                           CGSWindowIDList list,
   261                                           CGSWindowCount *listCount);
   262 
   263 extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid,
   264                                            CGSWindowID wid,
   265                                            CGSRect *rect);
   266 
   267 extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid,
   268                                         CGSWindowID wid,
   269                                         CGSWindowLevel *level);
   270 
   271 extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
   272                                   unsigned int w, unsigned int h, unsigned int color);
   273 
   274 extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id);
   275 
   276 extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags);
   277 
   278 int CGSDisplayHWSync (CGDirectDisplayID id);
   279 
   280 /* Bootstrap functions */
   281 static int              QZ_Available ();
   282 static SDL_VideoDevice* QZ_CreateDevice (int device_index);
   283 static void             QZ_DeleteDevice (SDL_VideoDevice *device);
   284 
   285 /* Initialization, Query, Setup, and Redrawing functions */
   286 static int          QZ_VideoInit        (_THIS, SDL_PixelFormat *video_format);
   287 
   288 static SDL_Rect**   QZ_ListModes        (_THIS, SDL_PixelFormat *format,
   289                                          Uint32 flags);
   290 static void         QZ_UnsetVideoMode   (_THIS);
   291 
   292 static SDL_Surface* QZ_SetVideoMode     (_THIS, SDL_Surface *current,
   293                                          int width, int height, int bpp,
   294                                          Uint32 flags);
   295 static int          QZ_ToggleFullScreen (_THIS, int on);
   296 static int          QZ_SetColors        (_THIS, int first_color,
   297                                          int num_colors, SDL_Color *colors);
   298 
   299 static int          QZ_LockDoubleBuffer   (_THIS, SDL_Surface *surface);
   300 static void         QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface);
   301 static int          QZ_ThreadFlip         (_THIS);
   302 static int          QZ_FlipDoubleBuffer   (_THIS, SDL_Surface *surface);
   303 static void         QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects);
   304 
   305 static void         QZ_DirectUpdate     (_THIS, int num_rects, SDL_Rect *rects);
   306 static int          QZ_LockWindow       (_THIS, SDL_Surface *surface);
   307 static void         QZ_UnlockWindow     (_THIS, SDL_Surface *surface);
   308 static void         QZ_UpdateRects      (_THIS, int num_rects, SDL_Rect *rects);
   309 static void         QZ_VideoQuit        (_THIS);
   310 
   311 /* Hardware surface functions (for fullscreen mode only) */
   312 static int  QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
   313 static int  QZ_LockHWSurface(_THIS, SDL_Surface *surface);
   314 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface);
   315 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface);
   316 /* static int  QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */
   317 
   318 /* Gamma Functions */
   319 static int QZ_SetGamma     (_THIS, float red, float green, float blue);
   320 static int QZ_GetGamma     (_THIS, float *red, float *green, float *blue);
   321 static int QZ_SetGammaRamp (_THIS, Uint16 *ramp);
   322 static int QZ_GetGammaRamp (_THIS, Uint16 *ramp);
   323 
   324 /* OpenGL functions */
   325 static int    QZ_SetupOpenGL       (_THIS, int bpp, Uint32 flags);
   326 static void   QZ_TearDownOpenGL    (_THIS);
   327 static void*  QZ_GL_GetProcAddress (_THIS, const char *proc);
   328 static int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value);
   329 static int    QZ_GL_MakeCurrent    (_THIS);
   330 static void   QZ_GL_SwapBuffers    (_THIS);
   331 static int    QZ_GL_LoadLibrary    (_THIS, const char *location);
   332 
   333 /* Private function to warp the cursor (used internally) */
   334 static void  QZ_PrivateWarpCursor (_THIS, int x, int y);
   335 
   336 /* Cursor and Mouse functions */
   337 static void         QZ_FreeWMCursor     (_THIS, WMcursor *cursor);
   338 static WMcursor*    QZ_CreateWMCursor   (_THIS, Uint8 *data, Uint8 *mask,
   339                                          int w, int h, int hot_x, int hot_y);
   340 static int          QZ_ShowWMCursor     (_THIS, WMcursor *cursor);
   341 static void         QZ_WarpWMCursor     (_THIS, Uint16 x, Uint16 y);
   342 static void         QZ_MoveWMCursor     (_THIS, int x, int y);
   343 static void         QZ_CheckMouseMode   (_THIS);
   344 
   345 /* Event functions */
   346 static void         QZ_InitOSKeymap     (_THIS);
   347 static void         QZ_PumpEvents       (_THIS);
   348 
   349 /* Window Manager functions */
   350 static void QZ_SetCaption        (_THIS, const char *title, const char *icon);
   351 static void QZ_SetIcon           (_THIS, SDL_Surface *icon, Uint8 *mask);
   352 static int  QZ_IconifyWindow     (_THIS);
   353 static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
   354 /*static int  QZ_GetWMInfo     (_THIS, SDL_SysWMinfo *info);*/
   355 
   356 /* YUV functions */
   357 static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
   358                                          Uint32 format, SDL_Surface *display);