aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-11-05 03:49:20 +0100
committerSven Gothel <[email protected]>2012-11-05 03:49:20 +0100
commit3a00361952120f8127a3014623de703ac696e036 (patch)
treee2c2b1d5bdddc790fcc81451f2f0ed078a97fe6d
parent0b3f9ee017f7216ec9ff37c16bbb44848aa5cfa5 (diff)
Analyzed OSX Deadlock w/ AWT Applet & CALayer: Andres Colubri's Test Case, Commit 77db6a5c22cb4a53cf911b4caf57127770c70968
[1] - The AWT/Applet test case on OSX utilized offscreen CALayer, which is correct. [2] - the GLEventListener.display(..) method calls Frame.setTitle(".."); which is correct, but freezes when called right after GLEventListener.init(..) 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] Happens w/ Oracle's JRE7u9 as well! Workaround: - Set 'justInitialized' flag in GLEventListener.init(..) - Clear 'justInitialized' flag in GLEventListener.display(..) at the end - Skip Frame.setTitle(..) in GLEventListener.display(..) if 'true == justInitialized' Somebody may send a bugreport to Oracle / OpenJDK.
-rwxr-xr-xmake/scripts/tests.sh6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java93
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java89
3 files changed, 130 insertions, 58 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 50e070130..cc9a330a5 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -106,7 +106,7 @@ function jrun() {
#D_ARGS="-Dnewt.debug.MainThread"
#D_ARGS="-Dnewt.debug.Window"
#D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Dnativewindow.debug.NativeWindow"
- D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Animator -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLContext.TraceSwitch"
+ #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Animator -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLContext.TraceSwitch"
#D_ARGS="-Djogl.debug.GLContext -Djogl.debug.ExtensionAvailabilityCache"
#D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLProfile -Djogl.debug.GLDrawable"
#D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLProfile"
@@ -351,8 +351,8 @@ function testawtswt() {
#testawt com.jogamp.opengl.test.junit.jogl.glu.TestBug463ScaleImageMemoryAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock00AWT $*
-testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock01AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock02AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock01AWT $*
+testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock02AWT $*
#
# swt (testswt)
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 fa4d4a5e2..09609dd39 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
@@ -29,7 +29,9 @@
package com.jogamp.opengl.test.junit.jogl.awt;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.AnimatorBase;
@@ -61,23 +63,28 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
GLEventListener gle2 = null;
@Test
+ public void test00NoAnimator() throws InterruptedException {
+ testImpl(null, 0, false);
+ }
+
+ @Test
public void test01Animator() throws InterruptedException {
testImpl(new Animator(), 0, false);
}
- // @Test
+ @Test
public void test02FPSAnimator() throws InterruptedException {
testImpl(new FPSAnimator(30), 0, false);
}
- // @Test
+ @Test
public void test02FPSAnimator_RestartOnAWTEDT() throws InterruptedException {
- testImpl(new FPSAnimator(30), 100, false);
+ testImpl(new FPSAnimator(30), 200, false);
}
- // @Test
+ @Test
public void test02FPSAnimator_RestartOnCurrentThread() throws InterruptedException {
- testImpl(new FPSAnimator(30), 100, true);
+ testImpl(new FPSAnimator(30), 200, true);
}
void testImpl(final AnimatorBase animator, int restartPeriod, boolean restartOnCurrentThread) throws InterruptedException {
@@ -109,8 +116,11 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
});
gle1 = new GLEventListener() {
+ boolean justInitialized = true;
+
@Override
public void init(GLAutoDrawable drawable) {
+ justInitialized = true;
}
@Override
@@ -119,8 +129,22 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
@Override
public void display(GLAutoDrawable drawable) {
- frame1.setTitle("f "+frameCount+", fps "+animator.getLastFPS());
+ 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);
+
+ }
frameCount++;
+ justInitialized=false;
}
@Override
@@ -133,27 +157,37 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
glCanvas.addGLEventListener(gle1);
glCanvas.addGLEventListener(gle2);
- animator.setUpdateFPSFrames(60, System.err);
- animator.add(glCanvas);
- animator.start();
+ if(null != animator) {
+ System.err.println("About to start Animator: CT "+Thread.currentThread().getName());
+ animator.setUpdateFPSFrames(60, System.err);
+ animator.add(glCanvas);
+ animator.start();
+ }
attachGLCanvas(applet1, glCanvas, false);
+ System.err.println("About to setVisible.0 CT "+Thread.currentThread().getName());
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
+ System.err.println("About to setVisible.1.0 CT "+Thread.currentThread().getName());
frame1.setVisible(true);
+ System.err.println("About to setVisible.1.X CT "+Thread.currentThread().getName());
}});
} catch (Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
+ System.err.println("About to setVisible.X CT "+Thread.currentThread().getName());
final long sleep = 0 < restartPeriod ? restartPeriod : 100;
long togo = durationPerTest;
while( 0 < togo ) {
+ if(null == animator) {
+ glCanvas.display();
+ }
if(0 < restartPeriod) {
- glCanvas = restart(applet1, glCanvas, restartOnCurrentThread);
+ glCanvas = restart(frame1, applet1, glCanvas, restartOnCurrentThread);
}
Thread.sleep(sleep);
@@ -162,12 +196,30 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
}
dispose(frame1, applet1);
- animator.stop();
+ if(null != animator) {
+ animator.stop();
+ }
gle1 = null;
gle2 = null;
}
+ int frameCount = 0;
+
+ GLCanvas createGLCanvas() {
+ System.err.println("*** createGLCanvas.0");
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ // Iff using offscreen layer, use pbuffer, hence restore onscreen:=true.
+ // caps.setPBuffer(true);
+ // caps.setOnscreen(true);
+ final GLCanvas glCanvas = new GLCanvas(caps);
+ glCanvas.setBounds(0, 0, width, height);
+ Assert.assertNotNull(glCanvas);
+ System.err.println("*** createGLCanvas.X");
+ frameCount = 0;
+ return glCanvas;
+ }
+
void dispose(final Frame frame, final Applet applet) {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -181,14 +233,14 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
}
}
- GLCanvas restart(final Applet frame, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException {
+ GLCanvas restart(final Frame frame, final Applet applet, GLCanvas glCanvas, boolean restartOnCurrentThread) throws InterruptedException {
glCanvas.disposeGLEventListener(gle1, true);
glCanvas.disposeGLEventListener(gle2, true);
- detachGLCanvas(frame, glCanvas, restartOnCurrentThread);
+ detachGLCanvas(applet, glCanvas, restartOnCurrentThread);
glCanvas = createGLCanvas();
- attachGLCanvas(frame, glCanvas, restartOnCurrentThread);
+ attachGLCanvas(applet, glCanvas, restartOnCurrentThread);
glCanvas.addGLEventListener(gle1);
glCanvas.addGLEventListener(gle2);
@@ -226,7 +278,7 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- applet.remove(glCanvas);
+ applet.remove(glCanvas);
applet.validate();
}});
} catch (Throwable t) {
@@ -237,17 +289,6 @@ public class TestGLCanvasAWTActionDeadlock01AWT extends UITestCase {
System.err.println("*** detachGLCanvas.X");
}
- int frameCount = 0;
-
- GLCanvas createGLCanvas() {
- System.err.println("*** createGLCanvas.0");
- final GLCanvas glCanvas = new GLCanvas();
- glCanvas.setBounds(0, 0, width, height);
- Assert.assertNotNull(glCanvas);
- System.err.println("*** createGLCanvas.X");
- return glCanvas;
- }
-
public static void main(String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
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 7ea4a23fa..a74286232 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
@@ -43,6 +43,7 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
import java.util.Timer;
import java.util.TimerTask;
@@ -123,7 +124,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
private int frameCount = 0;
- void run() {
+ void run() throws InterruptedException, InvocationTargetException {
// Thread loop = new Thread("Animation Thread") {
// public void run() {
frameCount = 0;
@@ -133,7 +134,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
}
if (restartCanvas && restartTimeout == frameCount) {
- // restart();
+ restart();
}
if (useAnimator) {
@@ -155,7 +156,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
// loop.start();
}
- void setup() {
+ void setup() throws InterruptedException, InvocationTargetException {
if (printThreadInfo) System.out.println("Current thread at setup(): " + Thread.currentThread());
millisOffset = System.currentTimeMillis();
@@ -214,11 +215,18 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
frame.add(this);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
- dispose();
+ try {
+ dispose();
+ } catch (Exception ex) {
+ Assume.assumeNoException(ex);
+ }
}
});
- frame.setVisible(true);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.setVisible(true); // from here on all AWT mods must be done on AWT-EDT !
+ } } );
// Canvas setup ----------------------------------------------------------
@@ -227,17 +235,21 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
capabilities.setSampleBuffers(true);
capabilities.setNumSamples(numSamples);
capabilities.setDepthBits(24);
- capabilities.setStencilBits(8);
+ // capabilities.setStencilBits(8); // No Stencil on OSX w/ hw-accel !
capabilities.setAlphaBits(8);
canvas = new GLCanvas(capabilities);
canvas.setBounds(0, 0, width, height);
- this.setLayout(new BorderLayout());
- this.add(canvas, BorderLayout.CENTER);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ MiniPApplet.this.setLayout(new BorderLayout());
+ MiniPApplet.this.add(canvas, BorderLayout.CENTER);
+ MiniPApplet.this.validate();
+ } } );
canvas.addMouseMotionListener(this);
canvas.addKeyListener(this);
-
+
// Setting up animation
listener = new SimpleListener();
canvas.addGLEventListener(listener);
@@ -248,7 +260,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
initialized = true;
}
- void restart() {
+ void restart() throws InterruptedException, InvocationTargetException {
System.out.println("Restarting surface...");
// Stopping animation, removing current canvas.
@@ -267,8 +279,12 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
canvas.setBounds(0, 0, width, height);
// Setting up animation again
- this.setLayout(new BorderLayout());
- this.add(canvas, BorderLayout.CENTER);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ MiniPApplet.this.setLayout(new BorderLayout());
+ MiniPApplet.this.add(canvas, BorderLayout.CENTER);
+ MiniPApplet.this.validate();
+ } } );
canvas.addMouseMotionListener(this);
canvas.addKeyListener(this);
@@ -284,7 +300,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
System.out.println("Done");
}
- void dispose() {
+ void dispose() throws InterruptedException, InvocationTargetException {
if( null == frame ) {
return;
}
@@ -302,24 +318,28 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
frame.dispose();
frame = null;
} else {
- try {
- javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
- public void run() {
- MiniPApplet.this.remove(canvas);
- frame.remove(MiniPApplet.this);
- frame.validate();
- frame.dispose();
- frame = null;
- }});
- } catch (Throwable t) {
- t.printStackTrace();
- Assume.assumeNoException(t);
- }
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ MiniPApplet.this.remove(canvas);
+ frame.remove(MiniPApplet.this);
+ frame.validate();
+ frame.dispose();
+ frame = null;
+ }});
}
}
+ boolean justInitialized = true;
+
void draw(GL2 gl) {
- frame.setTitle("frame " + frameCount);
+ 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]
+ //
+ frame.setTitle("frame " + frameCount);
+ }
if (printThreadInfo) System.out.println("Current thread at draw(): " + Thread.currentThread());
@@ -336,6 +356,10 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
int[] temp = { 0 };
gl.glGetIntegerv(GL2.GL_MAX_SAMPLES, temp, 0);
System.out.println("Maximum number of samples supported by the hardware: " + temp[0]);
+ System.out.println("Frame: "+frame);
+ System.out.println("Applet: "+MiniPApplet.this);
+ System.out.println("GLCanvas: "+canvas);
+ System.out.println("GLDrawable: "+canvas.getDelegatedDrawable());
}
if (currentSamples == -1) {
@@ -418,13 +442,16 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
@Override
public void display(GLAutoDrawable drawable) {
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;
+ }
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { }
@@ -588,7 +615,11 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
throw new RuntimeException(e);
}
if (mini != null) {
- mini.run();
+ try {
+ mini.run();
+ } catch (Exception ex) {
+ Assume.assumeNoException(ex);
+ }
}
}