summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax/media/opengl/awt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-11-04 07:09:39 +0100
committerSven Gothel <[email protected]>2012-11-04 07:09:39 +0100
commitc002e04f848116922a1ed7bd96ead54961649bbd (patch)
tree37d51d971aceabb3f1afe8ce3cd7164a0096842b /src/jogl/classes/javax/media/opengl/awt
parent808c8da0729b845d010d3f5e0babf1fc6129c3e9 (diff)
GLAutoDrawable: Fix GLEventListener lifecycle and expose more user control (API Change) ; Added GLDrawableUtil
A GLEventListener resides in two states, initialized and uninitialized. When added to a GLAutoDrawable, it is uninitialized. A first 'display()' will issue GLEventListener's 'init(..)' which renders it initialized. This is usually accompanied by 'reshape(..)' propagating the drawable's dimension. Destruction of the GLAutoDrawable will issue GLEventListener's 'dispose(..)' which renders it uninitialized. It turns our these means of GLEventListener controls are not sufficient in case the user requires to remove and add them during the lifecycle and rendering of their GLAutoDrawable host. GLAutoDrawable 'removeGLEventListener(..)' merely removes the GLEventListener from the list, but does not complete it's lifecycle, i.e. issues 'dispose(..)' if initialized to realease GL related resources. Hence the following essential API changes are made to complete the lifecycle: + public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove); disposing a single GLEventListener, allowing it's removal from the list being optional This is demonstrated via GLDrawableUtil.swapGLContextAndAllGLEventListener(GLAutoDrawable a, GLAutoDrawable b), see below. ++++++++ Further more the following API changes were made to expose complete control of GLEventListener to the user: - public void removeGLEventListener(GLEventListener listener); + public GLEventListener removeGLEventListener(GLEventListener listener); The return value allows simple pipelining, and also delivers information whether the passed listener was actually removed. - public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException; + public int getGLEventListenerCount(); + public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException; Dropping the redundant removal by index, while adding count and get methods. + public boolean getGLEventListenerInitState(GLEventListener listener); + public void setGLEventListenerInitState(GLEventListener listener, boolean initialized); Allows retrieving and setting of listener states. All in all these API changes allows a user to experience all freedoms in dealing w/ GLEventListeners hosted by GLAutoDrawable impl. and shall be future proof. Note that we have avoided the Iterator pattern due to it's overhead of temporal objects creation. The simple indexed access allows us to implement each method as an atomic operation. +++++++++++ Further more a simple enqueue(..) method has been added, allowing to just enqueue a GLRunnable w/o provoking it's execution - as invoke(..) does. This method pleases a use case where GLRunnables are batched and shall be executed later on.. public boolean invoke(boolean wait, GLRunnable glRunnable); + public void enqueue(GLRunnable glRunnable); +++++++++++ Added GLDrawableUtil, exposes utility function to rearrange GLEventListener, modifiy GLAutoDrawable, etc. GLDrawableUtil.swapGLContextAndAllGLEventListener(GLAutoDrawable a, GLAutoDrawable b) is tested and demonstrated w/ TestGLContextDrawableSwitchNEWT. Manually tested on X11, OSX and Windows.
Diffstat (limited to 'src/jogl/classes/javax/media/opengl/awt')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java62
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java63
2 files changed, 110 insertions, 15 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 1e9fcc95e..5b5f800a4 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -495,7 +495,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
(int) ((getHeight() + bounds.getHeight()) / 2));
return;
}
- if( ! this.helper.isExternalAnimatorAnimating() ) {
+ if( ! this.helper.isAnimatorAnimatingOnOtherThread() ) {
display();
}
}
@@ -699,16 +699,38 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void removeGLEventListener(GLEventListener listener) {
- helper.removeGLEventListener(listener);
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
}
@Override
- public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
- return helper.removeGLEventListener(index);
+ public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
}
@Override
+ public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove) {
+ final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+ Threading.invoke(true, r, getTreeLock());
+ return r.listener;
+ }
+
+ @Override
+ public GLEventListener removeGLEventListener(GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
+ @Override
public void setAnimator(GLAnimatorControl animatorControl) {
helper.setAnimator(animatorControl);
}
@@ -724,6 +746,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public void enqueue(GLRunnable glRunnable) {
+ helper.enqueue(glRunnable);
+ }
+
+ @Override
public GLContext setContext(GLContext newCtx) {
final RecursiveLock _lock = lock;
_lock.lock();
@@ -984,15 +1011,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
};
- // Workaround for ATI driver bugs related to multithreading issues
- // like simultaneous rendering via Animators to canvases that are
- // being resized on the AWT event dispatch thread
private final Runnable displayOnEDTAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
- try {
+ try {
helper.invokeGL(drawable, context, displayAction, initAction);
} finally {
_lock.unlock();
@@ -1015,6 +1039,26 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
};
+ private class DisposeGLEventListenerAction implements Runnable {
+ GLEventListener listener;
+ private boolean remove;
+ private DisposeGLEventListenerAction(GLEventListener listener, boolean remove) {
+ this.listener = listener;
+ this.remove = remove;
+ }
+
+ @Override
+ public void run() {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
+ } finally {
+ _lock.unlock();
+ }
+ }
+ };
+
// Disables the AWT's erasing of this Canvas's background on Windows
// in Java SE 6. This internal API is not available in previous
// releases, but the system property
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index d0b9fb913..08d70211b 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -426,16 +426,48 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void removeGLEventListener(GLEventListener listener) {
- helper.removeGLEventListener(listener);
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
}
@Override
- public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
- return helper.removeGLEventListener(index);
- }
+ public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
+ }
+
+ @Override
+ public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove) {
+ final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+ if (EventQueue.isDispatchThread()) {
+ r.run();
+ } else {
+ // Multithreaded redrawing of Swing components is not allowed,
+ // so do everything on the event dispatch thread
+ try {
+ EventQueue.invokeAndWait(r);
+ } catch (Exception e) {
+ throw new GLException(e);
+ }
+ }
+ return r.listener;
+ }
@Override
+ public GLEventListener removeGLEventListener(GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
+ @Override
public void setAnimator(GLAnimatorControl animatorControl) {
helper.setAnimator(animatorControl);
}
@@ -451,6 +483,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
+ public void enqueue(GLRunnable glRunnable) {
+ helper.enqueue(glRunnable);
+ }
+
+ @Override
public GLContext createContext(GLContext shareWith) {
return (null != backend) ? backend.createContext(shareWith) : null;
}
@@ -685,7 +722,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public void dispose(GLAutoDrawable drawable) {
- helper.dispose(GLJPanel.this);
+ helper.disposeAllGLEventListener(GLJPanel.this, false);
}
@Override
@@ -758,6 +795,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
};
+ private class DisposeGLEventListenerAction implements Runnable {
+ GLEventListener listener;
+ private boolean remove;
+ private DisposeGLEventListenerAction(GLEventListener listener, boolean remove) {
+ this.listener = listener;
+ this.remove = remove;
+ }
+
+ @Override
+ public void run() {
+ listener = helper.disposeGLEventListener(GLJPanel.this, backend.getDrawable(), backend.getContext(), listener, remove);
+ }
+ };
+
private int getNextPowerOf2(int number) {
// Workaround for problems where 0 width or height are transiently
// seen during layout