From a59ece990413ad0c89c9b12c7a7f489cf61641ab Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Wed, 23 Mar 2011 14:16:42 +0000 Subject: Commits work in progress on fixing overlapping issues with the JAWTRenderer on Mac OS X. --- src/native/jawtrenderer/JAWTRenderer_MacOSX.m | 456 ++++++++------------- src/native/jawtrenderer/Makefile.macosx | 4 +- .../impl/gui/main/call/OneToOneCallPeerPanel.java | 34 +- .../jmfext/media/renderer/video/JAWTRenderer.java | 13 - 4 files changed, 191 insertions(+), 316 deletions(-) (limited to 'src') diff --git a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m index 4a6c60b..4464614 100644 --- a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m +++ b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m @@ -11,41 +11,30 @@ #include #include +#import #import -#import #import #import #import #import #import #import -#import -#import -#import #define JAWT_RENDERER_TEXTURE GL_TEXTURE_RECTANGLE_EXT #define JAWT_RENDERER_TEXTURE_FORMAT GL_BGRA #define JAWT_RENDERER_TEXTURE_TYPE GL_UNSIGNED_BYTE -@class JAWTRenderer; -@class JAWTRendererCALayer; - @interface JAWTRenderer : NSObject { @public /** - * The CAOpenGLLayer in which this JAWTRenderer paints. - */ - CALayer *layer; - - /** * The OpenGL context of this JAWTRenderer which shares - * texture with the OpenGL context of layer and enables - * this JAWTRederer to not directly access the OpenGL context of - * layer because it cannot guarantee synchronized access to it - * anyway. + * texture with the OpenGL contexts of subrenderers and + * enables this JAWTRederer to not directly access the OpenGL + * contexts of subrenderers because it cannot guarantee + * synchronized access to them anyway. */ - CGLContextObj glContext; + NSOpenGLContext *glContext; jint height; GLuint texture; @@ -77,7 +66,7 @@ - (void)addSubrenderer:(JAWTRenderer *)subrenderer; - (void)boundsDidChange:(NSNotification *)notification; -- (void)copyCGLContext:(CGLContextObj)glContext +- (void)copyCGLContext:(NSOpenGLContext *)glContext forPixelFormat:(CGLPixelFormatObj)pixelFormat; - (void)dealloc; - (void)frameDidChange:(NSNotification *)notification; @@ -87,23 +76,11 @@ - (void)removeSubrenderer:(JAWTRenderer *)subrenderer; - (void)removeSubrendererAtIndex:(NSUInteger)index; - (void)reshape; -- (void)setLayer:(CALayer *)aLayer; - (void)setSuperrenderer:(JAWTRenderer *)aSuperrenderer; - (void)setView:(NSView *)aView; - (void)update; @end /* JAWTRenderer */ -@interface JAWTRendererCALayer : CAOpenGLLayer -{ -@public - JAWTRenderer *renderer; -} - -- (void)dealloc; -- (id)init; -- (void)setRenderer:(JAWTRenderer *)aRenderer; -@end /* JAWTRendererCALayer */ - void JAWTRenderer_addNotifyLightweightComponent (jlong handle, jobject component, jlong parentHandle) @@ -116,12 +93,9 @@ JAWTRenderer_addNotifyLightweightComponent parentRenderer = (JAWTRenderer *) parentHandle; autoreleasePool = [[NSAutoreleasePool alloc] init]; - if (!(renderer->layer)) - { - [renderer setLayer:[JAWTRendererCALayer layer]]; - if (parentRenderer) - [parentRenderer addSubrenderer:renderer]; - } + if (parentRenderer) + [parentRenderer addSubrenderer:renderer]; + [renderer copyCGLContext:nil forPixelFormat:0]; [autoreleasePool release]; } @@ -216,7 +190,7 @@ JAWTRenderer_paintLightweightComponent renderer = (JAWTRenderer *) handle; autoreleasePool = [[NSAutoreleasePool alloc] init]; - [renderer paint]; + // TODO Auto-generated method stub [autoreleasePool release]; return JNI_TRUE; @@ -241,7 +215,7 @@ JAWTRenderer_process { if (renderer->glContext) { - CGLSetCurrentContext(renderer->glContext); + [renderer->glContext makeCurrentContext]; if (renderer->texture && ((width != renderer->width) @@ -323,8 +297,13 @@ JAWTRenderer_processLightweightComponentEvent renderer = (JAWTRenderer *) handle; autoreleasePool = [[NSAutoreleasePool alloc] init]; - if (renderer->layer) - [renderer->layer setFrame:CGRectMake(x, y, width, height)]; + @synchronized (renderer) + { + renderer->boundsX = x; + renderer->boundsY = y; + renderer->boundsWidth = width; + renderer->boundsHeight = height; + } [autoreleasePool release]; } @@ -339,7 +318,6 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) autoreleasePool = [[NSAutoreleasePool alloc] init]; [renderer removeFromSuperrenderer]; - [renderer setLayer:nil]; [autoreleasePool release]; } @@ -366,27 +344,37 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) [self reshape]; } -- (void)copyCGLContext:(CGLContextObj)glContext +- (void)copyCGLContext:(NSOpenGLContext *)glContext forPixelFormat:(CGLPixelFormatObj)pixelFormat { @synchronized (self) { if (self->glContext) { - CGLSetCurrentContext(self->glContext); + [self->glContext makeCurrentContext]; if (texture) { glDeleteTextures(1, &texture); texture = 0; } - CGLSetCurrentContext(0); + [NSOpenGLContext clearCurrentContext]; - CGLReleaseContext(self->glContext); - self->glContext = 0; + [self->glContext release]; + self->glContext = nil; } if (glContext) - CGLCreateContext(pixelFormat, glContext, &(self->glContext)); + { + NSOpenGLPixelFormat *format + = [[NSOpenGLPixelFormat alloc] + initWithCGLPixelFormatObj:pixelFormat]; + + self->glContext + = [[NSOpenGLContext alloc] + initWithFormat:format + shareContext:glContext]; + [format release]; + } } } @@ -410,8 +398,7 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) } [self setView:nil]; - [self setLayer:nil]; - [self copyCGLContext:0 forPixelFormat:0]; + [self copyCGLContext:nil forPixelFormat:0]; [super dealloc]; } @@ -426,8 +413,11 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) { if ((self = [super init])) { - layer = nil; - glContext = 0; + NSOpenGLPixelFormatAttribute pixelFormatAttribs[] + = { NSOpenGLPFAWindow, 0 }; + NSOpenGLPixelFormat *pixelFormat; + + glContext = nil; height = 0; texture = 0; @@ -447,58 +437,158 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) subrenderers = nil; superrenderer = nil; + + pixelFormat + = [[NSOpenGLPixelFormat alloc] + initWithAttributes:pixelFormatAttribs]; + if (pixelFormat) + { + glContext + = [[NSOpenGLContext alloc] + initWithFormat:pixelFormat + shareContext:nil]; + if (glContext) + { + GLint surfaceOpacity; + + // prepareOpenGL + [glContext makeCurrentContext]; + + surfaceOpacity = 1; + [glContext setValues:&surfaceOpacity + forParameter:NSOpenGLCPSurfaceOpacity]; + + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_CULL_FACE); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + else + { + [self release]; + self = nil; + } + [pixelFormat release]; + } + else + { + [self release]; + self = nil; + } } return self; } - (void)paint { - /* Make the component and its layer paint. */ - if (layer) + [glContext makeCurrentContext]; + + // drawRect: + glClear(GL_COLOR_BUFFER_BIT); + + @synchronized (self) { - @synchronized (self) + if (texture) { - if (subrenderers) - { - NSUInteger index = 0; - NSUInteger count = [subrenderers count]; + /* + * It may be a misunderstanding of OpenGL context sharing but + * JAWT_RENDERER_TEXTURE does not seem to work in glContext unless + * it is explicitly bound to texture while glContext is current. + */ + glBindTexture(JAWT_RENDERER_TEXTURE, texture); + glEnable(JAWT_RENDERER_TEXTURE); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1.0, 1.0); + glTexCoord2f(width, 0); + glVertex2f(1.0, 1.0); + glTexCoord2f(width, height); + glVertex2f(1.0, -1.0); + glTexCoord2f(0, height); + glVertex2f(-1.0, -1.0); + glEnd(); + glDisable(JAWT_RENDERER_TEXTURE); + } + + /* Draw the subrenderers of this JAWTRenderer. */ + if (subrenderers) + { + NSUInteger subrendererIndex = 0; + NSUInteger subrendererCount = [subrenderers count]; + CGLPixelFormatObj pixelFormat = 0; - [CATransaction begin]; - [CATransaction setValue:(id)kCFBooleanTrue - forKey:kCATransactionDisableActions]; + for (; + subrendererIndex < subrendererCount; + subrendererIndex++) + { + JAWTRenderer *subrenderer + = [subrenderers objectAtIndex:subrendererIndex]; - while (index < count) + @synchronized (subrenderer) { - JAWTRenderer *subrenderer - = [subrenderers objectAtIndex:index]; - - @synchronized (subrenderer) + GLfloat subrendererBoundsHeight; + GLfloat subrendererBoundsWidth; + + /* + * Make sure the subrenderer has an NSOpenGLContext + * which is compatible with glContext and shares its + * object state. + */ + if (!(subrenderer->glContext)) { - CALayer *sublayer = subrenderer->layer; - - if (sublayer && ([sublayer superlayer] != layer)) - { - [sublayer removeFromSuperlayer]; - [layer addSublayer:sublayer]; - } + if (!pixelFormat) + pixelFormat + = CGLGetPixelFormat([glContext CGLContextObj]); + [subrenderer copyCGLContext:glContext + forPixelFormat:pixelFormat]; } - index++; - } - [CATransaction commit]; + subrendererBoundsHeight = subrenderer->boundsHeight; + subrendererBoundsWidth = subrenderer->boundsWidth; + if (subrenderer->texture + && (subrendererBoundsHeight > 0) + && (subrendererBoundsWidth > 0)) + { + GLfloat x_1 + = -1.0 + 2 * subrenderer->boundsX / boundsWidth; + GLfloat y1 + = 1 - 2 * subrenderer->boundsY / boundsHeight; + GLfloat x1 + = x_1 + 2 * subrendererBoundsWidth / boundsWidth; + GLfloat y_1 + = y1 - 2 * subrendererBoundsHeight / boundsHeight; + + glBindTexture( + JAWT_RENDERER_TEXTURE, + subrenderer->texture); + glEnable(JAWT_RENDERER_TEXTURE); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(x_1, y1); + glTexCoord2f(subrenderer->width, 0); + glVertex2f(x1, y1); + glTexCoord2f(subrenderer->width, subrenderer->height); + glVertex2f(x1, y_1); + glTexCoord2f(0, subrenderer->height); + glVertex2f(x_1, y_1); + glEnd(); + glDisable(JAWT_RENDERER_TEXTURE); + } + } } } - - [layer setNeedsDisplay]; } - if (view) - [view displayIfNeededIgnoringOpacity]; + + glFlush(); } - (void)removeFromSuperrenderer { if (superrenderer) [superrenderer removeSubrenderer:self]; + [self copyCGLContext:nil forPixelFormat:nil]; } - (void)removeSubrenderer:(JAWTRenderer *)subrenderer @@ -539,52 +629,13 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) boundsWidth = bounds.size.width; boundsX = bounds.origin.x; boundsY = bounds.origin.y; - if ((bounds.size.width > 0) && (bounds.size.height > 0)) + if ((bounds.size.width > 0) && (bounds.size.height > 0) && glContext) { -// [glContext makeCurrentContext]; -// glViewport( -// bounds.origin.x, bounds.origin.y, -// bounds.size.width, bounds.size.height); - } -} - -- (void)setLayer:(CALayer *)aLayer -{ - if (layer != aLayer) - { - if (layer) - { - CALayer *superlayer; - - if ([layer isKindOfClass:[JAWTRendererCALayer class]]) - { - JAWTRendererCALayer *rendererLayer - = (JAWTRendererCALayer *) layer; - - if (rendererLayer->renderer == self) - [rendererLayer setRenderer:nil]; - } - - /* - * It may or may not be necessary to remove the layer from its - * superlayer but it should not hurt. - */ - superlayer = [layer superlayer]; - if (superlayer) - [layer removeFromSuperlayer]; - - [layer release]; - } - - layer = aLayer; + [glContext makeCurrentContext]; - if (layer) - { - [layer retain]; - - if ([layer isKindOfClass:[JAWTRendererCALayer class]]) - [((JAWTRendererCALayer *) layer) setRenderer:self]; - } + glViewport( + bounds.origin.x, bounds.origin.y, + bounds.size.width, bounds.size.height); } } @@ -608,8 +659,6 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) { if (view) { - CALayer *viewLayer; - #ifdef JAWT_RENDERER_USE_NSNOTIFICATIONCENTER NSNotificationCenter *notificationCenter; @@ -627,10 +676,6 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) } #endif /* JAWT_RENDERER_USE_NSNOTIFICATIONCENTER */ - viewLayer = [view layer]; - if (self->layer == viewLayer) - [self setLayer:nil]; - [view release]; } @@ -638,39 +683,14 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) if (view) { - CALayer *viewLayer; #ifdef JAWT_RENDERER_USE_NSNOTIFICATIONCENTER NSNotificationCenter *notificationCenter; #endif /* JAWT_RENDERER_USE_NSNOTIFICATIONCENTER */ [view retain]; - /* Host a JAWTRendererCALayer in the view. */ - viewLayer = [view layer]; - if (viewLayer - /*&& [viewLayer isKindOfClass:[JAWTRendererCALayer class]]*/) - { - [self setLayer:viewLayer]; - } - else - { - CALayer *rendererLayer - = [CALayer layer]; - - [self setLayer:rendererLayer]; - if (rendererLayer) - { - [view setLayer:rendererLayer]; - [view setWantsLayer:YES]; - - /* - * Make sure that the view has accepted to host the - * rendererLayer. - */ - if ([view layer] != rendererLayer) - [self setLayer:nil]; - } - } + if ([glContext view] != view) + [glContext setView:view]; #ifdef JAWT_RENDERER_USE_NSNOTIFICATIONCENTER notificationCenter = [NSNotificationCenter defaultCenter]; @@ -705,127 +725,9 @@ JAWTRenderer_removeNotifyLightweightComponent(jlong handle, jobject component) frameWidth = frame.size.width; frameX = frame.origin.x; frameY = frame.origin.y; - //[glContext update]; + if (glContext) + [glContext update]; [self reshape]; } @end /* JAWTRenderer */ - -@implementation JAWTRendererCALayer -- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat -{ - CGLContextObj glContext = [super copyCGLContextForPixelFormat:pixelFormat]; - - if (glContext) - { - GLint surfaceOpacity; - GLclampf color; - - surfaceOpacity = 1; - CGLSetParameter(glContext, kCGLCPSurfaceOpacity, &surfaceOpacity); - - CGLSetCurrentContext(glContext); - - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDisable(GL_CULL_FACE); - - color = 0.0f; - glClearColor(color, color, color, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - } - - if (renderer) - [renderer copyCGLContext:glContext forPixelFormat:pixelFormat]; - - return glContext; -} - -- (void)dealloc -{ - [self setRenderer:nil]; - - [super dealloc]; -} - -- (void)drawInCGLContext:(CGLContextObj)glContext - pixelFormat:(CGLPixelFormatObj)pixelFormat - forLayerTime:(CFTimeInterval)timeInterval - displayTime:(const CVTimeStamp *)timeStamp -{ - CGLSetCurrentContext(glContext); - - glClear(GL_COLOR_BUFFER_BIT); - - if (renderer) - { - @synchronized (renderer) - { - if (renderer->texture) - { - /* - * It may be a misunderstanding of OpenGL context sharing but - * JAWT_RENDERER_TEXTURE does not seem to work in glContext - * unless it is explicitly bound to renderer->texture while - * glContext is current. - */ - glBindTexture(JAWT_RENDERER_TEXTURE, renderer->texture); - - glEnable(JAWT_RENDERER_TEXTURE); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1.0, 1.0); - glTexCoord2f(renderer->width, 0); - glVertex2f(1.0, 1.0); - glTexCoord2f(renderer->width, renderer->height); - glVertex2f(1.0, -1.0); - glTexCoord2f(0, renderer->height); - glVertex2f(-1.0, -1.0); - glEnd(); - glDisable(JAWT_RENDERER_TEXTURE); - } - } - } - - [super drawInCGLContext:glContext - pixelFormat:pixelFormat - forLayerTime:timeInterval - displayTime:timeStamp]; -} - -- (id)init -{ - if ((self = [super init])) - { - renderer = nil; - - [self setAnchorPoint:CGPointMake(0, 0)]; - /* AWT will be driving the painting. */ - [self setAsynchronous:YES]; - } - return self; -} - -- (void)releaseCGLContext:(CGLContextObj)glContext -{ - if (renderer) - [renderer copyCGLContext:0 forPixelFormat:0]; - - [super releaseCGLContext:glContext]; -} - -- (void)setRenderer:(JAWTRenderer *)aRenderer -{ - if (renderer != aRenderer) - { - if (renderer) - [renderer release]; - - renderer = aRenderer; - - if (renderer) - [renderer retain]; - } -} -@end /* JAWTRendererCALayer */ diff --git a/src/native/jawtrenderer/Makefile.macosx b/src/native/jawtrenderer/Makefile.macosx index 9cf393b..357a9de 100644 --- a/src/native/jawtrenderer/Makefile.macosx +++ b/src/native/jawtrenderer/Makefile.macosx @@ -14,11 +14,9 @@ CPPFLAGS=-I$(JAVA_HOME)/Headers LDFLAGS=-dynamiclib LIBS= \ -framework AppKit \ - -framework ApplicationServices \ -framework Foundation \ -framework JavaVM \ - -framework OpenGL \ - -framework QuartzCore + -framework OpenGL TARGET=../../../lib/native/mac/lib$(TARGET_BASENAME).jnilib CPPFLAGS:=-Wall -Wreturn-type -DJNI_IMPLEMENTATION \ diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java index 5cafc5e..2eced0c 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java @@ -1761,33 +1761,21 @@ public class OneToOneCallPeerPanel { if (isVisible) { - if (OSUtils.IS_MAC - && (localVideo instanceof JComponent)) - { - /* - * There are overlapping issues on Mac OS X so we'd - * better take the safest route. - */ - handleVideoEvent(null, videoContainer); - } - else - { - Container localVideoParent = localVideo.getParent(); + Container localVideoParent = localVideo.getParent(); - if (localVideoParent != null) - localVideoParent.remove(localVideo); + if (localVideoParent != null) + localVideoParent.remove(localVideo); - Container closeButtonParent - = closeButton.getParent(); + Container closeButtonParent + = closeButton.getParent(); - if (closeButtonParent != null) - closeButtonParent.remove(closeButton); + if (closeButtonParent != null) + closeButtonParent.remove(closeButton); - videoContainer.add(localVideo, VideoLayout.LOCAL); - videoContainer.add( - closeButton, - VideoLayout.CLOSE_LOCAL_BUTTON); - } + videoContainer.add(localVideo, VideoLayout.LOCAL); + videoContainer.add( + closeButton, + VideoLayout.CLOSE_LOCAL_BUTTON); } else { diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/video/JAWTRenderer.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/video/JAWTRenderer.java index da89765..c21b0cb 100644 --- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/video/JAWTRenderer.java +++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/renderer/video/JAWTRenderer.java @@ -836,19 +836,6 @@ public class JAWTRenderer { if (handle != 0) { - /* - * CALayer on Mac OS X has a different coordinate - * system. - */ - Component parent = getParent(); - - if (parent != null) - { - bounds.y - = parent.getHeight() - - (bounds.y + bounds.height); - } - JAWTRenderer.processLightweightComponentEvent( handle, bounds.x, -- cgit v1.1