diff options
author | Sven Gothel <[email protected]> | 2013-04-23 07:53:31 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-04-23 07:53:31 +0200 |
commit | 0f7412855c118cb501d8a001df7a7487354b5029 (patch) | |
tree | 13da9cd0d86bb37aedbad199811700f1de87ef04 /src/test/com/jogamp/opengl | |
parent | 03a3f209aff955410e0f3133e73078529c23d3e1 (diff) |
Fix Bug 722: Make GLEventListenerState 'transaction' safe Animator.pause[ surface.lock[ modify ] ]
GLEventListenerState:
New model for GLEventListenerState's transaction safety:
- Z Decorate-1: Animator.pause [ X ] Animator.resume
- X Decorate-2: Surface.lock [ Y ] Surface.unlock
- Instead of setting AbstractGraphicsDevice, just swap the handle and ownership.
- Issuing setRealized(..) only if required, i.e. having an upstream-surface (EGL..) depending on used device
- Utilizing setRealized(..) on the GLAD's delegated 'real' drawable, avoiding optional GLAD locking.
- Cleanup and above changes shall render impl. easier to read.
GLEventListenerState Unit Tests:
- If swapping/moving from AWT -> NEWT, use a NEWT dedicated Display
avoiding ATI driver XCB crash - read comment.
Diffstat (limited to 'src/test/com/jogamp/opengl')
5 files changed, 229 insertions, 44 deletions
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java index 300b4ec85..905cbcf25 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java @@ -42,6 +42,7 @@ import javax.media.opengl.awt.GLCanvas; import jogamp.nativewindow.jawt.JAWTUtil; +import com.jogamp.newt.Screen; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.GLEventListenerState; @@ -150,11 +151,12 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { return true; } - protected void testGLADOneLifecycle(GLCapabilities caps, GLADType gladType, int width, int height, - GLEventListenerCounter glelTracker, SnapshotGLEventListener snapshotGLEventListener, - GLEventListenerState glelsIn, GLEventListenerState glelsOut[], GLAnimatorControl animator) + protected void testGLADOneLifecycle(Screen screen, GLCapabilities caps, GLADType gladType, int width, + int height, GLEventListenerCounter glelTracker, + SnapshotGLEventListener snapshotGLEventListener, final GLEventListenerState glelsIn, final GLEventListenerState glelsOut[], GLAnimatorControl animator) throws InterruptedException { + System.err.println("GLAD Lifecycle.0 "+gladType+", restoring "+((null!=glelsIn)?true:false)+", preserving "+((null!=glelsOut)?true:false)); final Frame frame; final GLAutoDrawable glad; if( GLADType.GLCanvasOnscreen == gladType ) { @@ -179,7 +181,11 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { } else if( GLADType.GLWindow == gladType ) { frame = null; - glad = GLWindow.create(caps); + if( null != screen ) { + glad = GLWindow.create(screen, caps); + } else { + glad = GLWindow.create(caps); + } ((GLWindow)glad).setTitle("Newt GLWindow"); ((GLWindow)glad).setSize(width, height); } else if( GLADType.GLOffscreen == gladType ) { @@ -212,7 +218,9 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { if( null != glelsIn ) { Assert.assertEquals(0, glad.getGLEventListenerCount()); - glelsIn.moveTo(glad); + System.err.println(".. restoring.0"); + glelsIn.moveTo(glad); + System.err.println(".. restoring.X"); Assert.assertEquals(1, glelTracker.initCount); Assert.assertTrue(1 <= glelTracker.reshapeCount); @@ -227,6 +235,12 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { Assert.assertEquals(false, glelsIn.isOwner()); } + for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && + ( 1 > glelTracker.initCount || 1 > glelTracker.reshapeCount || 1 > glelTracker.displayCount ); + wait++) { + Thread.sleep(AWTRobotUtil.TIME_SLICE); + } + final long t0 = System.currentTimeMillis(); long t1 = t0; @@ -242,17 +256,17 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { if( null != glelsOut ) { final GLContext context1 = glad.getContext(); - final GLEventListenerState _gllsOut = GLEventListenerState.moveFrom(glad); + System.err.println(".. preserving.0"); + glelsOut[0] = GLEventListenerState.moveFrom(glad); + System.err.println(".. preserving.X"); - Assert.assertEquals(context1, _gllsOut.context); + Assert.assertEquals(context1, glelsOut[0].context); Assert.assertNull(context1.getGLReadDrawable()); Assert.assertNull(context1.getGLDrawable()); - Assert.assertEquals(3, _gllsOut.listenerCount()); - Assert.assertEquals(true, _gllsOut.isOwner()); + Assert.assertEquals(3, glelsOut[0].listenerCount()); + Assert.assertEquals(true, glelsOut[0].isOwner()); Assert.assertEquals(null, glad.getContext()); Assert.assertEquals(0, glad.getGLEventListenerCount()); - - glelsOut[0] = _gllsOut; } if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) { destroyFrame(frame); @@ -272,5 +286,6 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { } else { Assert.assertEquals(1, glelTracker.disposeCount); } + System.err.println("GLAD Lifecycle.X "+gladType); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java new file mode 100644 index 000000000..a11978784 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java @@ -0,0 +1,143 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore.glels; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + + +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.MiscUtils; + +import org.junit.Test; + +/** + * Tests Bug 722 + * <p> + * See Bug 722 - https://jogamp.org/bugzilla/show_bug.cgi?id=722. + * </p> + */ +public class TestBug722GLContextDrawableSwitchNewt2AWT extends GLContextDrawableSwitchBase { + + static int loops = 10; + static long duration2 = 100; // ms + + /** + * Interesting artifact w/ ATI proprietary driver is that the + * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display} + * also causes an XCB crash when reusing the X11 display connection + * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced + * to avoid such re-usage worksaround this problem. + */ + public static boolean fixedNewtDisplay = true; + + @Test(timeout=3000000) + public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException { + final GLCapabilities caps = getCaps(GLProfile.GL2ES2); + if(null == caps) return; + + GLADType gladType1 = GLADType.GLWindow; + GLADType gladType2 = GLADType.GLCanvasOnscreen; + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final Animator animator = new Animator(); + animator.start(); + + final Display dpy; + final Screen screen; + if( fixedNewtDisplay ) { + dpy = NewtFactory.createDisplay(null); + screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + } else { + dpy = null; + screen = null; + } + + duration = duration2; + + for(int i=0; i<loops; i++) { + final GLEventListenerState glels[] = new GLEventListenerState[1]; + final GLEventListenerCounter glelTracker = new GLEventListenerCounter(); + + // - create glad1 w/o context + // - create context using glad1 and assign it to glad1 + { + System.err.println("Test "+i+"/"+loops+".1: GLAD-1 "+gladType1+", preserving."); + testGLADOneLifecycle(screen, caps, gladType1, width, height, + glelTracker, snapshotGLEventListener, + null, + glels, animator); + System.err.println("Test "+i+"/"+loops+".1: done"); + } + + // - create glad2 w/ survived context + { + System.err.println("Test "+i+"/"+loops+".2: GLAD-1 "+gladType2+", restoring."); + testGLADOneLifecycle(screen, caps, gladType2, width+100, height+100, + glelTracker, snapshotGLEventListener, + glels[0], + null, null); + System.err.println("Test "+i+"/"+loops+".2: done."); + } + } + animator.stop(); + + if( fixedNewtDisplay ) { + screen.removeReference(); + } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration2 = MiscUtils.atol(args[i], duration2); + } else if(args[i].equals("-loops")) { + i++; + loops = MiscUtils.atoi(args[i], loops); + } else if(args[i].equals("-noFixedNewtDisplay")) { + fixedNewtDisplay = false; + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestBug722GLContextDrawableSwitchNewt2AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java index 68f74a27a..a3f3ffbee 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java @@ -84,18 +84,18 @@ public class TestGLContextDrawableSwitch11NewtAWT extends GLContextDrawableSwitc // - create glad1 w/o context // - create context using glad1 and assign it to glad1 { - testGLADOneLifecycle(caps, GLADType.GLWindow, width, height, - glelTracker, snapshotGLEventListener, - null, - glels, animator); + testGLADOneLifecycle(null, caps, GLADType.GLWindow, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); } // - create glad2 w/ survived context { - testGLADOneLifecycle(caps, GLADType.GLWindow, width+100, height+100, - glelTracker, snapshotGLEventListener, - glels[0], - null, null); + testGLADOneLifecycle(null, caps, GLADType.GLWindow, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); } animator.stop(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java index 684208909..95e895d44 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java @@ -110,18 +110,18 @@ public class TestGLContextDrawableSwitch12AWT extends GLContextDrawableSwitchBas // - create glad1 w/o context // - create context using glad1 and assign it to glad1 { - testGLADOneLifecycle(caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width, height, - glelTracker, snapshotGLEventListener, - null, - glels, animator); + testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); } // - create glad2 w/ survived context { - testGLADOneLifecycle(caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width+100, height+100, - glelTracker, snapshotGLEventListener, - glels[0], - null, null); + testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); } animator.stop(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java index 87057f5a9..d337570ec 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java @@ -34,7 +34,11 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.GLRendererQuirks; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; @@ -58,6 +62,13 @@ import org.junit.Test; * <p> * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665. * </p> + * <p> + * Interesting artifact w/ ATI proprietary driver is that the + * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display} + * also causes an XCB crash when reusing the X11 display connection + * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced + * to avoid such re-usage worksaround this problem. + * </p> */ public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwitchBase { @@ -65,59 +76,75 @@ public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwit public void test01GLCanvasOnScrn2GLWindowGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test02GLCanvasOnScrn2GLWindowGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + screen.removeReference(); } @Test(timeout=30000) public void test12GLWindow2GLCanvasOnScrnGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + screen.removeReference(); } @Test(timeout=30000) public void test21GLCanvasOffScrn2GLWindowGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test22GLCanvasOffScrn2GLWindowGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test31GLWindow2GLCanvasOffScrnGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + screen.removeReference(); } @Test(timeout=30000) public void test32GLWindow2GLCanvasOffScrnGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + screen.removeReference(); } - private void testGLCanvas2GLWindowImpl(GLCapabilities caps, GLADType gladType1, GLADType gladType2) throws InterruptedException { + private void testGLCanvas2GLWindowImpl(Screen screen, GLCapabilities caps, GLADType gladType1, GLADType gladType2) throws InterruptedException { if( !validateOnOffscreenLayer(gladType1, gladType2) ) { return; } @@ -131,18 +158,18 @@ public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwit // - create glad1 w/o context // - create context using glad1 and assign it to glad1 { - testGLADOneLifecycle(caps, gladType1, width, height, - glelTracker, snapshotGLEventListener, - null, - glels, animator); + testGLADOneLifecycle(screen, caps, gladType1, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); } // - create glad2 w/ survived context { - testGLADOneLifecycle(caps, gladType2, width+100, height+100, - glelTracker, snapshotGLEventListener, - glels[0], - null, null); + testGLADOneLifecycle(screen, caps, gladType2, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); } animator.stop(); } |