aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax/media/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/javax/media/opengl')
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawable.java52
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java68
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java43
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java39
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();