diff options
author | Sven Gothel <[email protected]> | 2012-07-05 14:57:18 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-07-05 14:57:18 +0200 |
commit | d5866a5d55f9445c7cedc1df03dc7958d6fd229e (patch) | |
tree | ee3322121592bda1cea2eb0523b8992604263e7d /src/test | |
parent | a26d6e9361fb3287cba053aaf1a6318c853da95a (diff) |
GLContext adds FBO availability to profile mapping; Fix GL[Auto]Drawable/GLContext re-association (switch) incl. unit test.
- GLContext adds FBO availability to profile mapping
- GLContext added 'GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly)'
allowing to set the write GLDrawable. This method enables switching context/drawable.
Fix GL[Auto]Drawable/GLContext re-association (switch) incl. unit test
Commit eed8508ae1132e5f45f788e9cb3f3d5a1050ac70 impl. of GLAutoDrawable's setContext(..)
enabled proper setting of the GLAutoDrawable context incl. updating the context's drawables.
Test covers:
- remove/set (GLContext, GLEventListener) of GL[Auto]Drawable
- switch (GLContext, GLEventListener) of 2 GLAutoDrawables
Diffstat (limited to 'src/test')
4 files changed, 394 insertions, 17 deletions
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java new file mode 100644 index 000000000..483a09735 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java @@ -0,0 +1,322 @@ +/** + * Copyright 2010 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; + +import java.io.IOException; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowListener; +import com.jogamp.newt.event.WindowUpdateEvent; +import com.jogamp.newt.opengl.GLWindow; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLAutoDrawableDelegate; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import com.jogamp.opengl.util.Animator; + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestGLContextDrawableSwitchNEWT extends UITestCase { + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + caps = new GLCapabilities(glp); + width = 256; + height = 256; + } + + /** Note: No GLContext is attached w/ this implementation ! */ + private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException { + final Window window = NewtFactory.createWindow(caps); + Assert.assertNotNull(window); + window.setPosition(x, y); + window.setSize(width, height); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + + GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null) { + @Override + public void destroy() { + super.destroy(); // destroys drawable/context + window.destroy(); // destroys the actual window + } + }; + + // add basic window interaction + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.defaultWindowRepaintOp(); + } + @Override + public void windowResized(WindowEvent e) { + glad.defaultWindowResizedOp(); + } + @Override + public void windowDestroyNotify(WindowEvent e) { + glad.defaultWindowDestroyNotifyOp(); + } + }); + window.addWindowListener(wl); + + return glad; + } + + @Test(timeout=30000) + public void testSwitch2WindowSingleContext() throws InterruptedException { + final QuitAdapter quitAdapter = new QuitAdapter(); + + GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter); // no GLContext! + GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter); // no GLContext! + + // create single context using glad1 and assign it to glad1 + { + GLContext singleCtx = glad1.createContext(null); + Assert.assertNotNull(singleCtx); + int res = singleCtx.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + singleCtx.release(); + glad1.setContext(singleCtx); + } + + GearsES2 gears = new GearsES2(1); + glad1.addGLEventListener(gears); + + Animator animator = new Animator(); + animator.add(glad1); + animator.add(glad2); + animator.start(); + + int s = 0; + long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + if( ( t1 - t0 ) / period > s) { + s++; + System.err.println(s+" - switch - START "+ ( t1 - t0 )); + animator.pause(); + + if(0 == s%2) { + glad1.addGLEventListener(0, glad2.removeGLEventListener(0)); + GLContext ctx1 = glad1.setContext(glad2.getContext()); + glad2.setContext(ctx1); + } else { + glad2.addGLEventListener(0, glad1.removeGLEventListener(0)); + GLContext ctx2 = glad2.setContext(glad1.getContext()); + glad1.setContext(ctx2); + } + + System.err.println(s+" - switch - END "+ ( t1 - t0 )); + + animator.resume(); + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + animator.stop(); + glad1.destroy(); + glad2.destroy(); + } + + @Test(timeout=30000) + public void testSwitch2GLWindowOneDemo() throws InterruptedException { + GearsES2 gears = new GearsES2(1); + final QuitAdapter quitAdapter = new QuitAdapter(); + + GLWindow glWindow1 = GLWindow.create(caps); + glWindow1.setTitle("win1"); + glWindow1.setSize(width, height); + glWindow1.setPosition(64, 64); + glWindow1.addGLEventListener(0, gears); + glWindow1.addWindowListener(quitAdapter); + + GLWindow glWindow2 = GLWindow.create(caps); + glWindow2.setTitle("win2"); + glWindow2.setSize(width+100, height+100); + glWindow2.setPosition(2*64+width, 64); + glWindow2.addWindowListener(quitAdapter); + + Animator animator = new Animator(); + animator.add(glWindow1); + animator.add(glWindow2); + animator.start(); + + glWindow1.setVisible(true); + glWindow2.setVisible(true); + + int s = 0; + long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + if( ( t1 - t0 ) / period > s) { + s++; + System.err.println(s+" - switch - START "+ ( t1 - t0 )); + animator.pause(); + + if(0 == s%2) { + glWindow1.addGLEventListener(0, glWindow2.removeGLEventListener(0)); + GLContext ctx1 = glWindow1.setContext(glWindow2.getContext()); + glWindow2.setContext(ctx1); + } else { + glWindow2.addGLEventListener(0, glWindow1.removeGLEventListener(0)); + GLContext ctx2 = glWindow2.setContext(glWindow1.getContext()); + glWindow1.setContext(ctx2); + } + + System.err.println(s+" - switch - END "+ ( t1 - t0 )); + + animator.resume(); + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + animator.stop(); + glWindow1.destroy(); + glWindow2.destroy(); + + } + + @Test(timeout=30000) + public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException { + GearsES2 gears = new GearsES2(1); + RedSquareES2 rsquare = new RedSquareES2(1); + final QuitAdapter quitAdapter = new QuitAdapter(); + + GLWindow glWindow1 = GLWindow.create(caps); + glWindow1.setTitle("win1"); + glWindow1.setSize(width, height); + glWindow1.setPosition(64, 64); + glWindow1.addGLEventListener(0, gears); + glWindow1.addWindowListener(quitAdapter); + + GLWindow glWindow2 = GLWindow.create(caps); + glWindow2.setTitle("win2"); + glWindow2.setSize(width+100, height+100); + glWindow2.setPosition(2*64+width, 64); + glWindow2.addGLEventListener(0, rsquare); + glWindow2.addWindowListener(quitAdapter); + + Animator animator = new Animator(); + animator.add(glWindow1); + animator.add(glWindow2); + animator.start(); + + glWindow1.setVisible(true); + glWindow2.setVisible(true); + + int s = 0; + long t0 = System.currentTimeMillis(); + long t1 = t0; + + while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) { + if( ( t1 - t0 ) / period > s) { + s++; + System.err.println(s+" - switch - START "+ ( t1 - t0 )); + animator.pause(); + + GLEventListener demo1 = glWindow1.removeGLEventListener(0); + GLEventListener demo2 = glWindow2.removeGLEventListener(0); + + GLContext ctx1 = glWindow1.setContext(glWindow2.getContext()); + glWindow1.addGLEventListener(0, demo2); + + glWindow2.setContext(ctx1); + glWindow2.addGLEventListener(0, demo1); + + System.err.println(s+" - switch - END "+ ( t1 - t0 )); + + animator.resume(); + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + animator.stop(); + glWindow1.destroy(); + glWindow2.destroy(); + + } + + // default timing for 2 switches + static long duration = 2200; // ms + static long period = 1000; // ms + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-period")) { + i++; + try { + period = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + /** + 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(TestGLContextDrawableSwitchNEWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index c6c34d05a..6aea5bb9c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -64,6 +64,7 @@ public class GearsES2 implements GLEventListener { private KeyListener gearsKeys = new GearsKeyAdapter(); private int prevMouseX, prevMouseY; + private boolean isInitialized = false; public GearsES2(int swapInterval) { this.swapInterval = swapInterval; @@ -100,6 +101,11 @@ public class GearsES2 implements GLEventListener { public void init(GLAutoDrawable drawable) { + if(isInitialized) { + System.err.println(Thread.currentThread()+" GearsES2.init skipped!"); + return; + } + isInitialized = true; System.err.println(Thread.currentThread()+" GearsES2.init ..."); GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -174,15 +180,15 @@ public class GearsES2 implements GLEventListener { } st.useProgram(gl, false); - gl.setSwapInterval(swapInterval); - System.err.println(Thread.currentThread()+" GearsES2.init FIN"); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - // System.err.println(Thread.currentThread()+" GearsES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); + System.err.println(Thread.currentThread()+" GearsES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + st.useProgram(gl, true); pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); pmvMatrix.glLoadIdentity(); @@ -206,6 +212,11 @@ public class GearsES2 implements GLEventListener { // private boolean useAndroidDebug = false; public void dispose(GLAutoDrawable drawable) { + if(!isInitialized) { + System.err.println(Thread.currentThread()+" GearsES2.dispose skipped!"); + return; + } + isInitialized = false; System.err.println(Thread.currentThread()+" GearsES2.dispose ... "); if (drawable.getNativeSurface() instanceof Window) { Window window = (Window) drawable.getNativeSurface(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java index 11f96ed77..6982d61b7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java @@ -55,6 +55,7 @@ public class RedSquareES2 implements GLEventListener { GLWindow glWindow = null; float aspect = 1.0f; boolean doRotate = true; + boolean isInitialized = false; public RedSquareES2(int swapInterval) { this.swapInterval = swapInterval; @@ -68,6 +69,11 @@ public class RedSquareES2 implements GLEventListener { public void setDoRotation(boolean rotate) { this.doRotate = rotate; } public void init(GLAutoDrawable glad) { + if(isInitialized) { + System.err.println(Thread.currentThread()+" RedSquareES2.init skipped!"); + return; + } + isInitialized = true; System.err.println(Thread.currentThread()+" RedSquareES2.init ..."); GL2ES2 gl = glad.getGL().getGL2ES2(); @@ -127,8 +133,6 @@ public class RedSquareES2 implements GLEventListener { gl.glEnable(GL2ES2.GL_DEPTH_TEST); st.useProgram(gl, false); - gl.setSwapInterval(swapInterval); - if (glad instanceof GLWindow) { glWindow = (GLWindow) glad; glWindow.addMouseListener(myMouse); @@ -167,6 +171,8 @@ public class RedSquareES2 implements GLEventListener { System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); GL2ES2 gl = glad.getGL().getGL2ES2(); + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + st.useProgram(gl, true); // Set location in front of camera pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); @@ -180,6 +186,11 @@ public class RedSquareES2 implements GLEventListener { } public void dispose(GLAutoDrawable glad) { + if(!isInitialized) { + System.err.println(Thread.currentThread()+" RedSquareES2.dispose skipped!"); + return; + } + isInitialized = false; System.err.println(Thread.currentThread()+" RedSquareES2.dispose ... "); if (null != glWindow) { glWindow.removeMouseListener(myMouse); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java index 41c69336c..4b02be873 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java @@ -102,7 +102,7 @@ public class TestParenting01cSwingAWT extends UITestCase { synchronized(this) { isRunning = true; this.notifyAll(); - System.out.println("$"); + System.err.println("$"); } while(!shallStop) { try { @@ -166,7 +166,7 @@ public class TestParenting01cSwingAWT extends UITestCase { jFrame1.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // equivalent to Frame, use windowClosing event! jFrame1.setContentPane(jPanel1); jFrame1.setSize(width, height); - System.out.println("Demos: 1 - Visible"); + System.err.println("Demos: 1 - Visible"); SwingUtilities.invokeAndWait(new Runnable() { public void run() { jFrame1.setVisible(true); @@ -181,27 +181,30 @@ public class TestParenting01cSwingAWT extends UITestCase { while(animator1.isAnimating() && animator1.getTotalFPSDuration()<durationPerTest) { Thread.sleep(100); } - System.out.println("Demos: 2 - StopAnimator"); + System.err.println("Demos: 2 - StopAnimator"); animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - System.out.println("Demos: 3 - !Visible"); + System.err.println("Demos: 3 - !Visible"); jFrame1.setVisible(false); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, false)); SwingUtilities.invokeAndWait(new Runnable() { public void run() { - System.out.println("Demos: 4 - Visible"); + System.err.println("Demos: 4 - Visible"); jFrame1.setVisible(true); } }); Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true)); + // Always recommended to remove our native parented Window + // from the AWT resources before destruction, since it could lead + // to a BadMatch X11 error w/o. SwingUtilities.invokeAndWait(new Runnable() { public void run() { - System.out.println("Demos: 5 - X Container"); + System.err.println("Demos: 5 - X Container"); jPanel1.remove(container1); jFrame1.validate(); } }); @@ -209,13 +212,17 @@ public class TestParenting01cSwingAWT extends UITestCase { SwingUtilities.invokeAndWait(new Runnable() { public void run() { + System.err.println("Demos: 6 - X Frame"); jFrame1.dispose(); } }); Assert.assertEquals(true, glWindow1.isNativeValid()); - disturbanceAction.stopAndWaitUntilDone(); + System.err.println("Demos: 7 - X GLWindow"); glWindow1.destroy(); Assert.assertEquals(false, glWindow1.isNativeValid()); + + System.err.println("Demos: 8 - X DisturbanceThread"); + disturbanceAction.stopAndWaitUntilDone(); } @Test @@ -344,24 +351,48 @@ public class TestParenting01cSwingAWT extends UITestCase { animator1.stop(); Assert.assertEquals(false, animator1.isAnimating()); - disturbanceAction.stopAndWaitUntilDone(); - + /* + * Always recommended to remove our native parented Window + * from the AWT resources before destruction, since it could lead + * to a BadMatch X11 error w/o (-> XAWT related). + * Or ensure old/new parent is visible, see below. + * SwingUtilities.invokeAndWait(new Runnable() { public void run() { + System.err.println("Demos: 1 - X Container 1"); + container1.remove(newtCanvasAWT); + jFrame1.validate(); + System.err.println("Demos: 1 - X Container 2"); + jPanel2.remove(newtCanvasAWT); + jFrame2.validate(); + } }); */ + /* + * Invisible X11 windows may also case BadMatch (-> XAWT related) + */ + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + System.err.println("Demos: 2 - !visible"); jFrame1.setVisible(false); + System.err.println("Demos: 3 - !visible"); jFrame2.setVisible(false); } }); Assert.assertEquals(true, glWindow1.isNativeValid()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { + System.err.println("Demos: 4 - X frame"); jFrame1.dispose(); + System.err.println("Demos: 5 - X frame"); jFrame2.dispose(); } }); Assert.assertEquals(true, glWindow1.isNativeValid()); + System.err.println("Demos: 6 - X GLWindow"); glWindow1.destroy(); Assert.assertEquals(false, glWindow1.isNativeValid()); + + System.err.println("Demos: 7 - X DisturbanceThread"); + disturbanceAction.stopAndWaitUntilDone(); } public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { @@ -393,8 +424,10 @@ public class TestParenting01cSwingAWT extends UITestCase { waitReparent = atoi(args[++i]); } } - System.out.println("durationPerTest "+durationPerTest); - System.out.println("waitReparent "+waitReparent); + System.err.println("durationPerTest "+durationPerTest); + System.err.println("waitReparent "+waitReparent); + org.junit.runner.JUnitCore.main(TestParenting01cSwingAWT.class.getName()); + /** String tstname = TestParenting01cSwingAWT.class.getName(); org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { tstname, @@ -406,7 +439,7 @@ public class TestParenting01cSwingAWT extends UITestCase { "logfailedtests=true", "logtestlistenerevents=true", "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", - "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); */ } } |