aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-11-08 18:07:19 +0100
committerSven Gothel <[email protected]>2012-11-08 18:07:19 +0100
commitd0f91a8ed17fbb1a7b56511c4e53a29e576f01af (patch)
tree3e3f906f794ba1abe340190a4dfac12dadf5c921 /src
parent9ce042df68b70a0e62b21b93d2a1a64722e1e49e (diff)
Fix GLAutoDrawable.dispose(): Dispose drawable even w/o context; JAWTWindow.lockSurface(): Check AWT component's native peer
- Fix GLAutoDrawable.dispose(): Dispose drawable even w/o context - It is possible to have the GLContext not being created (not made current), so drawable shall be disposed independent. - Merge Runnable 'postDisposeOnEDTAction' to dispose Runnable for clarity - GLDrawableHelper: Split disposeGL from invokeGLImpl for clarity - JAWTWindow.lockSurface(): Check AWT component's native peer - W/o a native peer (!isDisplayable()), JAWT locking cannot succeed. - On OSX OpenJDK 1.7, attempting to JAWT lock a peer-less component crashes the VM - MacOSXJAWTWindow.lockSurfaceImpl(): Remove redundant null checks
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java58
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java90
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java29
-rw-r--r--src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java33
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java181
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java47
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java40
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java74
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java51
9 files changed, 334 insertions, 269 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 755a7c392..e80079c20 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -173,45 +173,49 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/*
* Disposes of OpenGL resources
*/
- private final Runnable postDisposeGLAction = new Runnable() {
- @Override
- public void run() {
- context = null;
- if (null != drawable) {
- drawable.setRealized(false);
- drawable = null;
- }
- }
- };
-
private final Runnable disposeOnEDTGLAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
try {
- if (null != drawable && null != context) {
- boolean animatorPaused = false;
- final GLAnimatorControl animator = getAnimator();
- if (null != animator) {
- animatorPaused = animator.pause();
- }
-
- if(context.isCreated()) {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction);
- }
-
- if (animatorPaused) {
- animator.resume();
- }
+ final GLAnimatorControl animator = getAnimator();
+ final boolean animatorPaused;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
+ } else {
+ animatorPaused = false;
+ }
+
+ if ( null != context ) {
+ if( context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(GLCanvas.this, context);
+ } catch (GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ context = null;
+ }
+ if ( null != drawable ) {
+ drawable.setRealized(false);
+ drawable = null;
}
// SWT is owner of the device handle, not us.
// Hence close() operation is a NOP.
if (null != device) {
- device.close();
- device = null;
+ device.close();
+ device = null;
}
SWTAccessor.setRealized(GLCanvas.this, false); // unrealize ..
+
+ if (animatorPaused) {
+ animator.resume();
+ }
+
} finally {
_lock.unlock();
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 1d8666e6a..a40cdcf88 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -888,33 +888,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
//
private boolean disposeRegenerate;
- private final Runnable postDisposeOnEDTAction = new Runnable() {
- @Override
- public void run() {
- context=null;
- if(null!=drawable) {
- drawable.setRealized(false);
- drawable=null;
- if(null!=jawtWindow) {
- jawtWindow.destroy();
- jawtWindow=null;
- }
- }
-
- if(disposeRegenerate) {
- // Similar process as in addNotify()!
-
- // Recreate GLDrawable/GLContext to reflect it's new graphics configuration
- createDrawableAndContext();
-
- if(DEBUG) {
- System.err.println(getThreadName()+": GLCanvas.dispose(true): new drawable: "+drawable);
- }
- validateGLDrawable(); // immediate attempt to recreate the drawable
- }
- }
- };
-
private final Runnable disposeOnEDTAction = new Runnable() {
@Override
public void run() {
@@ -929,31 +902,64 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
Thread.dumpStack();
}
- if(null!=drawable && null!=context) {
- boolean animatorPaused = false;
- if(null!=animator) {
- // can't remove us from animator for recreational addNotify()
- animatorPaused = animator.pause();
- }
-
- if(context.isCreated()) {
- helper.disposeGL(GLCanvas.this, drawable, context, postDisposeOnEDTAction);
+ final boolean animatorPaused;
+ if(null!=animator) {
+ // can't remove us from animator for recreational addNotify()
+ animatorPaused = animator.pause();
+ } else {
+ animatorPaused = false;
+ }
+
+ if( null != context ) {
+ if( context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(GLCanvas.this, context);
+ } catch (GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ context=null;
+ }
+ if( null != drawable ) {
+ drawable.setRealized(false);
+ if(DEBUG) {
+ System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - 1: "+drawable);
}
-
- if(animatorPaused) {
- animator.resume();
+ drawable=null;
+ }
+ if( null != jawtWindow ) {
+ jawtWindow.destroy();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - 2: "+jawtWindow);
}
+ jawtWindow=null;
}
-
- if(!disposeRegenerate) {
+
+ if(disposeRegenerate) {
+ // Similar process as in addNotify()!
+
+ // Recreate GLDrawable/GLContext to reflect it's new graphics configuration
+ createDrawableAndContext();
+
+ if(DEBUG) {
+ System.err.println(getThreadName()+": GLCanvas.dispose(true): new drawable: "+drawable);
+ }
+ validateGLDrawable(); // immediate attempt to recreate the drawable
+ } else {
if(null != awtConfig) {
AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT);
}
awtConfig=null;
}
+ if(animatorPaused) {
+ animator.resume();
+ }
+
if(DEBUG) {
- System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, "+animator);
+ System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, animator "+animator);
}
} finally {
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 58b1baa65..dcfc1f0dd 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -757,21 +757,26 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+"]";
}
- private final Runnable postDisposeAction = new Runnable() {
- @Override
- public void run() {
- if (backend != null && !backend.isUsingOwnThreadManagment()) {
- backend.destroy();
- backend = null;
- isInitialized = false;
- }
- }
- };
-
private final Runnable disposeAction = new Runnable() {
@Override
public void run() {
- helper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction);
+ if ( null != backend ) {
+ final GLContext _context = backend.getContext();
+ if( null != _context && _context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(GLJPanel.this, _context);
+ } catch (GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ if ( !backend.isUsingOwnThreadManagment() ) {
+ backend.destroy();
+ backend = null;
+ isInitialized = false;
+ }
+ }
}
};
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index 7bcd37ecd..68fbe3dd5 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -223,27 +223,26 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
* In such case call <code>super.destroyImplInLock</code> first.</p>
*/
protected void destroyImplInLock() {
- final GLContext _context = context;
- final GLDrawable _drawable = drawable;
- if( null != _drawable ) {
- if( _drawable.isRealized() ) {
- if( null != _context && _context.isCreated() ) {
- // Catch dispose GLExceptions by GLEventListener, just 'print' them
- // so we can continue with the destruction.
- try {
- helper.disposeGL(this, _drawable, _context, null);
- } catch (GLException gle) {
- gle.printStackTrace();
- }
+ if( null != context ) {
+ if( context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(this, context);
+ } catch (GLException gle) {
+ gle.printStackTrace();
}
- _drawable.setRealized(false);
}
+ context = null;
+ }
+ if( null != drawable ) {
+ final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ drawable.setRealized(false);
+ drawable = null;
if( ownsDevice ) {
- _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close();
+ device.close();
}
- }
- context = null;
- drawable = null;
+ }
}
public final void defaultSwapBuffers() throws GLException {
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 36dc933ab..f7f846b05 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -397,8 +397,8 @@ public class GLDrawableHelper {
* otherwise maked uninitialized.
* </p>
* <p>
- * Please consider using {@link #disposeAllGLEventListener(GLAutoDrawable, GLDrawable, GLContext)}
- * or {@link #disposeGL(GLAutoDrawable, GLDrawable, GLContext, Runnable)}
+ * Please consider using {@link #disposeAllGLEventListener(GLAutoDrawable, GLContext, boolean)}
+ * or {@link #disposeGL(GLAutoDrawable, GLContext)}
* for correctness, i.e. encapsulating all calls w/ makeCurrent etc.
* </p>
* @param autoDrawable
@@ -483,8 +483,7 @@ public class GLDrawableHelper {
*
* @param autoDrawable
* @param context
- * @param listener
- * @param initAction
+ * @param remove
*/
public final void disposeAllGLEventListener(final GLAutoDrawable autoDrawable,
final GLDrawable drawable,
@@ -505,29 +504,6 @@ public class GLDrawableHelper {
}
}
- /**
- * Principal helper method which runs
- * {@link #disposeAllGLEventListener(GLAutoDrawable, boolean) disposeAllGLEventListener(autoDrawable, false)}
- * with the context made current <b>and</b> destroys the context afterwards while holding the lock.
- * @param autoDrawable
- * @param drawable
- * @param context
- * @param postAction
- */
- public final void disposeGL(final GLAutoDrawable autoDrawable,
- final GLDrawable drawable,
- final GLContext context,
- final Runnable postAction) {
- if(PERF_STATS) {
- invokeGLImplStats(drawable, context, null, null, autoDrawable);
- } else {
- invokeGLImpl(drawable, context, null, null, autoDrawable);
- }
- if(null != postAction) {
- postAction.run();
- }
- }
-
private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) {
l.init(drawable);
if(sendReshape) {
@@ -842,21 +818,66 @@ public class GLDrawableHelper {
}
if(PERF_STATS) {
- invokeGLImplStats(drawable, context, runnable, initAction, null);
+ invokeGLImplStats(drawable, context, runnable, initAction);
} else {
- invokeGLImpl(drawable, context, runnable, initAction, null);
+ invokeGLImpl(drawable, context, runnable, initAction);
}
}
+ /**
+ * Principal helper method which runs
+ * {@link #disposeAllGLEventListener(GLAutoDrawable, boolean) disposeAllGLEventListener(autoDrawable, false)}
+ * with the context made current <b>and</b> destroys the context afterwards while holding the lock.
+ * @param autoDrawable
+ * @param context
+ */
+ public final void disposeGL(final GLAutoDrawable autoDrawable,
+ final GLContext context) {
+ // Support for recursive makeCurrent() calls as well as calling
+ // other drawables' display() methods from within another one's
+ GLContext lastContext = GLContext.getCurrent();
+ Runnable lastInitAction = null;
+ if (lastContext != null) {
+ if (lastContext == context) {
+ lastContext = null; // utilize recursive locking
+ } else {
+ lastInitAction = perThreadInitAction.get();
+ lastContext.release();
+ }
+ }
+ int res = GLContext.CONTEXT_NOT_CURRENT;
+
+ try {
+ res = context.makeCurrent();
+ if (GLContext.CONTEXT_NOT_CURRENT != res) {
+ if(GLContext.CONTEXT_CURRENT_NEW == res) {
+ throw new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
+ }
+ if( listeners.size() > 0 && null != autoDrawable ) {
+ disposeAllGLEventListener(autoDrawable, false);
+ }
+ }
+ } finally {
+ try {
+ context.destroy();
+ flushGLRunnables();
+ } catch (Exception e) {
+ System.err.println("Catched: "+e.getMessage());
+ e.printStackTrace();
+ }
+ if (lastContext != null) {
+ final int res2 = lastContext.makeCurrent();
+ if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
+ lastInitAction.run();
+ }
+ }
+ }
+ }
+
private final void invokeGLImpl(final GLDrawable drawable,
final GLContext context,
final Runnable runnable,
- final Runnable initAction,
- final GLAutoDrawable disposeAutoDrawable) {
- final Thread currentThread = Thread.currentThread();
-
- final boolean isDisposeAction = null==initAction ;
-
+ final Runnable initAction) {
// Support for recursive makeCurrent() calls as well as calling
// other drawables' display() methods from within another one's
GLContext lastContext = GLContext.getCurrent();
@@ -874,35 +895,21 @@ public class GLDrawableHelper {
try {
res = context.makeCurrent();
if (GLContext.CONTEXT_NOT_CURRENT != res) {
- if(!isDisposeAction) {
- perThreadInitAction.set(initAction);
- if (GLContext.CONTEXT_CURRENT_NEW == res) {
- if (DEBUG) {
- System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
- }
- initAction.run();
- }
- runnable.run();
- if (autoSwapBufferMode) {
- drawable.swapBuffers();
- }
- } else {
- if(GLContext.CONTEXT_CURRENT_NEW == res) {
- throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
- }
- if( listeners.size() > 0 && null != disposeAutoDrawable ) {
- disposeAllGLEventListener(disposeAutoDrawable, false);
- }
+ perThreadInitAction.set(initAction);
+ if (GLContext.CONTEXT_CURRENT_NEW == res) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+ }
+ initAction.run();
+ }
+ runnable.run();
+ if ( autoSwapBufferMode ) {
+ drawable.swapBuffers();
}
}
} finally {
try {
- if(isDisposeAction) {
- context.destroy();
- flushGLRunnables();
- } else if( GLContext.CONTEXT_NOT_CURRENT != res ) {
- context.release();
- }
+ context.release();
} catch (Exception e) {
System.err.println("Catched: "+e.getMessage());
e.printStackTrace();
@@ -919,12 +926,9 @@ public class GLDrawableHelper {
private final void invokeGLImplStats(final GLDrawable drawable,
final GLContext context,
final Runnable runnable,
- final Runnable initAction,
- final GLAutoDrawable disposeAutoDrawable) {
+ final Runnable initAction) {
final Thread currentThread = Thread.currentThread();
- final boolean isDisposeAction = null==initAction ;
-
// Support for recursive makeCurrent() calls as well as calling
// other drawables' display() methods from within another one's
int res = GLContext.CONTEXT_NOT_CURRENT;
@@ -956,41 +960,28 @@ public class GLDrawableHelper {
ctxClaimed = true;
}
if (res != GLContext.CONTEXT_NOT_CURRENT) {
- if(!isDisposeAction) {
- perThreadInitAction.set(initAction);
- if (res == GLContext.CONTEXT_CURRENT_NEW) {
- if (DEBUG) {
- System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
- }
- initAction.run();
- }
- tdR = System.currentTimeMillis();
- tdA = tdR - t0; // makeCurrent
- runnable.run();
- tdS = System.currentTimeMillis();
- tdR = tdS - tdR; // render time
- if (autoSwapBufferMode) {
- drawable.swapBuffers();
- tdX = System.currentTimeMillis();
- tdS = tdX - tdS; // swapBuffers
- }
- } else {
- if(res == GLContext.CONTEXT_CURRENT_NEW) {
- throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
- }
- if( listeners.size() > 0 && null != disposeAutoDrawable ) {
- disposeAllGLEventListener(disposeAutoDrawable, false);
- }
+ perThreadInitAction.set(initAction);
+ if (res == GLContext.CONTEXT_CURRENT_NEW) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+ }
+ initAction.run();
+ }
+ tdR = System.currentTimeMillis();
+ tdA = tdR - t0; // makeCurrent
+ runnable.run();
+ tdS = System.currentTimeMillis();
+ tdR = tdS - tdR; // render time
+ if (autoSwapBufferMode) {
+ drawable.swapBuffers();
+ tdX = System.currentTimeMillis();
+ tdS = tdX - tdS; // swapBuffers
}
}
} finally {
try {
- if(isDisposeAction) {
- context.destroy();
- flushGLRunnables();
- ctxDestroyed = true;
- } else if( res != GLContext.CONTEXT_NOT_CURRENT &&
- (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) {
+ if( res != GLContext.CONTEXT_NOT_CURRENT &&
+ (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) {
context.release();
ctxReleased = true;
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index 35c919f28..8527a0200 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -320,32 +320,41 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
if ( LOCK_SURFACE_NOT_READY == res ) {
- determineIfApplet();
- try {
- final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
- adevice.lock();
+ if( !component.isDisplayable() ) {
+ // W/o native peer, we cannot utilize JAWT for locking.
+ surfaceLock.unlock();
+ if(DEBUG) {
+ System.err.println("JAWTWindow: Can't lock surface, component peer n/a. Component displayable "+component.isDisplayable()+", "+component);
+ Thread.dumpStack();
+ }
+ } else {
+ determineIfApplet();
try {
- if(null == jawt) { // no need to re-fetch for each frame
- jawt = fetchJAWTImpl();
- isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
- }
- res = lockSurfaceImpl();
- if(LOCK_SUCCESS == res && drawable_old != drawable) {
- res = LOCK_SURFACE_CHANGED;
- if(DEBUG) {
- System.err.println("JAWTWindow: surface change 0x"+Long.toHexString(drawable_old)+" -> 0x"+Long.toHexString(drawable));
- // Thread.dumpStack();
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ adevice.lock();
+ try {
+ if(null == jawt) { // no need to re-fetch for each frame
+ jawt = fetchJAWTImpl();
+ isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
+ }
+ res = lockSurfaceImpl();
+ if(LOCK_SUCCESS == res && drawable_old != drawable) {
+ res = LOCK_SURFACE_CHANGED;
+ if(DEBUG) {
+ System.err.println("JAWTWindow: surface change 0x"+Long.toHexString(drawable_old)+" -> 0x"+Long.toHexString(drawable));
+ // Thread.dumpStack();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ adevice.unlock();
}
}
} finally {
if (LOCK_SURFACE_NOT_READY >= res) {
- adevice.unlock();
+ surfaceLock.unlock();
}
}
- } finally {
- if (LOCK_SURFACE_NOT_READY >= res) {
- surfaceLock.unlock();
- }
}
}
return res;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index 5fd242247..449121be1 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -119,13 +119,11 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
}
protected int lockSurfaceImpl() throws NativeWindowException {
int ret = NativeWindow.LOCK_SURFACE_NOT_READY;
- if(null == ds) {
- ds = getJAWT().GetDrawingSurface(component);
- if (ds == null) {
- // Widget not yet realized
- unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
- }
+ ds = getJAWT().GetDrawingSurface(component);
+ if (ds == null) {
+ // Widget not yet realized
+ unlockSurfaceImpl();
+ return NativeWindow.LOCK_SURFACE_NOT_READY;
}
int res = ds.Lock();
dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
@@ -141,21 +139,19 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
ret = NativeWindow.LOCK_SURFACE_CHANGED;
}
- if(null == dsi) {
- if (firstLock) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- dsi = ds.GetDrawingSurfaceInfo();
- return null;
- }
- });
- } else {
- dsi = ds.GetDrawingSurfaceInfo();
- }
- if (dsi == null) {
- unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
- }
+ if (firstLock) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ dsi = ds.GetDrawingSurfaceInfo();
+ return null;
+ }
+ });
+ } else {
+ dsi = ds.GetDrawingSurfaceInfo();
+ }
+ if (dsi == null) {
+ unlockSurfaceImpl();
+ return NativeWindow.LOCK_SURFACE_NOT_READY;
}
updateBounds(dsi.getBounds());
if (DEBUG && firstLock ) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java
index c2b6f1551..c51972c39 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java
@@ -33,6 +33,9 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.AnimatorBase;
import com.jogamp.opengl.util.FPSAnimator;
@@ -53,7 +56,21 @@ import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
-
+/**
+ * BUG on OSX/CALayer w/ Java6:
+ * If frame.setTitle() is issued right after initialization the call hangs in
+ * <pre>
+ * at apple.awt.CWindow._setTitle(Native Method)
+ * at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
+ * </pre>
+ * <p>
+ * OSX/CALayer is forced by using an Applet component in this unit test.
+ * </p>
+ * <p>
+ * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child,
+ * e.g. setResizable*().
+ * </p>
+ */
public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
static long durationPerTest = 1000; // ms
static final int width = 512;
@@ -87,6 +104,14 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException {
testImpl(new FPSAnimator(30), 200, true);
} */
+
+ private static void setFrameTitle(Frame frame, String msg) {
+ System.err.println("About to setTitle: <"+msg+"> CT "+Thread.currentThread().getName()+", "+
+ frame+", displayable "+frame.isDisplayable()+
+ ", valid "+frame.isValid()+", visible "+frame.isVisible());
+ // Thread.dumpStack();
+ frame.setTitle(msg);
+ }
void testImpl(final AnimatorBase animator, int restartPeriod, boolean restartOnCurrentThread) throws InterruptedException {
final Frame frame1 = new Frame("Frame 1");
@@ -94,6 +119,13 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
private static final long serialVersionUID = 1L;
};
+ final VersionNumber version170 = new VersionNumber(1, 7, 0);
+ final boolean osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
+ 0 > Platform.getJavaVersionNumber().compareTo(version170);
+ System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug);
+ System.err.println("OSType "+Platform.getOSType());
+ System.err.println("Java Version "+Platform.getJavaVersionNumber());
+
Assert.assertNotNull(frame1);
frame1.setLayout(null);
frame1.pack();
@@ -109,7 +141,7 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
frame1.setLocation(0, 0);
frame1.setTitle("Generic Title");
frame1.add(applet1);
-
+
frame1.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose(frame1, applet1);
@@ -122,34 +154,36 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
@Override
public void init(GLAutoDrawable drawable) {
justInitialized = true;
+ if( !osxCALayerAWTModBug ) {
+ System.err.println("*Init*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "INIT");
+ frame1.setResizable(false);
+ }
}
@Override
public void dispose(GLAutoDrawable drawable) {
+ System.err.println("*Dispose*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "DISPOSE");
}
@Override
public void display(GLAutoDrawable drawable) {
- if(!justInitialized) {
- // BUG on OSX/CALayer: If frame.setTitle() is issued right after initialization
- // the call hangs in
- // at apple.awt.CWindow._setTitle(Native Method)
- // at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
- //
- final String msg = "f "+frameCount+", fps "+( null != animator ? animator.getLastFPS() : 0);
- System.err.println("About to setTitle: CT "+Thread.currentThread().getName()+", "+msg+
- frame1+", displayable "+frame1.isDisplayable()+
- ", valid "+frame1.isValid()+", visible "+frame1.isVisible());
- // Thread.dumpStack();
- frame1.setTitle(msg);
-
+ if( !osxCALayerAWTModBug || !justInitialized ) {
+ System.err.println("*Display*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "f "+frameCount+", fps "+( null != animator ? animator.getLastFPS() : 0));
+ frame1.setResizable(false);
}
frameCount++;
- justInitialized=false;
+ justInitialized = false;
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ if( !osxCALayerAWTModBug || !justInitialized ) {
+ System.err.println("*Reshape*: CT "+Thread.currentThread().getName());
+ setFrameTitle(frame1, "RESHAPE");
+ }
}
};
gle2 = new GearsES2();
@@ -188,7 +222,7 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
glCanvas.display();
}
if(0 < restartPeriod) {
- glCanvas = restart(frame1, applet1, glCanvas, restartOnCurrentThread);
+ glCanvas = restart(applet1, glCanvas, restartOnCurrentThread);
}
Thread.sleep(sleep);
@@ -234,7 +268,7 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
}
}
- GLCanvas restart(final Frame frame, final Applet applet, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException {
+ GLCanvas restart(final Applet applet, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException {
glCanvas.disposeGLEventListener(gle1, true);
glCanvas.disposeGLEventListener(gle2, true);
detachGLCanvas(applet, glCanvas, restartOnCurrentThread);
@@ -253,7 +287,7 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
if( restartOnCurrentThread ) {
applet.setLayout(new BorderLayout());
applet.add(glCanvas, BorderLayout.CENTER);
- applet.validate();
+ applet.validate();
} else {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -274,7 +308,7 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
System.err.println("*** detachGLCanvas.0 on-current-thread "+restartOnCurrentThread+", currentThread "+Thread.currentThread().getName());
if( restartOnCurrentThread ) {
applet.remove(glCanvas);
- applet.validate();
+ applet.validate();
} else {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
index a74286232..d8f25868b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
@@ -53,12 +53,31 @@ import javax.media.opengl.awt.GLCanvas;
import org.junit.Assume;
import org.junit.Test;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.opengl.util.AnimatorBase;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
-// Sample program that relies on JOGL's mechanism to handle the OpenGL context
-// and rendering loop when using an AWT canvas attached to an Applet.
+/**
+ * Sample program that relies on JOGL's mechanism to handle the OpenGL context
+ * and rendering loop when using an AWT canvas attached to an Applet.
+ * <p>
+ * BUG on OSX/CALayer w/ Java6:
+ * If frame.setTitle() is issued right after initialization the call hangs in
+ * <pre>
+ * at apple.awt.CWindow._setTitle(Native Method)
+ * at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
+ * </pre>
+ * </p>
+ * <p>
+ * OSX/CALayer is forced by using an Applet component in this unit test.
+ * </p>
+ * <p>
+ * Similar deadlock has been experienced w/ other mutable operation on an AWT Container owning a GLCanvas child,
+ * e.g. setResizable*().
+ * </p>
+ */
public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
static int framesPerTest = 240; // frames
@@ -109,7 +128,9 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
private long frameRatePeriod = 1000000000L / frameRate;
private boolean initialized = false;
-
+ private boolean osxCALayerAWTModBug = false;
+ boolean justInitialized = true;
+
private double theta = 0;
private double s = 0;
private double c = 0;
@@ -161,6 +182,13 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
millisOffset = System.currentTimeMillis();
+ final VersionNumber version170 = new VersionNumber(1, 7, 0);
+ osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
+ 0 > Platform.getJavaVersionNumber().compareTo(version170);
+ System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug);
+ System.err.println("OSType "+Platform.getOSType());
+ System.err.println("Java Version "+Platform.getJavaVersionNumber());
+
// Frame setup ----------------------------------------------------------
width = 300;
@@ -328,16 +356,9 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
}});
}
}
-
- boolean justInitialized = true;
-
+
void draw(GL2 gl) {
- if(!justInitialized) {
- // BUG on OSX/CALayer: If frame.setTitle() is issued right after initialization
- // the call hangs in
- // at apple.awt.CWindow._setTitle(Native Method)
- // at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
- //
+ if( !osxCALayerAWTModBug || !justInitialized ) {
frame.setTitle("frame " + frameCount);
}
@@ -441,15 +462,15 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
class SimpleListener implements GLEventListener {
@Override
public void display(GLAutoDrawable drawable) {
- draw(drawable.getGL().getGL2());
- justInitialized = false;
+ draw(drawable.getGL().getGL2());
+ justInitialized = false;
}
@Override
public void dispose(GLAutoDrawable drawable) { }
@Override
- public void init(GLAutoDrawable drawable) {
+ public void init(GLAutoDrawable drawable) {
justInitialized = true;
}