diff options
Diffstat (limited to 'src/jogl/classes/javax/media/opengl')
4 files changed, 140 insertions, 62 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java index e4aaad23d..80d4f796c 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -165,16 +165,32 @@ public interface GLAutoDrawable extends GLDrawable { * @param listener The GLEventListener object to be inserted * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 */ - public void addGLEventListener(int index, GLEventListener listener) - throws IndexOutOfBoundsException; + public void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException; - /** Removes a {@link GLEventListener} from this drawable. Note that - if this is done from within a particular drawable's {@link - GLEventListener} handler (reshape, display, etc.) that it is not - guaranteed that all other listeners will be evaluated properly - during this update cycle. */ + /** + * Removes a {@link GLEventListener} from this drawable. + * Note that if this is done from within a particular drawable's + * {@link GLEventListener} handler (reshape, display, etc.) that it is not + * guaranteed that all other listeners will be evaluated properly + * during this update cycle. + * @param listener The GLEventListener object to be removed + */ public void removeGLEventListener(GLEventListener listener); + /** + * Removes a {@link GLEventListener} at the given index from this drawable. + * Note that if this is done from within a particular drawable's + * {@link GLEventListener} handler (reshape, display, etc.) that it is not + * guaranteed that all other listeners will be evaluated properly + * during this update cycle. + * @param index Position of the listener to be removed. + * Should be within (0 <= index && index < size()). + * An index value of -1 is interpreted as last listener, size()-1. + * @return The removed GLEventListener object + * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index < size()), or -1 + */ + public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException; + /** * <p> * Registers the usage of an animator, an {@link javax.media.opengl.GLAnimatorControl} implementation. @@ -221,14 +237,30 @@ public interface GLAutoDrawable extends GLDrawable { * <p> * If an {@link GLAnimatorControl} is animating,<br> * no {@link #display()} call is issued, since the animator thread performs it.<br> - * If <code>wait</code> is true, the implementation waits until the <code>GLRunnable</code> is executed.<br> - * </p><br> + * </p> + * <p> + * If <code>wait</code> is <code>true</code> the call blocks until the <code>glRunnable</code> + * has been executed.<p> + * <p> + * If <code>wait</code> is <code>true</code> <b>and</b> + * {@link #isRealized()} returns <code>false</code> <i>or</i> {@link #getContext()} returns <code>null</code>, + * the call is ignored and returns <code>false</code>.<br> + * This helps avoiding deadlocking the caller. + * </p> + * <p> + * The internal queue of {@link GLRunnable}'s is being flushed with {@link #destroy()} + * where all blocked callers are being notified. + * </p> * + * @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediatly w/o waiting + * @param glRunnable the {@link GLRunnable} to execute within {@link #display()} + * @return <code>true</code> if the {@link GLRunnable} has been processed or queued, otherwise <code>false</code>. + * * @see #setAnimator(GLAnimatorControl) * @see #display() * @see GLRunnable */ - public void invoke(boolean wait, GLRunnable glRunnable); + public boolean invoke(boolean wait, GLRunnable glRunnable); /** Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext. diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java index 992bf9fee..89d5cc4cb 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java @@ -28,6 +28,9 @@ package javax.media.opengl; +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + import jogamp.opengl.Debug; import jogamp.opengl.GLAutoDrawableBase; import jogamp.opengl.GLContextImpl; @@ -39,11 +42,16 @@ import jogamp.opengl.GLDrawableImpl; * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. * <p> * Since no native windowing system events are being processed, it is recommended - * to handle at least {@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize}, - * {@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} - * and maybe {@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint}. - * The latter is only required if no {@link GLAnimatorControl} is being used. - * </p> + * to handle at least: + * <ul> + * <li>{@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #defaultWindowRepaintOp()}</li> + * <li>{@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #defaultWindowResizedOp()}</li> + * <li>{@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #defaultWindowDestroyNotifyOp()}</li> + * </ul> + * </p> + * <p> + * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. + * </p> */ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); @@ -52,36 +60,64 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase { super((GLDrawableImpl)drawable, (GLContextImpl)context); } - public void defaultRepaintOp() { - super.defaultRepaintOp(); + // + // make protected methods accessible + // + + public void defaultWindowRepaintOp() { + super.defaultWindowRepaintOp(); + } + + public void defaultWindowResizedOp() { + super.defaultWindowResizedOp(); } - public void defaultReshapeOp() { - super.defaultReshapeOp(); + public void defaultWindowDestroyNotifyOp() { + super.defaultWindowDestroyNotifyOp(); } // // Complete GLAutoDrawable // + private RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock + /** * {@inheritDoc} * <p> - * This implementation simply removes references to drawable and context. + * This implementation calls {@link #defaultDestroyOp()}. + * </p> + * <p> + * User still needs to destroy the upstream window, which details are hidden from this aspect. * </p> */ @Override public void destroy() { - drawable = null; - context = null; + lock.lock(); + try { + defaultDestroyOp(); + } finally { + lock.unlock(); + } } @Override public void display() { - if( null == drawable || !drawable.isRealized() || null == context ) { return; } - - // surface is locked/unlocked implicit by context's makeCurrent/release - helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); + if( sendDestroy ) { + sendDestroy=false; + destroy(); + return; + } + + lock.lock(); // sync: context/drawable could been recreated/destroyed while animating + try { + if( null != drawable && drawable.isRealized() && null != context ) { + // surface is locked/unlocked implicit by context's makeCurrent/release + helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); + } + } finally { + lock.unlock(); + } } // diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 8c6e594b5..3161f898d 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -153,7 +153,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private static final boolean DEBUG = Debug.debug("GLCanvas"); - private final GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private final GLDrawableHelper helper = new GLDrawableHelper(); private AWTGraphicsConfiguration awtConfig; private volatile GLDrawable drawable; // volatile avoids locking all accessors. FIXME still need to sync destroy/display private GLContextImpl context; @@ -510,7 +510,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing (int) ((getHeight() + bounds.getHeight()) / 2)); return; } - if( ! this.drawableHelper.isAnimatorAnimating() ) { + if( ! this.helper.isAnimatorAnimating() ) { display(); } } @@ -670,38 +670,43 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void addGLEventListener(GLEventListener listener) { - drawableHelper.addGLEventListener(listener); + helper.addGLEventListener(listener); } @Override - public void addGLEventListener(int index, GLEventListener listener) { - drawableHelper.addGLEventListener(index, listener); + public void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException { + helper.addGLEventListener(index, listener); } @Override public void removeGLEventListener(GLEventListener listener) { - drawableHelper.removeGLEventListener(listener); + helper.removeGLEventListener(listener); } @Override + public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException { + return helper.removeGLEventListener(index); + } + + @Override public void setAnimator(GLAnimatorControl animatorControl) { - drawableHelper.setAnimator(animatorControl); + helper.setAnimator(animatorControl); } @Override public GLAnimatorControl getAnimator() { - return drawableHelper.getAnimator(); + return helper.getAnimator(); } @Override - public void invoke(boolean wait, GLRunnable glRunnable) { - drawableHelper.invoke(this, wait, glRunnable); + public boolean invoke(boolean wait, GLRunnable glRunnable) { + return helper.invoke(this, wait, glRunnable); } @Override public GLContext setContext(GLContext newCtx) { final GLContext oldCtx = context; - final boolean newCtxCurrent = drawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -736,12 +741,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void setAutoSwapBufferMode(boolean onOrOff) { - drawableHelper.setAutoSwapBufferMode(onOrOff); + helper.setAutoSwapBufferMode(onOrOff); } @Override public boolean getAutoSwapBufferMode() { - return drawableHelper.getAutoSwapBufferMode(); + return helper.getAutoSwapBufferMode(); } @Override @@ -849,7 +854,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final Runnable disposeOnEDTAction = new Runnable() { @Override public void run() { - drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction); + helper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction); } }; @@ -897,7 +902,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final Runnable initAction = new Runnable() { @Override public void run() { - drawableHelper.init(GLCanvas.this); + helper.init(GLCanvas.this); } }; @@ -910,11 +915,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } // Note: we ignore the given x and y within the parent component // since we are drawing directly into this heavyweight component. - drawableHelper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight()); + helper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight()); sendReshape = false; } - drawableHelper.display(GLCanvas.this); + helper.display(GLCanvas.this); } }; @@ -931,14 +936,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final Runnable displayOnEDTAction = new Runnable() { @Override public void run() { - drawableHelper.invokeGL(drawable, context, displayAction, initAction); + helper.invokeGL(drawable, context, displayAction, initAction); } }; private final Runnable swapBuffersOnEDTAction = new Runnable() { @Override public void run() { - drawableHelper.invokeGL(drawable, context, swapBuffersAction, initAction); + helper.invokeGL(drawable, context, swapBuffersAction, initAction); } }; diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index c6c7cf9a1..cd18c5098 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -125,7 +125,7 @@ import com.jogamp.opengl.util.GLBuffers; public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("GLJPanel"); - private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private GLDrawableHelper helper = new GLDrawableHelper(); private volatile boolean isInitialized; // Data used for either pbuffers or pixmap-based offscreen surfaces @@ -413,32 +413,37 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public void addGLEventListener(GLEventListener listener) { - drawableHelper.addGLEventListener(listener); + helper.addGLEventListener(listener); } @Override public void addGLEventListener(int index, GLEventListener listener) { - drawableHelper.addGLEventListener(index, listener); + helper.addGLEventListener(index, listener); } @Override public void removeGLEventListener(GLEventListener listener) { - drawableHelper.removeGLEventListener(listener); + helper.removeGLEventListener(listener); } @Override + public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException { + return helper.removeGLEventListener(index); + } + + @Override public void setAnimator(GLAnimatorControl animatorControl) { - drawableHelper.setAnimator(animatorControl); + helper.setAnimator(animatorControl); } @Override public GLAnimatorControl getAnimator() { - return drawableHelper.getAnimator(); + return helper.getAnimator(); } @Override - public void invoke(boolean wait, GLRunnable glRunnable) { - drawableHelper.invoke(this, wait, glRunnable); + public boolean invoke(boolean wait, GLRunnable glRunnable) { + return helper.invoke(this, wait, glRunnable); } @Override @@ -461,7 +466,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return null; } final GLContext oldCtx = backend.getContext(); - final boolean newCtxCurrent = drawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = helper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); backend.setContext(newCtx); if(newCtxCurrent) { newCtx.makeCurrent(); @@ -662,13 +667,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if (!backend.preGL(g)) { return; } - drawableHelper.init(GLJPanel.this); + helper.init(GLJPanel.this); backend.postGL(g, false); } @Override public void dispose(GLAutoDrawable drawable) { - drawableHelper.dispose(GLJPanel.this); + helper.dispose(GLJPanel.this); } @Override @@ -680,11 +685,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if (DEBUG) { System.err.println(getThreadName()+": GLJPanel.display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + ")"); } - drawableHelper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight); + helper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight); sendReshape = false; } - drawableHelper.display(GLJPanel.this); + helper.display(GLJPanel.this); backend.postGL(g, true); } @@ -716,7 +721,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private final Runnable disposeAction = new Runnable() { @Override public void run() { - drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction); + helper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction); } }; @@ -1035,7 +1040,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } if (offscreenDrawable != null) { final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); - offscreenDrawable.destroy(); + offscreenDrawable.setRealized(false); offscreenDrawable = null; if(null != adevice) { adevice.close(); @@ -1094,7 +1099,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override protected void doPaintComponentImpl() { - drawableHelper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction); + helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction); } @Override @@ -1711,7 +1716,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing ((Java2DGLContext) joglContext).setGraphics(g); } - drawableHelper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction); + helper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction); } } finally { j2dContext.release(); |