diff options
author | Sven Gothel <[email protected]> | 2012-11-29 18:21:02 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-11-29 18:21:02 +0100 |
commit | 0bb202f2883e1eb82256140f13310046f7b13c62 (patch) | |
tree | 2c19c4f89717b63793ee4c1243f18c5b54773a6f | |
parent | 03d74338497130f8100272803cae475043d8ceee (diff) |
Bug628: Adding unit-test 'TestNewtCanvasSWTBug628ResizeDeadlock' exposing NewtCanvasSWT asyncExec(..) bug w/ native parenting
The unit test shows, that while using JOGL's SWT GLCanvas Display's asyncExec(..) works properly,
but w/ NewtCanvasSWT on Windows does not.
NewtCanvasSWT differs w/:
- Using native parenting [Newt GLWindow to SWT Canvas]
- Processing native events in own NEWT EDT, w/ own Windows dispatch hook [For the child GLWindow only]
4 files changed, 292 insertions, 9 deletions
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index f340af552..7a2946d31 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -54,9 +54,10 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestP REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn %* -scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock %* +scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 2d8f3e1a8..0669efb37 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -370,9 +370,10 @@ function testawtswt() { # #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $* #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $* -testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* +#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $* #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock $* +testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec $* # # newt.awt (testawt) diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java index 9c0762c12..834261d22 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java @@ -65,7 +65,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase { - static int duration = 1000; + static int duration = 500; static class BigFlashingX implements GLEventListener { @@ -262,7 +262,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase { shell = new Shell( display ); Assert.assertNotNull( shell ); shell.setLayout( new FillLayout() ); - composite = new Composite( shell, SWT.NONE ); + composite = new Composite( shell, SWT.NO_BACKGROUND ); composite.setLayout( new FillLayout() ); Assert.assertNotNull( composite ); }}); @@ -301,10 +301,9 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase { dsc.init(); final GLWindow glWindow; - final NewtCanvasSWT canvas; { final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ; - GLCapabilities caps = new GLCapabilities( gl2Profile ) ; + final GLCapabilities caps = new GLCapabilities( gl2Profile ) ; glWindow = GLWindow.create( caps ) ; glWindow.addGLEventListener( new BigFlashingX() ) ; glWindow.addKeyListener(new KeyAdapter() { @@ -314,7 +313,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase { glWindow.display(); } }); - canvas = NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ; + NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ; } dsc.display.syncExec( new Runnable() { @@ -374,8 +373,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase { Assert.assertTrue("Deadlock @ dispatch: "+e0, false); } - System.err.println("NewtCanvasAWT Dispose"); - canvas.dispose(); + // canvas is disposed implicit, due to it's disposed listener ! dsc.dispose(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java new file mode 100644 index 000000000..ccea76c02 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java @@ -0,0 +1,283 @@ +/** + * Copyright 2012 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.swt; + +import java.awt.AWTException; +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.swt.SWT ; + +import org.eclipse.swt.layout.FillLayout ; + +import org.eclipse.swt.widgets.Composite ; +import org.eclipse.swt.widgets.Display ; +import org.eclipse.swt.widgets.Shell ; +import org.junit.Assume; +import org.junit.Test; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities ; +import javax.media.opengl.GLProfile; + +import junit.framework.Assert; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.opengl.GLWindow ; +import com.jogamp.newt.swt.NewtCanvasSWT ; +import com.jogamp.opengl.swt.GLCanvas; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +//////////////////////////////////////////////////////////////////////////////// + + +public class TestSWTBug643AsyncExec extends UITestCase { + + static int duration = 500; + + //////////////////////////////////////////////////////////////////////////////// + + static void resetAsyncExecCount() { + synchronized(asyncExecCountSync) { + asyncExecCount=0; + } + } + static int incrAsyncExecCount() { + synchronized(asyncExecCountSync) { + asyncExecCount++; + return asyncExecCount; + } + } + static int getAsyncExecCount() { + synchronized(asyncExecCountSync) { + return asyncExecCount; + } + } + static Object asyncExecCountSync = new Object(); + static int asyncExecCount = 0; + + //////////////////////////////////////////////////////////////////////////////// + + static class AsyncExecFeederThread extends Thread { + volatile boolean shallStop = false; + private Display display ; + private int n ; + + public AsyncExecFeederThread( Display display ) + { + super(); + this.display = display ; + } + + final Runnable asyncAction = new Runnable() { + public void run() + { + ++n ; + System.err.println("[A-i shallStop "+shallStop+", disposed "+display.isDisposed()+"]: Counter[loc "+n+", glob: "+incrAsyncExecCount()+"]"); + } }; + + public void run() + { + System.err.println("[A-0 shallStop "+shallStop+", disposed "+display.isDisposed()+"]"); + + // final Display d = Display.getDefault(); + final Display d = this.display; + + while( !shallStop && !d.isDisposed() ) + { + try + { + System.err.println("[A-n shallStop "+shallStop+", disposed "+d.isDisposed()+"]"); + d.asyncExec( asyncAction ); + d.wake(); + + Thread.sleep( 50L ) ; + } catch( InterruptedException e ) { + break ; + } + } + System.err.println("*R-Exit* shallStop "+shallStop+", disposed "+d.isDisposed()); + } + } + + //////////////////////////////////////////////////////////////////////////////// + + private volatile boolean shallStop = false; + + static class SWT_DSC { + Display display; + Shell shell; + Composite composite; + + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + }}); + + display.syncExec(new Runnable() { + public void run() { + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NO_BACKGROUND ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + } + + public void dispose() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + display.syncExec(new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + }}); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite = null; + } + } + + private void testImpl(boolean useJOGLGLCanvas, boolean useNewtCanvasSWT) throws InterruptedException, AWTException, InvocationTargetException { + resetAsyncExecCount(); + + final SWT_DSC dsc = new SWT_DSC(); + dsc.init(); + + { + final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ; + final GLCapabilities caps = new GLCapabilities( gl2Profile ) ; + + final GLAutoDrawable glad; + if( useJOGLGLCanvas ) { + glad = GLCanvas.create(dsc.composite, 0, caps, null, null); + } else if( useNewtCanvasSWT ) { + final GLWindow glWindow = GLWindow.create( caps ) ; + glad = glWindow; + NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ; + } else { + throw new InternalError("XXX"); + } + glad.addGLEventListener( new GearsES2() ) ; + } + + dsc.display.syncExec( new Runnable() { + public void run() { + dsc.shell.setText( "NewtCanvasSWT Resize Bug Demo" ) ; + dsc.shell.setSize( 400, 450 ) ; + dsc.shell.open() ; + } } ); + + shallStop = false; + + final int[] ayncExecCountBeforeExit = new int[] { 0 }; + + final AsyncExecFeederThread asyncExecFeeder; + { + asyncExecFeeder = new AsyncExecFeederThread( dsc.display) ; + asyncExecFeeder.start() ; + } + + { + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(duration); + } catch (InterruptedException e) {} + + ayncExecCountBeforeExit[0] = getAsyncExecCount(); + asyncExecFeeder.shallStop = true; + try + { + asyncExecFeeder.join(); + } catch( InterruptedException e ) { } + shallStop = true; + dsc.display.wake(); + } } ).start(); + } + + try { + final Display d = dsc.display; + while( !shallStop && !d.isDisposed() ) { + final boolean r = d.readAndDispatch(); + System.err.print(","); + if( !r ) { + dsc.display.sleep(); + } + } + } catch (Exception e0) { + e0.printStackTrace(); + Assert.assertTrue("Deadlock @ dispatch: "+e0, false); + } + + // canvas is disposed implicit, due to it's disposed listener ! + + dsc.dispose(); + + System.err.println("AsyncExecCount before exit: " + ayncExecCountBeforeExit[0]); + Assert.assertTrue("AsyncExecCount not greater zero before dispose!", 0 < ayncExecCountBeforeExit[0]); + } + + @Test + public void test01JOGLGLCanvas() throws InterruptedException, AWTException, InvocationTargetException { + testImpl(true /* useJOGLGLCanvas */, false /* useNewtCanvasSWT */); + } + + @Test + public void test02NewtCanvasSWT() throws InterruptedException, AWTException, InvocationTargetException { + testImpl(false /* useJOGLGLCanvas */, true /* useNewtCanvasSWT */); + } + + public static void main( String[] args ) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + duration = MiscUtils.atoi(args[++i], duration); + } + } + System.out.println("durationPerTest: "+duration); + org.junit.runner.JUnitCore.main(TestSWTBug643AsyncExec.class.getName()); + } + +} |