From 1751e870007e51689ced8b8db352d534f7744466 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 21 Sep 2009 06:08:23 +0000 Subject: [PATCH] 1.2 Quartz video: Ripped out QuickDraw and QuickTime. Now we use the software path for YUV, and CoreGraphics for 2D stuff. There are several other 10.6 fixes in here, too...now we can build a 64-bit SDL for Snow Leopard! --- configure.in | 4 +- src/video/quartz/SDL_QuartzGL.m | 15 +- src/video/quartz/SDL_QuartzVideo.h | 27 +- src/video/quartz/SDL_QuartzVideo.m | 545 ++++++---------------------- src/video/quartz/SDL_QuartzWM.m | 12 +- src/video/quartz/SDL_QuartzWindow.h | 6 +- src/video/quartz/SDL_QuartzWindow.m | 27 +- src/video/quartz/SDL_QuartzYUV.m | 330 ----------------- 8 files changed, 139 insertions(+), 827 deletions(-) delete mode 100644 src/video/quartz/SDL_QuartzYUV.m diff --git a/configure.in b/configure.in index 4c22f8917..30d4713a1 100644 --- a/configure.in +++ b/configure.in @@ -2696,8 +2696,8 @@ case "$host" in need_iokit_framework=yes fi if test x$enable_video_carbon = xyes -o x$enable_video_cocoa = xyes; then - # The Cocoa backend still needs Carbon, and the YUV code QuickTime - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuickTime -Wl,-framework,ApplicationServices" + # The Cocoa backend still needs Carbon + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ApplicationServices" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon" fi # If either the audio or CD driver is used, add the AudioUnit framework diff --git a/src/video/quartz/SDL_QuartzGL.m b/src/video/quartz/SDL_QuartzGL.m index 3864e6892..1549c08ab 100644 --- a/src/video/quartz/SDL_QuartzGL.m +++ b/src/video/quartz/SDL_QuartzGL.m @@ -41,13 +41,24 @@ #define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56) #endif - +#ifdef __powerpc__ /* we lost this in 10.6, which has no PPC support. */ @implementation NSOpenGLContext (CGLContextAccess) - (CGLContextObj) cglContext; { return _contextAuxiliary; } @end +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) +{ + return [nsctx cglContext]; +} +#else +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) +{ + return (CGLContextObj) [nsctx CGLContextObj]; +} +#endif + /* OpenGL helper functions (used internally) */ @@ -165,7 +176,7 @@ int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { { long cache_max = 64; - CGLContextObj ctx = [ gl_context cglContext ]; + CGLContextObj ctx = QZ_GetCGLContextObj(gl_context); CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max); CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); } diff --git a/src/video/quartz/SDL_QuartzVideo.h b/src/video/quartz/SDL_QuartzVideo.h index 237594450..720587bb1 100644 --- a/src/video/quartz/SDL_QuartzVideo.h +++ b/src/video/quartz/SDL_QuartzVideo.h @@ -53,7 +53,6 @@ #include #include -#include #include /* For CGL functions and types */ #include /* For powersave handling */ #include @@ -68,13 +67,21 @@ #include "../SDL_pixels_c.h" #include "../../events/SDL_events_c.h" + +#ifdef __powerpc__ /* This is a workaround to directly access NSOpenGLContext's CGL context We need this to check for errors NSOpenGLContext doesn't support + Please note this is only used on PowerPC (Intel Macs are guaranteed to + have a better API for this, since it showed up in Mac OS X 10.3). */ @interface NSOpenGLContext (CGLContextAccess) - (CGLContextObj) cglContext; @end +#endif + +/* use this to get the CGLContext; it handles Cocoa interface changes. */ +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx); /* Main driver structure to store required state information */ @@ -93,7 +100,8 @@ typedef struct SDL_PrivateVideoData { Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */ Uint32 warp_ticks; /* timestamp when the warp occured */ NSWindow *window; /* Cocoa window to implement the SDL window */ - NSQuickDrawView *view; /* the window's view; draw 2D and OpenGL into this view */ + NSView *view; /* the window's view; draw 2D and OpenGL into this view */ + CGContextRef cg_context; /* CoreGraphics rendering context */ 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 */ SDL_Rect **client_mode_list; /* resolution list to pass back to client */ @@ -113,14 +121,6 @@ typedef struct SDL_PrivateVideoData { Uint8 *current_buffer; /* the buffer being copied to the screen */ BOOL quit_thread; /* used to quit the async blitting thread */ SInt32 system_version; /* used to dis-/enable workarounds depending on the system version */ - - ImageDescriptionHandle yuv_idh; - MatrixRecordPtr yuv_matrix; - DecompressorComponent yuv_codec; - ImageSequence yuv_seq; - PlanarPixmapInfoYUV420 *yuv_pixmap; - Sint16 yuv_width, yuv_height; - CGrafPtr yuv_port; void *opengl_library; /* dynamically loaded OpenGL library. */ } SDL_PrivateVideoData; @@ -139,6 +139,7 @@ typedef struct SDL_PrivateVideoData { #define mode_flags (this->hidden->flags) #define qz_window (this->hidden->window) #define window_view (this->hidden->view) +#define cg_context (this->hidden->cg_context) #define video_set (this->hidden->video_set) #define warp_ticks (this->hidden->warp_ticks) #define warp_flag (this->hidden->warp_flag) @@ -156,6 +157,7 @@ typedef struct SDL_PrivateVideoData { #define cursor_should_be_visible (this->hidden->cursor_should_be_visible) #define cursor_visible (this->hidden->cursor_visible) #define sw_buffers (this->hidden->sw_buffers) +#define sw_contexts (this->hidden->sw_contexts) #define thread (this->hidden->thread) #define sem1 (this->hidden->sem1) #define sem2 (this->hidden->sem2) @@ -215,11 +217,6 @@ int QZ_IconifyWindow (_THIS); SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); /*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ -/* YUV functions */ -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); diff --git a/src/video/quartz/SDL_QuartzVideo.m b/src/video/quartz/SDL_QuartzVideo.m index eaaac0d7b..d2701253f 100644 --- a/src/video/quartz/SDL_QuartzVideo.m +++ b/src/video/quartz/SDL_QuartzVideo.m @@ -24,7 +24,8 @@ #include "SDL_QuartzVideo.h" #include "SDL_QuartzWindow.h" -/* +#ifdef __powerpc__ /* I'm gambling they fixed this by 10.4. --ryan. */ +/* 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 @@ -41,6 +42,15 @@ - (void) setFrame:(NSRect)frame; _frame = frame; } @end +static inline void QZ_SetFrame(NSScreen *nsscreen, NSRect frame) +{ + [nsscreen setFrame:frame]; +} +#else +static inline void QZ_SetFrame(NSScreen *nsscreen, NSRect frame) +{ +} +#endif @interface SDLTranslatorResponder : NSTextView { @@ -52,6 +62,8 @@ @implementation SDLTranslatorResponder - (void) doCommandBySelector:(SEL) myselector {} @end +/* absent in 10.3.9. */ +CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef); /* Bootstrap functions */ static int QZ_Available (); @@ -79,8 +91,6 @@ static int QZ_SetColors (_THIS, int first_color, 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); @@ -164,7 +174,14 @@ static int QZ_Available () { /*device->GetWMInfo = QZ_GetWMInfo;*/ device->GrabInput = QZ_GrabInput; - device->CreateYUVOverlay = QZ_CreateYUVOverlay; + /* + * This is a big hassle, needing QuickDraw and QuickTime on older + * systems, and god knows what on 10.6, so we immediately fail here, + * which causes SDL to make an RGB surface and manage the YUV overlay + * in software. Sorry. Use SDL 1.3 if you want YUV rendering in a pixel + * shader. :) + */ + /*device->CreateYUVOverlay = QZ_CreateYUVOverlay;*/ device->free = QZ_DeleteDevice; @@ -371,6 +388,12 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { this->LockHWSurface = NULL; this->UnlockHWSurface = NULL; + if (cg_context) { + CGContextFlush (cg_context); + CGContextRelease (cg_context); + cg_context = nil; + } + /* Release fullscreen resources */ if ( mode_flags & SDL_FULLSCREEN ) { @@ -412,7 +435,7 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { See comment in QZ_SetVideoFullscreen for why we do this */ screen_rect = NSMakeRect(0,0,device_width,device_height); - [ [ NSScreen mainScreen ] setFrame:screen_rect ]; + QZ_SetFrame([ NSScreen mainScreen ], screen_rect); } } /* Release window mode resources */ @@ -440,7 +463,7 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { NSRect contentRect; BOOL isCustom = NO; CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; - + /* Fade to black to hide resolution-switching flicker (and garbage that is displayed by a destroyed OpenGL context, if applicable) */ if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { @@ -451,6 +474,12 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { if (video_set == SDL_TRUE) QZ_UnsetVideoMode (this, FALSE); + /* Sorry, QuickDraw was ripped out. */ + if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { + SDL_SetError ("Embedded QuickDraw windows are no longer supported"); + goto ERR_NO_MATCH; + } + /* See if requested mode exists */ mode = CGDisplayBestModeForParameters (display_id, bpp, width, height, &exact_match); @@ -487,7 +516,8 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { current->flags |= SDL_FULLSCREEN; current->flags |= SDL_HWSURFACE; current->flags |= SDL_PREALLOC; - + /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */ + this->UpdateRects = QZ_DirectUpdate; this->LockHWSurface = QZ_LockHWSurface; this->UnlockHWSurface = QZ_UnlockHWSurface; @@ -531,42 +561,12 @@ other blitting while waiting on the VBL (and hence results in higher framerates) if ( CGDisplayCanSetPalette (display_id) ) current->flags |= SDL_HWPALETTE; - /* The code below checks for any valid custom windows and views. If none are - available, then we create new ones. Window/View code was added in FULLSCREEN - so that special events like the changing of the cursor image would be handled - ( only the front-most and active application can change the cursor appearance - and with no valid window/view in FULLSCREEN, SDL wouldn't update its cursor. ) - */ - /* Check for user-specified window and view */ - { - char *windowPtrString = getenv ("SDL_NSWindowPointer"); - char *viewPtrString = getenv ("SDL_NSQuickDrawViewPointer"); - - contentRect = NSMakeRect (0, 0, width, height); - - if (windowPtrString && viewPtrString) { - /* Release any previous window */ - if ( qz_window ) { - [ qz_window release ]; - qz_window = nil; - } - - qz_window = (NSWindow*)atoi(windowPtrString); - window_view = (NSQuickDrawView*)atoi(viewPtrString); - isCustom = YES; - /* - Retain reference to window because we - might release it in QZ_UnsetVideoMode - */ - [ qz_window retain ]; - } - } /* Check if we should recreate the window */ if (qz_window == nil) { /* Manually create a window, avoids having a nib file resource */ qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:contentRect - styleMask:nil + styleMask:0 backing:NSBackingStoreBuffered defer:NO ]; @@ -600,7 +600,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) [ [ qz_window contentView ] addSubview:window_view ]; [ window_view release ]; - ctx = [ gl_context cglContext ]; + ctx = QZ_GetCGLContextObj (gl_context); err = CGLSetFullScreen (ctx); if (err) { @@ -634,7 +634,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) ourselves. This hack should be removed if/when the bug is fixed. */ screen_rect = NSMakeRect(0,0,width,height); - [ [ NSScreen mainScreen ] setFrame:screen_rect ]; + QZ_SetFrame([ NSScreen mainScreen ], screen_rect); /* Save the flags to ensure correct tear-down */ mode_flags = current->flags; @@ -694,40 +694,16 @@ other blitting while waiting on the VBL (and hence results in higher framerates) } } - /* Check for user-specified window and view */ - { - char *windowPtrString = getenv ("SDL_NSWindowPointer"); - char *viewPtrString = getenv ("SDL_NSQuickDrawViewPointer"); - - if (windowPtrString && viewPtrString) { - - /* Release any previous window */ - if ( qz_window ) { - [ qz_window release ]; - qz_window = nil; - } - - qz_window = (NSWindow*)atoi(windowPtrString); - window_view = (NSQuickDrawView*)atoi(viewPtrString); - isCustom = YES; - - /* - Retain reference to window because we - might release it in QZ_UnsetVideoMode - */ - [ qz_window retain ]; - - style = [ qz_window styleMask ]; - /* Check resizability */ - if ( style & NSResizableWindowMask ) - current->flags |= SDL_RESIZABLE; - - /* Check frame */ - if ( style & NSBorderlessWindowMask ) - current->flags |= SDL_NOFRAME; + /* Sorry, QuickDraw was ripped out. */ + if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { + SDL_SetError ("Embedded QuickDraw windows are no longer supported"); + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); } + return NULL; } - + /* Check if we should recreate the window */ if (qz_window == nil) { @@ -807,48 +783,36 @@ other blitting while waiting on the VBL (and hence results in higher framerates) [ qz_window makeKeyAndOrderFront:nil ]; current->flags |= SDL_OPENGL; } - /* For 2D, we set the subview to an NSQuickDrawView */ + /* For 2D, we build a CGBitmapContext */ else { - short qdbpp = 0; + CGColorSpaceRef cgColorspace; /* Only recreate the view if it doesn't already exist */ if (window_view == nil) { - window_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; [ [ qz_window contentView ] addSubview:window_view ]; [ window_view release ]; [ qz_window makeKeyAndOrderFront:nil ]; } - LockPortBits ( [ window_view qdPort ] ); - current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) ); - current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) ); - qdbpp = GetPixDepth ( GetPortPixMap ( [ window_view qdPort ] ) ); - UnlockPortBits ( [ window_view qdPort ] ); - - /* QuickDraw may give a 16-bit shadow surface on 8-bit displays! */ - *bpp = qdbpp; - + cgColorspace = CGColorSpaceCreateDeviceRGB(); + current->pitch = 4 * current->w; + current->pixels = SDL_malloc (current->h * current->pitch); + + cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, + 8, current->pitch, cgColorspace, + kCGImageAlphaNoneSkipFirst); + CGColorSpaceRelease (cgColorspace); + current->flags |= SDL_SWSURFACE; - current->flags |= SDL_PREALLOC; current->flags |= SDL_ASYNCBLIT; + current->hwdata = (void *) cg_context; - /* - current->pixels now points to the window's pixels - We want it to point to the *view's* pixels - */ - { - int vOffset = [ qz_window frame ].size.height - - [ window_view frame ].size.height - [ window_view frame ].origin.y; - - int hOffset = [ window_view frame ].origin.x; - - current->pixels = (Uint8 *)current->pixels + (vOffset * current->pitch) + hOffset * (qdbpp/8); - } this->UpdateRects = QZ_UpdateRects; - this->LockHWSurface = QZ_LockWindow; - this->UnlockHWSurface = QZ_UnlockWindow; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; } /* Save flags to ensure correct teardown */ @@ -877,8 +841,8 @@ other blitting while waiting on the VBL (and hence results in higher framerates) } /* Setup windowed video */ else { - /* Force bpp to the device's bpp */ - bpp = device_bpp; + /* Force bpp to 32 */ + bpp = 32; current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags); if (current == NULL) return NULL; @@ -903,9 +867,15 @@ other blitting while waiting on the VBL (and hence results in higher framerates) return NULL; case 32: /* (8)-8-8-8 ARGB */ amask = 0x00000000; +#ifdef __LITTLE_ENDIAN__ + rmask = 0x0000FF00; + gmask = 0x00FF0000; + bmask = 0xFF000000; +#else rmask = 0x00FF0000; gmask = 0x0000FF00; bmask = 0x000000FF; +#endif break; } @@ -1062,6 +1032,9 @@ static int QZ_ThreadFlip (_THIS) { /* On error, skip VBL delay */ ERROR: + /* TODO: use CGContextDrawImage here too! Create two CGContextRefs the same way we + create two buffers, replace current_buffer with current_context and set it + appropriately in QZ_FlipDoubleBuffer. */ while ( h-- ) { SDL_memcpy (dst, src, len); @@ -1105,253 +1078,6 @@ static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { #pragma unused(this,num_rects,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) { - - -#if TEST_OBSCURED - - /* - In order to determine if a direct copy to the screen is possible, - we must figure out if there are any windows covering ours (including shadows). - This can be done by querying the window server about the on screen - windows for their screen rectangle and window level. - The procedure used below is puts accuracy before speed; however, it aims to call - the window server the fewest number of times possible to keep things reasonable. - In my testing on a 300mhz G3, this routine typically takes < 2 ms. -DW - - Notes: - -Calls into the Window Server involve IPC which is slow. - -Getting a rectangle seems slower than getting the window level - -The window list we get back is in sorted order, top to bottom - -On average, I suspect, most windows above ours are dock icon windows (hence optimization) - -Some windows above ours are always there, and cannot move or obscure us (menu bar) - - Bugs: - -no way (yet) to deactivate direct drawing when a window is dragged, - or suddenly obscured, so drawing continues and can produce garbage - We need some kind of locking mechanism on window movement to prevent this - - -deactivated normal windows use activated normal - window shadows (slight inaccuraccy) - */ - - /* Cache the connection to the window server */ - static CGSConnectionID cgsConnection = (CGSConnectionID) -1; - - /* Cache the dock icon windows */ - static CGSWindowID dockIcons[kMaxWindows]; - static int numCachedDockIcons = 0; - - CGSWindowID windows[kMaxWindows]; - CGSWindowCount i, count; - CGSWindowLevel winLevel; - CGSRect winRect; - - CGSRect contentRect; - int windowNumber; - int firstDockIcon; - int dockIconCacheMiss; - int windowContentOffset; - - int obscured = SDL_TRUE; - - if ( [ window isVisible ] ) { - - /* - walk the window list looking for windows over top of - (or casting a shadow on) ours - */ - - /* - Get a connection to the window server - Should probably be moved out into SetVideoMode() or InitVideo() - */ - if (cgsConnection == (CGSConnectionID) -1) { - cgsConnection = (CGSConnectionID) 0; - cgsConnection = _CGSDefaultConnection (); - } - - if (cgsConnection) { - - if ( ! [ window styleMask ] & NSBorderlessWindowMask ) - windowContentOffset = 22; - else - windowContentOffset = 0; - - windowNumber = [ window windowNumber ]; - - /* The window list is sorted according to order on the screen */ - count = 0; - CGSGetOnScreenWindowList (cgsConnection, 0, kMaxWindows, windows, &count); - CGSGetScreenRectForWindow (cgsConnection, windowNumber, &contentRect); - - /* adjust rect for window title bar (if present) */ - contentRect.origin.y += windowContentOffset; - contentRect.size.height -= windowContentOffset; - - firstDockIcon = -1; - dockIconCacheMiss = SDL_FALSE; - - /* - The first window is always an empty window with level kCGSWindowLevelTop - so start at index 1 - */ - for (i = 1; i < count; i++) { - - /* If we reach our window in the list, it cannot be obscured */ - if (windows[i] == windowNumber) { - - obscured = SDL_FALSE; - break; - } - else { - - float shadowSide; - float shadowTop; - float shadowBottom; - - CGSGetWindowLevel (cgsConnection, windows[i], &winLevel); - - if (winLevel == kCGSWindowLevelDockIcon) { - - int j; - - if (firstDockIcon < 0) { - - firstDockIcon = i; - - if (numCachedDockIcons > 0) { - - for (j = 0; j < numCachedDockIcons; j++) { - - if (windows[i] == dockIcons[j]) - i++; - else - break; - } - - if (j != 0) { - - i--; - - if (j < numCachedDockIcons) { - - dockIconCacheMiss = SDL_TRUE; - } - } - - } - } - - continue; - } - else if (winLevel == kCGSWindowLevelMenuIgnore - /* winLevel == kCGSWindowLevelTop */) { - - continue; /* cannot obscure window */ - } - else if (winLevel == kCGSWindowLevelDockMenu || - winLevel == kCGSWindowLevelMenu) { - - shadowSide = 18; - shadowTop = 4; - shadowBottom = 22; - } - else if (winLevel == kCGSWindowLevelUtility) { - - shadowSide = 8; - shadowTop = 4; - shadowBottom = 12; - } - else if (winLevel == kCGSWindowLevelNormal) { - - /* - These numbers are for foreground windows, - they are too big (but will work) for background windows - */ - shadowSide = 20; - shadowTop = 10; - shadowBottom = 24; - } - else if (winLevel == kCGSWindowLevelDock) { - - /* Create dock icon cache */ - if (numCachedDockIcons != (i-firstDockIcon) || - dockIconCacheMiss) { - - numCachedDockIcons = i - firstDockIcon; - SDL_memcpy (dockIcons, &(windows[firstDockIcon]), - numCachedDockIcons * sizeof(*windows)); - } - - /* no shadow */ - shadowSide = 0; - shadowTop = 0; - shadowBottom = 0; - } - else { - - /* - kCGSWindowLevelDockLabel, - kCGSWindowLevelDock, - kOther??? - */ - - /* no shadow */ - shadowSide = 0; - shadowTop = 0; - shadowBottom = 0; - } - - CGSGetScreenRectForWindow (cgsConnection, windows[i], &winRect); - - winRect.origin.x -= shadowSide; - winRect.origin.y -= shadowTop; - winRect.size.width += shadowSide; - winRect.size.height += shadowBottom; - - if (NSIntersectsRect (contentRect, winRect)) { - - obscured = SDL_TRUE; - break; - } - - } /* window was not our window */ - - } /* iterate over windows */ - - } /* get cgsConnection */ - - } /* window is visible */ - - return obscured; -#else - return SDL_TRUE; -#endif -} - - -/* Locking functions for the software window buffer */ -static int QZ_LockWindow (_THIS, SDL_Surface *surface) { - - return LockPortBits ( [ window_view qdPort ] ); -} - -static void QZ_UnlockWindow (_THIS, SDL_Surface *surface) { - - UnlockPortBits ( [ window_view qdPort ] ); -} /* Resize icon, BMP format */ static const unsigned char QZ_ResizeIcon[] = { @@ -1393,41 +1119,34 @@ static void QZ_UnlockWindow (_THIS, SDL_Surface *surface) { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b }; -static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) { +static void QZ_DrawResizeIcon (_THIS) { /* 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; - SDL_Rect icon_rect; + /* Create the icon image */ + if (resize_icon == NULL) { + + SDL_RWops *rw; + SDL_Surface *tmp; - /* Create the icon image */ - if (resize_icon == NULL) { + rw = SDL_RWFromConstMem (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_RWops *rw; - SDL_Surface *tmp; - - rw = SDL_RWFromConstMem (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); - } + 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; + 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); - } + SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect); } } @@ -1441,75 +1160,19 @@ static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { /* Do nothing if miniaturized */ } - else if ( ! QZ_IsWindowObscured (qz_window) ) { - - /* Use direct copy to flush contents to the display */ - CGrafPtr savePort; - CGrafPtr dstPort, srcPort; - const BitMap *dstBits, *srcBits; - Rect dstRect, srcRect; - Point offset; - int i; - - GetPort (&savePort); - - dstPort = CreateNewPortForCGDisplayID ((UInt32)display_id); - srcPort = [ window_view qdPort ]; - - offset.h = 0; - offset.v = 0; - SetPort (srcPort); - LocalToGlobal (&offset); - - SetPort (dstPort); - - LockPortBits (dstPort); - LockPortBits (srcPort); - - dstBits = GetPortBitMapForCopyBits (dstPort); - srcBits = GetPortBitMapForCopyBits (srcPort); - - for (i = 0; i < numRects; i++) { - - SetRect (&srcRect, rects[i].x, rects[i].y, - rects[i].x + rects[i].w, - rects[i].y + rects[i].h); - - SetRect (&dstRect, - rects[i].x + offset.h, - rects[i].y + offset.v, - rects[i].x + rects[i].w + offset.h, - rects[i].y + rects[i].h + offset.v); - - CopyBits (srcBits, dstBits, - &srcRect, &dstRect, srcCopy, NULL); - - } - - SetPort (savePort); - } else { - /* Use QDFlushPortBuffer() to flush content to display */ - int i; - RgnHandle dirty = NewRgn (); - RgnHandle temp = NewRgn (); - - SetEmptyRgn (dirty); - - /* Build the region of dirty rectangles */ - for (i = 0; i < numRects; i++) { - - MacSetRectRgn (temp, rects[i].x, rects[i].y, - rects[i].x + rects[i].w, rects[i].y + rects[i].h); - MacUnionRgn (dirty, temp, dirty); - } - - QZ_DrawResizeIcon (this, dirty); + CGContextRef cgc = (CGContextRef) + [[NSGraphicsContext graphicsContextWithWindow: qz_window] + graphicsPort]; + QZ_DrawResizeIcon (this); + CGContextFlush (cg_context); + CGImageRef image = CGBitmapContextCreateImage (cg_context); + CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height); - /* Flush the dirty region */ - QDFlushPortBuffer ( [ window_view qdPort ], dirty ); - DisposeRgn (dirty); - DisposeRgn (temp); + CGContextDrawImage (cgc, rectangle, image); + CGImageRelease(image); + CGContextFlush (cgc); + CGContextRelease (cgc); } } diff --git a/src/video/quartz/SDL_QuartzWM.m b/src/video/quartz/SDL_QuartzWM.m index b32d08150..b0c4002c3 100644 --- a/src/video/quartz/SDL_QuartzWM.m +++ b/src/video/quartz/SDL_QuartzWM.m @@ -171,11 +171,7 @@ void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { else { *p = [ window_view convertPoint:*p toView: nil ]; - - /* We need a workaround in OpenGL mode */ - if ( SDL_VideoSurface->flags & SDL_OPENGL ) { - p->y = [window_view frame].size.height - p->y; - } + p->y = [window_view frame].size.height - p->y; } } @@ -189,11 +185,7 @@ void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { else { *p = [ window_view convertPoint:*p fromView: nil ]; - - /* We need a workaround in OpenGL mode */ - if ( SDL_VideoSurface != NULL && (SDL_VideoSurface->flags & SDL_OPENGL) ) { - p->y = [window_view frame].size.height - p->y; - } + p->y = [window_view frame].size.height - p->y; } } diff --git a/src/video/quartz/SDL_QuartzWindow.h b/src/video/quartz/SDL_QuartzWindow.h index 4d7ade6b8..a1939ba7d 100644 --- a/src/video/quartz/SDL_QuartzWindow.h +++ b/src/video/quartz/SDL_QuartzWindow.h @@ -21,6 +21,10 @@ */ #include "SDL_config.h" +#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 +typedef unsigned int NSUInteger; +#endif + /* Subclass of NSWindow to fix genie effect and support resize events */ @interface SDL_QuartzWindow : NSWindow - (void)miniaturize:(id)sender; @@ -29,7 +33,7 @@ - (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; +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag; @end /* Delegate for our NSWindow to send SDLQuit() on close */ diff --git a/src/video/quartz/SDL_QuartzWindow.m b/src/video/quartz/SDL_QuartzWindow.m index b3a6a9dd7..1b006bfc4 100644 --- a/src/video/quartz/SDL_QuartzWindow.m +++ b/src/video/quartz/SDL_QuartzWindow.m @@ -125,31 +125,6 @@ - (void)setFrame:(NSRect)frameRect display:(BOOL)flag newViewFrame = [ window_view frame ]; SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height); - - /* If not OpenGL, we have to update the pixels and pitch */ - if ( ! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) { - - CGrafPtr thePort = [ window_view qdPort ]; - LockPortBits ( thePort ); - - SDL_VideoSurface->pixels = GetPixBaseAddr ( GetPortPixMap ( thePort ) ); - SDL_VideoSurface->pitch = GetPixRowBytes ( GetPortPixMap ( thePort ) ); - - /* - SDL_VideoSurface->pixels now points to the window's pixels - We want it to point to the *view's* pixels - */ - { - int vOffset = [ qz_window frame ].size.height - - newViewFrame.size.height - newViewFrame.origin.y; - - int hOffset = newViewFrame.origin.x; - - SDL_VideoSurface->pixels = (Uint8 *)SDL_VideoSurface->pixels + (vOffset * SDL_VideoSurface->pitch) + hOffset * (device_bpp/8); - } - - UnlockPortBits ( thePort ); - } } } @@ -183,7 +158,7 @@ - (void)appDidUnhide:(NSNotification*)note SDL_PrivateAppActive (1, SDL_APPACTIVE); } -- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag { /* Make our window subclass receive these application notifications */ [ [ NSNotificationCenter defaultCenter ] addObserver:self diff --git a/src/video/quartz/SDL_QuartzYUV.m b/src/video/quartz/SDL_QuartzYUV.m deleted file mode 100644 index 1f21d96ac..000000000 --- a/src/video/quartz/SDL_QuartzYUV.m +++ /dev/null @@ -1,330 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2009 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_config.h" - -#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 *src, SDL_Rect *dst) { - - OSErr err; - CodecFlags flags; - - if (dst->x != 0 || dst->y != 0) { - - SDL_SetError ("Need a dst at (0,0)"); - return -1; - } - - if (dst->w != yuv_width || dst->h != yuv_height) { - - Fixed scale_x, scale_y; - - scale_x = FixDiv ( Long2Fix (dst->w), Long2Fix (overlay->w) ); - scale_y = FixDiv ( Long2Fix (dst->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 = dst->w; - yuv_height = dst->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(); - - SDL_free (overlay->hwfuncs); - SDL_free (overlay->pitches); - SDL_free (overlay->pixels); - - if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { - [ qz_window close ]; - qz_window = nil; - } - - SDL_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) SDL_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*) SDL_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**) SDL_malloc (sizeof(*pixels) * 3); - pitches = (Uint16*) SDL_malloc (sizeof(*pitches) * 3); - if (pixels == NULL || pitches == NULL) { - SDL_OutOfMemory(); - return NULL; - } - - /* Fix: jc.bertin@free.fr - PlanarPixmapInfoYUV420 is a big-endian struct */ - yuv_pixmap = (PlanarPixmapInfoYUV420*) - SDL_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 = EndianS32_NtoB(offset); - yuv_pixmap->componentInfoY.rowBytes = EndianU32_NtoB(width); - - offset += width * height; - pixels[plane2] = (Uint8*)yuv_pixmap + offset; - pitches[plane2] = width / 2; - yuv_pixmap->componentInfoCb.offset = EndianS32_NtoB(offset); - yuv_pixmap->componentInfoCb.rowBytes = EndianU32_NtoB(width / 2); - - offset += (width * height / 4); - pixels[plane3] = (Uint8*)yuv_pixmap + offset; - pitches[plane3] = width / 2; - yuv_pixmap->componentInfoCr.offset = EndianS32_NtoB(offset); - yuv_pixmap->componentInfoCr.rowBytes = EndianU32_NtoB(width / 2); - - overlay->pixels = pixels; - overlay->pitches = pitches; - } - - overlay->hwfuncs = SDL_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; -}