src/video/quartz/SDL_QuartzVideo.h
author Sam Lantinga
Sat, 09 Aug 2003 21:13:22 +0000
changeset 679 74b4b9f9e5e1
parent 656 864e2d2a9a55
child 761 c5b2b6d2d1fe
permissions -rw-r--r--
*** empty log message ***
     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 <OpenGL/gl.h>
    54 #include <OpenGL/glext.h>
    55 #include <Carbon/Carbon.h>
    56 #include <QuickTime/QuickTime.h>
    57 #include <IOKit/IOKitLib.h>	/* For powersave handling */
    58 #include <pthread.h>
    59 
    60 #include "SDL_thread.h"
    61 #include "SDL_video.h"
    62 #include "SDL_error.h"
    63 #include "SDL_timer.h"
    64 #include "SDL_syswm.h"
    65 #include "SDL_sysvideo.h"
    66 #include "SDL_pixels_c.h"
    67 #include "SDL_events_c.h"
    68 
    69 /* 
    70     Add methods to get at private members of NSScreen. 
    71     Since there is a bug in Apple's screen switching code
    72     that does not update this variable when switching
    73     to fullscreen, we'll set it manually (but only for the
    74     main screen).
    75 */
    76 @interface NSScreen (NSScreenAccess)
    77 - (void) setFrame:(NSRect)frame;
    78 @end
    79 
    80 @implementation NSScreen (NSScreenAccess)
    81 - (void) setFrame:(NSRect)frame;
    82 {
    83     _frame = frame;
    84 }
    85 @end
    86 
    87 /* 
    88     This is a workaround to directly access NSOpenGLContext's CGL context
    89     We need this to check for errors NSOpenGLContext doesn't support
    90 */
    91 @interface NSOpenGLContext (CGLContextAccess)
    92 - (CGLContextObj) cglContext;
    93 @end
    94 
    95 @implementation NSOpenGLContext (CGLContextAccess)
    96 - (CGLContextObj) cglContext;
    97 {
    98     return _contextAuxiliary;
    99 }
   100 @end
   101 
   102 /* 
   103     Structure for rez switch gamma fades
   104     We can hide the monitor flicker by setting the gamma tables to 0
   105 */
   106 #define QZ_GAMMA_TABLE_SIZE 256
   107 
   108 typedef struct {
   109 
   110     CGGammaValue red[QZ_GAMMA_TABLE_SIZE];
   111     CGGammaValue green[QZ_GAMMA_TABLE_SIZE];
   112     CGGammaValue blue[QZ_GAMMA_TABLE_SIZE];
   113 
   114 } SDL_QuartzGammaTable;
   115 
   116 /* Main driver structure to store required state information */
   117 typedef struct SDL_PrivateVideoData {
   118 
   119     CGDirectDisplayID  display;            /* 0 == main display (only support single display) */
   120     CFDictionaryRef    mode;               /* current mode of the display */
   121     CFDictionaryRef    save_mode;          /* original mode of the display */
   122     CFArrayRef         mode_list;          /* list of available fullscreen modes */
   123     CGDirectPaletteRef palette;            /* palette of an 8-bit display */
   124     NSOpenGLContext    *gl_context;        /* OpenGL rendering context */
   125     Uint32             width, height, bpp; /* frequently used data about the display */
   126     Uint32             flags;              /* flags for current mode, for teardown purposes */
   127     Uint32             video_set;          /* boolean; indicates if video was set correctly */
   128     Uint32             warp_flag;          /* boolean; notify to event loop that a warp just occured */
   129     Uint32             warp_ticks;         /* timestamp when the warp occured */
   130     NSWindow           *window;            /* Cocoa window to implement the SDL window */
   131     NSQuickDrawView    *view;              /* the window's view; draw 2D and OpenGL into this view */
   132     SDL_Surface        *resize_icon;       /* icon for the resize badge, we have to draw it by hand */
   133     SDL_GrabMode       current_grab_mode;  /* default value is SDL_GRAB_OFF */
   134     BOOL               in_foreground;      /* boolean; indicate if app is in foreground or not */
   135     SDL_Rect           **client_mode_list; /* resolution list to pass back to client */
   136     SDLKey             keymap[256];        /* Mac OS X to SDL key mapping */
   137     Uint32             current_mods;       /* current keyboard modifiers, to track modifier state */
   138     Uint32             last_virtual_button;/* last virtual mouse button pressed */
   139     io_connect_t       power_connection;   /* used with IOKit to detect wake from sleep */
   140     Uint8              expect_mouse_up;    /* used to determine when to send mouse up events */
   141     Uint8              grab_state;         /* used to manage grab behavior */
   142     NSPoint            cursor_loc;         /* saved cursor coords, for activate/deactivate when grabbed */
   143     BOOL          	   cursor_visible;     /* tells if cursor was instructed to be hidden or not (SDL_ShowCursor) */
   144     BOOL               cursor_hidden;      /* tells if cursor is *actually* hidden or not */
   145     Uint8*             sw_buffers[2];      /* pointers to the two software buffers for double-buffer emulation */
   146     SDL_Thread         *thread;            /* thread for async updates to the screen */
   147     SDL_sem            *sem1, *sem2;       /* synchronization for async screen updates */
   148     Uint8              *current_buffer;    /* the buffer being copied to the screen */
   149     BOOL               quit_thread;        /* used to quit the async blitting thread */
   150     
   151     ImageDescriptionHandle yuv_idh;
   152     MatrixRecordPtr        yuv_matrix;
   153     DecompressorComponent  yuv_codec;
   154     ImageSequence          yuv_seq;
   155     PlanarPixmapInfoYUV420 *yuv_pixmap;
   156     Sint16                  yuv_width, yuv_height;
   157     CGrafPtr                yuv_port;
   158 
   159 } SDL_PrivateVideoData ;
   160 
   161 #define _THIS    SDL_VideoDevice *this
   162 #define display_id (this->hidden->display)
   163 #define mode (this->hidden->mode)
   164 #define save_mode (this->hidden->save_mode)
   165 #define mode_list (this->hidden->mode_list)
   166 #define palette (this->hidden->palette)
   167 #define gl_context (this->hidden->gl_context)
   168 #define device_width (this->hidden->width)
   169 #define device_height (this->hidden->height)
   170 #define device_bpp (this->hidden->bpp)
   171 #define mode_flags (this->hidden->flags)
   172 #define qz_window (this->hidden->window)
   173 #define window_view (this->hidden->view)
   174 #define video_set (this->hidden->video_set)
   175 #define warp_ticks (this->hidden->warp_ticks)
   176 #define warp_flag (this->hidden->warp_flag)
   177 #define resize_icon (this->hidden->resize_icon)
   178 #define current_grab_mode (this->hidden->current_grab_mode)
   179 #define in_foreground (this->hidden->in_foreground)
   180 #define client_mode_list (this->hidden->client_mode_list)
   181 #define keymap (this->hidden->keymap)
   182 #define current_mods (this->hidden->current_mods)
   183 #define last_virtual_button (this->hidden->last_virtual_button)
   184 #define power_connection (this->hidden->power_connection)
   185 #define expect_mouse_up (this->hidden->expect_mouse_up)
   186 #define grab_state (this->hidden->grab_state)
   187 #define cursor_loc (this->hidden->cursor_loc)
   188 #define cursor_visible (this->hidden->cursor_visible)
   189 #define cursor_hidden (this->hidden->cursor_hidden)
   190 #define sw_buffers (this->hidden->sw_buffers)
   191 #define thread (this->hidden->thread)
   192 #define sem1 (this->hidden->sem1)
   193 #define sem2 (this->hidden->sem2)
   194 #define current_buffer (this->hidden->current_buffer)
   195 #define quit_thread (this->hidden->quit_thread)
   196 
   197 #define yuv_idh (this->hidden->yuv_idh)
   198 #define yuv_matrix (this->hidden->yuv_matrix)
   199 #define yuv_codec (this->hidden->yuv_codec)
   200 #define yuv_seq (this->hidden->yuv_seq)
   201 #define yuv_pixmap (this->hidden->yuv_pixmap)
   202 #define yuv_data (this->hidden->yuv_data)
   203 #define yuv_width (this->hidden->yuv_width)
   204 #define yuv_height (this->hidden->yuv_height)
   205 #define yuv_port (this->hidden->yuv_port)
   206 
   207 
   208 /* grab states - the input is in one of these states */
   209 enum {
   210     QZ_UNGRABBED = 0,
   211     QZ_VISIBLE_GRAB,
   212     QZ_INVISIBLE_GRAB
   213 };
   214 
   215 /* grab actions - these can change the grabbed state */
   216 enum {
   217     QZ_ENABLE_GRAB = 0,
   218     QZ_DISABLE_GRAB,
   219     QZ_HIDECURSOR,
   220     QZ_SHOWCURSOR
   221 };
   222 
   223 /* 
   224     Obscuring code: maximum number of windows above ours (inclusive) 
   225     
   226     Note: this doesn't work too well in practice and should be
   227     phased out when we add OpenGL 2D acceleration. It was never
   228     enabled in the first place, so this shouldn't be a problem ;-)
   229 */
   230 #define kMaxWindows 256
   231 
   232 /* Some of the Core Graphics Server API for obscuring code */
   233 #define kCGSWindowLevelTop          2147483632
   234 #define kCGSWindowLevelDockIconDrag 500
   235 #define kCGSWindowLevelDockMenu     101
   236 #define kCGSWindowLevelMenuIgnore    21
   237 #define kCGSWindowLevelMenu          20
   238 #define kCGSWindowLevelDockLabel     12
   239 #define kCGSWindowLevelDockIcon      11
   240 #define kCGSWindowLevelDock          10
   241 #define kCGSWindowLevelUtility        3
   242 #define kCGSWindowLevelNormal         0
   243 
   244 /* 
   245     For completeness; We never use these window levels, they are always below us
   246     #define kCGSWindowLevelMBarShadow -20
   247     #define kCGSWindowLevelDesktopPicture -2147483647
   248     #define kCGSWindowLevelDesktop        -2147483648
   249 */
   250 
   251 typedef CGError       CGSError;
   252 typedef long          CGSWindowCount;
   253 typedef void *        CGSConnectionID;
   254 typedef int           CGSWindowID;
   255 typedef CGSWindowID*  CGSWindowIDList;
   256 typedef CGWindowLevel CGSWindowLevel;
   257 typedef NSRect        CGSRect;
   258 
   259 extern CGSConnectionID _CGSDefaultConnection ();
   260 
   261 extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid,
   262                                           CGSConnectionID owner,
   263                                           CGSWindowCount listCapacity,
   264                                           CGSWindowIDList list,
   265                                           CGSWindowCount *listCount);
   266 
   267 extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid,
   268                                            CGSWindowID wid,
   269                                            CGSRect *rect);
   270 
   271 extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid,
   272                                         CGSWindowID wid,
   273                                         CGSWindowLevel *level);
   274 
   275 extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y,
   276                                   unsigned int w, unsigned int h, unsigned int color);
   277 
   278 extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id);
   279 
   280 extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags);
   281 
   282 int CGSDisplayHWSync (CGDirectDisplayID id);
   283 
   284 /* Bootstrap functions */
   285 static int              QZ_Available ();
   286 static SDL_VideoDevice* QZ_CreateDevice (int device_index);
   287 static void             QZ_DeleteDevice (SDL_VideoDevice *device);
   288 
   289 /* Initialization, Query, Setup, and Redrawing functions */
   290 static int          QZ_VideoInit        (_THIS, SDL_PixelFormat *video_format);
   291 
   292 static SDL_Rect**   QZ_ListModes        (_THIS, SDL_PixelFormat *format,
   293                                          Uint32 flags);
   294 static void         QZ_UnsetVideoMode   (_THIS);
   295 
   296 static SDL_Surface* QZ_SetVideoMode     (_THIS, SDL_Surface *current,
   297                                          int width, int height, int bpp,
   298                                          Uint32 flags);
   299 static int          QZ_ToggleFullScreen (_THIS, int on);
   300 static int          QZ_SetColors        (_THIS, int first_color,
   301                                          int num_colors, SDL_Color *colors);
   302 
   303 static int          QZ_LockDoubleBuffer   (_THIS, SDL_Surface *surface);
   304 static void         QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface);
   305 static int          QZ_ThreadFlip         (_THIS);
   306 static int          QZ_FlipDoubleBuffer   (_THIS, SDL_Surface *surface);
   307 static void         QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects);
   308 
   309 static void         QZ_DirectUpdate     (_THIS, int num_rects, SDL_Rect *rects);
   310 static int          QZ_LockWindow       (_THIS, SDL_Surface *surface);
   311 static void         QZ_UnlockWindow     (_THIS, SDL_Surface *surface);
   312 static void         QZ_UpdateRects      (_THIS, int num_rects, SDL_Rect *rects);
   313 static void         QZ_VideoQuit        (_THIS);
   314 
   315 /* Hardware surface functions (for fullscreen mode only) */
   316 #if 0 /* Not used (apparently, it's really slow) */
   317 static int  QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
   318 #endif
   319 static int  QZ_LockHWSurface(_THIS, SDL_Surface *surface);
   320 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface);
   321 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface);
   322 /* static int  QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */
   323 
   324 /* Gamma Functions */
   325 static int QZ_SetGamma     (_THIS, float red, float green, float blue);
   326 static int QZ_GetGamma     (_THIS, float *red, float *green, float *blue);
   327 static int QZ_SetGammaRamp (_THIS, Uint16 *ramp);
   328 static int QZ_GetGammaRamp (_THIS, Uint16 *ramp);
   329 
   330 /* OpenGL functions */
   331 static int    QZ_SetupOpenGL       (_THIS, int bpp, Uint32 flags);
   332 static void   QZ_TearDownOpenGL    (_THIS);
   333 static void*  QZ_GL_GetProcAddress (_THIS, const char *proc);
   334 static int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value);
   335 static int    QZ_GL_MakeCurrent    (_THIS);
   336 static void   QZ_GL_SwapBuffers    (_THIS);
   337 static int    QZ_GL_LoadLibrary    (_THIS, const char *location);
   338 
   339 /* Private function to warp the cursor (used internally) */
   340 static void  QZ_PrivateWarpCursor (_THIS, int x, int y);
   341 
   342 /* Cursor and Mouse functions */
   343 static void         QZ_FreeWMCursor     (_THIS, WMcursor *cursor);
   344 static WMcursor*    QZ_CreateWMCursor   (_THIS, Uint8 *data, Uint8 *mask,
   345                                          int w, int h, int hot_x, int hot_y);
   346 static int          QZ_ShowWMCursor     (_THIS, WMcursor *cursor);
   347 static void         QZ_WarpWMCursor     (_THIS, Uint16 x, Uint16 y);
   348 static void         QZ_MoveWMCursor     (_THIS, int x, int y);
   349 static void         QZ_CheckMouseMode   (_THIS);
   350 
   351 /* Event functions */
   352 static void         QZ_InitOSKeymap     (_THIS);
   353 static void         QZ_PumpEvents       (_THIS);
   354 
   355 /* Window Manager functions */
   356 static void QZ_SetCaption        (_THIS, const char *title, const char *icon);
   357 static void QZ_SetIcon           (_THIS, SDL_Surface *icon, Uint8 *mask);
   358 static int  QZ_IconifyWindow     (_THIS);
   359 static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
   360 /*static int  QZ_GetWMInfo     (_THIS, SDL_SysWMinfo *info);*/
   361 
   362 /* YUV functions */
   363 static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
   364                                          Uint32 format, SDL_Surface *display);