diff options
9 files changed, 427 insertions, 52 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index c0ca6c99e..bce9a6907 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -475,6 +475,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLException01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $* @@ -538,7 +539,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext12FPSAnimNEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch02NEWT $* -testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch02AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch02AWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch10NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NewtAWT $* diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 03c6d6929..c409bb253 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -205,10 +205,9 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS animatorPaused = false; } - if ( null != context ) { + GLException exceptionOnDisposeGL = null; + if( null != context ) { if( context.isCreated() ) { - // Catch dispose GLExceptions by GLEventListener, just 'print' them - // so we can continue with the destruction. try { if( !GLCanvas.this.isDisposed() ) { helper.disposeGL(GLCanvas.this, context, true); @@ -216,28 +215,50 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS context.destroy(); } } catch (final GLException gle) { - gle.printStackTrace(); + exceptionOnDisposeGL = gle; } } context = null; } - if ( null != drawable ) { - drawable.setRealized(false); + + Throwable exceptionOnUnrealize = null; + if( null != drawable ) { + try { + drawable.setRealized(false); + } catch( final Throwable re ) { + exceptionOnUnrealize = re; + } drawable = null; } - if( 0 != x11Window) { - SWTAccessor.destroyX11Window(screen.getDevice(), x11Window); - x11Window = 0; - } else if( 0 != gdkWindow) { - SWTAccessor.destroyGDKWindow(gdkWindow); - gdkWindow = 0; + + Throwable exceptionOnDeviceClose = null; + try { + if( 0 != x11Window) { + SWTAccessor.destroyX11Window(screen.getDevice(), x11Window); + x11Window = 0; + } else if( 0 != gdkWindow) { + SWTAccessor.destroyGDKWindow(gdkWindow); + gdkWindow = 0; + } + screen.getDevice().close(); + } catch (final Throwable re) { + exceptionOnDeviceClose = re; } - screen.getDevice().close(); if (animatorPaused) { animator.resume(); } + // throw exception in order of occurrence .. + if( null != exceptionOnDisposeGL ) { + throw exceptionOnDisposeGL; + } + if( null != exceptionOnUnrealize ) { + throw GLException.newGLException(exceptionOnUnrealize); + } + if( null != exceptionOnDeviceClose ) { + throw GLException.newGLException(exceptionOnDeviceClose); + } } finally { _lock.unlock(); } diff --git a/src/jogl/classes/javax/media/opengl/GLException.java b/src/jogl/classes/javax/media/opengl/GLException.java index 6a287c969..15e9cddac 100644 --- a/src/jogl/classes/javax/media/opengl/GLException.java +++ b/src/jogl/classes/javax/media/opengl/GLException.java @@ -41,7 +41,7 @@ package javax.media.opengl; /** A generic exception for OpenGL errors used throughout the binding as a substitute for {@link RuntimeException}. */ - +@SuppressWarnings("serial") public class GLException extends RuntimeException { /** Constructs a GLException object. */ public GLException() { @@ -65,4 +65,16 @@ public class GLException extends RuntimeException { public GLException(final Throwable cause) { super(cause); } + + /** Constructs a GLException object with the specified root + cause with a decorating message including the current thread name. */ + public static GLException newGLException(final Throwable t) { + return new GLException("Caught "+t.getClass().getSimpleName()+": "+t.getMessage()+" on thread "+Thread.currentThread().getName(), t); + } + + /** Dumps a Throwable in a decorating message including the current thread name, and stack trace. */ + public static void dumpThrowable(final Throwable t) { + System.err.println("Caught "+t.getClass().getSimpleName()+": "+t.getMessage()+" on thread "+Thread.currentThread().getName()); + t.printStackTrace(); + } } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 0599c1086..ca5cf0e45 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -1232,26 +1232,32 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing animatorPaused = false; } + GLException exceptionOnDisposeGL = null; + // OLS will be detached by disposeGL's context destruction below 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, true); if(DEBUG) { System.err.println(getThreadName()+": destroyOnEDTAction() - post ctx: "+context); } } catch (final GLException gle) { - gle.printStackTrace(); + exceptionOnDisposeGL = gle; } } context = null; } + + Throwable exceptionOnUnrealize = null; if( null != drawable ) { - drawable.setRealized(false); - if(DEBUG) { - System.err.println(getThreadName()+": destroyOnEDTAction() - post drawable: "+drawable); + try { + drawable.setRealized(false); + if(DEBUG) { + System.err.println(getThreadName()+": destroyOnEDTAction() - post drawable: "+drawable); + } + } catch( final Throwable re ) { + exceptionOnUnrealize = re; } drawable = null; } @@ -1260,6 +1266,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing animator.resume(); } + // throw exception in order of occurrence .. + if( null != exceptionOnDisposeGL ) { + throw exceptionOnDisposeGL; + } + if( null != exceptionOnUnrealize ) { + throw GLException.newGLException(exceptionOnUnrealize); + } + if(DEBUG) { System.err.println(getThreadName()+": dispose() - END, animator "+animator); } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 6e6bb1cad..d08839b7f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -1338,20 +1338,33 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if ( null != backend ) { final GLContext _context = backend.getContext(); final boolean backendDestroy = !backend.isUsingOwnLifecycle(); + + GLException exceptionOnDisposeGL = null; 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, !backendDestroy); } catch (final GLException gle) { - gle.printStackTrace(); + exceptionOnDisposeGL = gle; } } + Throwable exceptionBackendDestroy = null; if ( backendDestroy ) { - backend.destroy(); + try { + backend.destroy(); + } catch( final Throwable re ) { + exceptionBackendDestroy = re; + } backend = null; isInitialized = false; } + + // throw exception in order of occurrence .. + if( null != exceptionOnDisposeGL ) { + throw exceptionOnDisposeGL; + } + if( null != exceptionBackendDestroy ) { + throw GLException.newGLException(exceptionBackendDestroy); + } } } }; diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index 45240df29..016d07ed6 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -356,25 +356,48 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe preserveGLStateAtDestroy(false); preserveGLEventListenerState(); } + + GLException exceptionOnDisposeGL = null; 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, true); } catch (final GLException gle) { - gle.printStackTrace(); + exceptionOnDisposeGL = gle; } } context = null; } + + final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + Throwable exceptionOnUnrealize = null; if( null != drawable ) { - final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); - drawable.setRealized(false); + try { + drawable.setRealized(false); + } catch( final Throwable re ) { + exceptionOnUnrealize = re; + } drawable = null; + } + + Throwable exceptionOnDeviceClose = null; + try { if( ownsDevice ) { device.close(); } + } catch (final Throwable re) { + exceptionOnDeviceClose = re; + } + + // throw exception in order of occurrence .. + if( null != exceptionOnDisposeGL ) { + throw exceptionOnDisposeGL; + } + if( null != exceptionOnUnrealize ) { + throw GLException.newGLException(exceptionOnUnrealize); + } + if( null != exceptionOnDeviceClose ) { + throw GLException.newGLException(exceptionOnDeviceClose); } } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 7d05174ce..6462b801b 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -511,15 +511,24 @@ public class GLDrawableHelper { * </p> * @param autoDrawable * @return the disposal count + * @throws GLException caused by {@link GLEventListener#dispose(GLAutoDrawable)} */ - public final int disposeAllGLEventListener(final GLAutoDrawable autoDrawable, final boolean remove) { + public final int disposeAllGLEventListener(final GLAutoDrawable autoDrawable, final boolean remove) throws GLException { + Throwable firstCaught = null; int disposeCount = 0; synchronized(listenersLock) { if( remove ) { for (int count = listeners.size(); 0 < count && 0 < listeners.size(); count--) { final GLEventListener listener = listeners.remove(0); if( !listenersToBeInit.remove(listener) ) { - listener.dispose(autoDrawable); + try { + listener.dispose(autoDrawable); + } catch (final Throwable t) { + if( null == firstCaught ) { + firstCaught = t; + } + GLException.dumpThrowable(t); + } disposeCount++; } } @@ -527,13 +536,23 @@ public class GLDrawableHelper { for (int i = 0; i < listeners.size(); i++) { final GLEventListener listener = listeners.get(i); if( !listenersToBeInit.contains(listener) ) { - listener.dispose(autoDrawable); + try { + listener.dispose(autoDrawable); + } catch (final Throwable t) { + if( null == firstCaught ) { + firstCaught = t; + } + GLException.dumpThrowable(t); + } listenersToBeInit.add(listener); disposeCount++; } } } } + if( null != firstCaught ) { + throw GLException.newGLException(firstCaught); + } return disposeCount; } @@ -1048,8 +1067,7 @@ public class GLDrawableHelper { try { forceNativeRelease(context); } catch (final Throwable ex) { - ex.printStackTrace(); - throw new GLException(ex); + throw GLException.newGLException(ex); } } exclusiveContextThread = t; @@ -1105,8 +1123,8 @@ public class GLDrawableHelper { final Runnable initAction) { if(null==context) { if (DEBUG) { - final Exception e = new GLException(getThreadName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); - e.printStackTrace(); + final Exception e = new GLException("Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); + GLException.dumpThrowable(e); } return; } @@ -1131,9 +1149,11 @@ public class GLDrawableHelper { * @param autoDrawable * @param context * @param destroyContext destroy context in the end while holding the lock + * @throws GLException caused by {@link GLEventListener#dispose(GLAutoDrawable)} or context closing + * */ public final void disposeGL(final GLAutoDrawable autoDrawable, - final GLContext context, final boolean destroyContext) { + final GLContext context, final boolean destroyContext) throws GLException { // Support for recursive makeCurrent() calls as well as calling // other drawables' display() methods from within another one's GLContext lastContext = GLContext.getCurrent(); @@ -1148,15 +1168,22 @@ public class GLDrawableHelper { } } + GLException disposeCaught = null; + Throwable contextCloseCaught = null; + int res; try { res = context.makeCurrent(); if (GLContext.CONTEXT_NOT_CURRENT != res) { if(GLContext.CONTEXT_CURRENT_NEW == res) { - throw new GLException(getThreadName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); + throw new GLException(GLDrawableHelper.getThreadName()+" 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); + try { + disposeAllGLEventListener(autoDrawable, false); + } catch(final GLException t) { + disposeCaught = t; + } } } } finally { @@ -1167,9 +1194,9 @@ public class GLDrawableHelper { forceNativeRelease(context); } flushGLRunnables(); - } catch (final Exception e) { - System.err.println("Caught exception on thread "+getThreadName()); - e.printStackTrace(); + } catch (final Throwable t) { + GLException.dumpThrowable(t); + contextCloseCaught = t; } if (lastContext != null) { final int res2 = lastContext.makeCurrent(); @@ -1177,6 +1204,12 @@ public class GLDrawableHelper { lastInitAction.run(); } } + if( null != disposeCaught ) { + throw disposeCaught; + } + if( null != contextCloseCaught ) { + throw GLException.newGLException(contextCloseCaught); + } } } @@ -1186,6 +1219,9 @@ public class GLDrawableHelper { final Runnable initAction) { final Thread currentThread = Thread.currentThread(); + Throwable glEventListenerCaught = null; + Throwable contextReleaseCaught = null; + // Exclusive Cases: // 1: lock - unlock : default // 2: lock - - : exclusive, not locked yet @@ -1243,6 +1279,9 @@ public class GLDrawableHelper { if ( autoSwapBufferMode ) { drawable.swapBuffers(); } + } catch (final Throwable t) { + GLException.dumpThrowable(t); + glEventListenerCaught = t; } finally { if( _releaseExclusiveThread ) { exclusiveContextThread = null; @@ -1253,9 +1292,9 @@ public class GLDrawableHelper { if( releaseContext ) { try { context.release(); - } catch (final Exception e) { - System.err.println("Caught exception on thread "+getThreadName()); - e.printStackTrace(); + } catch (final Throwable t) { + GLException.dumpThrowable(t); + contextReleaseCaught = t; } } } @@ -1267,6 +1306,12 @@ public class GLDrawableHelper { lastInitAction.run(); } } + if( null != glEventListenerCaught ) { + throw GLException.newGLException(glEventListenerCaught); + } + if( null != contextReleaseCaught ) { + throw GLException.newGLException(contextReleaseCaught); + } } } @@ -1276,6 +1321,9 @@ public class GLDrawableHelper { final Runnable initAction) { final Thread currentThread = Thread.currentThread(); + Throwable glEventListenerCaught = null; + Throwable contextReleaseCaught = null; + // Exclusive Cases: // 1: lock - unlock : default // 2: lock - - : exclusive, not locked yet @@ -1347,6 +1395,9 @@ public class GLDrawableHelper { tdX = System.currentTimeMillis(); tdS = tdX - tdS; // swapBuffers } + } catch (final Throwable t) { + GLException.dumpThrowable(t); + glEventListenerCaught = t; } finally { if( _releaseExclusiveThread ) { exclusiveContextSwitch = 0; @@ -1359,9 +1410,9 @@ public class GLDrawableHelper { try { context.release(); ctxReleased = true; - } catch (final Exception e) { - System.err.println("Caught exception on thread "+getThreadName()); - e.printStackTrace(); + } catch (final Throwable t) { + GLException.dumpThrowable(t); + contextReleaseCaught = t; } } } @@ -1374,11 +1425,16 @@ public class GLDrawableHelper { lastInitAction.run(); } } + if( null != glEventListenerCaught ) { + throw GLException.newGLException(glEventListenerCaught); + } + if( null != contextReleaseCaught ) { + throw GLException.newGLException(contextReleaseCaught); + } } final long td = System.currentTimeMillis() - t0; System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed); } protected static String getThreadName() { return Thread.currentThread().getName(); } - } diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 2d0f8f70b..a779fed3b 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -322,10 +322,10 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { } } if(null != tFBO) { - throw new GLException("GLFBODrawableImpl.reset(..) FBObject.reset(..) exception", tFBO); + throw GLException.newGLException(tFBO); } if(null != tGL) { - throw new GLException("GLFBODrawableImpl.reset(..) GLContext.release() exception", tGL); + throw GLException.newGLException(tGL); } if(DEBUG) { System.err.println("GLFBODrawableImpl.reset(newSamples "+newSamples+"): END "+this); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java new file mode 100644 index 000000000..a2dca2dda --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java @@ -0,0 +1,235 @@ +/** + * Copyright 2011 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.util.concurrent.atomic.AtomicInteger; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLException01NEWT extends UITestCase { + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull(glp); + width = 512; + height = 512; + } + + public static void dumpThrowable(final Throwable t) { + System.err.println("User caught exception "+t.getClass().getSimpleName()+": "+t.getMessage()+" on thread "+Thread.currentThread().getName()); + t.printStackTrace(); + } + + protected void runTestGL(final GLCapabilities caps, final boolean onThread, + final boolean throwInInit, final boolean throwInDisplay, + final boolean throwInReshape, final boolean throwInDispose) throws InterruptedException { + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("NEWT Exception Test"); + final GearsES2 demo1 = new GearsES2(); + demo1.setVerbose(false); + glWindow.addGLEventListener(demo1); + final AtomicInteger initCount = new AtomicInteger(); + final AtomicInteger disposeCount = new AtomicInteger(); + final AtomicInteger displayCount = new AtomicInteger(); + final AtomicInteger reshapeCount = new AtomicInteger(); + final AtomicInteger exceptionSent = new AtomicInteger(); + + glWindow.addGLEventListener(new GLEventListener() { + @Override + public void init(final GLAutoDrawable drawable) { + if( throwInInit && 0 == exceptionSent.get() ) { + exceptionSent.incrementAndGet(); + throw new RuntimeException("Injected GLEventListener exception in init"); + } + } + @Override + public void dispose(final GLAutoDrawable drawable) { + if( throwInDispose && 0 == exceptionSent.get() ) { + exceptionSent.incrementAndGet(); + throw new RuntimeException("Injected GLEventListener exception in dispose"); + } + } + @Override + public void display(final GLAutoDrawable drawable) { + if( throwInDisplay && 0 == exceptionSent.get() ) { + exceptionSent.incrementAndGet(); + throw new RuntimeException("Injected GLEventListener exception in display"); + } + } + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + if( throwInReshape && 0 == exceptionSent.get() ) { + exceptionSent.incrementAndGet(); + throw new RuntimeException("Injected GLEventListener exception in reshape"); + } + } + }); + glWindow.addGLEventListener(new GLEventListener() { + @Override + public void init(final GLAutoDrawable drawable) { + initCount.incrementAndGet(); + } + @Override + public void dispose(final GLAutoDrawable drawable) { + disposeCount.incrementAndGet(); + } + @Override + public void display(final GLAutoDrawable drawable) { + displayCount.incrementAndGet(); + } + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + reshapeCount.incrementAndGet(); + } + }); + + RuntimeException execptionAtInitReshapeDisplay = null; + RuntimeException execptionAtDispose = null; + + final Animator animator = !onThread ? new Animator(glWindow) : null; + + glWindow.setSize(width, height); + + if( !onThread ) { + animator.setUpdateFPSFrames(1, null); + animator.start(); + } + try { + glWindow.setVisible(true); + } catch (final RuntimeException re) { + execptionAtInitReshapeDisplay = re; + dumpThrowable(re); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(0 == exceptionSent.get() && ( onThread || animator.isAnimating() ) && t1-t0<duration ) { + if( onThread ) { + try { + glWindow.display(); + } catch (final RuntimeException re) { + execptionAtInitReshapeDisplay = re; + dumpThrowable(re); + } + } + Thread.sleep(100); + t1 = System.currentTimeMillis(); + } + + if( !onThread ) { + animator.stop(); + } + try { + glWindow.destroy(); + } catch (final RuntimeException re) { + execptionAtDispose = re; + dumpThrowable(re); + } + + if( throwInInit || throwInReshape || throwInDisplay || throwInDispose ) { + Assert.assertEquals("Not one exception sent", 1, exceptionSent.get()); + if( throwInInit ) { + Assert.assertNotNull("No exception forwarded from init", execptionAtInitReshapeDisplay); + } + if( throwInReshape ) { + Assert.assertNotNull("No exception forwarded from reshape", execptionAtInitReshapeDisplay); + } + if( throwInDisplay ) { + Assert.assertNotNull("No exception forwarded from display", execptionAtInitReshapeDisplay); + } + if( throwInDispose ) { + Assert.assertNotNull("No exception forwarded from dispose", execptionAtDispose); + } + } + } + + @Test + public void test01OnThreadAtInit() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setBackgroundOpaque(true); // default + runTestGL(caps, true /* onThread */, true /* init */, false /* display */, false /* reshape */, false /* dispose */); + } + @Test + public void test02OnThreadAtReshape() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setBackgroundOpaque(true); // default + runTestGL(caps, true /* onThread */, false /* init */, false /* display */, true /* reshape */, false /* dispose */); + } + @Test + public void test03OnThreadAtDisplay() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setBackgroundOpaque(true); // default + runTestGL(caps, true /* onThread */, false /* init */, true /* display */, false /* reshape */, false /* dispose */); + } + @Test + public void test04OnThreadAtDispose() throws InterruptedException { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setBackgroundOpaque(true); // default + runTestGL(caps, true /* onThread */, false /* init */, false /* display */, false /* reshape */, true /* dispose */); + } + + static long duration = 500; // ms + + public static void main(final String args[]) { + boolean waitForKey = false; + + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + if( waitForKey ) { + UITestCase.waitForKey("main"); + } + org.junit.runner.JUnitCore.main(TestGLException01NEWT.class.getName()); + } +} |