mirror of
https://github.com/yawut/SDL.git
synced 2026-10-02 05:06:46 -05:00
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
This commit is contained 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <QuickTime/QuickTime.h>
|
||||
#include <OpenGL/OpenGL.h> /* For CGL functions and types */
|
||||
#include <IOKit/IOKitLib.h> /* For powersave handling */
|
||||
#include <pthread.h>
|
||||
@@ -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);
|
||||
|
||||
@@ -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 @@
|
||||
_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 @@
|
||||
- (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_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);
|
||||
|
||||
@@ -164,7 +174,14 @@ static SDL_VideoDevice* QZ_CreateDevice (int device_index) {
|
||||
/*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 SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
|
||||
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 SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
|
||||
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 SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
|
||||
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 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
|
||||
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 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
|
||||
[ [ 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 @@ static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int widt
|
||||
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 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 @@ static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
|
||||
[ 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;
|
||||
|
||||
current->flags |= SDL_SWSURFACE;
|
||||
current->flags |= SDL_PREALLOC;
|
||||
current->flags |= SDL_ASYNCBLIT;
|
||||
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_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 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
|
||||
}
|
||||
/* 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 @@ static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
|
||||
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 const unsigned char QZ_ResizeIcon[] = {
|
||||
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);
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -125,31 +125,6 @@ static void QZ_SetPortAlphaOpaque () {
|
||||
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 @@ static void QZ_SetPortAlphaOpaque () {
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user