From f589d9c3ed2315a91057963583327f870e56f86b Mon Sep 17 00:00:00 2001 From: Matt Messier Date: Tue, 3 Apr 2007 21:32:31 -0700 Subject: Overhaul the Mac OS X video output plugin. XineOpenGLView is almost completely rewritten, and various fixes and changes have been made to the supporting code. It's still not perfect, but it at least works now. --- src/video_out/macosx/XineOpenGLView.h | 155 +++-- src/video_out/macosx/XineOpenGLView.m | 1124 +++++++++++++++----------------- src/video_out/macosx/XineVideoWindow.m | 2 +- src/video_out/video_out_macosx.m | 55 +- 4 files changed, 635 insertions(+), 701 deletions(-) diff --git a/src/video_out/macosx/XineOpenGLView.h b/src/video_out/macosx/XineOpenGLView.h index 063a33eb2..b63738047 100644 --- a/src/video_out/macosx/XineOpenGLView.h +++ b/src/video_out/macosx/XineOpenGLView.h @@ -23,6 +23,7 @@ #define __HAVE_XINE_OPENGL_VIEW_H__ #import +#import #import "XineVideoWindow.h" @@ -32,74 +33,106 @@ extern NSString *XineViewDidResizeNotification; @interface XineOpenGLView : NSOpenGLView { + @private IBOutlet id delegate; - int video_width, video_height; - char *texture_buffer; - unsigned long i_texture; - BOOL initDone; - BOOL isFullScreen; - XineVideoWindowFullScreenMode fullscreen_mode; - NSOpenGLContext *fullScreenContext; - NSOpenGLContext *currentContext; - NSLock *mutex; - BOOL keepsVideoAspectRatio; - BOOL resizeViewOnVideoSizeChange; - NSCursor *currentCursor; - id _xineController; - NSColor *initialColor; - unsigned int initialColorYUV; - BOOL initialColorYUVIsSet; + IBOutlet id controller; + + NSRecursiveLock * mutex; + BOOL initDone; + + NSSize videoSize; + char * textureBuffer; + GLuint texture; + + BOOL keepsVideoAspectRatio; + BOOL resizeViewOnVideoSizeChange; + NSCursor * currentCursor; + + NSColor * initialColor; + unsigned int initialColorYUV; + BOOL initialColorYUVIsSet; + + BOOL isFullScreen; + BOOL isFullScreenPrepared; + XineVideoWindowFullScreenMode fullScreenMode; + NSOpenGLContext * fullScreenContext; } -- (void) displayTexture; -- (void) drawQuad; -- (void) drawRect: (NSRect) rect; -- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode; -- (void) exitFullScreen; -- (BOOL) isFullScreen; -- (void) reshape; -- (void) initTextures; -- (void) reloadTexture; -- (char *) getTextureBuffer; -- (void) setViewSizeInMainThread:(NSSize)size; -// TODO: replace set...Size below with setSize:(double)videoSizeMultiplier -- (void) setNormalSize; -- (void) setHalfSize; -- (void) setDoubleSize; -- (void) setResizeViewOnVideoSizeChange:(BOOL)flag; -- (BOOL) resizeViewOnVideoSizeChange; -- (void) resetCursorRectsInMainThread; - -// Accessors -- (void) setVideoSize:(NSSize)size; -- (NSSize) videoSize; -- (void) setKeepsVideoAspectRatio:(BOOL)flag; -- (BOOL) keepsVideoAspectRatio; -- (void) setCurrentCursor:(NSCursor *)cursor; -- (NSCursor *) currentCursor; -- (void) setXineController:(id)controller; -- (id) xineController; -- (void) setInitialColor:(NSColor *)color; -- (NSColor *) initialColor; - -// Delegate Methods -- (id) delegate; -- (void) setDelegate:(id)aDelegate; ++ (NSOpenGLPixelFormat *)defaultPixelFormat; ++ (NSOpenGLPixelFormat *)fullScreenPixelFormat; -@end +- (id)initWithCoder:(NSCoder *)coder; +- (id)initWithFrame:(NSRect)frame; +- (id)initWithFrame:(NSRect)frame pixelFormat:(NSOpenGLPixelFormat *)pixelFormat; -/* XineOpenGLView delegate methods */ +- (void)dealloc; + +- (void)encodeWithCoder:(NSCoder *)coder; + +- (NSOpenGLContext *)openGLContext; +- (void)prepareOpenGL; +- (void)reshape; +- (void)update; + +- (void)initTextures; +- (void)updateTexture; +- (void)drawRect:(NSRect)rect; + +- (NSColor *)initialColor; +- (void)setInitialColor:(NSColor *)color; + +- (void)setNormalSize; +- (void)setHalfSize; +- (void)setDoubleSize; -@interface NSObject (XineOpenGLViewDelegate) +- (NSSize)videoSize; -- (NSSize) xineViewWillResize:(NSSize)oldSize toSize:(NSSize)proposedSize; -- (void) xineViewDidResize:(NSNotification *)aNotification; -- (void) mouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) mouseMoved:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) otherMouseDown:(NSEvent *)theEvent - inXineView:(XineOpenGLView *)theView; -- (void) rightMouseDown:(NSEvent *)theEvent - inXineView:(XineOpenGLView *)theView; +- (BOOL)keepsVideoAspectRatio; +- (void)setKeepsVideoAspectRatio:(BOOL)flag; +- (BOOL)resizeViewOnVideoSizeChange; +- (void)setResizeViewOnVideoSizeChange:(BOOL)flag; + +- (void)setViewSize:(NSValue *)sizeWrapper; +- (void)setViewSizeInMainThread:(NSSize)size; + +- (NSCursor *)currentCursor; +- (void)setCurrentCursor:(NSCursor *)cursor; + +- (BOOL)isFullScreen; +- (void)goFullScreen:(XineVideoWindowFullScreenMode)mode; +- (void)exitFullScreen; + +- (id)delegate; +- (void)setDelegate:(id)aDelegate; +- (id)xineController; +- (void)setXineController:(id)aController; + +- (BOOL)acceptsFirstResponder; +- (BOOL)mouseDownCanMoveWindow; + +// Not intended for public use: +- (char *)textureBuffer; +- (void)setVideoSize:(NSSize)size; +- (void)resetCursorRects; +- (void)resetCursorRectsInMainThread; +- (void)calcFullScreenAspect; +- (void)releaseInMainThread; +- (void)passEventToDelegate:(NSEvent *)theEvent withSelector:(SEL)selector; + +- (BOOL)acceptsFirstResponder; +- (BOOL)mouseDownCanMoveWindow; + +@end + +/* XineOpenGLView delegate methods */ +@protocol XineOpenGLViewDelegate + +- (void)mouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void)mouseMoved:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void)otherMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void)rightMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (NSSize)xineViewWillResize:(NSSize)oldSize toSize:(NSSize)proposedSize; +- (void)xineViewDidResize:(NSNotification *)note; @end diff --git a/src/video_out/macosx/XineOpenGLView.m b/src/video_out/macosx/XineOpenGLView.m index e939575a0..c29f95dc7 100644 --- a/src/video_out/macosx/XineOpenGLView.m +++ b/src/video_out/macosx/XineOpenGLView.m @@ -19,7 +19,6 @@ * */ - /* #define LOG */ @@ -37,700 +36,411 @@ # include #endif +NSString *XineViewDidResizeNotification EXPORTED = @"XineViewDidResizeNotification"; -NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; - - -/* XineOpenGLView delegate methods */ - -@protocol XineOpenGLViewDelegate - -- (void) mouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) mouseMoved:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) otherMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) rightMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (NSSize) xineViewWillResize:(NSSize)oldSize toSize:(NSSize)proposedSize; -- (void) xineViewDidResize:(NSNotification *)note; - -@end - +static uint32_t +NSColorToYUV(NSColor *color) +{ + float red, green, blue, alpha; + uint32_t yuv; + unsigned char r, g, b; + unsigned char y, u, v; -static uint32_t NSColorToYUV (NSColor *color); + NSColor *calibratedColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + [calibratedColor getRed:&red green:&green blue:&blue alpha:&alpha]; + r = red * 255; + g = green * 255; + b = blue * 255; -@implementation XineOpenGLView + init_yuv_conversion(); -- (void) setKeepsVideoAspectRatio:(BOOL)flag -{ - keepsVideoAspectRatio = flag; -} + y = COMPUTE_Y(r, g, b); + u = COMPUTE_U(r, g, b); + v = COMPUTE_V(r, g, b); -- (BOOL) keepsVideoAspectRatio -{ - return keepsVideoAspectRatio; + yuv = (y << 24) | (u << 16) | (y << 8) | v; + return yuv; } -- (void) setResizeViewOnVideoSizeChange:(BOOL)flag -{ - resizeViewOnVideoSizeChange = flag; -} +@implementation XineOpenGLView -- (BOOL) resizeViewOnVideoSizeChange ++ (NSOpenGLPixelFormat *)defaultPixelFormat { - return resizeViewOnVideoSizeChange; -} + NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAWindow, + 0 + }; -- (BOOL)mouseDownCanMoveWindow -{ - return YES; + return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; } -- (void)passEventToDelegate:(NSEvent *)theEvent withSelector:(SEL)selector ++ (NSOpenGLPixelFormat *)fullScreenPixelFormat { - NSPoint point = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - - if (!NSMouseInRect(point, [self bounds], [self isFlipped])) return; - - if ([delegate respondsToSelector:selector]) - { - [delegate performSelector:selector - withObject:theEvent - withObject:self]; - return; - } + NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAFullScreen, + NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), + 0 + }; - if ([_xineController respondsToSelector:selector]) - { - [_xineController performSelector:selector - withObject:theEvent - withObject:self]; - return; - } + return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; } -- (void)mouseMoved:(NSEvent *)theEvent +- (id)initWithCoder:(NSCoder *)coder { - [self passEventToDelegate:theEvent - withSelector:@selector(mouseMoved:inXineView:)]; - - [super mouseMoved:theEvent]; -} + NSColor *color; -- (void)mouseDown:(NSEvent *)theEvent -{ - [self passEventToDelegate:theEvent - withSelector:@selector(mouseDown:inXineView:)]; - - [super mouseDown:theEvent]; -} + if ((self = [super initWithCoder:coder]) != nil) { + videoSize = [self frame].size; + mutex = [[NSRecursiveLock alloc] init]; + currentCursor = [[NSCursor arrowCursor] retain]; -- (void)rightMouseDown:(NSEvent *)theEvent -{ - [self passEventToDelegate:theEvent - withSelector:@selector(rightMouseDown:inXineView:)]; - - [super rightMouseDown:theEvent]; -} + if ([coder allowsKeyedCoding]) { + keepsVideoAspectRatio = [coder decodeBoolForKey:@"keepsVideoAspectRatio"]; + resizeViewOnVideoSizeChange = [coder decodeBoolForKey:@"resizeViewOnVideoSizeChange"]; + color = [coder decodeObjectForKey:@"initialColor"]; + } + else { /* Must decode values in the same order as encodeWithCoder: */ + [coder decodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; + [coder decodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; + color = [coder decodeObject]; + } + [self setInitialColor:color]; -- (void)otherMouseDown:(NSEvent *)theEvent -{ - [self passEventToDelegate:theEvent - withSelector:@selector(otherMouseDown:inXineView:)]; - - [super otherMouseDown:theEvent]; +#ifdef LOG + NSLog(@"XineOpenGLView: initWithCoder called"); +#endif + } + return self; } -- (NSSize)videoSize +- (id)initWithFrame:(NSRect)frame { - return NSMakeSize(video_width, video_height); -} - -- (void) displayTexture { - if ([self lockFocusIfCanDraw]) - { - [self drawRect: [self bounds]]; - [self reloadTexture]; - [self unlockFocus]; - } + return [self initWithFrame:frame pixelFormat:[[self class] defaultPixelFormat]]; } -- (id) initWithFrame: (NSRect) frame +- (id)initWithFrame:(NSRect)frame pixelFormat:(NSOpenGLPixelFormat *)format { - NSOpenGLPixelFormatAttribute attribs[] = { - NSOpenGLPFAAccelerated, - NSOpenGLPFANoRecovery, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 24, - NSOpenGLPFAWindow, - 0 - }; - - NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] - initWithAttributes: attribs]; - - if (!fmt) - { - NSLog (@"Cannot create NSOpenGLPixelFormat\n"); - return nil; - } - - self = [super initWithFrame:frame pixelFormat:fmt]; - - currentContext = [self openGLContext]; - [currentContext makeCurrentContext]; - [mutex lock]; - [currentContext update]; - [mutex unlock]; - - i_texture = 0; - initDone = NO; - isFullScreen = NO; - video_width = frame.size.width; - video_height = frame.size.height; - texture_buffer = nil; - mutex = [[NSLock alloc] init]; - currentCursor = [[NSCursor arrowCursor] retain]; - initialColor = nil; - initialColorYUV = 0; - initialColorYUVIsSet = NO; - _xineController = nil; - - [self initTextures]; - - /* Set GL_COLOR_BUFFER_BIT to black */ - glClearColor (0.0, 0.0, 0.0, 0.0); + format = (format ? : [[self class] defaultPixelFormat]); + if ((self = [super initWithFrame:frame pixelFormat:format]) != nil) { + videoSize = frame.size; + mutex = [[NSRecursiveLock alloc] init]; + currentCursor = [[NSCursor arrowCursor] retain]; + [self setInitialColor:nil]; #ifdef LOG - NSLog(@"XineOpenGLView: initWithFrame called"); + NSLog(@"XineOpenGLView: initWithFrame called"); #endif - + } return self; } -- (void) awakeFromNib -{ -#ifdef LOG - NSLog(@"XineOpenGLView: awakeFromNib called"); -#endif -} - -- (id) initWithCoder:(NSCoder *)coder +- (void)dealloc { - self = [super initWithCoder:coder]; - - self = [self initWithFrame:[self frame]]; - - if ([coder allowsKeyedCoding]) - { - keepsVideoAspectRatio = [coder decodeBoolForKey:@"keepsVideoAspectRatio"]; - resizeViewOnVideoSizeChange = [coder decodeBoolForKey: - @"resizeViewOnVideoSizeChange"]; - - NSColor *color = [coder decodeObjectForKey:@"initialColor"]; - if (color) - initialColor = [color copy]; + if (isFullScreen) { + [self exitFullScreen]; } - else - { - /* Must decode values in the same order as encodeWithCoder: */ - [coder decodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; - [coder decodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; - NSColor *color = [coder decodeObject]; - if (color) - initialColor = [color copy]; + if (texture) { + [[self openGLContext] makeCurrentContext]; + glDeleteTextures(1, &texture); + texture = 0; } + free(textureBuffer); - [self initTextures]; + [currentCursor release], currentCursor = nil; + [initialColor release], initialColor = nil; + [delegate release], delegate = nil; + [controller release], controller = nil; + [mutex release], mutex = nil; -#ifdef LOG - NSLog(@"XineOpenGLView: initWithCoder called"); -#endif - - return self; + [super dealloc]; } -- (void) encodeWithCoder:(NSCoder *)coder +- (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; - if ([coder allowsKeyedCoding]) - { + if ([coder allowsKeyedCoding]) { [coder encodeBool:keepsVideoAspectRatio forKey:@"keepsVideoAspectRatio"]; - [coder encodeBool:resizeViewOnVideoSizeChange - forKey:@"resizeViewOnVideoSizeChange"]; + [coder encodeBool:resizeViewOnVideoSizeChange forKey:@"resizeViewOnVideoSizeChange"]; [coder encodeObject:initialColor forKey:@"initialColor"]; } - else - { + else { [coder encodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; [coder encodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; [coder encodeObject:initialColor]; } } -- (void) dealloc { - if (texture_buffer) - free (texture_buffer); - - if (fullScreenContext) - { - [NSOpenGLContext clearCurrentContext]; - [mutex lock]; - [fullScreenContext clearDrawable]; - [fullScreenContext release]; - [mutex unlock]; - if (currentContext == fullScreenContext) currentContext = nil; - fullScreenContext = nil; - } - - if (currentContext) - { - [NSOpenGLContext clearCurrentContext]; - [mutex lock]; - [currentContext clearDrawable]; - [currentContext release]; - [mutex unlock]; - currentContext = nil; - } - - [mutex dealloc]; +- (NSOpenGLContext *)openGLContext +{ + NSOpenGLContext *context; - if (currentCursor) - { - [currentCursor release]; - currentCursor = NULL; + [mutex lock]; + if (!(context = [[fullScreenContext retain] autorelease])) { + context = [[[super openGLContext] retain] autorelease]; } - - if (initialColor) - { - [initialColor release]; - initialColor = NULL; + else if (!isFullScreenPrepared) { + [self prepareOpenGL]; + isFullScreenPrepared = YES; } + [mutex unlock]; - // Enabling the [super dealloc] below (which should be correct behaviour) - // crashes -- not sure why ... - // - // [super dealloc]; - // - // Maybe dealloc in main thread? + return context; } -- (void) reshape +// NOTE: This does not exist prior to Panther (10.3) +- (void)prepareOpenGL { + long swapInterval = 1; + [mutex lock]; - - if (!initDone) - { - [mutex unlock]; - return; - } - - [currentContext makeCurrentContext]; - - NSRect bounds = [self bounds]; - glViewport (0, 0, bounds.size.width, bounds.size.height); - -#ifdef LOG - NSLog(@"XineOpenGLView: Reshape: %x%x%x%x%x%x%x%x", - texture_buffer[0], - texture_buffer[1], - texture_buffer[2], - texture_buffer[3], - texture_buffer[4], - texture_buffer[5], - texture_buffer[6], - texture_buffer[7] - ); -#endif + [super prepareOpenGL]; + + [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; + + [self initTextures]; + + /* Set GL_COLOR_BUFFER_BIT to black */ + glClearColor (0.0, 0.0, 0.0, 0.0); [mutex unlock]; } -- (void) setNormalSize +- (void)reshape { - NSSize size; - - if (isFullScreen) - return; - - size.width = video_width; - size.height = video_height; - - [self setViewSizeInMainThread:size]; + [mutex lock]; + [super reshape]; + if (initDone) { + [[self openGLContext] makeCurrentContext]; + + NSRect bounds = [self bounds]; + glViewport(0, 0, bounds.size.width, bounds.size.height); + +#ifdef LOG + NSLog(@"XineOpenGLView: Reshape: %x%x%x%x%x%x%x%x", + textureBuffer[0], textureBuffer[1], textureBuffer[2], textureBuffer[3], + textureBuffer[4], textureBuffer[5], textureBuffer[6], textureBuffer[7]); +#endif + } + [mutex unlock]; } -- (void) setHalfSize +- (void)update { - NSSize size; - - if (isFullScreen) - return; - - size.width = video_width / 2; - size.height = video_height / 2; - - [self setViewSizeInMainThread:size]; + [mutex lock]; + [super update]; + [mutex unlock]; } -- (void) setDoubleSize +- (void)initTextures { - NSSize size; - - if (isFullScreen) - return; - - size.width = video_width * 2; - size.height = video_height * 2; - - [self setViewSizeInMainThread:size]; -} + uint32_t *p, *q, yuv; -- (void) initTextures -{ [mutex lock]; - [currentContext makeCurrentContext]; - /* Free previous texture if any */ - if (i_texture) - glDeleteTextures (1, &i_texture); + if (texture) { + glDeleteTextures(1, &texture); + texture = 0; + } - if (texture_buffer) - { - texture_buffer = realloc (texture_buffer, sizeof (char) * - video_width * video_height * 3); + if (!initialColorYUVIsSet && initialColor) { + initialColorYUV = NSColorToYUV(initialColor); + initialColorYUVIsSet = YES; } - else - { - texture_buffer = malloc (sizeof (char) * - video_width * video_height * 3); - - { - // There _has_ to be a better way of doing this ... - - uint32_t *p, *q; - p = (uint32_t *) texture_buffer; - q = (uint32_t *) (char *) (texture_buffer + (sizeof(char) * video_width * video_height * 3)); - - for (; p < q; p++) *p = initialColorYUV; - } + if (textureBuffer) { + textureBuffer = (char *)realloc(textureBuffer, videoSize.width * videoSize.height * 4); } + else { + textureBuffer = (char *)malloc(videoSize.width * videoSize.height * 4); - if (!initialColorYUVIsSet && initialColor) - { - initialColorYUV = NSColorToYUV(initialColor); - initialColorYUVIsSet = YES; + // There _has_ to be a better way of doing this ... + + yuv = OSSwapHostToBigInt32(initialColorYUV); + q = (uint32_t *)(char *)(textureBuffer + (int)(videoSize.width * videoSize.height * 4)); + for (p = (uint32_t *)textureBuffer; p < q; *p++ = yuv); } /* Create textures */ - glGenTextures (1, &i_texture); + glGenTextures(1, &texture); - glEnable (GL_TEXTURE_RECTANGLE_EXT); - glEnable (GL_UNPACK_CLIENT_STORAGE_APPLE); + glEnable(GL_TEXTURE_RECTANGLE_EXT); + glEnable(GL_UNPACK_CLIENT_STORAGE_APPLE); - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - glPixelStorei (GL_UNPACK_ROW_LENGTH, video_width); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, videoSize.width); - glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); /* Use VRAM texturing */ - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); /* Tell the driver not to make a copy of the texture but to use our buffer */ - glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); /* Linear interpolation */ - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* I have no idea what this exactly does, but it seems to be necessary for scaling */ - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, - video_width, video_height, 0, - GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, - texture_buffer); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, + videoSize.width, videoSize.height, 0, GL_YCBCR_422_APPLE, +#if WORDS_BIGENDIAN + GL_UNSIGNED_SHORT_8_8_APPLE, +#else + GL_UNSIGNED_SHORT_8_8_REV_APPLE, +#endif + textureBuffer); initDone = YES; [mutex unlock]; #ifdef LOG NSLog(@"XineOpenGLView: initTextures called: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx", - texture_buffer[0], - texture_buffer[1], - texture_buffer[2], - texture_buffer[3], - texture_buffer[4], - texture_buffer[5], - texture_buffer[6], - texture_buffer[7] - ); + textureBuffer[0], textureBuffer[1], textureBuffer[2], textureBuffer[3], + textureBuffer[4], textureBuffer[5], textureBuffer[6], textureBuffer[7]); #endif } -- (void) reloadTexture +- (void)updateTexture { - if (!initDone) - { - return; - } - [mutex lock]; - - [currentContext makeCurrentContext]; - - glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); - glPixelStorei (GL_UNPACK_ROW_LENGTH, video_width); - + [[self openGLContext] makeCurrentContext]; + + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, videoSize.width); + // glTexSubImage2D is faster than glTexImage2D // http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/TextureRange/MainOpenGLView.m.htm - glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, - video_width, video_height, - GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, - texture_buffer); - - [mutex unlock]; - -#ifdef LOG - NSLog(@"reloadTexture called"); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, + videoSize.width, videoSize.height, GL_YCBCR_422_APPLE, +#if WORDS_BIG_ENDIAN + GL_UNSIGNED_SHORT_8_8_APPLE, +#else + GL_UNSIGNED_SHORT_8_8_REV_APPLE, #endif + textureBuffer); + + [self setNeedsDisplay:YES]; + [mutex unlock]; } -- (void) calcFullScreenAspect +- (void)drawRect:(NSRect)rect { - int fs_width, fs_height, x = 0, y = 0, w = 0, h = 0; - - fs_width = CGDisplayPixelsWide (kCGDirectMainDisplay); - fs_height = CGDisplayPixelsHigh (kCGDirectMainDisplay); - - switch (fullscreen_mode) { - case XINE_FULLSCREEN_OVERSCAN: - if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) - { - w = (float) video_width * ((float) fs_height / (float) video_height); - h = fs_height; - x = (fs_width - w) / 2; - y = 0; - } - else - { - w = fs_width; - h = (float) video_height * ((float) fs_width / (float) video_width); - x = 0; - y = (fs_height - h) / 2; - } - break; - - case XINE_FULLSCREEN_CROP: - if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) - { - w = fs_width; - h = (float) video_height * ((float) fs_width / (float) video_width); - x = 0; - y = (fs_height - h) / 2; - } - else - { - w = (float) video_width * ((float) fs_height / (float) video_height); - h = fs_height; - x = (fs_width - w) / 2; - y = 0; - } - break; - } - - NSLog(@"MacOSX fullscreen mode: %dx%d => %dx%d @ %d,%d\n", - video_width, video_height, w, h, x, y); - [mutex lock]; - glViewport (x, y, w, h); + if (initDone && texture) { + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture); + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0); // top left + glTexCoord2f(0.0, videoSize.height); glVertex2f(-1.0, -1.0); // bottom left + glTexCoord2f(videoSize.width, videoSize.height); glVertex2f( 1.0, -1.0); // bottom right + glTexCoord2f(videoSize.width, 0.0); glVertex2f( 1.0, 1.0); // top right + glEnd(); + [[self openGLContext] flushBuffer]; + } [mutex unlock]; } -- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode +- (NSColor *)initialColor +{ + return initialColor; +} + +- (void) setInitialColor:(NSColor *)color +{ + [initialColor autorelease]; + initialColor = (color ? [color copy] : [[NSColor blackColor] retain]); +} + +- (void)setNormalSize { [mutex lock]; - - /* Create the new pixel format */ - NSOpenGLPixelFormatAttribute attribs[] = - { - NSOpenGLPFAAccelerated, - NSOpenGLPFANoRecovery, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 24, - NSOpenGLPFAFullScreen, - NSOpenGLPFAScreenMask, - CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay), - 0 - }; - - NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] - initWithAttributes: attribs]; - - if (!fmt) - { - NSLog (@"Cannot create NSOpenGLPixelFormat\n"); - return; - } - - /* Create the new OpenGL context */ - fullScreenContext = [[NSOpenGLContext alloc] - initWithFormat: fmt shareContext: nil]; - - if (!fullScreenContext) - { - NSLog(@"Failed to create new NSOpenGLContext\n"); - return; + if (!isFullScreen) { + [self setViewSizeInMainThread:videoSize]; } - currentContext = fullScreenContext; - - /* Capture display, switch to fullscreen */ - if (CGCaptureAllDisplays() != CGDisplayNoErr) - { - NSLog(@"CGCaptureAllDisplays() failed\n"); - return; - } - - [fullScreenContext setFullScreen]; - [fullScreenContext makeCurrentContext]; [mutex unlock]; - - fullscreen_mode = mode; - - [self initTextures]; - [self calcFullScreenAspect]; - - /* Redraw the last picture */ - [self setNeedsDisplay: YES]; - - isFullScreen = YES; } -- (void) exitFullScreen +- (void)setHalfSize { - initDone = NO; - - currentContext = [self openGLContext]; - - /* Free current OpenGL context */ - [NSOpenGLContext clearCurrentContext]; + NSSize size; + [mutex lock]; - [fullScreenContext clearDrawable]; + if (!isFullScreen) { + size.width = trunc(videoSize.width / 2); + size.height = trunc(videoSize.height / 2); + [self setViewSizeInMainThread:size]; + } [mutex unlock]; - [fullScreenContext release]; - fullScreenContext = nil; - CGReleaseAllDisplays(); - - [self reshape]; - [self initTextures]; - - /* Redraw the last picture */ - [self setNeedsDisplay: YES]; - - isFullScreen = NO; - initDone = YES; } -- (void) drawQuad +- (void)setDoubleSize { - float f_x = 1.0, f_y = 1.0; - - glBegin (GL_QUADS); - /* Top left */ - glTexCoord2f (0.0, 0.0); - glVertex2f (-f_x, f_y); - /* Bottom left */ - glTexCoord2f (0.0, (float) video_height); - glVertex2f (-f_x, -f_y); - /* Bottom right */ - glTexCoord2f ((float) video_width, (float) video_height); - glVertex2f (f_x, -f_y); - /* Top right */ - glTexCoord2f ((float) video_width, 0.0); - glVertex2f (f_x, f_y); - glEnd(); -} - -- (void) drawRect: (NSRect) rect -{ - [currentContext makeCurrentContext]; - - if (!initDone) - return; - + NSSize size; + [mutex lock]; - - // Swap buffers only during the vertical retrace of the monitor. - // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL/chap5/chapter_5_section_44.html - - long params[] = { 1 }; - CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, params); - - /* Draw */ - glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); - [self drawQuad]; - - /* Wait for the job to be done */ - [currentContext flushBuffer]; - + if (!isFullScreen) { + size.width = videoSize.width * 2; + size.height = videoSize.height * 2; + [self setViewSizeInMainThread:size]; + } [mutex unlock]; } -- (char *) getTextureBuffer +- (NSSize)videoSize { - return texture_buffer; + return videoSize; } -- (void) setVideoSize:(NSSize)size +- (BOOL)keepsVideoAspectRatio { - video_width = size.width; - video_height = size.height; - - if (resizeViewOnVideoSizeChange) - [self setViewSizeInMainThread:size]; - - [self initTextures]; + return keepsVideoAspectRatio; } -- (void) setViewSizeInMainThread:(NSSize)size +- (void)setKeepsVideoAspectRatio:(BOOL)flag { - // Create an autorelease pool, since we're running in a xine thread that - // may not have a pool of its own */ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSValue *sizeWrapper = [NSValue valueWithBytes:&size - objCType:@encode(NSSize)]; - - [self performSelectorOnMainThread:@selector(setViewSize:) - withObject:sizeWrapper - waitUntilDone:NO]; - -#ifdef LOG - NSLog(@"setViewSizeInMainThread called"); -#endif - - [pool release]; + keepsVideoAspectRatio = flag; +} + +- (BOOL)resizeViewOnVideoSizeChange +{ + return resizeViewOnVideoSizeChange; +} + +- (void)setResizeViewOnVideoSizeChange:(BOOL)flag +{ + resizeViewOnVideoSizeChange = flag; } -- (void) setViewSize:(NSValue *)sizeWrapper +- (void)setViewSize:(NSValue *)sizeWrapper { - NSSize proposedSize, newSize, currentSize; + NSSize currentSize, newSize, proposedSize; [sizeWrapper getValue:&proposedSize]; newSize = proposedSize; @@ -742,19 +452,17 @@ static uint32_t NSColorToYUV (NSColor *color); return; } - /* If our controller handles xineViewWillResize:toSize:, send the - * message to him first. Note that the delegate still has a chance - * to override the controller's resize preference ... */ - if ([_xineController respondsToSelector:@selector(xineViewWillResize:toSize:)]) - { + // If our controller handles xineViewWillResize:toSize:, send the + // message to him first. Note that the delegate still has a chance + // to override the controller's resize preference ... + if ([controller respondsToSelector:@selector(xineViewWillResize:toSize:)]) { NSSize oldSize = [self frame].size; - newSize = [_xineController xineViewWillResize:oldSize toSize:proposedSize]; + newSize = [controller xineViewWillResize:oldSize toSize:proposedSize]; } - /* If our delegate handles xineViewWillResize:toSize:, send the - * message to him; otherwise, just resize ourselves */ - if ([delegate respondsToSelector:@selector(xineViewWillResize:toSize:)]) - { + // If our delegate handles xineViewWillResize:toSize:, send the + // message to him; otherwise, just resize ourselves + if ([delegate respondsToSelector:@selector(xineViewWillResize:toSize:)]) { NSSize oldSize = [self frame].size; newSize = [delegate xineViewWillResize:oldSize toSize:proposedSize]; } @@ -769,110 +477,294 @@ static uint32_t NSColorToYUV (NSColor *color); object:self]; [[NSNotificationCenter defaultCenter] postNotification:note]; - if ([_xineController respondsToSelector:@selector(xineViewDidResize:)]) - [_xineController xineViewDidResize:note]; + if ([controller respondsToSelector:@selector(xineViewDidResize:)]) { + [controller xineViewDidResize:note]; + } - if ([delegate respondsToSelector:@selector(xineViewDidResize:)]) + if ([delegate respondsToSelector:@selector(xineViewDidResize:)]) { [delegate xineViewDidResize:note]; - - if (isFullScreen) + } + + [mutex lock]; + [[self openGLContext] makeCurrentContext]; + if (isFullScreen) { [self calcFullScreenAspect]; - + } [self initTextures]; + [mutex unlock]; +} + +- (void)setViewSizeInMainThread:(NSSize)size +{ + // Create an autorelease pool, since we're running in a xine thread that + // may not have a pool of its own + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSValue *sizeWrapper = [NSValue valueWithBytes:&size + objCType:@encode(NSSize)]; + + [self performSelectorOnMainThread:@selector(setViewSize:) + withObject:sizeWrapper + waitUntilDone:NO]; + +#ifdef LOG + NSLog(@"setViewSizeInMainThread called"); +#endif + + [pool release]; +} + +- (NSCursor *)currentCursor +{ + return currentCursor; +} + +- (void)setCurrentCursor:(NSCursor *)cursor +{ + [currentCursor autorelease]; + currentCursor = [cursor retain]; + [self resetCursorRectsInMainThread]; } -- (BOOL) isFullScreen +- (BOOL)isFullScreen { return isFullScreen; } -- (id) delegate +- (void)goFullScreen:(XineVideoWindowFullScreenMode)mode { - return delegate; + NSOpenGLPixelFormat *pixelFormat; + + if (!(pixelFormat = [[self class] fullScreenPixelFormat])) { + NSLog(@"Cannot create NSOpenGLPixelFormat for full screen mode"); + return; + } + + if (!(fullScreenContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil])) { + NSLog(@"Cannot create NSOpenGLContext for full screen mode"); + return; + } + + if (CGCaptureAllDisplays() != CGDisplayNoErr) { + [fullScreenContext release], fullScreenContext = nil; + NSLog(@"CGCaptureAllDisplays() failed"); + return; + } + + [mutex lock]; + fullScreenMode = mode; + isFullScreenPrepared = NO; + + [fullScreenContext setFullScreen]; + [[self openGLContext] makeCurrentContext]; + + // Redraw the last picture + [self setNeedsDisplay:YES]; + + isFullScreen = YES; + [mutex unlock]; } -- (void) setDelegate:(id)aDelegate { - delegate = aDelegate; +- (void)exitFullScreen +{ + NSOpenGLContext *context; + + [mutex lock]; + if (isFullScreen) { + context = fullScreenContext; + fullScreenContext = nil; + [[self openGLContext] makeCurrentContext]; + + [context clearDrawable]; + [context release]; + + [self reshape]; + [self initTextures]; + + CGReleaseAllDisplays(); + [self setNeedsDisplay:YES]; + isFullScreen = NO; + } + [mutex unlock]; } -- (BOOL)acceptsFirstResponder { - return YES; +- (id)delegate +{ + return [[delegate retain] autorelease]; } -- (void) setCurrentCursor:(NSCursor *)cursor +- (void)setDelegate:(id)aDelegate { - currentCursor = cursor; - [currentCursor retain]; - [self resetCursorRectsInMainThread]; + [delegate autorelease]; + delegate = [aDelegate retain]; } -- (NSCursor *) currentCursor +- (id)xineController { - return currentCursor; + return controller; } -- (void) resetCursorRectsInMainThread +- (void)setXineController:(id)aController { - [self discardCursorRects]; - [self performSelectorOnMainThread:@selector(resetCursorRects) - withObject:nil - waitUntilDone:NO]; + [controller autorelease]; + controller = [aController retain]; } -- (void) resetCursorRects +- (char *)textureBuffer { - [self addCursorRect:[self visibleRect] cursor:currentCursor]; - [currentCursor set]; + return textureBuffer; } -- (void) setXineController:(id)controller +- (void)setVideoSize:(NSSize)size { - [_xineController autorelease]; - _xineController = controller; - [_xineController retain]; + [mutex lock]; + videoSize = size; + if (resizeViewOnVideoSizeChange) { + [self setViewSizeInMainThread:size]; + } + + if (initDone) { + [[self openGLContext] makeCurrentContext]; + [self initTextures]; + } + [mutex unlock]; } -- (id) xineController +- (void)resetCursorRects { - return _xineController; + [mutex lock]; + [self discardCursorRects]; + [self addCursorRect:[self visibleRect] cursor:currentCursor]; + [currentCursor set]; + [mutex unlock]; } -- (void) setInitialColor:(NSColor *)color +- (void)resetCursorRectsInMainThread { - [initialColor autorelease]; - initialColor = [color copy]; + [self performSelectorOnMainThread:@selector(resetCursorRects) + withObject:nil + waitUntilDone:NO]; } -- (NSColor *) initialColor +- (void)releaseInMainThread { - return initialColor; + [self performSelectorOnMainThread:@selector(release) + withObject:nil + waitUntilDone:NO]; } -@end /* XineOpenGLView */ +- (void)calcFullScreenAspect +{ + float fs_height, fs_width, h, w, x, y; + + // Feh, should go to main or should go to current display of window? + fs_width = CGDisplayPixelsWide(kCGDirectMainDisplay); + fs_height = CGDisplayPixelsHigh(kCGDirectMainDisplay); + + switch (fullScreenMode) { + case XINE_FULLSCREEN_OVERSCAN: + if ((fs_width / fs_height) > (videoSize.width / videoSize.height)) { + w = videoSize.width * (fs_height / videoSize.height); + h = fs_height; + x = (fs_width - w) / 2; + y = 0; + } + else { + w = fs_width; + h = videoSize.height * (fs_width / videoSize.width); + x = 0; + y = (fs_height - h) / 2; + } + break; + + case XINE_FULLSCREEN_CROP: + if ((fs_width / fs_height) > (videoSize.width / videoSize.height)) { + w = fs_width; + h = videoSize.height * (fs_width / videoSize.width); + x = 0; + y = (fs_height - h) / 2; + } + else { + w = videoSize.width * (fs_height / videoSize.height); + h = fs_height; + x = (fs_width - w) / 2; + y = 0; + } + break; + + default: + NSLog(@"Mac OS X fullscreen mode unrecognized: %d", fullScreenMode); + return; + } + +#ifdef LOG + NSLog(@"Mac OS X fullscreen mode: %fx%f => %fx%f @ %f,%f\n", + videoSize.width, videoSize.height, w, h, x, y); +#endif + // Assumes locked and current context set + glViewport(x, y, w, h); +} -static uint32_t NSColorToYUV (NSColor *color) +- (void)passEventToDelegate:(NSEvent *)theEvent withSelector:(SEL)selector { - float red, green, blue, alpha; - unsigned char r, g, b; - unsigned char y, u, v; - uint32_t yuv; + NSPoint point = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + + if (NSMouseInRect(point, [self bounds], [self isFlipped])) { + if ([delegate respondsToSelector:selector]) { + [delegate performSelector:selector + withObject:theEvent + withObject:self]; + } + else if ([controller respondsToSelector:selector]) { + [controller performSelector:selector + withObject:theEvent + withObject:self]; + } + } +} - NSColor *calibratedColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; - [calibratedColor getRed:&red green:&green blue:&blue alpha:&alpha]; +- (void)mouseMoved:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(mouseMoved:inXineView:)]; + + [super mouseMoved:theEvent]; +} - r = red * 255; - g = green * 255; - b = blue * 255; +- (void)mouseDown:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(mouseDown:inXineView:)]; + + [super mouseDown:theEvent]; +} - init_yuv_conversion(); +- (void)rightMouseDown:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(rightMouseDown:inXineView:)]; + + [super rightMouseDown:theEvent]; +} - y = COMPUTE_Y(r, g, b); - u = COMPUTE_U(r, g, b); - v = COMPUTE_V(r, g, b); +- (void)otherMouseDown:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(otherMouseDown:inXineView:)]; + + [super otherMouseDown:theEvent]; +} - yuv = y << 24 | u << 16 | y << 8 | v; +- (BOOL)acceptsFirstResponder +{ + return YES; +} - return yuv; +- (BOOL)mouseDownCanMoveWindow +{ + return YES; } +@end diff --git a/src/video_out/macosx/XineVideoWindow.m b/src/video_out/macosx/XineVideoWindow.m index b61a5b418..0dd2caa28 100644 --- a/src/video_out/macosx/XineVideoWindow.m +++ b/src/video_out/macosx/XineVideoWindow.m @@ -108,7 +108,7 @@ } -- (XineOpenGLView *) xineView +- (id) xineView { return xineView; } diff --git a/src/video_out/video_out_macosx.m b/src/video_out/video_out_macosx.m index 1a8fb821d..845bd9b94 100644 --- a/src/video_out/video_out_macosx.m +++ b/src/video_out/video_out_macosx.m @@ -170,7 +170,9 @@ static void macosx_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_fr } + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [this->view setVideoSize:video_size]; + [pool release]; if((format == XINE_IMGFMT_YV12 && (frame->vo_frame.base[0] == NULL @@ -189,29 +191,35 @@ static void macosx_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_fr static void macosx_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) { macosx_driver_t *driver = (macosx_driver_t *)vo_driver; macosx_frame_t *frame = (macosx_frame_t *)vo_frame; - char *texture_buffer = [driver->view getTextureBuffer]; - - switch (vo_frame->format) { - case XINE_IMGFMT_YV12: - yv12_to_yuy2 (vo_frame->base[0], vo_frame->pitches[0], - vo_frame->base[1], vo_frame->pitches[1], - vo_frame->base[2], vo_frame->pitches[2], - texture_buffer, vo_frame->width * 2, - vo_frame->width, vo_frame->height, 0); + char *texture_buffer; - [driver->view displayTexture]; - break; - case XINE_IMGFMT_YUY2: - xine_fast_memcpy (texture_buffer, vo_frame->base[0], - vo_frame->pitches[0] * vo_frame->height * 2); - [driver->view displayTexture]; - break; - default: - /* unsupported frame format, do nothing. */ - break; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + if ((texture_buffer = [driver->view textureBuffer]) != NULL) { + switch (vo_frame->format) { + case XINE_IMGFMT_YV12: + yv12_to_yuy2 (vo_frame->base[0], vo_frame->pitches[0], + vo_frame->base[1], vo_frame->pitches[1], + vo_frame->base[2], vo_frame->pitches[2], + (unsigned char *)texture_buffer, + vo_frame->width * 2, + vo_frame->width, vo_frame->height, 0); + + [driver->view updateTexture]; + break; + case XINE_IMGFMT_YUY2: + xine_fast_memcpy (texture_buffer, vo_frame->base[0], + vo_frame->pitches[0] * vo_frame->height * 2); + [driver->view updateTexture]; + break; + default: + /* unsupported frame format, do nothing. */ + break; + } } frame->vo_frame.free(&frame->vo_frame); + [pool release]; } static void macosx_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, @@ -228,11 +236,11 @@ static void macosx_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, if (frame->format == XINE_IMGFMT_YV12) /* TODO: It may be possible to accelerate the blending via Quartz * Extreme ... */ - blend_yuv(frame->vo_frame.base, overlay, + _x_blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); else - blend_yuy2(frame->vo_frame.base[0], overlay, + _x_blend_yuy2(frame->vo_frame.base[0], overlay, frame->width, frame->height, frame->vo_frame.pitches[0], &this->alphablend_extra_data); } @@ -299,6 +307,7 @@ static void macosx_dispose(vo_driver_t *vo_driver) { macosx_driver_t *this = (macosx_driver_t *) vo_driver; _x_alphablend_free(&this->alphablend_extra_data); + [this->view releaseInMainThread]; free(this); } @@ -318,7 +327,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *driver_class, const void * driver->config = class->config; driver->xine = class->xine; driver->ratio = XINE_VO_ASPECT_AUTO; - driver->view = view; + driver->view = [view retain]; driver->vo_driver.get_capabilities = macosx_get_capabilities; driver->vo_driver.alloc_frame = macosx_alloc_frame; @@ -377,7 +386,7 @@ static const vo_info_t vo_info_macosx = { XINE_VISUAL_TYPE_MACOSX /* Visual type */ }; -plugin_info_t xine_plugin_info[] = { +plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ /* work around the problem that dlclose() is not allowed to * get rid of an image module which contains objective C code and simply -- cgit v1.2.3