From 4191f6a8099e6f6e1c687ff4654d1586de9b1f2d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 4 Jan 2004 14:55:35 +0000 Subject: [PATCH] Date: Wed, 31 Dec 2003 21:55:30 +0100 From: Max Horn Subject: SDL: video/quartz cleanup while doing some experimental changes in the quartz code, I was annoyed by having to recompile that one big .o file over and over again. So I decided to finally realize one TODO: properly splitting the code over multiple files :-). With two exceptions, I didn't make code changes, only rearranged files and added new headers. Since there are several new files, making a patch didn't work out so well, so I decided to just send you all the new & modified files. The one source change I made is related to showing/hiding the mouse. I renamed cursor_visible to cursor_should_be_visible and cursor_hidden to cursor_visible; I think that makes reading the code easier. Then I added two new functions: QZ_ShowMouse and QZ_HideMouse. They help manage cursor_visible (the former 'cursor_hidden'). Finally I replaced the Carbon ShowCursor/HiderCuror calls by [NSCursor hide] and [NSCursor unhide]. The API docs are not conclusive, but it might be that with those the "cursor_visible" (former 'cursor_hidden') hack may not be necessary anymore; however so far I didn't test this hypothesis, so I left that in. The other change was to remove in_foreground and use [NSApp isActive] instead: Manually keeping track of whether we are in the foreground is error prone. This should work better in some corner cases. --- src/video/quartz/CGS.h | 83 ++++ src/video/quartz/Makefile.am | 13 +- src/video/quartz/SDL_QuartzEvents.m | 35 +- src/video/quartz/SDL_QuartzGL.m | 228 ++++++++++ src/video/quartz/SDL_QuartzKeys.h | 12 +- src/video/quartz/SDL_QuartzVideo.h | 239 ++-------- src/video/quartz/SDL_QuartzVideo.m | 663 +++++++--------------------- src/video/quartz/SDL_QuartzWM.m | 157 ++----- src/video/quartz/SDL_QuartzWindow.h | 38 ++ src/video/quartz/SDL_QuartzWindow.m | 50 +-- src/video/quartz/SDL_QuartzYUV.m | 327 ++++++++++++++ 11 files changed, 983 insertions(+), 862 deletions(-) create mode 100644 src/video/quartz/CGS.h create mode 100644 src/video/quartz/SDL_QuartzGL.m create mode 100644 src/video/quartz/SDL_QuartzWindow.h create mode 100644 src/video/quartz/SDL_QuartzYUV.m diff --git a/src/video/quartz/CGS.h b/src/video/quartz/CGS.h new file mode 100644 index 000000000..223918c88 --- /dev/null +++ b/src/video/quartz/CGS.h @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2003 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + Obscuring code: maximum number of windows above ours (inclusive) + + Note: this doesn't work too well in practice and should be + phased out when we add OpenGL 2D acceleration. It was never + enabled in the first place, so this shouldn't be a problem ;-) +*/ +#define kMaxWindows 256 + +/* Some of the Core Graphics Server API for obscuring code */ +#define kCGSWindowLevelTop 2147483632 +#define kCGSWindowLevelDockIconDrag 500 +#define kCGSWindowLevelDockMenu 101 +#define kCGSWindowLevelMenuIgnore 21 +#define kCGSWindowLevelMenu 20 +#define kCGSWindowLevelDockLabel 12 +#define kCGSWindowLevelDockIcon 11 +#define kCGSWindowLevelDock 10 +#define kCGSWindowLevelUtility 3 +#define kCGSWindowLevelNormal 0 + +/* + For completeness; We never use these window levels, they are always below us + #define kCGSWindowLevelMBarShadow -20 + #define kCGSWindowLevelDesktopPicture -2147483647 + #define kCGSWindowLevelDesktop -2147483648 +*/ + +typedef CGError CGSError; +typedef long CGSWindowCount; +typedef void * CGSConnectionID; +typedef int CGSWindowID; +typedef CGSWindowID* CGSWindowIDList; +typedef CGWindowLevel CGSWindowLevel; +typedef NSRect CGSRect; + +extern CGSConnectionID _CGSDefaultConnection (); + +extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid, + CGSConnectionID owner, + CGSWindowCount listCapacity, + CGSWindowIDList list, + CGSWindowCount *listCount); + +extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid, + CGSWindowID wid, + CGSRect *rect); + +extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid, + CGSWindowID wid, + CGSWindowLevel *level); + +extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y, + unsigned int w, unsigned int h, unsigned int color); + +extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id); + +extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags); + +int CGSDisplayHWSync (CGDirectDisplayID id); + diff --git a/src/video/quartz/Makefile.am b/src/video/quartz/Makefile.am index 09aaa72cb..a5e12da59 100644 --- a/src/video/quartz/Makefile.am +++ b/src/video/quartz/Makefile.am @@ -6,12 +6,13 @@ libvideo_quartz_la_SOURCES = $(QUARTZ_SRCS) # The SDL MacOS X Quartz video driver sources QUARTZ_SRCS = \ + CGS.h \ + SDL_QuartzEvents.m \ + SDL_QuartzGL.m \ SDL_QuartzKeys.h \ SDL_QuartzVideo.h \ - SDL_QuartzVideo.m - -# These files are included by SDL_QuartzVideo.m (is that right??) -noinst_HEADERS = \ - SDL_QuartzEvents.m \ + SDL_QuartzVideo.m \ + SDL_QuartzWindow.h \ + SDL_QuartzWindow.m \ SDL_QuartzWM.m \ - SDL_QuartzWindow.m + SDL_QuartzYUV.m diff --git a/src/video/quartz/SDL_QuartzEvents.m b/src/video/quartz/SDL_QuartzEvents.m index 631299862..2dc7de9c6 100644 --- a/src/video/quartz/SDL_QuartzEvents.m +++ b/src/video/quartz/SDL_QuartzEvents.m @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + Copyright (C) 1997-2003 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,12 +19,15 @@ Sam Lantinga slouken@libsdl.org */ -#include // For getenv() + +#include "SDL_QuartzVideo.h" + +#include // For getenv() #include // For wake from sleep detection #include // For wake from sleep detection #include "SDL_QuartzKeys.h" -static void QZ_InitOSKeymap (_THIS) { +void QZ_InitOSKeymap (_THIS) { const void *KCHRPtr; UInt32 state; UInt32 value; @@ -283,7 +286,7 @@ static void QZ_DoModifiers (_THIS, unsigned int newMods) { key.sym = mapping[i]; /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ if (bit == NSAlphaShiftKeyMask) - SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_PRESSED, &key); SDL_PrivateKeyboard (SDL_RELEASED, &key); } else if ( newMask && @@ -302,13 +305,9 @@ static void QZ_DoModifiers (_THIS, unsigned int newMods) { static void QZ_DoActivate (_THIS) { - in_foreground = YES; - /* Hide the cursor if it was hidden by SDL_ShowCursor() */ - if (!cursor_visible && !cursor_hidden) { - HideCursor (); - cursor_hidden = YES; - } + if (!cursor_should_be_visible) + QZ_HideMouse (this); /* Regrab input, only if it was previously grabbed */ if ( current_grab_mode == SDL_GRAB_ON ) { @@ -323,8 +322,6 @@ static void QZ_DoActivate (_THIS) static void QZ_DoDeactivate (_THIS) { - in_foreground = NO; - /* Get the current cursor location, for restore on activate */ cursor_loc = [ NSEvent mouseLocation ]; /* global coordinates */ if (qz_window) @@ -335,10 +332,8 @@ static void QZ_DoDeactivate (_THIS) { CGAssociateMouseAndMouseCursorPosition (1); /* Show the cursor if it was hidden by SDL_ShowCursor() */ - if (!cursor_visible && cursor_hidden) { - ShowCursor (); - cursor_hidden = NO; - } + if (!cursor_should_be_visible) + QZ_ShowMouse (this); SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS); } @@ -359,13 +354,13 @@ void QZ_SleepNotificationHandler (void * refcon, IOAllowPowerChange(power_connection, (long) messageArgument); break; case kIOMessageSystemHasPoweredOn: - /* awake */ + /* awake */ SDL_PrivateExpose(); break; } } -static void QZ_RegisterForSleepNotifications (_THIS) +void QZ_RegisterForSleepNotifications (_THIS) { CFRunLoopSourceRef rls; IONotificationPortRef thePortRef; @@ -400,7 +395,7 @@ static int QZ_OtherMouseButtonToSDL(int button) } -static void QZ_PumpEvents (_THIS) +void QZ_PumpEvents (_THIS) { int firstMouseEvent; CGMouseDelta dx, dy; @@ -445,7 +440,7 @@ static void QZ_PumpEvents (_THIS) BOOL isInGameWin; #define DO_MOUSE_DOWN(button) do { \ - if ( in_foreground ) { \ + if ( [ NSApp isActive ] ) { \ if ( isInGameWin ) { \ SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \ expect_mouse_up |= 1<gl_config.depth_size; + + if ( this->gl_config.double_buffer ) { + attr[i++] = NSOpenGLPFADoubleBuffer; + } + + if ( this->gl_config.stereo ) { + attr[i++] = NSOpenGLPFAStereo; + } + + if ( this->gl_config.stencil_size != 0 ) { + attr[i++] = NSOpenGLPFAStencilSize; + attr[i++] = this->gl_config.stencil_size; + } + +#if NSOPENGL_CURRENT_VERSION > 1 /* What version should this be? */ + if ( this->gl_config.multisamplebuffers != 0 ) { + attr[i++] = NSOpenGLPFASampleBuffers; + attr[i++] = this->gl_config.multisamplebuffers; + } + + if ( this->gl_config.multisamplesamples != 0 ) { + attr[i++] = NSOpenGLPFASamples; + attr[i++] = this->gl_config.multisamplesamples; + } +#endif + + attr[i++] = NSOpenGLPFAScreenMask; + attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id); + attr[i] = 0; + + fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ]; + if (fmt == nil) { + SDL_SetError ("Failed creating OpenGL pixel format"); + return 0; + } + + gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt + shareContext:nil]; + + if (gl_context == nil) { + SDL_SetError ("Failed creating OpenGL context"); + return 0; + } + + /* + * Wisdom from Apple engineer in reference to UT2003's OpenGL performance: + * "You are blowing a couple of the internal OpenGL function caches. This + * appears to be happening in the VAO case. You can tell OpenGL to up + * the cache size by issuing the following calls right after you create + * the OpenGL context. The default cache size is 16." --ryan. + */ + + #ifndef GLI_ARRAY_FUNC_CACHE_MAX + #define GLI_ARRAY_FUNC_CACHE_MAX 284 + #endif + + #ifndef GLI_SUBMIT_FUNC_CACHE_MAX + #define GLI_SUBMIT_FUNC_CACHE_MAX 280 + #endif + + { + long cache_max = 64; + CGLContextObj ctx = [ gl_context cglContext ]; + CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max); + CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); + } + + /* End Wisdom from Apple Engineer section. --ryan. */ + + /* Convince SDL that the GL "driver" is loaded */ + this->gl_config.driver_loaded = 1; + + [ fmt release ]; + + return 1; +} + +void QZ_TearDownOpenGL (_THIS) { + + [ NSOpenGLContext clearCurrentContext ]; + [ gl_context clearDrawable ]; + [ gl_context release ]; +} + + +/* SDL OpenGL functions */ + +int QZ_GL_LoadLibrary (_THIS, const char *location) { + this->gl_config.driver_loaded = 1; + return 1; +} + +void* QZ_GL_GetProcAddress (_THIS, const char *proc) { + + /* We may want to cache the bundleRef at some point */ + CFBundleRef bundle; + CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, + CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true); + + CFStringRef functionName = CFStringCreateWithCString + (kCFAllocatorDefault, proc, kCFStringEncodingASCII); + + void *function; + + bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL); + assert (bundle != NULL); + + function = CFBundleGetFunctionPointerForName (bundle, functionName); + + CFRelease ( bundleURL ); + CFRelease ( functionName ); + CFRelease ( bundle ); + + return function; +} + +int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) { + + GLenum attr = 0; + + QZ_GL_MakeCurrent (this); + + switch (attrib) { + case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break; + case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break; + case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break; + case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break; + case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break; + case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break; + case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break; + case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break; + case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break; + case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break; + case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break; + case SDL_GL_STEREO: attr = GL_STEREO; break; + case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break; + case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break; + case SDL_GL_BUFFER_SIZE: + { + GLint bits = 0; + GLint component; + + /* there doesn't seem to be a single flag in OpenGL for this! */ + glGetIntegerv (GL_RED_BITS, &component); bits += component; + glGetIntegerv (GL_GREEN_BITS,&component); bits += component; + glGetIntegerv (GL_BLUE_BITS, &component); bits += component; + glGetIntegerv (GL_ALPHA_BITS, &component); bits += component; + + *value = bits; + } + return 0; + } + + glGetIntegerv (attr, (GLint *)value); + return 0; +} + +int QZ_GL_MakeCurrent (_THIS) { + [ gl_context makeCurrentContext ]; + return 0; +} + +void QZ_GL_SwapBuffers (_THIS) { + [ gl_context flushBuffer ]; +} diff --git a/src/video/quartz/SDL_QuartzKeys.h b/src/video/quartz/SDL_QuartzKeys.h index 3d12b522f..5929d4da4 100644 --- a/src/video/quartz/SDL_QuartzKeys.h +++ b/src/video/quartz/SDL_QuartzKeys.h @@ -1,24 +1,24 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga - + Copyright (C) 1997-2003 Sam Lantinga + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - + You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + Sam Lantinga slouken@libsdl.org - */ +*/ /* These are the Macintosh key scancode constants -- from Inside Macintosh */ diff --git a/src/video/quartz/SDL_QuartzVideo.h b/src/video/quartz/SDL_QuartzVideo.h index 777211873..014fd3d8f 100644 --- a/src/video/quartz/SDL_QuartzVideo.h +++ b/src/video/quartz/SDL_QuartzVideo.h @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + Copyright (C) 1997-2003 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -54,7 +54,7 @@ #include #include #include -#include /* For powersave handling */ +#include /* For powersave handling */ #include #include "SDL_thread.h" @@ -66,53 +66,6 @@ #include "SDL_pixels_c.h" #include "SDL_events_c.h" -/* - Add methods to get at private members of NSScreen. - Since there is a bug in Apple's screen switching code - that does not update this variable when switching - to fullscreen, we'll set it manually (but only for the - main screen). -*/ -@interface NSScreen (NSScreenAccess) -- (void) setFrame:(NSRect)frame; -@end - -@implementation NSScreen (NSScreenAccess) -- (void) setFrame:(NSRect)frame; -{ - _frame = frame; -} -@end - -/* - This is a workaround to directly access NSOpenGLContext's CGL context - We need this to check for errors NSOpenGLContext doesn't support -*/ -@interface NSOpenGLContext (CGLContextAccess) -- (CGLContextObj) cglContext; -@end - -@implementation NSOpenGLContext (CGLContextAccess) -- (CGLContextObj) cglContext; -{ - return _contextAuxiliary; -} -@end - -/* - Structure for rez switch gamma fades - We can hide the monitor flicker by setting the gamma tables to 0 -*/ -#define QZ_GAMMA_TABLE_SIZE 256 - -typedef struct { - - CGGammaValue red[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue green[QZ_GAMMA_TABLE_SIZE]; - CGGammaValue blue[QZ_GAMMA_TABLE_SIZE]; - -} SDL_QuartzGammaTable; - /* Main driver structure to store required state information */ typedef struct SDL_PrivateVideoData { @@ -131,7 +84,6 @@ typedef struct SDL_PrivateVideoData { NSQuickDrawView *view; /* the window's view; draw 2D and OpenGL into this view */ SDL_Surface *resize_icon; /* icon for the resize badge, we have to draw it by hand */ SDL_GrabMode current_grab_mode; /* default value is SDL_GRAB_OFF */ - BOOL in_foreground; /* boolean; indicate if app is in foreground or not */ SDL_Rect **client_mode_list; /* resolution list to pass back to client */ SDLKey keymap[256]; /* Mac OS X to SDL key mapping */ Uint32 current_mods; /* current keyboard modifiers, to track modifier state */ @@ -140,8 +92,8 @@ typedef struct SDL_PrivateVideoData { Uint8 expect_mouse_up; /* used to determine when to send mouse up events */ Uint8 grab_state; /* used to manage grab behavior */ NSPoint cursor_loc; /* saved cursor coords, for activate/deactivate when grabbed */ - BOOL cursor_visible; /* tells if cursor was instructed to be hidden or not (SDL_ShowCursor) */ - BOOL cursor_hidden; /* tells if cursor is *actually* hidden or not */ + BOOL cursor_should_be_visible; /* tells if cursor is supposed to be visible (SDL_ShowCursor) */ + BOOL cursor_visible; /* tells if cursor is *actually* visible or not */ Uint8* sw_buffers[2]; /* pointers to the two software buffers for double-buffer emulation */ SDL_Thread *thread; /* thread for async updates to the screen */ SDL_sem *sem1, *sem2; /* synchronization for async screen updates */ @@ -156,7 +108,7 @@ typedef struct SDL_PrivateVideoData { Sint16 yuv_width, yuv_height; CGrafPtr yuv_port; -} SDL_PrivateVideoData ; +} SDL_PrivateVideoData; #define _THIS SDL_VideoDevice *this #define display_id (this->hidden->display) @@ -176,7 +128,6 @@ typedef struct SDL_PrivateVideoData { #define warp_flag (this->hidden->warp_flag) #define resize_icon (this->hidden->resize_icon) #define current_grab_mode (this->hidden->current_grab_mode) -#define in_foreground (this->hidden->in_foreground) #define client_mode_list (this->hidden->client_mode_list) #define keymap (this->hidden->keymap) #define current_mods (this->hidden->current_mods) @@ -185,8 +136,8 @@ typedef struct SDL_PrivateVideoData { #define expect_mouse_up (this->hidden->expect_mouse_up) #define grab_state (this->hidden->grab_state) #define cursor_loc (this->hidden->cursor_loc) +#define cursor_should_be_visible (this->hidden->cursor_should_be_visible) #define cursor_visible (this->hidden->cursor_visible) -#define cursor_hidden (this->hidden->cursor_hidden) #define sw_buffers (this->hidden->sw_buffers) #define thread (this->hidden->thread) #define sem1 (this->hidden->sem1) @@ -194,17 +145,6 @@ typedef struct SDL_PrivateVideoData { #define current_buffer (this->hidden->current_buffer) #define quit_thread (this->hidden->quit_thread) -#define yuv_idh (this->hidden->yuv_idh) -#define yuv_matrix (this->hidden->yuv_matrix) -#define yuv_codec (this->hidden->yuv_codec) -#define yuv_seq (this->hidden->yuv_seq) -#define yuv_pixmap (this->hidden->yuv_pixmap) -#define yuv_data (this->hidden->yuv_data) -#define yuv_width (this->hidden->yuv_width) -#define yuv_height (this->hidden->yuv_height) -#define yuv_port (this->hidden->yuv_port) - - /* grab states - the input is in one of these states */ enum { QZ_UNGRABBED = 0, @@ -220,145 +160,52 @@ enum { QZ_SHOWCURSOR }; -/* - Obscuring code: maximum number of windows above ours (inclusive) - - Note: this doesn't work too well in practice and should be - phased out when we add OpenGL 2D acceleration. It was never - enabled in the first place, so this shouldn't be a problem ;-) -*/ -#define kMaxWindows 256 - -/* Some of the Core Graphics Server API for obscuring code */ -#define kCGSWindowLevelTop 2147483632 -#define kCGSWindowLevelDockIconDrag 500 -#define kCGSWindowLevelDockMenu 101 -#define kCGSWindowLevelMenuIgnore 21 -#define kCGSWindowLevelMenu 20 -#define kCGSWindowLevelDockLabel 12 -#define kCGSWindowLevelDockIcon 11 -#define kCGSWindowLevelDock 10 -#define kCGSWindowLevelUtility 3 -#define kCGSWindowLevelNormal 0 - -/* - For completeness; We never use these window levels, they are always below us - #define kCGSWindowLevelMBarShadow -20 - #define kCGSWindowLevelDesktopPicture -2147483647 - #define kCGSWindowLevelDesktop -2147483648 -*/ - -typedef CGError CGSError; -typedef long CGSWindowCount; -typedef void * CGSConnectionID; -typedef int CGSWindowID; -typedef CGSWindowID* CGSWindowIDList; -typedef CGWindowLevel CGSWindowLevel; -typedef NSRect CGSRect; - -extern CGSConnectionID _CGSDefaultConnection (); - -extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid, - CGSConnectionID owner, - CGSWindowCount listCapacity, - CGSWindowIDList list, - CGSWindowCount *listCount); - -extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid, - CGSWindowID wid, - CGSRect *rect); - -extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid, - CGSWindowID wid, - CGSWindowLevel *level); - -extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y, - unsigned int w, unsigned int h, unsigned int color); - -extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id); - -extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags); - -int CGSDisplayHWSync (CGDirectDisplayID id); - -/* Bootstrap functions */ -static int QZ_Available (); -static SDL_VideoDevice* QZ_CreateDevice (int device_index); -static void QZ_DeleteDevice (SDL_VideoDevice *device); - -/* Initialization, Query, Setup, and Redrawing functions */ -static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format); - -static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, - Uint32 flags); -static void QZ_UnsetVideoMode (_THIS); - -static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, - int width, int height, int bpp, - Uint32 flags); -static int QZ_ToggleFullScreen (_THIS, int on); -static int QZ_SetColors (_THIS, int first_color, - int num_colors, SDL_Color *colors); - -static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface); -static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface); -static int QZ_ThreadFlip (_THIS); -static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); -static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); - -static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); -static int QZ_LockWindow (_THIS, SDL_Surface *surface); -static void QZ_UnlockWindow (_THIS, SDL_Surface *surface); -static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); -static void QZ_VideoQuit (_THIS); - -/* Hardware surface functions (for fullscreen mode only) */ -#if 0 /* Not used (apparently, it's really slow) */ -static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); -#endif -static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); -static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); -static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); -/* static int QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */ - /* Gamma Functions */ -static int QZ_SetGamma (_THIS, float red, float green, float blue); -static int QZ_GetGamma (_THIS, float *red, float *green, float *blue); -static int QZ_SetGammaRamp (_THIS, Uint16 *ramp); -static int QZ_GetGammaRamp (_THIS, Uint16 *ramp); +int QZ_SetGamma (_THIS, float red, float green, float blue); +int QZ_GetGamma (_THIS, float *red, float *green, float *blue); +int QZ_SetGammaRamp (_THIS, Uint16 *ramp); +int QZ_GetGammaRamp (_THIS, Uint16 *ramp); /* OpenGL functions */ -static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags); -static void QZ_TearDownOpenGL (_THIS); -static void* QZ_GL_GetProcAddress (_THIS, const char *proc); -static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value); -static int QZ_GL_MakeCurrent (_THIS); -static void QZ_GL_SwapBuffers (_THIS); -static int QZ_GL_LoadLibrary (_THIS, const char *location); - -/* Private function to warp the cursor (used internally) */ -static void QZ_PrivateWarpCursor (_THIS, int x, int y); +int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags); +void QZ_TearDownOpenGL (_THIS); +void* QZ_GL_GetProcAddress (_THIS, const char *proc); +int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value); +int QZ_GL_MakeCurrent (_THIS); +void QZ_GL_SwapBuffers (_THIS); +int QZ_GL_LoadLibrary (_THIS, const char *location); /* Cursor and Mouse functions */ -static void QZ_FreeWMCursor (_THIS, WMcursor *cursor); -static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, - int w, int h, int hot_x, int hot_y); -static int QZ_ShowWMCursor (_THIS, WMcursor *cursor); -static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y); -static void QZ_MoveWMCursor (_THIS, int x, int y); -static void QZ_CheckMouseMode (_THIS); +void QZ_FreeWMCursor (_THIS, WMcursor *cursor); +WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y); +int QZ_ShowWMCursor (_THIS, WMcursor *cursor); +void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y); +void QZ_MoveWMCursor (_THIS, int x, int y); +void QZ_CheckMouseMode (_THIS); /* Event functions */ -static void QZ_InitOSKeymap (_THIS); -static void QZ_PumpEvents (_THIS); +void QZ_InitOSKeymap (_THIS); +void QZ_PumpEvents (_THIS); /* Window Manager functions */ -static void QZ_SetCaption (_THIS, const char *title, const char *icon); -static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask); -static int QZ_IconifyWindow (_THIS); -static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); -/*static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ +void QZ_SetCaption (_THIS, const char *title, const char *icon); +void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask); +int QZ_IconifyWindow (_THIS); +SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); +/*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ /* YUV functions */ -static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, +SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, Uint32 format, SDL_Surface *display); + + +/* Private functions (used internally) */ +void QZ_PrivateWarpCursor (_THIS, int x, int y); +void QZ_ChangeGrabState (_THIS, int action); +void QZ_RegisterForSleepNotifications (_THIS); +void QZ_ShowMouse (_THIS); +void QZ_HideMouse (_THIS); +void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p); +void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p); + diff --git a/src/video/quartz/SDL_QuartzVideo.m b/src/video/quartz/SDL_QuartzVideo.m index faee91116..95fc0b20c 100644 --- a/src/video/quartz/SDL_QuartzVideo.m +++ b/src/video/quartz/SDL_QuartzVideo.m @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + Copyright (C) 1997-2003 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -21,11 +21,82 @@ */ #include "SDL_QuartzVideo.h" +#include "SDL_QuartzWindow.h" -/* Include files into one compile unit...break apart eventually */ -#include "SDL_QuartzWM.m" -#include "SDL_QuartzEvents.m" -#include "SDL_QuartzWindow.m" + +/* + Add methods to get at private members of NSScreen. + Since there is a bug in Apple's screen switching code + that does not update this variable when switching + to fullscreen, we'll set it manually (but only for the + main screen). +*/ +@interface NSScreen (NSScreenAccess) +- (void) setFrame:(NSRect)frame; +@end + +@implementation NSScreen (NSScreenAccess) +- (void) setFrame:(NSRect)frame; +{ + _frame = frame; +} +@end + + +/* + Structure for rez switch gamma fades + We can hide the monitor flicker by setting the gamma tables to 0 +*/ +#define QZ_GAMMA_TABLE_SIZE 256 + +typedef struct { + + CGGammaValue red[QZ_GAMMA_TABLE_SIZE]; + CGGammaValue green[QZ_GAMMA_TABLE_SIZE]; + CGGammaValue blue[QZ_GAMMA_TABLE_SIZE]; + +} SDL_QuartzGammaTable; + + +/* Bootstrap functions */ +static int QZ_Available (); +static SDL_VideoDevice* QZ_CreateDevice (int device_index); +static void QZ_DeleteDevice (SDL_VideoDevice *device); + +/* Initialization, Query, Setup, and Redrawing functions */ +static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format); + +static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, + Uint32 flags); +static void QZ_UnsetVideoMode (_THIS); + +static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags); +static int QZ_ToggleFullScreen (_THIS, int on); +static int QZ_SetColors (_THIS, int first_color, + int num_colors, SDL_Color *colors); + +static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface); +static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface); +static int QZ_ThreadFlip (_THIS); +static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); +static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); + +static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); +static int QZ_LockWindow (_THIS, SDL_Surface *surface); +static void QZ_UnlockWindow (_THIS, SDL_Surface *surface); +static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); +static void QZ_VideoQuit (_THIS); + +/* Hardware surface functions (for fullscreen mode only) */ +#if 0 /* Not used (apparently, it's really slow) */ +static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); +#endif +static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); +static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); +/* static int QZ_FlipHWSurface (_THIS, SDL_Surface *surface); */ /* Bootstrap binding, enables entry point into the driver */ VideoBootStrap QZ_bootstrap = { @@ -130,8 +201,7 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { /* Set misc globals */ current_grab_mode = SDL_GRAB_OFF; - in_foreground = YES; - cursor_visible = YES; + cursor_should_be_visible = YES; /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ QZ_RegisterForSleepNotifications (this); @@ -712,7 +782,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) /* Only recreate the view if it doesn't already exist */ if (window_view == nil) { - window_view = [ [ SDL_QuartzWindowView alloc ] initWithFrame:contentRect ]; + window_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; [ window_view setAutoresizingMask: NSViewMinYMargin ]; [ [ qz_window contentView ] addSubview:window_view ]; [ window_view release ]; @@ -851,7 +921,7 @@ static AbsoluteTime QZ_SecondsToAbsolute ( double seconds ) { union { - UInt64 i; + UInt64 i; Nanoseconds ns; } temp; @@ -990,9 +1060,15 @@ static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com, who supplied sample code for Carbon. */ + +//#define TEST_OBSCURED 1 + +#if TEST_OBSCURED +#include "CGS.h" +#endif + static int QZ_IsWindowObscured (NSWindow *window) { - //#define TEST_OBSCURED 1 #if TEST_OBSCURED @@ -1230,6 +1306,84 @@ static void QZ_UnlockWindow (_THIS, SDL_Surface *surface) { UnlockPortBits ( [ window_view qdPort ] ); } +/* Resize icon, BMP format */ +static const unsigned char QZ_ResizeIcon[] = { + 0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00, + 0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00, + 0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda, + 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87, + 0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8, + 0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8, + 0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda, + 0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda, + 0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7, + 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8, + 0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc, + 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb, + 0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc, + 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b +}; + +static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) { + + /* Check if we should draw the resize icon */ + if (SDL_VideoSurface->flags & SDL_RESIZABLE) { + + Rect icon; + SetRect (&icon, SDL_VideoSurface->w - 13, SDL_VideoSurface->h - 13, + SDL_VideoSurface->w, SDL_VideoSurface->h); + + if (RectInRgn (&icon, dirtyRegion)) { + + SDL_Rect icon_rect; + + /* Create the icon image */ + if (resize_icon == NULL) { + + SDL_RWops *rw; + SDL_Surface *tmp; + + rw = SDL_RWFromMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon)); + tmp = SDL_LoadBMP_RW (rw, SDL_TRUE); + + resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY); + SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF); + + SDL_FreeSurface (tmp); + } + + icon_rect.x = SDL_VideoSurface->w - 13; + icon_rect.y = SDL_VideoSurface->h - 13; + icon_rect.w = 13; + icon_rect.h = 13; + + SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect); + } + } +} + static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { @@ -1353,7 +1507,7 @@ int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) { */ /* Gamma functions */ -static int QZ_SetGamma (_THIS, float red, float green, float blue) { +int QZ_SetGamma (_THIS, float red, float green, float blue) { const CGGammaValue min = 0.0, max = 1.0; @@ -1383,7 +1537,7 @@ static int QZ_SetGamma (_THIS, float red, float green, float blue) { } } -static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { +int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { CGGammaValue dummy; if ( CGDisplayNoErr == CGGetDisplayTransferByFormula @@ -1395,7 +1549,7 @@ static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { return -1; } -static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { +int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { const CGTableCount tableSize = 255; CGGammaValue redTable[tableSize]; @@ -1421,7 +1575,7 @@ static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { return -1; } -static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { +int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { const CGTableCount tableSize = 255; CGGammaValue redTable[tableSize]; @@ -1449,484 +1603,3 @@ static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { return 0; } -/* OpenGL helper functions (used internally) */ - -static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { - - NSOpenGLPixelFormatAttribute attr[32]; - NSOpenGLPixelFormat *fmt; - int i = 0; - int colorBits = bpp; - - if ( flags & SDL_FULLSCREEN ) { - - attr[i++] = NSOpenGLPFAFullScreen; - } - /* In windowed mode, the OpenGL pixel depth must match device pixel depth */ - else if ( colorBits != device_bpp ) { - - colorBits = device_bpp; - } - - attr[i++] = NSOpenGLPFAColorSize; - attr[i++] = colorBits; - - attr[i++] = NSOpenGLPFADepthSize; - attr[i++] = this->gl_config.depth_size; - - if ( this->gl_config.double_buffer ) { - attr[i++] = NSOpenGLPFADoubleBuffer; - } - - if ( this->gl_config.stereo ) { - attr[i++] = NSOpenGLPFAStereo; - } - - if ( this->gl_config.stencil_size != 0 ) { - attr[i++] = NSOpenGLPFAStencilSize; - attr[i++] = this->gl_config.stencil_size; - } - -#if NSOPENGL_CURRENT_VERSION > 1 /* What version should this be? */ - if ( this->gl_config.multisamplebuffers != 0 ) { - attr[i++] = NSOpenGLPFASampleBuffers; - attr[i++] = this->gl_config.multisamplebuffers; - } - - if ( this->gl_config.multisamplesamples != 0 ) { - attr[i++] = NSOpenGLPFASamples; - attr[i++] = this->gl_config.multisamplesamples; - } -#endif - - attr[i++] = NSOpenGLPFAScreenMask; - attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id); - attr[i] = 0; - - fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ]; - if (fmt == nil) { - SDL_SetError ("Failed creating OpenGL pixel format"); - return 0; - } - - gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt - shareContext:nil]; - - if (gl_context == nil) { - SDL_SetError ("Failed creating OpenGL context"); - return 0; - } - - /* - * Wisdom from Apple engineer in reference to UT2003's OpenGL performance: - * "You are blowing a couple of the internal OpenGL function caches. This - * appears to be happening in the VAO case. You can tell OpenGL to up - * the cache size by issuing the following calls right after you create - * the OpenGL context. The default cache size is 16." --ryan. - */ - - #ifndef GLI_ARRAY_FUNC_CACHE_MAX - #define GLI_ARRAY_FUNC_CACHE_MAX 284 - #endif - - #ifndef GLI_SUBMIT_FUNC_CACHE_MAX - #define GLI_SUBMIT_FUNC_CACHE_MAX 280 - #endif - - { - long cache_max = 64; - CGLContextObj ctx = [ gl_context cglContext ]; - CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max); - CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); - } - - /* End Wisdom from Apple Engineer section. --ryan. */ - - /* Convince SDL that the GL "driver" is loaded */ - this->gl_config.driver_loaded = 1; - - [ fmt release ]; - - return 1; -} - -static void QZ_TearDownOpenGL (_THIS) { - - [ NSOpenGLContext clearCurrentContext ]; - [ gl_context clearDrawable ]; - [ gl_context release ]; -} - - -/* SDL OpenGL functions */ - -static int QZ_GL_LoadLibrary (_THIS, const char *location) { - this->gl_config.driver_loaded = 1; - return 1; -} - -static void* QZ_GL_GetProcAddress (_THIS, const char *proc) { - - /* We may want to cache the bundleRef at some point */ - CFBundleRef bundle; - CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, - CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true); - - CFStringRef functionName = CFStringCreateWithCString - (kCFAllocatorDefault, proc, kCFStringEncodingASCII); - - void *function; - - bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL); - assert (bundle != NULL); - - function = CFBundleGetFunctionPointerForName (bundle, functionName); - - CFRelease ( bundleURL ); - CFRelease ( functionName ); - CFRelease ( bundle ); - - return function; -} - -static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) { - - GLenum attr = 0; - - QZ_GL_MakeCurrent (this); - - switch (attrib) { - case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break; - case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break; - case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break; - case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break; - case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break; - case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break; - case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break; - case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break; - case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break; - case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break; - case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break; - case SDL_GL_STEREO: attr = GL_STEREO; break; - case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break; - case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break; - case SDL_GL_BUFFER_SIZE: - { - GLint bits = 0; - GLint component; - - /* there doesn't seem to be a single flag in OpenGL for this! */ - glGetIntegerv (GL_RED_BITS, &component); bits += component; - glGetIntegerv (GL_GREEN_BITS,&component); bits += component; - glGetIntegerv (GL_BLUE_BITS, &component); bits += component; - glGetIntegerv (GL_ALPHA_BITS, &component); bits += component; - - *value = bits; - } - return 0; - } - - glGetIntegerv (attr, (GLint *)value); - return 0; -} - -static int QZ_GL_MakeCurrent (_THIS) { - [ gl_context makeCurrentContext ]; - return 0; -} - -static void QZ_GL_SwapBuffers (_THIS) { - [ gl_context flushBuffer ]; -} - -static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) { - - return 0; -} - -static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) { - - ; -} - -static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) { - - OSErr err; - CodecFlags flags; - - if (dstrect->x != 0 || dstrect->y != 0) { - - SDL_SetError ("Need a dstrect at (0,0)"); - return -1; - } - - if (dstrect->w != yuv_width || dstrect->h != yuv_height) { - - Fixed scale_x, scale_y; - - scale_x = FixDiv ( Long2Fix (dstrect->w), Long2Fix (overlay->w) ); - scale_y = FixDiv ( Long2Fix (dstrect->h), Long2Fix (overlay->h) ); - - SetIdentityMatrix (yuv_matrix); - ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0)); - - SetDSequenceMatrix (yuv_seq, yuv_matrix); - - yuv_width = dstrect->w; - yuv_height = dstrect->h; - } - - if( ( err = DecompressSequenceFrameS( - yuv_seq, - (void*)yuv_pixmap, - sizeof (PlanarPixmapInfoYUV420), - codecFlagUseImageBuffer, &flags, nil ) != noErr ) ) - { - SDL_SetError ("DecompressSequenceFrameS failed"); - } - - return err == noErr; -} - -static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) { - - CDSequenceEnd (yuv_seq); - ExitMovies(); - - free (overlay->hwfuncs); - free (overlay->pitches); - free (overlay->pixels); - - if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { - [ qz_window close ]; - qz_window = nil; - } - - free (yuv_matrix); - DisposeHandle ((Handle)yuv_idh); -} - -#include "SDL_yuvfuncs.h" - -/* check for 16 byte alignment, bail otherwise */ -#define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0) - -/* align a byte offset, return how much to add to make it a multiple of 16 */ -#define ALIGN(x) ((16 - (x & 15)) & 15) - -static SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, - Uint32 format, SDL_Surface *display) { - - Uint32 codec; - OSStatus err; - CGrafPtr port; - SDL_Overlay *overlay; - - if (format == SDL_YV12_OVERLAY || - format == SDL_IYUV_OVERLAY) { - - codec = kYUV420CodecType; - } - else { - SDL_SetError ("Hardware: unsupported video format"); - return NULL; - } - - yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription)); - if (yuv_idh == NULL) { - SDL_OutOfMemory(); - return NULL; - } - - yuv_matrix = (MatrixRecordPtr) malloc (sizeof(MatrixRecord)); - if (yuv_matrix == NULL) { - SDL_OutOfMemory(); - return NULL; - } - - if ( EnterMovies() != noErr ) { - SDL_SetError ("Could not init QuickTime for YUV playback"); - return NULL; - } - - err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec); - if (err != noErr) { - SDL_SetError ("Could not find QuickTime codec for format"); - return NULL; - } - - if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { - - /* - Acceleration requires a window to be present. - A CGrafPtr that points to the screen isn't good enough - */ - NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); - - qz_window = [ [ SDL_QuartzWindow alloc ] - initWithContentRect:content - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered defer:NO ]; - - if (qz_window == nil) { - SDL_SetError ("Could not create the Cocoa window"); - return NULL; - } - - [ qz_window setContentView:[ [ SDL_QuartzWindowView alloc ] init ] ]; - [ qz_window setReleasedWhenClosed:YES ]; - [ qz_window center ]; - [ qz_window setAcceptsMouseMovedEvents:YES ]; - [ qz_window setLevel:CGShieldingWindowLevel() ]; - [ qz_window makeKeyAndOrderFront:nil ]; - - port = [ [ qz_window contentView ] qdPort ]; - SetPort (port); - - /* - BUG: would like to remove white flash when window kicks in - { - Rect r; - SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); - PaintRect (&r); - QDFlushPortBuffer (port, nil); - } - */ - } - else { - port = [ window_view qdPort ]; - SetPort (port); - } - - SetIdentityMatrix (yuv_matrix); - - HLock ((Handle)yuv_idh); - - (**yuv_idh).idSize = sizeof(ImageDescription); - (**yuv_idh).cType = codec; - (**yuv_idh).version = 1; - (**yuv_idh).revisionLevel = 0; - (**yuv_idh).width = width; - (**yuv_idh).height = height; - (**yuv_idh).hRes = Long2Fix(72); - (**yuv_idh).vRes = Long2Fix(72); - (**yuv_idh).spatialQuality = codecLosslessQuality; - (**yuv_idh).frameCount = 1; - (**yuv_idh).clutID = -1; - (**yuv_idh).dataSize = 0; - (**yuv_idh).depth = 24; - - HUnlock ((Handle)yuv_idh); - - err = DecompressSequenceBeginS ( - &yuv_seq, - yuv_idh, - NULL, - 0, - port, - NULL, - NULL, - yuv_matrix, - 0, - NULL, - codecFlagUseImageBuffer, - codecLosslessQuality, - yuv_codec); - - if (err != noErr) { - SDL_SetError ("Error trying to start YUV codec."); - return NULL; - } - - overlay = (SDL_Overlay*) malloc (sizeof(*overlay)); - if (overlay == NULL) { - SDL_OutOfMemory(); - return NULL; - } - - overlay->format = format; - overlay->w = width; - overlay->h = height; - overlay->planes = 3; - overlay->hw_overlay = 1; - { - int offset; - Uint8 **pixels; - Uint16 *pitches; - int plane2, plane3; - - if (format == SDL_IYUV_OVERLAY) { - - plane2 = 1; /* Native codec format */ - plane3 = 2; - } - else if (format == SDL_YV12_OVERLAY) { - - /* switch the U and V planes */ - plane2 = 2; /* U plane maps to plane 3 */ - plane3 = 1; /* V plane maps to plane 2 */ - } - else { - SDL_SetError("Unsupported YUV format"); - return NULL; - } - - pixels = (Uint8**) malloc (sizeof(*pixels) * 3); - pitches = (Uint16*) malloc (sizeof(*pitches) * 3); - if (pixels == NULL || pitches == NULL) { - SDL_OutOfMemory(); - return NULL; - } - - yuv_pixmap = (PlanarPixmapInfoYUV420*) - malloc (sizeof(PlanarPixmapInfoYUV420) + - (width * height * 2)); - if (yuv_pixmap == NULL) { - SDL_OutOfMemory (); - return NULL; - } - - /* CHECK_ALIGN(yuv_pixmap); */ - offset = sizeof(PlanarPixmapInfoYUV420); - /* offset += ALIGN(offset); */ - /* CHECK_ALIGN(offset); */ - - pixels[0] = (Uint8*)yuv_pixmap + offset; - /* CHECK_ALIGN(pixels[0]); */ - - pitches[0] = width; - yuv_pixmap->componentInfoY.offset = offset; - yuv_pixmap->componentInfoY.rowBytes = width; - - offset += width * height; - pixels[plane2] = (Uint8*)yuv_pixmap + offset; - pitches[plane2] = width / 2; - yuv_pixmap->componentInfoCb.offset = offset; - yuv_pixmap->componentInfoCb.rowBytes = width / 2; - - offset += (width * height / 4); - pixels[plane3] = (Uint8*)yuv_pixmap + offset; - pitches[plane3] = width / 2; - yuv_pixmap->componentInfoCr.offset = offset; - yuv_pixmap->componentInfoCr.rowBytes = width / 2; - - overlay->pixels = pixels; - overlay->pitches = pitches; - } - - overlay->hwfuncs = malloc (sizeof(*overlay->hwfuncs)); - if (overlay->hwfuncs == NULL) { - SDL_OutOfMemory(); - return NULL; - } - - overlay->hwfuncs->Lock = QZ_LockYUV; - overlay->hwfuncs->Unlock = QZ_UnlockYUV; - overlay->hwfuncs->Display = QZ_DisplayYUV; - overlay->hwfuncs->FreeHW = QZ_FreeHWYUV; - - yuv_width = overlay->w; - yuv_height = overlay->h; - - return overlay; -} diff --git a/src/video/quartz/SDL_QuartzWM.m b/src/video/quartz/SDL_QuartzWM.m index 6f9f4a51b..bcddb0e5e 100644 --- a/src/video/quartz/SDL_QuartzWM.m +++ b/src/video/quartz/SDL_QuartzWM.m @@ -1,6 +1,6 @@ /* SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + Copyright (C) 1997-2003 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -20,20 +20,21 @@ slouken@libsdl.org */ -static void QZ_ChangeGrabState (_THIS, int action); +#include "SDL_QuartzVideo.h" + struct WMcursor { Cursor curs; }; -static void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { +void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { if ( cursor != NULL ) free (cursor); } /* Use the Carbon cursor routines for now */ -static WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, +WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) { WMcursor *cursor; int row, bytes; @@ -68,26 +69,34 @@ static void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { return(cursor); } -static int QZ_ShowWMCursor (_THIS, WMcursor *cursor) { +void QZ_ShowMouse (_THIS) { + if (!cursor_visible) { + [ NSCursor unhide ]; + cursor_visible = YES; + } +} + +void QZ_HideMouse (_THIS) { + if (cursor_visible) { + [ NSCursor hide ]; + cursor_visible = NO; + } +} + +int QZ_ShowWMCursor (_THIS, WMcursor *cursor) { if ( cursor == NULL) { - if ( cursor_visible ) { - if (!cursor_hidden) { - HideCursor (); - cursor_hidden = YES; - } - cursor_visible = NO; + if ( cursor_should_be_visible ) { + QZ_HideMouse (this); + cursor_should_be_visible = NO; QZ_ChangeGrabState (this, QZ_HIDECURSOR); } } else { SetCursor(&cursor->curs); - if ( ! cursor_visible ) { - if (cursor_hidden) { - ShowCursor (); - cursor_hidden = NO; - } - cursor_visible = YES; + if ( ! cursor_should_be_visible ) { + QZ_ShowMouse (this); + cursor_should_be_visible = YES; QZ_ChangeGrabState (this, QZ_SHOWCURSOR); } } @@ -104,20 +113,20 @@ static int QZ_ShowWMCursor (_THIS, WMcursor *cursor) { */ /* Convert Cocoa screen coordinate to Cocoa window coordinate */ -static void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) { +void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) { *p = [ qz_window convertScreenToBase:*p ]; } /* Convert Cocoa window coordinate to Cocoa screen coordinate */ -static void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) { +void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) { *p = [ qz_window convertBaseToScreen:*p ]; } /* Convert SDL coordinate to Cocoa coordinate */ -static void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { +void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */ @@ -134,7 +143,7 @@ static void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { } /* Convert Cocoa coordinate to SDL coordinate */ -static void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { +void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */ @@ -151,7 +160,7 @@ static void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { } /* Convert SDL coordinate to window server (CoreGraphics) coordinate */ -static CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) { +CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) { CGPoint cgp; @@ -174,7 +183,7 @@ static CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) { #if 0 /* Dead code */ /* Convert window server (CoreGraphics) coordinate to SDL coordinate */ -static void QZ_PrivateCGToSDL (_THIS, NSPoint *p) { +void QZ_PrivateCGToSDL (_THIS, NSPoint *p) { if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */ @@ -190,7 +199,7 @@ static void QZ_PrivateCGToSDL (_THIS, NSPoint *p) { } #endif /* Dead code */ -static void QZ_PrivateWarpCursor (_THIS, int x, int y) { +void QZ_PrivateWarpCursor (_THIS, int x, int y) { NSPoint p; CGPoint cgp; @@ -203,10 +212,10 @@ static void QZ_PrivateWarpCursor (_THIS, int x, int y) { CGWarpMouseCursorPosition (cgp); } -static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) { +void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) { /* Only allow warping when in foreground */ - if ( ! in_foreground ) + if ( ! [ NSApp isActive ] ) return; /* Do the actual warp */ @@ -216,10 +225,10 @@ static void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) { SDL_PrivateMouseMotion (0, 0, x, y); } -static void QZ_MoveWMCursor (_THIS, int x, int y) { } -static void QZ_CheckMouseMode (_THIS) { } +void QZ_MoveWMCursor (_THIS, int x, int y) { } +void QZ_CheckMouseMode (_THIS) { } -static void QZ_SetCaption (_THIS, const char *title, const char *icon) { +void QZ_SetCaption (_THIS, const char *title, const char *icon) { if ( qz_window != nil ) { NSString *string; @@ -236,7 +245,7 @@ static void QZ_SetCaption (_THIS, const char *title, const char *icon) { } } -static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask) +void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask) { NSBitmapImageRep *imgrep; NSImage *img; @@ -305,7 +314,7 @@ static void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask) [pool release]; } -static int QZ_IconifyWindow (_THIS) { +int QZ_IconifyWindow (_THIS) { if ( ! [ qz_window isMiniaturized ] ) { [ qz_window miniaturize:nil ]; @@ -318,12 +327,12 @@ static int QZ_IconifyWindow (_THIS) { } /* -static int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { +int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { info->nsWindowPtr = qz_window; return 0; }*/ -static void QZ_ChangeGrabState (_THIS, int action) { +void QZ_ChangeGrabState (_THIS, int action) { /* Figure out what the next state should be based on the action. @@ -331,7 +340,7 @@ static void QZ_ChangeGrabState (_THIS, int action) { */ if ( grab_state == QZ_UNGRABBED ) { if ( action == QZ_ENABLE_GRAB ) { - if ( cursor_visible ) + if ( cursor_should_be_visible ) grab_state = QZ_VISIBLE_GRAB; else grab_state = QZ_INVISIBLE_GRAB; @@ -369,7 +378,7 @@ static void QZ_ChangeGrabState (_THIS, int action) { } } -static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) { +SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) { int doGrab = grab_mode & SDL_GRAB_ON; /*int fullscreen = grab_mode & SDL_GRAB_FULLSCREEN;*/ @@ -396,81 +405,3 @@ static SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) { return current_grab_mode; } - -/* Resize icon, BMP format */ -static unsigned char QZ_ResizeIcon[] = { - 0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00, - 0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00, - 0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda, - 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, - 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87, - 0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8, - 0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8, - 0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda, - 0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda, - 0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7, - 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, - 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8, - 0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc, - 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb, - 0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8, - 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc, - 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b -}; - -static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) { - - /* Check if we should draw the resize icon */ - if (SDL_VideoSurface->flags & SDL_RESIZABLE) { - - Rect icon; - SetRect (&icon, SDL_VideoSurface->w - 13, SDL_VideoSurface->h - 13, - SDL_VideoSurface->w, SDL_VideoSurface->h); - - if (RectInRgn (&icon, dirtyRegion)) { - - SDL_Rect icon_rect; - - /* Create the icon image */ - if (resize_icon == NULL) { - - SDL_RWops *rw; - SDL_Surface *tmp; - - rw = SDL_RWFromMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon)); - tmp = SDL_LoadBMP_RW (rw, SDL_TRUE); - - resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY); - SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF); - - SDL_FreeSurface (tmp); - } - - icon_rect.x = SDL_VideoSurface->w - 13; - icon_rect.y = SDL_VideoSurface->h - 13; - icon_rect.w = 13; - icon_rect.h = 13; - - SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect); - } - } -} diff --git a/src/video/quartz/SDL_QuartzWindow.h b/src/video/quartz/SDL_QuartzWindow.h new file mode 100644 index 000000000..f90c579f4 --- /dev/null +++ b/src/video/quartz/SDL_QuartzWindow.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2003 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* Subclass of NSWindow to fix genie effect and support resize events */ +@interface SDL_QuartzWindow : NSWindow +- (void)miniaturize:(id)sender; +- (void)display; +- (void)setFrame:(NSRect)frameRect display:(BOOL)flag; +- (void)appDidHide:(NSNotification*)note; +- (void)appWillUnhide:(NSNotification*)note; +- (void)appDidUnhide:(NSNotification*)note; +- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag; +@end + +/* Delegate for our NSWindow to send SDLQuit() on close */ +@interface SDL_QuartzWindowDelegate : NSObject +- (BOOL)windowShouldClose:(id)sender; +@end + diff --git a/src/video/quartz/SDL_QuartzWindow.m b/src/video/quartz/SDL_QuartzWindow.m index 1692a92a5..d6ffddf27 100644 --- a/src/video/quartz/SDL_QuartzWindow.m +++ b/src/video/quartz/SDL_QuartzWindow.m @@ -1,3 +1,27 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2003 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWindow.h" /* This function makes the *SDL region* of the window 100% opaque. @@ -25,18 +49,6 @@ static void QZ_SetPortAlphaOpaque () { } } -/* Subclass of NSWindow to fix genie effect and support resize events */ -@interface SDL_QuartzWindow : NSWindow -{} -- (void)miniaturize:(id)sender; -- (void)display; -- (void)setFrame:(NSRect)frameRect display:(BOOL)flag; -- (void)appDidHide:(NSNotification*)note; -- (void)appWillUnhide:(NSNotification*)note; -- (void)appDidUnhide:(NSNotification*)note; -- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag; -@end - @implementation SDL_QuartzWindow /* we override these methods to fix the miniaturize animation/dock icon bug */ @@ -186,12 +198,6 @@ - (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask @end -/* Delegate for our NSWindow to send SDLQuit() on close */ -@interface SDL_QuartzWindowDelegate : NSObject -{} -- (BOOL)windowShouldClose:(id)sender; -@end - @implementation SDL_QuartzWindowDelegate - (BOOL)windowShouldClose:(id)sender { @@ -199,11 +205,3 @@ - (BOOL)windowShouldClose:(id)sender return NO; } @end - -/* Subclass of NSQuickDrawView for the window's subview */ -@interface SDL_QuartzWindowView : NSQuickDrawView -{} -@end - -@implementation SDL_QuartzWindowView -@end diff --git a/src/video/quartz/SDL_QuartzYUV.m b/src/video/quartz/SDL_QuartzYUV.m new file mode 100644 index 000000000..3943a6f16 --- /dev/null +++ b/src/video/quartz/SDL_QuartzYUV.m @@ -0,0 +1,327 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2003 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWindow.h" +#include "SDL_yuvfuncs.h" + + +#define yuv_idh (this->hidden->yuv_idh) +#define yuv_matrix (this->hidden->yuv_matrix) +#define yuv_codec (this->hidden->yuv_codec) +#define yuv_seq (this->hidden->yuv_seq) +#define yuv_pixmap (this->hidden->yuv_pixmap) +#define yuv_data (this->hidden->yuv_data) +#define yuv_width (this->hidden->yuv_width) +#define yuv_height (this->hidden->yuv_height) +#define yuv_port (this->hidden->yuv_port) + + +static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) { + + return 0; +} + +static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) { + + ; +} + +static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) { + + OSErr err; + CodecFlags flags; + + if (dstrect->x != 0 || dstrect->y != 0) { + + SDL_SetError ("Need a dstrect at (0,0)"); + return -1; + } + + if (dstrect->w != yuv_width || dstrect->h != yuv_height) { + + Fixed scale_x, scale_y; + + scale_x = FixDiv ( Long2Fix (dstrect->w), Long2Fix (overlay->w) ); + scale_y = FixDiv ( Long2Fix (dstrect->h), Long2Fix (overlay->h) ); + + SetIdentityMatrix (yuv_matrix); + ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0)); + + SetDSequenceMatrix (yuv_seq, yuv_matrix); + + yuv_width = dstrect->w; + yuv_height = dstrect->h; + } + + if( ( err = DecompressSequenceFrameS( + yuv_seq, + (void*)yuv_pixmap, + sizeof (PlanarPixmapInfoYUV420), + codecFlagUseImageBuffer, &flags, nil ) != noErr ) ) + { + SDL_SetError ("DecompressSequenceFrameS failed"); + } + + return err == noErr; +} + +static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) { + + CDSequenceEnd (yuv_seq); + ExitMovies(); + + free (overlay->hwfuncs); + free (overlay->pitches); + free (overlay->pixels); + + if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { + [ qz_window close ]; + qz_window = nil; + } + + free (yuv_matrix); + DisposeHandle ((Handle)yuv_idh); +} + +/* check for 16 byte alignment, bail otherwise */ +#define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0) + +/* align a byte offset, return how much to add to make it a multiple of 16 */ +#define ALIGN(x) ((16 - (x & 15)) & 15) + +SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, + Uint32 format, SDL_Surface *display) { + + Uint32 codec; + OSStatus err; + CGrafPtr port; + SDL_Overlay *overlay; + + if (format == SDL_YV12_OVERLAY || + format == SDL_IYUV_OVERLAY) { + + codec = kYUV420CodecType; + } + else { + SDL_SetError ("Hardware: unsupported video format"); + return NULL; + } + + yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription)); + if (yuv_idh == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + yuv_matrix = (MatrixRecordPtr) malloc (sizeof(MatrixRecord)); + if (yuv_matrix == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + if ( EnterMovies() != noErr ) { + SDL_SetError ("Could not init QuickTime for YUV playback"); + return NULL; + } + + err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec); + if (err != noErr) { + SDL_SetError ("Could not find QuickTime codec for format"); + return NULL; + } + + if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { + + /* + Acceleration requires a window to be present. + A CGrafPtr that points to the screen isn't good enough + */ + NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); + + qz_window = [ [ SDL_QuartzWindow alloc ] + initWithContentRect:content + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered defer:NO ]; + + if (qz_window == nil) { + SDL_SetError ("Could not create the Cocoa window"); + return NULL; + } + + [ qz_window setContentView:[ [ NSQuickDrawView alloc ] init ] ]; + [ qz_window setReleasedWhenClosed:YES ]; + [ qz_window center ]; + [ qz_window setAcceptsMouseMovedEvents:YES ]; + [ qz_window setLevel:CGShieldingWindowLevel() ]; + [ qz_window makeKeyAndOrderFront:nil ]; + + port = [ [ qz_window contentView ] qdPort ]; + SetPort (port); + + /* + BUG: would like to remove white flash when window kicks in + { + Rect r; + SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); + PaintRect (&r); + QDFlushPortBuffer (port, nil); + } + */ + } + else { + port = [ window_view qdPort ]; + SetPort (port); + } + + SetIdentityMatrix (yuv_matrix); + + HLock ((Handle)yuv_idh); + + (**yuv_idh).idSize = sizeof(ImageDescription); + (**yuv_idh).cType = codec; + (**yuv_idh).version = 1; + (**yuv_idh).revisionLevel = 0; + (**yuv_idh).width = width; + (**yuv_idh).height = height; + (**yuv_idh).hRes = Long2Fix(72); + (**yuv_idh).vRes = Long2Fix(72); + (**yuv_idh).spatialQuality = codecLosslessQuality; + (**yuv_idh).frameCount = 1; + (**yuv_idh).clutID = -1; + (**yuv_idh).dataSize = 0; + (**yuv_idh).depth = 24; + + HUnlock ((Handle)yuv_idh); + + err = DecompressSequenceBeginS ( + &yuv_seq, + yuv_idh, + NULL, + 0, + port, + NULL, + NULL, + yuv_matrix, + 0, + NULL, + codecFlagUseImageBuffer, + codecLosslessQuality, + yuv_codec); + + if (err != noErr) { + SDL_SetError ("Error trying to start YUV codec."); + return NULL; + } + + overlay = (SDL_Overlay*) malloc (sizeof(*overlay)); + if (overlay == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->planes = 3; + overlay->hw_overlay = 1; + { + int offset; + Uint8 **pixels; + Uint16 *pitches; + int plane2, plane3; + + if (format == SDL_IYUV_OVERLAY) { + + plane2 = 1; /* Native codec format */ + plane3 = 2; + } + else if (format == SDL_YV12_OVERLAY) { + + /* switch the U and V planes */ + plane2 = 2; /* U plane maps to plane 3 */ + plane3 = 1; /* V plane maps to plane 2 */ + } + else { + SDL_SetError("Unsupported YUV format"); + return NULL; + } + + pixels = (Uint8**) malloc (sizeof(*pixels) * 3); + pitches = (Uint16*) malloc (sizeof(*pitches) * 3); + if (pixels == NULL || pitches == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + yuv_pixmap = (PlanarPixmapInfoYUV420*) + malloc (sizeof(PlanarPixmapInfoYUV420) + + (width * height * 2)); + if (yuv_pixmap == NULL) { + SDL_OutOfMemory (); + return NULL; + } + + /* CHECK_ALIGN(yuv_pixmap); */ + offset = sizeof(PlanarPixmapInfoYUV420); + /* offset += ALIGN(offset); */ + /* CHECK_ALIGN(offset); */ + + pixels[0] = (Uint8*)yuv_pixmap + offset; + /* CHECK_ALIGN(pixels[0]); */ + + pitches[0] = width; + yuv_pixmap->componentInfoY.offset = offset; + yuv_pixmap->componentInfoY.rowBytes = width; + + offset += width * height; + pixels[plane2] = (Uint8*)yuv_pixmap + offset; + pitches[plane2] = width / 2; + yuv_pixmap->componentInfoCb.offset = offset; + yuv_pixmap->componentInfoCb.rowBytes = width / 2; + + offset += (width * height / 4); + pixels[plane3] = (Uint8*)yuv_pixmap + offset; + pitches[plane3] = width / 2; + yuv_pixmap->componentInfoCr.offset = offset; + yuv_pixmap->componentInfoCr.rowBytes = width / 2; + + overlay->pixels = pixels; + overlay->pitches = pitches; + } + + overlay->hwfuncs = malloc (sizeof(*overlay->hwfuncs)); + if (overlay->hwfuncs == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + overlay->hwfuncs->Lock = QZ_LockYUV; + overlay->hwfuncs->Unlock = QZ_UnlockYUV; + overlay->hwfuncs->Display = QZ_DisplayYUV; + overlay->hwfuncs->FreeHW = QZ_FreeHWYUV; + + yuv_width = overlay->w; + yuv_height = overlay->h; + + return overlay; +}