summaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-08-06 05:59:08 +0200
committerSven Gothel <[email protected]>2014-08-06 05:59:08 +0200
commit88eef9e4eae8e63762252f1d11bca2bd0fde809b (patch)
tree1a70cb2f54ada3a654928ec30432d5fca6ef822e /src/jogl
parent07a4801f3b5bfd4fba9a1a4a542ce2f2eae4396a (diff)
Bug 1039 - Specify behavior of GLEventListener Exceptions occurring while GLAutoDrawable processing [part-3]
Add GLAnimatorControl.UncaughtGLAnimatorExceptionHandler interface to optionally handle uncaught exception within an animator thread by the user. Implementation also requires to flush all enqueued GLRunnable instances via GLAutoDrawable.invoked(..) in case such exception occurs. Hence 'GLAutoDrawable.flushGLRunnables()' has been added. Only subsequent exceptions, which cannot be thrown are dumped to System.stderr. +++ Handling of exceptions during dispose() Exception in NEWT's disposeGL*() are also caught and re-thrown after the NEWT window has been destroyed in WindowImpl.destroyAction: - GLEventListener.dispose(..) - GLDrawableHelper.disposeAllGLEventListener(..) - GLDrawableHelper.disposeGL(..) - GLAutoDrawableBase.destroyImplInLock(..) - GLWindow.GLLifecycleHook.destroyActionInLock(..) - WindowImpl.destroyAction on NEWT-EDT - WindowImpl.destroy Further more, exceptions occuring in native windowing toolkit triggered destroy() are ignored: - GLAutoDrawableBase.defaultWindowDestroyNotifyOp(..) It has to be seen whether such exception handling for dispose() shall be added to AWT/SWT. +++ TestGLException01NEWT covers all GLEventListener exception cases on-thread and off-thread (via animator). +++
Diffstat (limited to 'src/jogl')
-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
15 files changed, 271 insertions, 62 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()