Commit b5dc26cf authored by Ryan C. Gordon's avatar Ryan C. Gordon

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!

--HG--
branch : SDL-1.2
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/branches/SDL-1.2%403838
parent ddb6f9bd
...@@ -2696,8 +2696,8 @@ case "$host" in ...@@ -2696,8 +2696,8 @@ case "$host" in
need_iokit_framework=yes need_iokit_framework=yes
fi fi
if test x$enable_video_carbon = xyes -o x$enable_video_cocoa = xyes; then 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 # The Cocoa backend still needs Carbon
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,QuickTime -Wl,-framework,ApplicationServices" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ApplicationServices"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
fi fi
# If either the audio or CD driver is used, add the AudioUnit framework # If either the audio or CD driver is used, add the AudioUnit framework
......
...@@ -41,13 +41,24 @@ ...@@ -41,13 +41,24 @@
#define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56) #define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56)
#endif #endif
#ifdef __powerpc__ /* we lost this in 10.6, which has no PPC support. */
@implementation NSOpenGLContext (CGLContextAccess) @implementation NSOpenGLContext (CGLContextAccess)
- (CGLContextObj) cglContext; - (CGLContextObj) cglContext;
{ {
return _contextAuxiliary; return _contextAuxiliary;
} }
@end @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) */ /* OpenGL helper functions (used internally) */
...@@ -165,7 +176,7 @@ int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { ...@@ -165,7 +176,7 @@ int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
{ {
long cache_max = 64; 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_SUBMIT_FUNC_CACHE_MAX, &cache_max);
CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
} }
......
...@@ -53,7 +53,6 @@ ...@@ -53,7 +53,6 @@
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
#include <QuickTime/QuickTime.h>
#include <OpenGL/OpenGL.h> /* For CGL functions and types */ #include <OpenGL/OpenGL.h> /* For CGL functions and types */
#include <IOKit/IOKitLib.h> /* For powersave handling */ #include <IOKit/IOKitLib.h> /* For powersave handling */
#include <pthread.h> #include <pthread.h>
...@@ -68,13 +67,21 @@ ...@@ -68,13 +67,21 @@
#include "../SDL_pixels_c.h" #include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h" #include "../../events/SDL_events_c.h"
#ifdef __powerpc__
/* /*
This is a workaround to directly access NSOpenGLContext's CGL context This is a workaround to directly access NSOpenGLContext's CGL context
We need this to check for errors NSOpenGLContext doesn't support 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) @interface NSOpenGLContext (CGLContextAccess)
- (CGLContextObj) cglContext; - (CGLContextObj) cglContext;
@end @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 */ /* Main driver structure to store required state information */
...@@ -93,7 +100,8 @@ typedef struct SDL_PrivateVideoData { ...@@ -93,7 +100,8 @@ typedef struct SDL_PrivateVideoData {
Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */ Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */
Uint32 warp_ticks; /* timestamp when the warp occured */ Uint32 warp_ticks; /* timestamp when the warp occured */
NSWindow *window; /* Cocoa window to implement the SDL window */ 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_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_GrabMode current_grab_mode; /* default value is SDL_GRAB_OFF */
SDL_Rect **client_mode_list; /* resolution list to pass back to client */ SDL_Rect **client_mode_list; /* resolution list to pass back to client */
...@@ -113,14 +121,6 @@ typedef struct SDL_PrivateVideoData { ...@@ -113,14 +121,6 @@ typedef struct SDL_PrivateVideoData {
Uint8 *current_buffer; /* the buffer being copied to the screen */ Uint8 *current_buffer; /* the buffer being copied to the screen */
BOOL quit_thread; /* used to quit the async blitting thread */ BOOL quit_thread; /* used to quit the async blitting thread */
SInt32 system_version; /* used to dis-/enable workarounds depending on the system version */ 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. */ void *opengl_library; /* dynamically loaded OpenGL library. */
} SDL_PrivateVideoData; } SDL_PrivateVideoData;
...@@ -139,6 +139,7 @@ typedef struct SDL_PrivateVideoData { ...@@ -139,6 +139,7 @@ typedef struct SDL_PrivateVideoData {
#define mode_flags (this->hidden->flags) #define mode_flags (this->hidden->flags)
#define qz_window (this->hidden->window) #define qz_window (this->hidden->window)
#define window_view (this->hidden->view) #define window_view (this->hidden->view)
#define cg_context (this->hidden->cg_context)
#define video_set (this->hidden->video_set) #define video_set (this->hidden->video_set)
#define warp_ticks (this->hidden->warp_ticks) #define warp_ticks (this->hidden->warp_ticks)
#define warp_flag (this->hidden->warp_flag) #define warp_flag (this->hidden->warp_flag)
...@@ -156,6 +157,7 @@ typedef struct SDL_PrivateVideoData { ...@@ -156,6 +157,7 @@ typedef struct SDL_PrivateVideoData {
#define cursor_should_be_visible (this->hidden->cursor_should_be_visible) #define cursor_should_be_visible (this->hidden->cursor_should_be_visible)
#define cursor_visible (this->hidden->cursor_visible) #define cursor_visible (this->hidden->cursor_visible)
#define sw_buffers (this->hidden->sw_buffers) #define sw_buffers (this->hidden->sw_buffers)
#define sw_contexts (this->hidden->sw_contexts)
#define thread (this->hidden->thread) #define thread (this->hidden->thread)
#define sem1 (this->hidden->sem1) #define sem1 (this->hidden->sem1)
#define sem2 (this->hidden->sem2) #define sem2 (this->hidden->sem2)
...@@ -215,11 +217,6 @@ int QZ_IconifyWindow (_THIS); ...@@ -215,11 +217,6 @@ int QZ_IconifyWindow (_THIS);
SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode);
/*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ /*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) */ /* Private functions (used internally) */
void QZ_PrivateWarpCursor (_THIS, int x, int y); void QZ_PrivateWarpCursor (_THIS, int x, int y);
void QZ_ChangeGrabState (_THIS, int action); void QZ_ChangeGrabState (_THIS, int action);
......
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
#include "SDL_QuartzVideo.h" #include "SDL_QuartzVideo.h"
#include "SDL_QuartzWindow.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. Add methods to get at private members of NSScreen.
Since there is a bug in Apple's screen switching code Since there is a bug in Apple's screen switching code
that does not update this variable when switching that does not update this variable when switching
...@@ -41,6 +42,15 @@ ...@@ -41,6 +42,15 @@
_frame = frame; _frame = frame;
} }
@end @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 @interface SDLTranslatorResponder : NSTextView
{ {
...@@ -52,6 +62,8 @@ ...@@ -52,6 +62,8 @@
- (void) doCommandBySelector:(SEL) myselector {} - (void) doCommandBySelector:(SEL) myselector {}
@end @end
/* absent in 10.3.9. */
CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
/* Bootstrap functions */ /* Bootstrap functions */
static int QZ_Available (); static int QZ_Available ();
...@@ -79,8 +91,6 @@ static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); ...@@ -79,8 +91,6 @@ static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface);
static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects);
static void QZ_DirectUpdate (_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_UpdateRects (_THIS, int num_rects, SDL_Rect *rects);
static void QZ_VideoQuit (_THIS); static void QZ_VideoQuit (_THIS);
...@@ -164,7 +174,14 @@ static SDL_VideoDevice* QZ_CreateDevice (int device_index) { ...@@ -164,7 +174,14 @@ static SDL_VideoDevice* QZ_CreateDevice (int device_index) {
/*device->GetWMInfo = QZ_GetWMInfo;*/ /*device->GetWMInfo = QZ_GetWMInfo;*/
device->GrabInput = QZ_GrabInput; 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; device->free = QZ_DeleteDevice;
...@@ -371,6 +388,12 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { ...@@ -371,6 +388,12 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) {
this->LockHWSurface = NULL; this->LockHWSurface = NULL;
this->UnlockHWSurface = NULL; this->UnlockHWSurface = NULL;
if (cg_context) {
CGContextFlush (cg_context);
CGContextRelease (cg_context);
cg_context = nil;
}
/* Release fullscreen resources */ /* Release fullscreen resources */
if ( mode_flags & SDL_FULLSCREEN ) { if ( mode_flags & SDL_FULLSCREEN ) {
...@@ -412,7 +435,7 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { ...@@ -412,7 +435,7 @@ static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) {
See comment in QZ_SetVideoFullscreen for why we do this See comment in QZ_SetVideoFullscreen for why we do this
*/ */
screen_rect = NSMakeRect(0,0,device_width,device_height); screen_rect = NSMakeRect(0,0,device_width,device_height);
[ [ NSScreen mainScreen ] setFrame:screen_rect ]; QZ_SetFrame([ NSScreen mainScreen ], screen_rect);
} }
} }
/* Release window mode resources */ /* Release window mode resources */
...@@ -440,7 +463,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -440,7 +463,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
NSRect contentRect; NSRect contentRect;
BOOL isCustom = NO; BOOL isCustom = NO;
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
/* Fade to black to hide resolution-switching flicker (and garbage /* Fade to black to hide resolution-switching flicker (and garbage
that is displayed by a destroyed OpenGL context, if applicable) */ that is displayed by a destroyed OpenGL context, if applicable) */
if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) {
...@@ -451,6 +474,12 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -451,6 +474,12 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
if (video_set == SDL_TRUE) if (video_set == SDL_TRUE)
QZ_UnsetVideoMode (this, FALSE); 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 */ /* See if requested mode exists */
mode = CGDisplayBestModeForParameters (display_id, bpp, width, mode = CGDisplayBestModeForParameters (display_id, bpp, width,
height, &exact_match); height, &exact_match);
...@@ -487,7 +516,8 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -487,7 +516,8 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
current->flags |= SDL_FULLSCREEN; current->flags |= SDL_FULLSCREEN;
current->flags |= SDL_HWSURFACE; current->flags |= SDL_HWSURFACE;
current->flags |= SDL_PREALLOC; current->flags |= SDL_PREALLOC;
/* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */
this->UpdateRects = QZ_DirectUpdate; this->UpdateRects = QZ_DirectUpdate;
this->LockHWSurface = QZ_LockHWSurface; this->LockHWSurface = QZ_LockHWSurface;
this->UnlockHWSurface = QZ_UnlockHWSurface; this->UnlockHWSurface = QZ_UnlockHWSurface;
...@@ -531,42 +561,12 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -531,42 +561,12 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
if ( CGDisplayCanSetPalette (display_id) ) if ( CGDisplayCanSetPalette (display_id) )
current->flags |= SDL_HWPALETTE; 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 */ /* Check if we should recreate the window */
if (qz_window == nil) { if (qz_window == nil) {
/* Manually create a window, avoids having a nib file resource */ /* Manually create a window, avoids having a nib file resource */
qz_window = [ [ SDL_QuartzWindow alloc ] qz_window = [ [ SDL_QuartzWindow alloc ]
initWithContentRect:contentRect initWithContentRect:contentRect
styleMask:nil styleMask:0
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:NO ]; defer:NO ];
...@@ -600,7 +600,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -600,7 +600,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
[ [ qz_window contentView ] addSubview:window_view ]; [ [ qz_window contentView ] addSubview:window_view ];
[ window_view release ]; [ window_view release ];
ctx = [ gl_context cglContext ]; ctx = QZ_GetCGLContextObj (gl_context);
err = CGLSetFullScreen (ctx); err = CGLSetFullScreen (ctx);
if (err) { if (err) {
...@@ -634,7 +634,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt ...@@ -634,7 +634,7 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
ourselves. This hack should be removed if/when the bug is fixed. ourselves. This hack should be removed if/when the bug is fixed.
*/ */
screen_rect = NSMakeRect(0,0,width,height); 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 */ /* Save the flags to ensure correct tear-down */
mode_flags = current->flags; mode_flags = current->flags;
...@@ -694,40 +694,16 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -694,40 +694,16 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
} }
} }
/* Check for user-specified window and view */ /* Sorry, QuickDraw was ripped out. */
{ if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) {
char *windowPtrString = getenv ("SDL_NSWindowPointer"); SDL_SetError ("Embedded QuickDraw windows are no longer supported");
char *viewPtrString = getenv ("SDL_NSQuickDrawViewPointer"); if (fade_token != kCGDisplayFadeReservationInvalidToken) {
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
if (windowPtrString && viewPtrString) { CGReleaseDisplayFadeReservation (fade_token);
/* 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;
} }
return NULL;
} }
/* Check if we should recreate the window */ /* Check if we should recreate the window */
if (qz_window == nil) { if (qz_window == nil) {
...@@ -807,48 +783,36 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, ...@@ -807,48 +783,36 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
[ qz_window makeKeyAndOrderFront:nil ]; [ qz_window makeKeyAndOrderFront:nil ];
current->flags |= SDL_OPENGL; current->flags |= SDL_OPENGL;
} }
/* For 2D, we set the subview to an NSQuickDrawView */ /* For 2D, we build a CGBitmapContext */
else { else {
short qdbpp = 0; CGColorSpaceRef cgColorspace;
/* Only recreate the view if it doesn't already exist */ /* Only recreate the view if it doesn't already exist */
if (window_view == nil) { if (window_view == nil) {
window_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; window_view = [ [ NSView alloc ] initWithFrame:contentRect ];
[ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
[ [ qz_window contentView ] addSubview:window_view ]; [ [ qz_window contentView ] addSubview:window_view ];
[ window_view release ]; [ window_view release ];
[ qz_window makeKeyAndOrderFront:nil ]; [ qz_window makeKeyAndOrderFront:nil ];
} }
LockPortBits ( [ window_view qdPort ] ); cgColorspace = CGColorSpaceCreateDeviceRGB();
current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) ); current->pitch = 4 * current->w;
current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) ); current->pixels = SDL_malloc (current->h * current->pitch);
qdbpp = GetPixDepth ( GetPortPixMap ( [ window_view qdPort ] ) );
UnlockPortBits ( [ window_view qdPort ] ); cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h,
8, current->pitch, cgColorspace,
/* QuickDraw may give a 16-bit shadow surface on 8-bit displays! */ kCGImageAlphaNoneSkipFirst);
*bpp = qdbpp; CGColorSpaceRelease (cgColorspace);
current->flags |= SDL_SWSURFACE; current->flags |= SDL_SWSURFACE;
current->flags |= SDL_PREALLOC;
current->flags |= SDL_ASYNCBLIT; 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->UpdateRects = QZ_UpdateRects;
this->LockHWSurface = QZ_LockWindow; this->LockHWSurface = QZ_LockHWSurface;
this->UnlockHWSurface = QZ_UnlockWindow; this->UnlockHWSurface = QZ_UnlockHWSurface;
} }
/* Save flags to ensure correct teardown */ /* Save flags to ensure correct teardown */
...@@ -877,8 +841,8 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, ...@@ -877,8 +841,8 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
} }
/* Setup windowed video */ /* Setup windowed video */
else { else {
/* Force bpp to the device's bpp */ /* Force bpp to 32 */
bpp = device_bpp; bpp = 32;
current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags); current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags);
if (current == NULL) if (current == NULL)
return NULL; return NULL;
...@@ -903,9 +867,15 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, ...@@ -903,9 +867,15 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
return NULL; return NULL;
case 32: /* (8)-8-8-8 ARGB */ case 32: /* (8)-8-8-8 ARGB */
amask = 0x00000000; amask = 0x00000000;
#ifdef __LITTLE_ENDIAN__
rmask = 0x0000FF00;
gmask = 0x00FF0000;
bmask = 0xFF000000;
#else
rmask = 0x00FF0000; rmask = 0x00FF0000;
gmask = 0x0000FF00; gmask = 0x0000FF00;
bmask = 0x000000FF; bmask = 0x000000FF;
#endif
break; break;
} }
...@@ -1062,6 +1032,9 @@ static int QZ_ThreadFlip (_THIS) { ...@@ -1062,6 +1032,9 @@ static int QZ_ThreadFlip (_THIS) {
/* On error, skip VBL delay */ /* On error, skip VBL delay */
ERROR: 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-- ) { while ( h-- ) {
SDL_memcpy (dst, src, len); SDL_memcpy (dst, src, len);
...@@ -1105,253 +1078,6 @@ static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { ...@@ -1105,253 +1078,6 @@ static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) {
#pragma unused(this,num_rects,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 */ /* Resize icon, BMP format */
static const unsigned char QZ_ResizeIcon[] = { static const unsigned char QZ_ResizeIcon[] = {
...@@ -1393,41 +1119,34 @@ static const unsigned char QZ_ResizeIcon[] = { ...@@ -1393,41 +1119,34 @@ static const unsigned char QZ_ResizeIcon[] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b 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 */ /* Check if we should draw the resize icon */
if (SDL_VideoSurface->flags & SDL_RESIZABLE) { if (SDL_VideoSurface->flags & SDL_RESIZABLE) {
Rect icon; SDL_Rect icon_rect;
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;
/* Create the icon image */ rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon));
if (resize_icon == NULL) { 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_FreeSurface (tmp);
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);
}
icon_rect.x = SDL_VideoSurface->w - 13; icon_rect.x = SDL_VideoSurface->w - 13;
icon_rect.y = SDL_VideoSurface->h - 13; icon_rect.y = SDL_VideoSurface->h - 13;
icon_rect.w = 13; icon_rect.w = 13;
icon_rect.h = 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) { ...@@ -1441,75 +1160,19 @@ static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) {
/* Do nothing if miniaturized */ /* 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 { else {
/* Use QDFlushPortBuffer() to flush content to display */ CGContextRef cgc = (CGContextRef)
int i; [[NSGraphicsContext graphicsContextWithWindow: qz_window]
RgnHandle dirty = NewRgn (); graphicsPort];
RgnHandle temp = NewRgn (); QZ_DrawResizeIcon (this);
CGContextFlush (cg_context);
SetEmptyRgn (dirty); CGImageRef image = CGBitmapContextCreateImage (cg_context);
CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height);
/* 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);
/* Flush the dirty region */ CGContextDrawImage (cgc, rectangle, image);
QDFlushPortBuffer ( [ window_view qdPort ], dirty ); CGImageRelease(image);
DisposeRgn (dirty); CGContextFlush (cgc);
DisposeRgn (temp); CGContextRelease (cgc);
} }
} }
......
...@@ -171,11 +171,7 @@ void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { ...@@ -171,11 +171,7 @@ void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) {
else { else {
*p = [ window_view convertPoint:*p toView: nil ]; *p = [ window_view convertPoint:*p toView: nil ];
p->y = [window_view frame].size.height - p->y;
/* We need a workaround in OpenGL mode */
if ( SDL_VideoSurface->flags & SDL_OPENGL ) {
p->y = [window_view frame].size.height - p->y;
}
} }
} }
...@@ -189,11 +185,7 @@ void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { ...@@ -189,11 +185,7 @@ void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) {
else { else {
*p = [ window_view convertPoint:*p fromView: nil ]; *p = [ window_view convertPoint:*p fromView: nil ];
p->y = [window_view frame].size.height - p->y;
/* 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;
}
} }
} }
......
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
*/ */
#include "SDL_config.h" #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 */ /* Subclass of NSWindow to fix genie effect and support resize events */
@interface SDL_QuartzWindow : NSWindow @interface SDL_QuartzWindow : NSWindow
- (void)miniaturize:(id)sender; - (void)miniaturize:(id)sender;
...@@ -29,7 +33,7 @@ ...@@ -29,7 +33,7 @@
- (void)appDidHide:(NSNotification*)note; - (void)appDidHide:(NSNotification*)note;
- (void)appWillUnhide:(NSNotification*)note; - (void)appWillUnhide:(NSNotification*)note;
- (void)appDidUnhide:(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 @end
/* Delegate for our NSWindow to send SDLQuit() on close */ /* Delegate for our NSWindow to send SDLQuit() on close */
......
...@@ -125,31 +125,6 @@ static void QZ_SetPortAlphaOpaque () { ...@@ -125,31 +125,6 @@ static void QZ_SetPortAlphaOpaque () {
newViewFrame = [ window_view frame ]; newViewFrame = [ window_view frame ];
SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height); 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 @@ static void QZ_SetPortAlphaOpaque () { ...@@ -183,7 +158,7 @@ static void QZ_SetPortAlphaOpaque () {
SDL_PrivateAppActive (1, SDL_APPACTIVE); 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 */ /* Make our window subclass receive these application notifications */
[ [ NSNotificationCenter defaultCenter ] addObserver:self [ [ NSNotificationCenter defaultCenter ] addObserver:self
......
/*
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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment