diff options
author | Sven Gothel <[email protected]> | 2012-09-20 22:45:19 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-09-20 22:45:19 +0200 |
commit | 60c63acc298fd33ada43f37962d1d6c32a0359c3 (patch) | |
tree | 0a2ef207ea469bb3d77b21787309b2ce14e11d63 /src | |
parent | 7da8654b49aa3ddd01fbc64a710b5efe04529381 (diff) |
OSX CALayer / MacOSXCGLContext: Remove pbuffer swap garbage; Split pbuffer/FBO revalidation/redraw; Don't sync @ needsDisplay
Simplified pbuffer replacement:
Simply keep holding the pbuffer reference in native code
until receiving newPBuffer @ swap.
The newPBuffer will be established @draw method.
This allows removing interaction at destroy pbuffer,
which caused garbage and crash.
Remove pbuffer swap garbage
See above.
Split pbuffer/FBO revalidation/redraw
Don't sync @ needsDisplay
- No need to sync @ repaint command setNSOpenGLLayerNeedsDisplay*
since we use volatiles and all lifecycle action is
done @draw -> faster
Diffstat (limited to 'src')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 45 | ||||
-rw-r--r-- | src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m | 130 |
2 files changed, 104 insertions, 71 deletions
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index e04955d87..929ac00c2 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -438,7 +438,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl private float screenVSyncTimeout; // microSec private int vsyncTimeout; // microSec - for nsOpenGLLayer mode private int lastWidth=0, lastHeight=0; // allowing to detect size change - private long lastPBufferHandle = 0; // allowing to detect pbuffer recreation + private boolean needsSetContextPBuffer = false; @Override public boolean isNSContext() { return true; } @@ -577,7 +577,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl @Override public boolean destroy(long ctx) { - lastPBufferHandle = 0; return CGL.deleteContext(ctx, true); } @@ -592,19 +591,20 @@ public abstract class MacOSXCGLContext extends GLContextImpl final long ctx = MacOSXCGLContext.this.getHandle(); final int texID; final long drawableHandle = drawable.getHandle(); + final long pbufferHandle; if(drawable instanceof GLFBODrawableImpl) { final GLFBODrawableImpl fbod = (GLFBODrawableImpl)drawable; - texID = fbod.getTextureBuffer(GL.GL_FRONT).getName(); + texID = fbod.getTextureBuffer(GL.GL_FRONT).getName(); + pbufferHandle = 0; fbod.setSwapBufferContext(new GLFBODrawableImpl.SwapBufferContext() { public void swapBuffers(boolean doubleBuffered) { MacOSXCGLContext.NSOpenGLImpl.this.swapBuffers(); } } ) ; - lastPBufferHandle = 0; } else if( chosenCaps.isPBuffer() && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) { texID = 0; - lastPBufferHandle = drawableHandle; + pbufferHandle = drawableHandle; if(0 != drawableHandle) { // complete 'validatePBufferConfig(..)' procedure - CGL.setContextPBuffer(ctx, drawableHandle); + CGL.setContextPBuffer(ctx, pbufferHandle); } } else { throw new GLException("BackingLayerHost w/ unknown handle (!FBO, !PBuffer): "+drawable); @@ -614,9 +614,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl if(0>=lastWidth || 0>=lastHeight || !drawable.isRealized()) { throw new GLException("Drawable not realized yet or invalid texture size, texSize "+lastWidth+"x"+lastHeight+", "+drawable); } - nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, lastPBufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight); + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight); if (DEBUG) { - System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(lastPBufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable); + System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable); } backingLayerHost.attachSurfaceLayer(nsOpenGLLayer); setSwapInterval(1); // enabled per default in layered surface @@ -642,18 +642,16 @@ public abstract class MacOSXCGLContext extends GLContextImpl CGL.deletePixelFormat(nsOpenGLLayerPFmt); nsOpenGLLayerPFmt = 0; } - lastPBufferHandle = 0; } backingLayerHost = null; return true; } private final void validatePBufferConfig(long ctx) { - final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities(); final long drawableHandle = drawable.getHandle(); - if( chosenCaps.isPBuffer() && lastPBufferHandle != drawableHandle && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) { + if( needsSetContextPBuffer && 0 != drawableHandle && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) { // Must associate the pbuffer with our newly-created context - lastPBufferHandle = drawableHandle; + needsSetContextPBuffer = false; if(0 != drawableHandle) { CGL.setContextPBuffer(ctx, drawableHandle); } @@ -724,13 +722,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl @Override public boolean detachPBuffer() { - if(0 != lastPBufferHandle) { - lastPBufferHandle = 0; - if(0 != nsOpenGLLayer) { - CGL.flushNSOpenGLLayerPBuffer(nsOpenGLLayer); // notify invalid pbuffer - } - // CGL.setContextPBuffer(contextHandle, 0); // doesn't work, i.e. not taking nil - } + needsSetContextPBuffer = true; + // CGL.setContextPBuffer(contextHandle, 0); // doesn't work, i.e. not taking nil return true; } @@ -759,12 +752,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl final int texID; final boolean valid; - if(drawable instanceof GLFBODrawableImpl) { + final boolean isFBO = drawable instanceof GLFBODrawableImpl; + if( isFBO ){ texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName(); valid = 0 != texID; } else { texID = 0; - valid = 0 != lastPBufferHandle; + valid = 0 != drawable.getHandle(); } if(valid) { if(0 == skipSync) { @@ -776,8 +770,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl } res = CGL.flushBuffer(contextHandle); if(res) { - // trigger CALayer to update incl. possible surface change - CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer, lastPBufferHandle, texID, lastWidth, lastHeight); + if(isFBO) { + // trigger CALayer to update incl. possible surface change (texture) + CGL.setNSOpenGLLayerNeedsDisplayFBO(nsOpenGLLayer, texID, lastWidth, lastHeight); + } else { + // trigger CALayer to update incl. possible surface change (new pbuffer handle) + CGL.setNSOpenGLLayerNeedsDisplayPBuffer(nsOpenGLLayer, drawable.getHandle(), lastWidth, lastHeight); + } } } else { res = true; diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m index f3495efff..e83d0adcb 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m @@ -87,6 +87,7 @@ volatile GLuint textureID; volatile int texWidth; volatile int texHeight; + volatile NSOpenGLPixelBuffer* newPBuffer; #ifdef HAS_CADisplayLink CADisplayLink* displayLink; #else @@ -117,7 +118,9 @@ - (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight; - (void) setTextureID: (int) _texID; -- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p; +- (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p; +- (void) setNewPBuffer: (NSOpenGLPixelBuffer*)p; +- (void) applyNewPBuffer; - (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat; - (void)disableAnimation; @@ -199,6 +202,7 @@ static const GLfloat gl_verts[] = { [self validateTexSizeWithNewSize]; [self setTextureID: texID]; + newPBuffer = NULL; pbuffer = p; if(NULL != pbuffer) { [pbuffer retain]; @@ -317,22 +321,60 @@ static const GLfloat gl_verts[] = { textureID = _texID; } -- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p +- (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p { - if( pbuffer != p ) { - DBG_PRINT("MyNSOpenGLLayer::validatePBuffer.0 %p, pbuffer %p, (refcnt %d)\n", self, p, (int)[self retainCount]); + return pbuffer == p || newPBuffer == p; +} - SYNC_PRINT("{PB-nil}"); +- (void)setNewPBuffer: (NSOpenGLPixelBuffer*)p +{ + SYNC_PRINT("<NP-S %p -> %p>", pbuffer, p); + newPBuffer = p; + [newPBuffer retain]; +} - [self deallocPBuffer]; +- (void) applyNewPBuffer +{ + if( NULL != newPBuffer ) { // volatile OK + SYNC_PRINT("<NP-A %p -> %p>", pbuffer, newPBuffer); - pbuffer = p; - if(NULL != pbuffer) { - [pbuffer retain]; + if( 0 != textureID ) { + glDeleteTextures(1, &textureID); + [self setTextureID: 0]; } - [self setTextureID: 0]; + [pbuffer release]; + + pbuffer = newPBuffer; + newPBuffer = NULL; + } +} + +- (void)deallocPBuffer +{ + if(NULL != pbuffer) { + NSOpenGLContext* context = [self openGLContext]; + if(NULL!=context) { + [context makeCurrentContext]; + + DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (with ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID); + + if( 0 != textureID ) { + glDeleteTextures(1, &textureID); + [self setTextureID: 0]; + } + if(NULL != pbuffer) { + [pbuffer release]; + pbuffer = NULL; + } + if(NULL != newPBuffer) { + [newPBuffer release]; + newPBuffer = NULL; + } - shallDraw = NO; + [context clearDrawable]; + } else { + DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (w/o ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID); + } } } @@ -371,29 +413,6 @@ static const GLfloat gl_verts[] = { pthread_mutex_unlock(&renderLock); } -- (void)deallocPBuffer -{ - if(NULL != pbuffer) { - NSOpenGLContext* context = [self openGLContext]; - if(NULL!=context) { - [context makeCurrentContext]; - - DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (with ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID); - - if( 0 != textureID ) { - glDeleteTextures(1, &textureID); - } - [pbuffer release]; - - [context clearDrawable]; - } else { - DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (w/o ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID); - } - pbuffer = NULL; - [self setTextureID: 0]; - } -} - - (void)releaseLayer { DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]); @@ -423,7 +442,7 @@ static const GLfloat gl_verts[] = { - (Bool)isGLSourceValid { - return NULL != pbuffer || 0 != textureID ; + return NULL != pbuffer || NULL != newPBuffer || 0 != textureID ; } - (void)resizeWithOldSuperlayerSize:(CGSize)size @@ -435,7 +454,7 @@ static const GLfloat gl_verts[] = { newTexWidth = lRectS.size.width; newTexHeight = lRectS.size.height; - shallDraw = YES; + shallDraw = [self isGLSourceValid]; SYNC_PRINT("<SZ %dx%d>", newTexWidth, newTexHeight); [super resizeWithOldSuperlayerSize: size]; @@ -455,9 +474,13 @@ static const GLfloat gl_verts[] = { SYNC_PRINT("<* "); // NSLog(@"MyNSOpenGLLayer::DRAW: %@",[NSThread callStackSymbols]); - if( shallDraw && ( NULL != pbuffer || 0 != textureID ) ) { + if( shallDraw && ( NULL != pbuffer || NULL != newPBuffer || 0 != textureID ) ) { [context makeCurrentContext]; + if( NULL != newPBuffer ) { // volatile OK + [self applyNewPBuffer]; + } + GLenum textureTarget; Bool texSizeChanged = [self validateTexSizeWithNewSize]; @@ -665,30 +688,41 @@ void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) { [pool release]; } -void flushNSOpenGLLayerPBuffer(NSOpenGLLayer* layer) { +void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID, int texWidth, int texHeight) { MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + Bool shallDraw; - pthread_mutex_lock(&l->renderLock); - [l validatePBuffer:0]; - pthread_mutex_unlock(&l->renderLock); + // volatile OK + [l setTextureID: texID]; + shallDraw = [l isGLSourceValid]; + l->shallDraw = shallDraw; + SYNC_PRINT("<! T%dx%d O%dx%d %d>", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw); + if(shallDraw) { + if ( [NSThread isMainThread] == YES ) { + [l setNeedsDisplay]; + } else { + // don't wait - using doublebuffering + [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; + } + } + // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); [pool release]; } -void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, uint32_t texID, int texWidth, int texHeight) { +void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, int texWidth, int texHeight) { MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; Bool shallDraw; - pthread_mutex_lock(&l->renderLock); - [l validatePBuffer:p]; - // l->newTexWidth = texWidth; - // l->newTexHeight = texHeight; - [l setTextureID: texID]; + if( NO == [l isSamePBuffer: p] ) { + [l setNewPBuffer: p]; + } + + // volatile OK shallDraw = [l isGLSourceValid]; l->shallDraw = shallDraw; - pthread_mutex_unlock(&l->renderLock); SYNC_PRINT("<! T%dx%d O%dx%d %d>", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw); if(shallDraw) { |