aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java5
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java12
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/Animator.java29
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java76
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java11
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java72
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAnimatorControl.java52
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawable.java17
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDrawable.java1
-rw-r--r--src/jogl/classes/javax/media/opengl/GLException.java10
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java5
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java13
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java23
-rw-r--r--src/jogl/classes/jogamp/opengl/GLRunnableTask.java2
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java259
17 files changed, 502 insertions, 104 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index c409bb253..e33ceeefb 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -789,6 +789,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextS
}
@Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
public void setAnimator(final GLAnimatorControl arg0) throws GLException {
helper.setAnimator(arg0);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
index 496fb88c0..62df3faca 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
@@ -41,12 +41,14 @@ import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+
import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
-
import javax.media.opengl.GLAutoDrawable;
+import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException;
+
/** Abstraction to factor out AWT dependencies from the Animator's
implementation in a way that still allows the FPSAnimator to pick
up this behavior if desired. */
@@ -61,7 +63,7 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
@Override
public void display(final ArrayList<GLAutoDrawable> drawables,
final boolean ignoreExceptions,
- final boolean printExceptions) {
+ final boolean printExceptions) throws UncaughtAnimatorException {
for (int i=0; i<drawables.size(); i++) {
final GLAutoDrawable drawable = drawables.get(i);
if (drawable instanceof JComponent) {
@@ -73,13 +75,13 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
} else {
try {
drawable.display();
- } catch (final RuntimeException e) {
+ } catch (final Throwable t) {
if (ignoreExceptions) {
if (printExceptions) {
- e.printStackTrace();
+ t.printStackTrace();
}
} else {
- throw(e);
+ throw new UncaughtAnimatorException(drawable, t);
}
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
index 634e83353..d9a957199 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
@@ -132,7 +132,7 @@ public class Animator extends AnimatorBase {
@Override
public void run() {
- GLException displayCaught = null;
+ UncaughtAnimatorException displayCaught = null;
try {
synchronized (Animator.this) {
@@ -161,9 +161,9 @@ public class Animator extends AnimatorBase {
ectCleared = true;
setDrawablesExclCtxState(false);
try {
- display(); // propagate exclusive change!
- } catch (final Throwable t) {
- displayCaught = GLException.newGLException(t);
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ displayCaught = dre;
stopIssued = true;
isAnimating = false;
break; // end pause loop
@@ -189,15 +189,15 @@ public class Animator extends AnimatorBase {
// Resume from pause or drawablesEmpty,
// implies !pauseIssued and !drawablesEmpty
isAnimating = true;
- setDrawablesExclCtxState(exclusiveContext);
+ setDrawablesExclCtxState(exclusiveContext); // may re-enable exclusive context
Animator.this.notifyAll();
}
} // sync Animator.this
if (!stopIssued) {
try {
display();
- } catch (final Throwable t) {
- displayCaught = GLException.newGLException(t);
+ } catch (final UncaughtAnimatorException dre) {
+ displayCaught = dre;
stopIssued = true;
isAnimating = false;
break; // end animation loop
@@ -216,14 +216,13 @@ public class Animator extends AnimatorBase {
} finally {
if( exclusiveContext && !drawablesEmpty ) {
setDrawablesExclCtxState(false);
- display(); // propagate exclusive change!
try {
- display(); // propagate exclusive change!
- } catch (final Throwable t) {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
if( null == displayCaught ) {
- displayCaught = GLException.newGLException(t);
+ displayCaught = dre;
} else {
- GLException.newGLException(t).printStackTrace();
+ dre.printStackTrace();
}
}
}
@@ -237,12 +236,12 @@ public class Animator extends AnimatorBase {
}
stopIssued = false;
pauseIssued = false;
- animThread = null;
isAnimating = false;
- Animator.this.notifyAll();
if( null != displayCaught ) {
- throw displayCaught;
+ handleUncaughtException(displayCaught);
}
+ animThread = null;
+ Animator.this.notifyAll();
}
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
index a5bdb9350..ed23a78ba 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
@@ -67,8 +67,25 @@ public abstract class AnimatorBase implements GLAnimatorControl {
*/
public static final int MODE_EXPECT_AWT_RENDERING_THREAD = 1 << 0;
- public interface AnimatorImpl {
- void display(ArrayList<GLAutoDrawable> drawables, boolean ignoreExceptions, boolean printExceptions);
+
+ @SuppressWarnings("serial")
+ public static class UncaughtAnimatorException extends RuntimeException {
+ final GLAutoDrawable drawable;
+ public UncaughtAnimatorException(final GLAutoDrawable drawable, final Throwable cause) {
+ super(cause);
+ this.drawable = drawable;
+ }
+ public final GLAutoDrawable getGLAutoDrawable() { return drawable; }
+ }
+
+ public static interface AnimatorImpl {
+ /**
+ * @param drawables
+ * @param ignoreExceptions
+ * @param printExceptions
+ * @throws UncaughtAnimatorException as caused by {@link GLAutoDrawable#display()}
+ */
+ void display(ArrayList<GLAutoDrawable> drawables, boolean ignoreExceptions, boolean printExceptions) throws UncaughtAnimatorException;
boolean blockUntilDone(Thread thread);
}
@@ -83,6 +100,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
protected boolean printExceptions;
protected boolean exclusiveContext;
protected Thread userExclusiveContextThread;
+ protected UncaughtGLAnimatorExceptionHandler uncaughtExceptionHandler;
protected FPSCounterImpl fpsCounter = new FPSCounterImpl();
private final static Class<?> awtAnimatorImplClazz;
@@ -313,11 +331,16 @@ public abstract class AnimatorBase implements GLAnimatorControl {
}
}
final Thread dECT = enable ? ( null != _exclusiveContextThread ? _exclusiveContextThread : animThread ) : null ;
+ UncaughtAnimatorException displayCaught = null;
if( propagateState ) {
setDrawablesExclCtxState(enable);
if( !enable ) {
if( Thread.currentThread() == getThread() || Thread.currentThread() == _exclusiveContextThread ) {
- display();
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ displayCaught = dre;
+ }
} else {
final boolean resumed = isAnimating() ? false : resume();
int counter = 10;
@@ -338,6 +361,13 @@ public abstract class AnimatorBase implements GLAnimatorControl {
}
if(DEBUG) {
System.err.println("AnimatorBase.setExclusiveContextThread: all-GLAD Ok: "+validateDrawablesExclCtxState(dECT)+", "+this);
+ if( null != displayCaught ) {
+ System.err.println("AnimatorBase.setExclusiveContextThread: caught: "+displayCaught.getMessage());
+ displayCaught.printStackTrace();
+ }
+ }
+ if( null != displayCaught ) {
+ throw displayCaught;
}
return oldExclusiveContext;
}
@@ -412,7 +442,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
this to get the most optimized painting behavior for the set of
components this Animator manages, in particular when multiple
lightweight widgets are continually being redrawn. */
- protected final void display() {
+ protected final void display() throws UncaughtAnimatorException {
impl.display(drawables, ignoreExceptions, printExceptions);
fpsCounter.tickFPS();
}
@@ -482,7 +512,43 @@ public abstract class AnimatorBase implements GLAnimatorControl {
this.printExceptions = printExceptions;
}
- protected interface Condition {
+ @Override
+ public final UncaughtGLAnimatorExceptionHandler getUncaughtExceptionHandler() {
+ return uncaughtExceptionHandler;
+ }
+
+ @Override
+ public final void setUncaughtExceptionHandler(final UncaughtGLAnimatorExceptionHandler handler) {
+ uncaughtExceptionHandler = handler;
+ }
+
+ /**
+ * Should be called in case of an uncaught exception
+ * from within the animator thread to flush all animator
+ */
+ protected final synchronized void handleUncaughtException(final UncaughtAnimatorException ue) {
+ if( null != uncaughtExceptionHandler ) {
+ try {
+ uncaughtExceptionHandler.uncaughtException(this, ue.getGLAutoDrawable(), ue.getCause());
+ } catch (final Throwable t) { /* ignore intentionally */ }
+ flushGLRunnables();
+ } else {
+ flushGLRunnables();
+ throw ue;
+ }
+ }
+
+ /**
+ * Should be called in case of an uncaught exception
+ * from within the animator thread to flush all animator
+ */
+ protected final synchronized void flushGLRunnables() {
+ for (int i=0; i<drawables.size(); i++) {
+ drawables.get(i).flushGLRunnables();
+ }
+ }
+
+ protected static interface Condition {
/**
* @return true if branching (continue waiting, action), otherwise false
*/
diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
index 7fa4011f8..6b1485a6a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
@@ -34,8 +34,11 @@
package com.jogamp.opengl.util;
import java.util.ArrayList;
+
import javax.media.opengl.GLAutoDrawable;
+import com.jogamp.opengl.util.AnimatorBase.UncaughtAnimatorException;
+
/** Abstraction to factor out AWT dependencies from the Animator's
implementation in a way that still allows the FPSAnimator to pick
up this behavior if desired. */
@@ -44,18 +47,18 @@ class DefaultAnimatorImpl implements AnimatorBase.AnimatorImpl {
@Override
public void display(final ArrayList<GLAutoDrawable> drawables,
final boolean ignoreExceptions,
- final boolean printExceptions) {
+ final boolean printExceptions) throws UncaughtAnimatorException {
for (int i=0; i<drawables.size(); i++) {
final GLAutoDrawable drawable = drawables.get(i);
try {
drawable.display();
- } catch (final RuntimeException e) {
+ } catch (final Throwable t) {
if (ignoreExceptions) {
if (printExceptions) {
- e.printStackTrace();
+ t.printStackTrace();
}
} else {
- throw(e);
+ throw new UncaughtAnimatorException(drawable, t);
}
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
index 746b642c2..9ae880414 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
@@ -148,6 +148,8 @@ public class FPSAnimator extends AnimatorBase {
@Override
public void run() {
+ UncaughtAnimatorException displayCaught = null;
+
if( justStarted ) {
justStarted = false;
synchronized (FPSAnimator.this) {
@@ -160,7 +162,7 @@ public class FPSAnimator extends AnimatorBase {
shouldRun = false; // isAnimating:=false @ pause below
} else {
shouldRun = true;
- setDrawablesExclCtxState(exclusiveContext);
+ setDrawablesExclCtxState(exclusiveContext); // may re-enable exclusive context
FPSAnimator.this.notifyAll();
}
if(DEBUG) {
@@ -168,46 +170,76 @@ public class FPSAnimator extends AnimatorBase {
}
}
}
- if( shouldRun ) {
- display();
- } else if( shouldStop ) { // STOP
+ if( shouldRun && !shouldStop ) { // RUN
+ try {
+ display();
+ } catch (final UncaughtAnimatorException dre) {
+ displayCaught = dre;
+ shouldRun = false;
+ shouldStop = true;
+ }
+ } else if( !shouldRun && !shouldStop ) { // PAUSE
if(DEBUG) {
- System.err.println("FPSAnimator P4: "+alreadyStopped+", "+ Thread.currentThread() + ": " + toString());
+ System.err.println("FPSAnimator pausing: "+alreadyPaused+", "+ Thread.currentThread() + ": " + toString());
}
this.cancel();
- if( !alreadyStopped ) {
- alreadyStopped = true;
+ if( !alreadyPaused ) { // PAUSE
+ alreadyPaused = true;
if( exclusiveContext && !drawablesEmpty ) {
setDrawablesExclCtxState(false);
- display(); // propagate exclusive change!
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ displayCaught = dre;
+ shouldRun = false;
+ shouldStop = true;
+ }
}
- synchronized (FPSAnimator.this) {
- if(DEBUG) {
- System.err.println("FPSAnimator stop " + Thread.currentThread() + ": " + toString());
+ if( null == displayCaught ) {
+ synchronized (FPSAnimator.this) {
+ if(DEBUG) {
+ System.err.println("FPSAnimator pause " + Thread.currentThread() + ": " + toString());
+ }
+ isAnimating = false;
+ FPSAnimator.this.notifyAll();
}
- animThread = null;
- isAnimating = false;
- FPSAnimator.this.notifyAll();
}
}
- } else {
+ }
+ if( shouldStop ) { // STOP
if(DEBUG) {
- System.err.println("FPSAnimator P5: "+alreadyPaused+", "+ Thread.currentThread() + ": " + toString());
+ System.err.println("FPSAnimator stopping: "+alreadyStopped+", "+ Thread.currentThread() + ": " + toString());
}
this.cancel();
- if( !alreadyPaused ) { // PAUSE
- alreadyPaused = true;
+ if( !alreadyStopped ) {
+ alreadyStopped = true;
if( exclusiveContext && !drawablesEmpty ) {
setDrawablesExclCtxState(false);
- display(); // propagate exclusive change!
+ try {
+ display(); // propagate exclusive context -> off!
+ } catch (final UncaughtAnimatorException dre) {
+ if( null == displayCaught ) {
+ displayCaught = dre;
+ } else {
+ dre.printStackTrace();
+ }
+ }
}
synchronized (FPSAnimator.this) {
if(DEBUG) {
- System.err.println("FPSAnimator pause " + Thread.currentThread() + ": " + toString());
+ System.err.println("FPSAnimator stop " + Thread.currentThread() + ": " + toString());
+ if( null != displayCaught ) {
+ System.err.println("AnimatorBase.setExclusiveContextThread: caught: "+displayCaught.getMessage());
+ displayCaught.printStackTrace();
+ }
}
isAnimating = false;
+ if( null != displayCaught ) {
+ handleUncaughtException(displayCaught);
+ }
+ animThread = null;
FPSAnimator.this.notifyAll();
}
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
index 827145654..50f7e9bbb 100644
--- a/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
+++ b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
@@ -33,6 +33,38 @@ package javax.media.opengl;
* which implementation may drive a {@link javax.media.opengl.GLAutoDrawable} animation.
*/
public interface GLAnimatorControl extends FPSCounter {
+ /**
+ * A {@link GLAnimatorControl#setUncaughtExceptionHandler(UncaughtGLAnimatorExceptionHandler) registered}
+ * {@link UncaughtGLAnimatorExceptionHandler} instance is invoked when an {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * @see #uncaughtException(GLAnimatorControl, GLAutoDrawable, Throwable)
+ * @see GLAnimatorControl#setUncaughtExceptionHandler(UncaughtGLAnimatorExceptionHandler)
+ * @since 2.2
+ */
+ public static interface UncaughtGLAnimatorExceptionHandler {
+ /**
+ * Method invoked when the given {@link GLAnimatorControl} is {@link GLAnimatorControl#stop() stopped} due to the
+ * given uncaught exception happened on the given {@link GLAutoDrawable}.
+ * <p>
+ * The animator thread can still be retrieved via {@link GLAnimatorControl#getThread()}.
+ * </p>
+ * <p>
+ * All {@link GLAnimatorControl} states already reflect its stopped state.
+ * </p>
+ * <p>
+ * After this handler method is called, the {@link GLAnimatorControl} is stopped.
+ * </p>
+ * <p>
+ * Any exception thrown by this method will be ignored.
+ * </p>
+ * @param animator the {@link GLAnimatorControl}
+ * @param drawable the causing {@link GLAutoDrawable}
+ * @param cause the uncaught exception
+ * @see GLAnimatorControl#setUncaughtExceptionHandler(UncaughtGLAnimatorExceptionHandler)
+ * @since 2.2
+ */
+ void uncaughtException(final GLAnimatorControl animator, final GLAutoDrawable drawable, final Throwable cause);
+ }
/**
* Indicates whether this animator has been {@link #start() started}.
@@ -181,4 +213,24 @@ public interface GLAnimatorControl extends FPSCounter {
* @throws IllegalArgumentException if drawable was not added to this animator
*/
void remove(GLAutoDrawable drawable);
+
+ /**
+ * Returns the {@link UncaughtGLAnimatorExceptionHandler} invoked when this {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * <p>
+ * Default is <code>null</code>.
+ * </p>
+ * @since 2.2
+ */
+ UncaughtGLAnimatorExceptionHandler getUncaughtExceptionHandler();
+
+ /**
+ * Set the handler invoked when this {@link GLAnimatorControl animator} abruptly {@link #stop() stops}
+ * due to an uncaught exception from one of its {@link GLAutoDrawable}s.
+ * @param handler the {@link UncaughtGLAnimatorExceptionHandler} to use as this {@link GLAnimatorControl animator}'s uncaught exception
+ * handler. Pass <code>null</code> to unset the handler.
+ * @see UncaughtGLAnimatorExceptionHandler#uncaughtException(GLAnimatorControl, GLAutoDrawable, Throwable)
+ * @since 2.2
+ */
+ void setUncaughtExceptionHandler(final UncaughtGLAnimatorExceptionHandler handler);
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 5745e197f..bded88d20 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -229,6 +229,7 @@ public interface GLAutoDrawable extends GLDrawable {
/**
* Returns true if all added {@link GLEventListener} are initialized, otherwise false.
+ * @since 2.2
*/
boolean areAllGLEventListenerInitialized();
@@ -458,6 +459,7 @@ public interface GLAutoDrawable extends GLDrawable {
* @see #display()
* @see GLRunnable
* @see #invoke(boolean, List)
+ * @see #flushGLRunnables()
*/
public boolean invoke(boolean wait, GLRunnable glRunnable) throws IllegalStateException ;
@@ -469,9 +471,22 @@ public interface GLAutoDrawable extends GLDrawable {
* @return <code>true</code> if the {@link GLRunnable}s has been processed or queued, otherwise <code>false</code>.
* @throws IllegalStateException in case of a detected deadlock situation ahead, see {@link #invoke(boolean, GLRunnable)}.
* @see #invoke(boolean, GLRunnable)
+ * @see #flushGLRunnables()
*/
public boolean invoke(boolean wait, List<GLRunnable> glRunnables) throws IllegalStateException;
+ /**
+ * Flushes all {@link #invoke(boolean, GLRunnable) enqueued} {@link GLRunnable} of this {@link GLAutoDrawable}
+ * including notifying waiting executor.
+ * <p>
+ * The executor which might have been blocked until notified
+ * will be unblocked and all tasks removed from the queue.
+ * </p>
+ * @see #invoke(boolean, GLRunnable)
+ * @since 2.2
+ */
+ public void flushGLRunnables();
+
/** Destroys all resources associated with this GLAutoDrawable,
inclusive the GLContext.
If a window is attached to it's implementation, it shall be closed.
@@ -602,6 +617,7 @@ public interface GLAutoDrawable extends GLDrawable {
* <p>
* See <a href="#locking">GLAutoDrawable Locking</a>.
* </p>
+ * @since 2.2
*/
public RecursiveLock getUpstreamLock();
@@ -613,6 +629,7 @@ public interface GLAutoDrawable extends GLDrawable {
* whether {@link #display()} performs the OpenGL commands on the current thread directly
* or spawns them on the dedicated OpenGL thread.
* </p>
+ * @since 2.2
*/
public boolean isThreadGLCapable();
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java
index ac8644640..7ed057ea4 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java
@@ -201,6 +201,7 @@ public interface GLDrawable extends NativeSurfaceHolder {
</p>
@return The immutable queried instance.
@see #getChosenGLCapabilities()
+ @since 2.2
*/
public GLCapabilitiesImmutable getRequestedGLCapabilities();
diff --git a/src/jogl/classes/javax/media/opengl/GLException.java b/src/jogl/classes/javax/media/opengl/GLException.java
index dff9b9dad..3f76a6299 100644
--- a/src/jogl/classes/javax/media/opengl/GLException.java
+++ b/src/jogl/classes/javax/media/opengl/GLException.java
@@ -69,14 +69,18 @@ public class GLException extends RuntimeException {
/**
* Constructs a GLException object with the specified root
* cause with a decorating message including the current thread name.
+ * @since 2.2
*/
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());
+ /**
+ * Dumps a Throwable in a decorating message including the current thread name, and stack trace.
+ * @since 2.2
+ */
+ public static void dumpThrowable(final String additionalDescr, final Throwable t) {
+ System.err.println("Caught "+additionalDescr+" "+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 ca5cf0e45..dba1dbc04 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -1059,6 +1059,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
final RecursiveLock _lock = lock;
_lock.lock();
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index d08839b7f..1682c6d2a 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -958,6 +958,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
public GLContext createContext(final GLContext shareWith) {
final Backend b = backend;
if ( null == b ) {
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index e1cd59a04..6e6aaf58d 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -279,7 +279,13 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
shallClose = true;
}
if( shallClose ) {
- destroyAvoidAwareOfLocking();
+ try {
+ destroyAvoidAwareOfLocking();
+ } catch( final Throwable t ) {
+ // Intentionally catch and ignore exception,
+ // so the destroy mechanism of the native windowing system is not corrupted!
+ GLException.dumpThrowable("ignored", t);
+ }
}
}
@@ -602,6 +608,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
}
@Override
+ public void flushGLRunnables() {
+ helper.flushGLRunnables();
+ }
+
+ @Override
public final void setAutoSwapBufferMode(final boolean enable) {
helper.setAutoSwapBufferMode(enable);
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 945ca5479..f91e1bdba 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -526,8 +526,9 @@ public class GLDrawableHelper {
} catch (final Throwable t) {
if( null == firstCaught ) {
firstCaught = t;
+ } else {
+ GLException.dumpThrowable("subsequent", t);
}
- GLException.dumpThrowable(t);
}
disposeCount++;
}
@@ -541,8 +542,9 @@ public class GLDrawableHelper {
} catch (final Throwable t) {
if( null == firstCaught ) {
firstCaught = t;
+ } else {
+ GLException.dumpThrowable("subsequent", t);
}
- GLException.dumpThrowable(t);
}
listenersToBeInit.add(listener);
disposeCount++;
@@ -1125,8 +1127,7 @@ public class GLDrawableHelper {
final Runnable initAction) {
if(null==context) {
if (DEBUG) {
- final Exception e = new GLException("Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext");
- GLException.dumpThrowable(e);
+ GLException.dumpThrowable("informal", new GLException("Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"));
}
return;
}
@@ -1196,7 +1197,6 @@ public class GLDrawableHelper {
forceNativeRelease(context);
}
} catch (final Throwable t) {
- GLException.dumpThrowable(t);
contextCloseCaught = t;
}
flushGLRunnables(); // always flush GLRunnables at dispose
@@ -1208,6 +1208,9 @@ public class GLDrawableHelper {
}
}
if( null != disposeCaught ) {
+ if( null != contextCloseCaught ) {
+ GLException.dumpThrowable("subsequent", contextCloseCaught);
+ }
throw disposeCaught;
}
if( null != contextCloseCaught ) {
@@ -1283,7 +1286,6 @@ public class GLDrawableHelper {
drawable.swapBuffers();
}
} catch (final Throwable t) {
- GLException.dumpThrowable(t);
glEventListenerCaught = t;
} finally {
if( _releaseExclusiveThread ) {
@@ -1296,7 +1298,6 @@ public class GLDrawableHelper {
try {
context.release();
} catch (final Throwable t) {
- GLException.dumpThrowable(t);
contextReleaseCaught = t;
}
}
@@ -1311,6 +1312,9 @@ public class GLDrawableHelper {
}
if( null != glEventListenerCaught ) {
flushGLRunnables();
+ if( null != contextReleaseCaught ) {
+ GLException.dumpThrowable("subsequent", contextReleaseCaught);
+ }
throw GLException.newGLException(glEventListenerCaught);
}
if( null != contextReleaseCaught ) {
@@ -1401,7 +1405,6 @@ public class GLDrawableHelper {
tdS = tdX - tdS; // swapBuffers
}
} catch (final Throwable t) {
- GLException.dumpThrowable(t);
glEventListenerCaught = t;
} finally {
if( _releaseExclusiveThread ) {
@@ -1416,7 +1419,6 @@ public class GLDrawableHelper {
context.release();
ctxReleased = true;
} catch (final Throwable t) {
- GLException.dumpThrowable(t);
contextReleaseCaught = t;
}
}
@@ -1432,6 +1434,9 @@ public class GLDrawableHelper {
}
if( null != glEventListenerCaught ) {
flushGLRunnables();
+ if( null != contextReleaseCaught ) {
+ GLException.dumpThrowable("subsequent", contextReleaseCaught);
+ }
throw GLException.newGLException(glEventListenerCaught);
}
if( null != contextReleaseCaught ) {
diff --git a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
index 0ceef6bf7..ca1c1869e 100644
--- a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
+++ b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
@@ -90,8 +90,10 @@ public class GLRunnableTask implements GLRunnable {
/**
* Simply flush this task and notify a waiting executor.
+ * <p>
* The executor which might have been blocked until notified
* will be unblocked and the task removed from the queue.
+ * </p>
*
* @see #isFlushed()
* @see #isInQueue()
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index ca6ffa18b..b62628962 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -1104,6 +1104,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=lifecycleHook) {
lifecycleHook.destroyActionPreLock();
}
+ RuntimeException lifecycleCaughtInLock = null;
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
@@ -1133,7 +1134,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=lifecycleHook) {
// send synced destroy notification for proper cleanup, eg GLWindow/OpenGL
- lifecycleHook.destroyActionInLock();
+ try {
+ lifecycleHook.destroyActionInLock();
+ } catch (final RuntimeException re) {
+ lifecycleCaughtInLock = re;
+ }
}
if( isNativeValid() ) {
@@ -1156,6 +1161,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.destroy() END "+getThreadName()/*+", "+WindowImpl.this*/);
+ if( null != lifecycleCaughtInLock ) {
+ System.err.println("Window.destroy() caught: "+lifecycleCaughtInLock.getMessage());
+ lifecycleCaughtInLock.printStackTrace();
+ }
+ }
+ if( null != lifecycleCaughtInLock ) {
+ throw lifecycleCaughtInLock;
}
} finally {
// update states before release window lock
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
index a2dca2dda..83d5e9cc5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLException01NEWT.java
@@ -28,6 +28,8 @@
package com.jogamp.opengl.test.junit.jogl.acore;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.jogamp.newt.opengl.GLWindow;
@@ -36,10 +38,12 @@ 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.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
import org.junit.Assert;
import org.junit.BeforeClass;
@@ -52,6 +56,19 @@ public class TestGLException01NEWT extends UITestCase {
static GLProfile glp;
static int width, height;
+ @SuppressWarnings("serial")
+ static class AnimException extends RuntimeException {
+ final Thread thread;
+ final GLAnimatorControl animator;
+ final GLAutoDrawable drawable;
+ public AnimException(final Thread thread, final GLAnimatorControl animator, final GLAutoDrawable drawable, final Throwable cause) {
+ super(cause);
+ this.thread = thread;
+ this.animator = animator;
+ this.drawable = drawable;
+ }
+ }
+
@BeforeClass
public static void initClass() {
glp = GLProfile.getGL2ES2();
@@ -67,72 +84,129 @@ public class TestGLException01NEWT extends UITestCase {
protected void runTestGL(final GLCapabilities caps, final boolean onThread,
final boolean throwInInit, final boolean throwInDisplay,
- final boolean throwInReshape, final boolean throwInDispose) throws InterruptedException {
+ final boolean throwInReshape, final boolean throwInInvoke,
+ final boolean throwInDispose) throws InterruptedException {
final GLWindow glWindow = GLWindow.create(caps);
Assert.assertNotNull(glWindow);
- glWindow.setTitle("NEWT Exception Test");
+ glWindow.setTitle(getTestMethodName());
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 cleanInitCount = new AtomicInteger();
+ final AtomicInteger cleanDisposeCount = new AtomicInteger();
+ final AtomicInteger cleanDisplayCount = new AtomicInteger();
+ final AtomicInteger cleanReshapeCount = new AtomicInteger();
+ final AtomicInteger cleanInvokeCount = new AtomicInteger();
+ final AtomicInteger allInitCount = new AtomicInteger();
+ final AtomicInteger allDisposeCount = new AtomicInteger();
+ final AtomicInteger allDisplayCount = new AtomicInteger();
+ final AtomicInteger allReshapeCount = new AtomicInteger();
+ final AtomicInteger allInvokeCount = new AtomicInteger();
final AtomicInteger exceptionSent = new AtomicInteger();
glWindow.addGLEventListener(new GLEventListener() {
@Override
public void init(final GLAutoDrawable drawable) {
- if( throwInInit && 0 == exceptionSent.get() ) {
+ if( throwInInit ) {
exceptionSent.incrementAndGet();
- throw new RuntimeException("Injected GLEventListener exception in init");
+ throw new RuntimeException("<Injected GLEventListener exception in init: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
}
}
@Override
public void dispose(final GLAutoDrawable drawable) {
- if( throwInDispose && 0 == exceptionSent.get() ) {
+ if( throwInDispose ) {
exceptionSent.incrementAndGet();
- throw new RuntimeException("Injected GLEventListener exception in dispose");
+ throw new RuntimeException("<Injected GLEventListener exception in dispose: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
}
}
@Override
public void display(final GLAutoDrawable drawable) {
- if( throwInDisplay && 0 == exceptionSent.get() ) {
+ if( throwInDisplay ) {
exceptionSent.incrementAndGet();
- throw new RuntimeException("Injected GLEventListener exception in display");
+ throw new RuntimeException("<Injected GLEventListener exception in display: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
}
}
@Override
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
- if( throwInReshape && 0 == exceptionSent.get() ) {
+ if( throwInReshape ) {
exceptionSent.incrementAndGet();
- throw new RuntimeException("Injected GLEventListener exception in reshape");
+ throw new RuntimeException("<Injected GLEventListener exception in reshape: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
}
}
});
+ final GLRunnable glRunnableInject = new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ if( throwInInvoke ) {
+ exceptionSent.incrementAndGet();
+ throw new RuntimeException("<Injected GLEventListener exception in invoke: #"+exceptionSent.get()+" on thread "+Thread.currentThread().getName()+">");
+ }
+ return true;
+ }
+ };
+ final GLRunnable glRunnableCount = new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ if( 0 == exceptionSent.get() ) {
+ cleanInvokeCount.incrementAndGet();
+ }
+ allInvokeCount.incrementAndGet();
+ return true;
+ }
+ };
+
glWindow.addGLEventListener(new GLEventListener() {
@Override
public void init(final GLAutoDrawable drawable) {
- initCount.incrementAndGet();
+ if( 0 == exceptionSent.get() ) {
+ cleanInitCount.incrementAndGet();
+ }
+ allInitCount.incrementAndGet();
}
@Override
public void dispose(final GLAutoDrawable drawable) {
- disposeCount.incrementAndGet();
+ if( 0 == exceptionSent.get() ) {
+ cleanDisposeCount.incrementAndGet();
+ }
+ allDisposeCount.incrementAndGet();
}
@Override
public void display(final GLAutoDrawable drawable) {
- displayCount.incrementAndGet();
+ if( 0 == exceptionSent.get() ) {
+ cleanDisplayCount.incrementAndGet();
+ }
+ allDisplayCount.incrementAndGet();
}
@Override
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
- reshapeCount.incrementAndGet();
+ if( 0 == exceptionSent.get() ) {
+ cleanReshapeCount.incrementAndGet();
+ }
+ allReshapeCount.incrementAndGet();
}
});
- RuntimeException execptionAtInitReshapeDisplay = null;
- RuntimeException execptionAtDispose = null;
+ RuntimeException exceptionAtInitReshapeDisplay = null;
+ RuntimeException exceptionAtInvoke = null;
+ RuntimeException exceptionAtDispose = null;
+ final List<AnimException> exceptionsAtGLAnimatorControl = new ArrayList<AnimException>();
+ final GLAnimatorControl.UncaughtGLAnimatorExceptionHandler uncaughtGLAnimatorExceptionHandler;
- final Animator animator = !onThread ? new Animator(glWindow) : null;
+ final Animator animator;
+ if( onThread ) {
+ animator = null;
+ uncaughtGLAnimatorExceptionHandler = null;
+ } else {
+ animator = new Animator(glWindow);
+ uncaughtGLAnimatorExceptionHandler = new GLAnimatorControl.UncaughtGLAnimatorExceptionHandler() {
+ @Override
+ public void uncaughtException(final GLAnimatorControl animator, final GLAutoDrawable drawable, final Throwable cause) {
+ final AnimException ae = new AnimException(animator.getThread(), animator, drawable, cause);
+ exceptionsAtGLAnimatorControl.add(ae);
+ dumpThrowable(ae);
+ } };
+ animator.setUncaughtExceptionHandler(uncaughtGLAnimatorExceptionHandler);
+ }
glWindow.setSize(width, height);
@@ -143,7 +217,15 @@ public class TestGLException01NEWT extends UITestCase {
try {
glWindow.setVisible(true);
} catch (final RuntimeException re) {
- execptionAtInitReshapeDisplay = re;
+ exceptionAtInitReshapeDisplay = re;
+ dumpThrowable(re);
+ }
+
+ try {
+ glWindow.invoke(true, glRunnableInject);
+ glWindow.invoke(true, glRunnableCount);
+ } catch (final RuntimeException re) {
+ exceptionAtInvoke = re;
dumpThrowable(re);
}
@@ -154,7 +236,7 @@ public class TestGLException01NEWT extends UITestCase {
try {
glWindow.display();
} catch (final RuntimeException re) {
- execptionAtInitReshapeDisplay = re;
+ exceptionAtInitReshapeDisplay = re;
dumpThrowable(re);
}
}
@@ -168,23 +250,81 @@ public class TestGLException01NEWT extends UITestCase {
try {
glWindow.destroy();
} catch (final RuntimeException re) {
- execptionAtDispose = re;
+ exceptionAtDispose = 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);
+ final boolean onAnimThread = !onThread && !throwInDispose; /** dispose happens on [AWT|NEWT] EDT, not on animator thread! */
+
+ System.err.println("This-Thread : "+onThread);
+ System.err.println("Anim-Thread : "+onAnimThread);
+ System.err.println("ExceptionSent : "+exceptionSent.get());
+ System.err.println("Exception @ Init/Reshape/Display: "+(null != exceptionAtInitReshapeDisplay));
+ System.err.println("Exception @ Invoke : "+(null != exceptionAtInvoke));
+ System.err.println("Exception @ Dispose : "+(null != exceptionAtDispose));
+ System.err.println("Exception @ GLAnimatorControl : "+exceptionsAtGLAnimatorControl.size());
+ System.err.println("Init Count : "+cleanInitCount.get()+" / "+allInitCount.get());
+ System.err.println("Reshape Count : "+cleanReshapeCount.get()+" / "+allReshapeCount.get());
+ System.err.println("Display Count : "+cleanDisplayCount.get()+" / "+allDisplayCount.get());
+ System.err.println("Invoke Count : "+cleanInvokeCount.get()+" / "+allInvokeCount.get());
+ System.err.println("Dispose Count : "+cleanDisposeCount.get()+" / "+allDisposeCount.get());
+
+ if( throwInInit || throwInReshape || throwInDisplay || throwInDispose || throwInInvoke ) {
+ Assert.assertTrue("Not one exception sent, but "+exceptionSent.get(), 0 < exceptionSent.get());
+ if( onAnimThread ) {
+ Assert.assertEquals("No exception forwarded from init to animator-handler", 1, exceptionsAtGLAnimatorControl.size());
+ Assert.assertNull("Exception forwarded from init, on-thread", exceptionAtInitReshapeDisplay);
}
- if( throwInDispose ) {
- Assert.assertNotNull("No exception forwarded from dispose", execptionAtDispose);
+ if( throwInInit ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from init, on-thread", exceptionAtInitReshapeDisplay);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 0, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 0, cleanReshapeCount.get());
+ Assert.assertEquals("Display Count", 0, cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInReshape ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from reshape, on-thread", exceptionAtInitReshapeDisplay);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 0, cleanReshapeCount.get());
+ Assert.assertEquals("Display Count", 0, cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInDisplay ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from display, on-thread", exceptionAtInitReshapeDisplay);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 1, cleanReshapeCount.get());
+ Assert.assertEquals("Display Count", 0, cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInInvoke ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from invoke, on-thread", exceptionAtInvoke);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 1, cleanReshapeCount.get());
+ Assert.assertTrue ("Display count not greater-equal 1, but "+cleanDisplayCount.get(), 1 <= cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 0, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
+ } else if( throwInDispose ) {
+ if( !onAnimThread ) {
+ Assert.assertNotNull("No exception forwarded from dispose, on-thread", exceptionAtDispose);
+ Assert.assertEquals("Exception forwarded from init to animator-handler", 0, exceptionsAtGLAnimatorControl.size());
+ }
+ Assert.assertEquals("Init Count", 1, cleanInitCount.get());
+ Assert.assertEquals("Reshape Count", 1, cleanReshapeCount.get());
+ Assert.assertTrue ("Display count not greater-equal 1, but "+cleanDisplayCount.get(), 1 <= cleanDisplayCount.get());
+ Assert.assertEquals("Invoke Count", 1, cleanInvokeCount.get());
+ Assert.assertEquals("Dispose Count", 0, cleanDisposeCount.get());
}
}
}
@@ -193,25 +333,62 @@ public class TestGLException01NEWT extends UITestCase {
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 */);
+ runTestGL(caps, true /* onThread */, true /* init */, false /* display */, false /* reshape */, false /* invoke */, 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 */);
+ runTestGL(caps, true /* onThread */, false /* init */, false /* display */, true /* reshape */, false /* invoke */, 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 */);
+ runTestGL(caps, true /* onThread */, false /* init */, true /* display */, false /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test04OnThreadAtInvoke() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, true /* onThread */, false /* init */, true /* display */, false /* reshape */, true /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test05OnThreadAtDispose() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, true /* onThread */, false /* init */, false /* display */, false /* reshape */, false /* invoke */, true /* dispose */);
+ }
+
+ @Test
+ public void test11OffThreadAtInit() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, true /* init */, false /* display */, false /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test12OffThreadAtReshape() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, false /* init */, false /* display */, true /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test13OffThreadAtDisplay() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, false /* init */, true /* display */, false /* reshape */, false /* invoke */, false /* dispose */);
+ }
+ @Test
+ public void test14OffThreadAtInvoke() throws InterruptedException {
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setBackgroundOpaque(true); // default
+ runTestGL(caps, false /* onThread */, false /* init */, true /* display */, false /* reshape */, true /* invoke */, false /* dispose */);
}
@Test
- public void test04OnThreadAtDispose() throws InterruptedException {
+ public void test15OffThreadAtDispose() throws InterruptedException {
final GLCapabilities caps = new GLCapabilities(glp);
caps.setBackgroundOpaque(true); // default
- runTestGL(caps, true /* onThread */, false /* init */, false /* display */, false /* reshape */, true /* dispose */);
+ runTestGL(caps, false /* onThread */, false /* init */, false /* display */, false /* reshape */, false /* invoke */, true /* dispose */);
}
static long duration = 500; // ms