aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-03-15 19:08:22 +0100
committerSven Gothel <[email protected]>2013-03-15 19:08:22 +0100
commit28c6472335b924080d638b33a28f8f4eedb459b1 (patch)
treee41dc5fec789634b4e0cb1c286385a7a2a43adab /src/jogl
parent538a41849192cc09da36eeaa5fa9ae10973d85b7 (diff)
Remodel OSX/CALayer Threading (commit 896e8b021b39e9415040a57a1d540d7d24b02db1): Run on main-thread w/o blocking ; Misc Changes
Commit 896e8b021b39e9415040a57a1d540d7d24b02db1 moved all native CALayer calls to the current thread to avoid deadlocks. Even though this seemed to be fine at least resource GC (release/dealloc calls) were issued very late in time, probably due to multithreading synchronization of JAWT and/or OSX API. Example: Our 'TestAddRemove01GLCanvasSwingAWT' test didn't freed CALayer resources incl. GL ctx when destroying the objects (AWT Frame, GLCanvas, ..), leading to resource starvation .. eventually. Remedy is a compromise of behavior before commit 896e8b021b39e9415040a57a1d540d7d24b02db1 and that commit, i.e. to run CALayer lifecycle methods on main-thread, but do not block! The careful part within MacOSXCGLContext.associateDrawable(..) performs the following block on main-thread: - lock the context - create NSOpenGLLayer (incl. it's own shared GL context and the DisplayLink) - attach NSOpenGLLayer to root CALayer - unlock the context Due to the GL ctx locking, this async offthread operation is safe within our course of operations. Details: - NSOpenGLContext - Context and CVDisplayLink creation at init - Call [ctx update] if texture/frame size changed - 'waitUntilRenderSignal' uses default TO value if given TO is 0 to avoid deadlocks +++ Misc Changes: - Fix object type detection: isMemberOfClass -> isKindOfClass - OSXUtil_isNSView0 OSXUtil_isNSWindow0, CGL_isNSOpenGLPixelBuffer - MacOSXCGLDrawable/MacOSXPbufferCGLDrawable: remove getNSViewHandle() method. MacOSXCGLContext uses common code to detect nature of the drawable handle. - MacOSXCGLContext/CALayer: Use safe screenVSyncTimeout values, never 0 to avoid deadlock! - JAWTWindow.invalidate: Call detachSurfaceLayer() if not done yet
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java1
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java127
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java6
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m85
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface.m83
6 files changed, 166 insertions, 140 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 278e2dc37..2fdf18404 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -946,6 +946,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
animatorPaused = false;
}
+ // OLS will be detached by disposeGL's context destruction below
if( null != context ) {
if( context.isCreated() ) {
// Catch dispose GLExceptions by GLEventListener, just 'print' them
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 9e6085030..f01e03a2f 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -462,9 +462,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// NSOpenGLContext-based implementation
class NSOpenGLImpl implements GLBackendImpl {
private long pixelFormat = 0; // lifecycle: [create - destroy]
- private long nsOpenGLLayer = 0; // lifecycle: [associateDrawable_true - associateDrawable_false]
- private float screenVSyncTimeout; // microSec
- private int vsyncTimeout; // microSec - for nsOpenGLLayer mode
+ private volatile long nsOpenGLLayer = 0; // lifecycle: [associateDrawable_true - associateDrawable_false]
+ private float screenVSyncTimeout = 16666; // microSec - defaults to 1/60s
+ private volatile int vsyncTimeout = 16666 + 1000; // microSec - for nsOpenGLLayer mode - defaults to 1/60s + 1ms
private int lastWidth=0, lastHeight=0; // allowing to detect size change
private boolean needsSetContextPBuffer = false;
private ShaderProgram gl3ShaderProgram = null;
@@ -472,6 +472,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean isNSContext() { return true; }
+
+ /** Only returns a valid NSView. If !NSView, return null and mark either pbuffer and FBO. */
private long getNSViewHandle(boolean[] isPBuffer, boolean[] isFBO) {
final long nsViewHandle;
if(drawable instanceof GLFBODrawableImpl) {
@@ -479,27 +481,15 @@ public abstract class MacOSXCGLContext extends GLContextImpl
isPBuffer[0] = false;
isFBO[0] = true;
if(DEBUG) {
- System.err.println("NS create GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
- }
- } else if(drawable instanceof MacOSXCGLDrawable) {
- // we allow null here! (special pbuffer case)
- nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle();
- isPBuffer[0] = CGL.isNSOpenGLPixelBuffer(drawable.getHandle());
- isFBO[0] = false;
- if(DEBUG) {
- System.err.println("NS create MacOSXCGLDrawable drawable handle isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ System.err.println("NS viewHandle.1: GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
}
} else {
- // we only allow a valid NSView here
final long drawableHandle = drawable.getHandle();
final boolean isNSView = OSXUtil.isNSView(drawableHandle);
final boolean isNSWindow = OSXUtil.isNSWindow(drawableHandle);
isPBuffer[0] = CGL.isNSOpenGLPixelBuffer(drawableHandle);
isFBO[0] = false;
- if(DEBUG) {
- System.err.println("NS create Anonymous drawable handle "+toHexString(drawableHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
- }
if( isNSView ) {
nsViewHandle = drawableHandle;
} else if( isNSWindow ) {
@@ -507,7 +497,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl
} else if( isPBuffer[0] ) {
nsViewHandle = 0;
} else {
- throw new RuntimeException("Anonymous drawable instance's handle neither NSView, NSWindow nor PBuffer: "+toHexString(drawableHandle)+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ throw new RuntimeException("Drawable's handle neither NSView, NSWindow nor PBuffer: drawableHandle "+toHexString(drawableHandle)+", isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO[0]+", isPBuffer "+isPBuffer[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ }
+ if(DEBUG) {
+ System.err.println("NS viewHandle.2: drawableHandle "+toHexString(drawableHandle)+" -> nsViewHandle "+toHexString(nsViewHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO[0]+", isPBuffer "+isPBuffer[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
}
}
needsSetContextPBuffer = isPBuffer[0];
@@ -567,8 +560,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl
_fixedCaps.setOnscreen( !isFBO && !isPBuffer );
fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(_fixedCaps, chosenCaps.isBackgroundOpaque());
}
- int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
- screenVSyncTimeout = 1000000f / sRefreshRate;
+ final int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
+ if( 0 < sRefreshRate ) {
+ screenVSyncTimeout = 1000000f / sRefreshRate;
+ }
if(DEBUG) {
System.err.println("NS create OSX>=lion "+isLionOrLater);
System.err.println("NS create incompleteView: "+incompleteView);
@@ -611,7 +606,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
pixelFormat = 0;
}
return CGL.deleteContext(ctx, true);
-
}
@Override
@@ -622,10 +616,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable: "+bound+", ctx "+toHexString(contextHandle)+", hasBackingLayerHost "+(null!=backingLayerHost));
}
- if( bound ) {
-
- if( null != backingLayerHost ) {
-
+ if( bound ) {
+ if( null != backingLayerHost ) {
if( 0 != nsOpenGLLayer ) { // FIXME: redundant
throw new InternalError("Lifecycle: bound=true, hasBackingLayerHost=true, but 'nsOpenGLLayer' is already/still set local: "+nsOpenGLLayer+", "+this);
}
@@ -676,32 +668,59 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
/**
- * NSOpenGLLayer creation is performed on the current thread,
- * which immediately creates it's own GL ctx sharing this ctx
- * not causing any locking issues.
+ * NSOpenGLLayer creation and it's attachment is performed on the main w/o blocking,
+ * due to OSX main-thread requirements.
+ * Note: It somewhat works from another thread, however,
+ * GC-dealloc of the 'released' resources would happen very late!
*
- * Subsequent attaching is performed on main-thread w/o blocking.
+ * NSOpenGLLayer initialization creates it's own GL ctx sharing
+ * this ctx, hence we have to lock this ctx in the main-thread.
*
- * This is a lock free operation.
- */
- final long cglCtx = CGL.getCGLContext(ctx);
- if(0 == cglCtx) {
- throw new InternalError("Null CGLContext for: "+this);
- }
- nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight);
- if (DEBUG) {
- 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
- } else {
+ * Locking of this ctx while creation and attachment
+ * also gives us good means of synchronization, i.e. it will be
+ * performed after this thread ends it's associateDrawable() [makeCurrent(), setDrawable(..)]
+ * and before the next display cycle involving makeCurrent().
+ */
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ if (DEBUG) {
+ System.err.println("NS create nsOpenGLLayer.0 "+Thread.currentThread().getName());
+ }
+ final long cglCtx = CGL.getCGLContext(ctx);
+ if(0 == cglCtx) {
+ throw new GLException("Null CGLContext for: "+MacOSXCGLContext.this);
+ }
+ if( CGL.kCGLNoError != CGL.CGLLockContext(cglCtx) ) {
+ throw new GLException("Could not lock CGLContext for: "+MacOSXCGLContext.this);
+ }
+ try {
+ nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight);
+ if (DEBUG) {
+ System.err.println("NS create nsOpenGLLayer.2 "+Thread.currentThread().getName()+": "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable);
+ }
+ backingLayerHost.attachSurfaceLayer(nsOpenGLLayer);
+ setSwapInterval(1); // enabled per default in layered surface
+ } catch (Throwable t) {
+ throw new GLException("createNSOpenGLLayer failed for: "+MacOSXCGLContext.this, t);
+ } finally {
+ if(CGL.kCGLNoError != CGL.CGLUnlockContext(cglCtx)) {
+ throw new GLException("Could not unlock CGLContext for: "+MacOSXCGLContext.this);
+ }
+ }
+ if (DEBUG) {
+ System.err.println("NS create nsOpenGLLayer.X "+Thread.currentThread().getName());
+ }
+ }
+ });
+ CGL.setContextView(contextHandle, 0); // [ctx clearDrawable]
+ } else { // -> null == backingLayerHost
lastWidth = drawable.getWidth();
lastHeight = drawable.getHeight();
boolean[] isPBuffer = { false };
boolean[] isFBO = { false };
- CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO));
+ CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO)); // will call [ctx clearDrawable] if view == 0, otherwise [ctx setView: view] if valid
}
- } else {
+ } else { // -> !bound
if( 0 != nsOpenGLLayer ) {
if( null == backingLayerHost ) { // FIXME: redundant
throw new InternalError("Lifecycle: bound=false, hasNSOpneGLLayer=true, but 'backingLayerHost' is null local: "+nsOpenGLLayer+", "+this);
@@ -714,13 +733,20 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// still having a valid OLS attached to surface (parent OLS could have been removed)
backingLayerHost.detachSurfaceLayer();
}
- CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
+ // All CALayer lifecycle calls are deferred on main-thread, so is this.
+ final long _nsOpenGLLayer = nsOpenGLLayer;
+ nsOpenGLLayer = 0;
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ CGL.releaseNSOpenGLLayer(_nsOpenGLLayer);
+ }
+ });
if( null != gl3ShaderProgram ) {
gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
gl3ShaderProgram = null;
}
- nsOpenGLLayer = 0;
}
+ CGL.setContextView(contextHandle, 0); // [ctx clearDrawable]
}
}
@@ -808,8 +834,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl
public boolean setSwapInterval(int interval) {
if(0 != nsOpenGLLayer) {
CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval);
- vsyncTimeout = interval * (int)screenVSyncTimeout + 1000; // +1ms
- if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); }
+ if( 0 < interval ) {
+ vsyncTimeout = interval * (int)screenVSyncTimeout + 1000; // +1ms
+ }
+ if(DEBUG) { System.err.println("NS setSwapInterval: "+interval+" -> "+vsyncTimeout+" micros"); }
}
CGL.setSwapInterval(contextHandle, interval);
return true;
@@ -839,8 +867,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
if(valid) {
if(0 == skipSync) {
- // If v-sync is disabled, frames will be drawn as quickly as possible
- // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync).
+ // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay,
+ // while still synchronizing w/ CALayer.
+ // If v-sync is enabled wait until next swap interval (v-sync).
CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout);
} else {
skipSync--;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index 0f282d33f..1daa892ba 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
@@ -106,10 +106,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
protected void setRealizedImpl() {
}
- protected long getNSViewHandle() {
- return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0;
- }
-
@Override
protected void associateContext(GLContext ctx, boolean bound) {
// NOTE: we need to keep track of the created contexts in order to
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index ddff43031..1e845d179 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -92,12 +92,6 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
return new MacOSXPbufferCGLContext(this, shareWith);
}
- @Override
- protected long getNSViewHandle() {
- // pbuffer handle is NSOpenGLPixelBuffer
- return 0;
- }
-
protected int getTextureTarget() { return pBufferTexTarget; }
protected int getTextureWidth() { return pBufferTexWidth; }
protected int getTextureHeight() { return pBufferTexHeight; }
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index 125ca8af8..96783c75d 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -117,6 +117,7 @@ extern GLboolean glIsVertexArray (GLuint array);
CGLContextObj cglCtx = [self CGLContextObj];
DBG_PRINT("MyNSOpenGLContext::dealloc.0 %p (refcnt %d) - CGL-Ctx %p\n", self, (int)[self retainCount], cglCtx);
+ // NSLog(@"MyNSOpenGLContext::dealloc: %@",[NSThread callStackSymbols]);
[self clearDrawable];
if( NULL != cglCtx ) {
CGLDestroyContext( cglCtx );
@@ -143,8 +144,8 @@ extern GLboolean glIsVertexArray (GLuint array);
NSOpenGLPixelFormat* parentPixelFmt;
int texWidth;
int texHeight;
- int dedicatedWidth;
- int dedicatedHeight;
+ volatile int dedicatedWidth;
+ volatile int dedicatedHeight;
volatile NSOpenGLPixelBuffer* pbuffer;
volatile GLuint textureID;
volatile NSOpenGLPixelBuffer* newPBuffer;
@@ -184,7 +185,6 @@ extern GLboolean glIsVertexArray (GLuint array);
- (void) setGLEnabled: (Bool) enable;
- (Bool) validateTexSizeWithDedicatedSize;
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight;
- (void) setTextureID: (int) _texID;
- (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p;
@@ -316,6 +316,14 @@ static const GLfloat gl_verts[] = {
}
}
if(NULL != displayLink) {
+ CVReturn cvres;
+ DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.1: setup DisplayLink %p\n", displayLink);
+ cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [glContext CGLContextObj], [parentPixelFmt CGLPixelFormatObj]);
+ if(kCVReturnSuccess != cvres) {
+ DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres);
+ }
+ }
+ if(NULL != displayLink) {
cvres = CVDisplayLinkSetOutputCallback(displayLink, renderMyNSOpenGLLayer, self);
if(kCVReturnSuccess != cvres) {
DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetOutputCallback failed: %d\n", self, cvres);
@@ -354,14 +362,9 @@ static const GLfloat gl_verts[] = {
- (Bool) validateTexSizeWithDedicatedSize
{
- return [self validateTexSize: dedicatedWidth texHeight: dedicatedHeight];
-}
-
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight
-{
- if(_texHeight != texHeight || _texWidth != texWidth) {
- texWidth = _texWidth;
- texHeight = _texHeight;
+ if( dedicatedHeight != texHeight || dedicatedWidth != texWidth ) {
+ texWidth = dedicatedWidth;
+ texHeight = dedicatedHeight;
GLfloat texCoordWidth, texCoordHeight;
if(NULL != pbuffer) {
@@ -477,10 +480,10 @@ static const GLfloat gl_verts[] = {
- (void)releaseLayer
{
DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [self setGLEnabled: NO];
[self disableAnimation];
pthread_mutex_lock(&renderLock);
[self deallocPBuffer];
- // [[self openGLContext] release];
if( NULL != glContext ) {
[glContext release];
glContext = NULL;
@@ -570,16 +573,6 @@ static const GLfloat gl_verts[] = {
{
DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.0: %p (refcnt %d) - pfmt %p, ctx %p, DisplayLink %p\n",
self, (int)[self retainCount], pixelFormat, glContext, displayLink);
-#ifndef HAS_CADisplayLink
- if(NULL != displayLink) {
- CVReturn cvres;
- DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.1: setup DisplayLink %p\n", displayLink);
- cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [glContext CGLContextObj], [pixelFormat CGLPixelFormatObj]);
- if(kCVReturnSuccess != cvres) {
- DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres);
- }
- }
-#endif
return glContext;
}
@@ -607,6 +600,9 @@ static const GLfloat gl_verts[] = {
GLenum textureTarget;
Bool texSizeChanged = [self validateTexSizeWithDedicatedSize];
+ if( texSizeChanged ) {
+ [context update];
+ }
if( NULL != pbuffer ) {
if( texSizeChanged && 0 != textureID ) {
@@ -812,29 +808,23 @@ static const GLfloat gl_verts[] = {
struct timespec t0, t1, td, td2;
timespec_now(&t0);
#endif
- if(0 < to_micros) {
- struct timespec to_abs = lastWaitTime;
- timespec_addmicros(&to_abs, to_micros);
- #ifdef DBG_SYNC
- timespec_subtract(&td, &to_abs, &t0);
- fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td));
- #endif
- wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
- } else {
- pthread_cond_wait (&renderSignal, &renderLock);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
+ if( 0 >= to_micros ) {
+ to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
+ NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
}
+ struct timespec to_abs = lastWaitTime;
+ timespec_addmicros(&to_abs, to_micros);
+ #ifdef DBG_SYNC
+ timespec_subtract(&td, &to_abs, &t0);
+ fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td));
+ #endif
+ wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs);
+ #ifdef DBG_SYNC
+ timespec_now(&t1);
+ timespec_subtract(&td, &t1, &t0);
+ timespec_subtract(&td2, &t1, &lastWaitTime);
+ fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
+ #endif
ready = YES;
}
} while (NO == ready && 0 == wr) ;
@@ -923,9 +913,16 @@ void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuff
void releaseNSOpenGLLayer(NSOpenGLLayer* layer) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l);
[l releaseLayer];
DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l);
+
+ [CATransaction commit];
+
[pool release];
}
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
index f8faeb8d0..38f1789e3 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
@@ -501,6 +501,28 @@ NSView* getNSView(NSOpenGLContext* ctx) {
return view;
}
+static Bool lockViewIfReady(NSView *view) {
+ Bool viewReady = false;
+
+ if (view != nil) {
+ if ([view lockFocusIfCanDraw] == NO) {
+ DBG_PRINT("lockViewIfReady.1 [view lockFocusIfCanDraw] failed\n");
+ } else {
+ NSRect frame = [view frame];
+ if ((frame.size.width == 0) || (frame.size.height == 0)) {
+ [view unlockFocus];
+ DBG_PRINT("lockViewIfReady.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height);
+ } else {
+ DBG_PRINT("lockViewIfReady.X ready and locked\n");
+ viewReady = true;
+ }
+ }
+ } else {
+ DBG_PRINT("lockViewIfReady.3 nil view\n");
+ }
+ return viewReady;
+}
+
NSOpenGLContext* createContext(NSOpenGLContext* share,
NSView* view,
Bool incompleteView,
@@ -515,40 +537,18 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
DBG_PRINT("createContext.0: share %p, view %p, incompleteView %d, pixfmt %p, opaque %d\n",
share, view, (int)incompleteView, fmt, opaque);
- if (view != nil) {
- Bool viewReady = true;
-
- if(!incompleteView) {
- if ([view lockFocusIfCanDraw] == NO) {
- DBG_PRINT("createContext.1 [view lockFocusIfCanDraw] failed\n");
- viewReady = false;
- }
- }
- if(viewReady) {
- NSRect frame = [view frame];
- if ((frame.size.width == 0) || (frame.size.height == 0)) {
- if(!incompleteView) {
- [view unlockFocus];
- }
- DBG_PRINT("createContext.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height);
- viewReady = false;
- }
- }
+ Bool viewReadyAndLocked = incompleteView ? false : lockViewIfReady(view);
- if (!viewReady)
- {
- if (viewNotReady != NULL)
- {
- *viewNotReady = 1;
- }
+ if (nil != viewNotReady) {
+ *viewNotReady = 1;
+ }
- // the view is not ready yet
- DBG_PRINT("createContext.X: view not ready yet\n");
- [pool release];
- return NULL;
- }
+ if (nil != view && !incompleteView && !viewReadyAndLocked) {
+ DBG_PRINT("createContext.X: Assumed complete view not ready yet\n");
+ [pool release];
+ return NULL;
}
-
+
NSOpenGLContext* ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share];
if ( nil != ctx && nil != view ) {
@@ -556,10 +556,8 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
GLint zeroOpacity = 0;
[ctx setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity];
}
- if(!incompleteView) {
- DBG_PRINT("createContext.3.0: setView\n");
+ if( viewReadyAndLocked ) {
[ctx setView:view];
- DBG_PRINT("createContext.3.X: setView\n");
[view unlockFocus];
}
}
@@ -571,8 +569,19 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
void setContextView(NSOpenGLContext* ctx, NSView* view) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- if ( nil != ctx && nil != view ) {
- [ctx setView:view];
+ if ( nil != ctx ) {
+ if ( nil != view ) {
+ Bool viewReadyAndLocked = lockViewIfReady(view);
+ DBG_PRINT("setContextView.0: ctx %p, view %p: setView: %d\n", ctx, view, viewReadyAndLocked);
+ if( viewReadyAndLocked ) {
+ [ctx setView:view];
+ [view unlockFocus];
+ }
+ } else {
+ DBG_PRINT("setContextView.1: ctx %p, view nil: clearDrawable\n", ctx);
+ [ctx clearDrawable];
+ }
+ DBG_PRINT("setContextView.X\n");
}
[pool release];
}
@@ -725,7 +734,7 @@ void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer*
Bool isNSOpenGLPixelBuffer(uint64_t object) {
NSObject *nsObj = (NSObject*) (intptr_t) object;
DBG_PRINT("isNSOpenGLPixelBuffer.0: obj %p\n", object);
- Bool res = [nsObj isMemberOfClass:[NSOpenGLPixelBuffer class]];
+ Bool res = [nsObj isKindOfClass:[NSOpenGLPixelBuffer class]];
DBG_PRINT("isNSOpenGLPixelBuffer.X: res %d\n", (int)res);
return res;
}