diff options
author | Sven Gothel <[email protected]> | 2010-06-26 06:59:48 +0300 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-06-26 06:59:48 +0300 |
commit | 969e427642d3b9be376cefaada9febd489b7b3d7 (patch) | |
tree | d2b4af8b500c0f561fc9d77807f318959ef41b4b /src/jogl/classes/com | |
parent | ce8c373576fe58fa5c71811fa376321e5379f71d (diff) |
GLAutoDrawable: setAnimator/getAnimator/invoke/display changes; NEWT: Adding native repaint; NewtCanvasAWT focus fix
Support for native repaint, which shall call display() in case no animator is running.
GLAutoDrawable invoke(GLRunnable) impl. handles case if invoked on animator thread,
or no animator thread is running (issueing a display() call).
The impl resides in GLDrawableHelper.
GLEventListener's init() and glViewport()/reshape() method must be called before the 1st display()
and after a dispose() call. It could miss the 1st display() call if added
after the setVisible(true) call - due to the native repainting.
The impl resides in GLDrawableHelper.
The Animator un-/registers itself at the GLAutoDrawable via setAnimator.
NEWT Window reparent always issues a resize() and display() call.
NEWT native Window uses direct send.*Event for input events (again),
instead of enqueueing it for performance.
NEWT Window implements all status change and Java native event callbacks,
instead of having duplicated code in all implementations.
NewtCanvasAWT if the Newt window is focused, the AWT/Swing component[s] will loose the focus.
Diffstat (limited to 'src/jogl/classes/com')
3 files changed, 123 insertions, 48 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java index 8fefe149e..1e954af1d 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java @@ -46,75 +46,123 @@ import javax.media.opengl.*; methods to be able to share it between GLCanvas and GLJPanel. */ public class GLDrawableHelper { - private volatile List listeners = new ArrayList(); private static final boolean DEBUG = Debug.debug("GLDrawableHelper"); private static final boolean VERBOSE = Debug.verbose(); - private static final boolean NVIDIA_CRASH_WORKAROUND = Debug.isPropertyDefined("jogl.nvidia.crash.workaround", true); + private Object listenersLock = new Object(); + private List listeners = new ArrayList(); + private Set listenersToBeInit = new HashSet(); private boolean autoSwapBufferMode = true; + private Object glRunnablesLock = new Object(); private ArrayList glRunnables = new ArrayList(); // one shot GL tasks + private Thread animatorThread = null; // default public GLDrawableHelper() { } - public synchronized String toString() { + public String toString() { StringBuffer sb = new StringBuffer(); - sb.append("GLEventListeners num "+listeners.size()+" ["); - for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { - sb.append(iter.next()+", "); + synchronized(listenersLock) { + sb.append("GLEventListeners num "+listeners.size()+" ["); + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + Object l = iter.next(); + sb.append(l); + sb.append("[init "); + sb.append( !listenersToBeInit.contains(l) ); + sb.append("], "); + } } sb.append("]"); return sb.toString(); } - public synchronized void addGLEventListener(GLEventListener listener) { + public void addGLEventListener(GLEventListener listener) { addGLEventListener(-1, listener); } - public synchronized void addGLEventListener(int index, GLEventListener listener) { - if(0>index) { - index = listeners.size(); + public void addGLEventListener(int index, GLEventListener listener) { + synchronized(listenersLock) { + if(0>index) { + index = listeners.size(); + } + listenersToBeInit.add(listener); + listeners.add(index, listener); } - List newListeners = (List) ((ArrayList) listeners).clone(); - newListeners.add(index, listener); - listeners = newListeners; } - public synchronized void removeGLEventListener(GLEventListener listener) { - List newListeners = (List) ((ArrayList) listeners).clone(); - newListeners.remove(listener); - listeners = newListeners; + public void removeGLEventListener(GLEventListener listener) { + synchronized(listenersLock) { + listeners.remove(listener); + listenersToBeInit.remove(listener); + } } - public synchronized void dispose(GLAutoDrawable drawable) { - for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { - ((GLEventListener) iter.next()).dispose(drawable); + public void dispose(GLAutoDrawable drawable) { + synchronized(listenersLock) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + GLEventListener listener = (GLEventListener) iter.next() ; + listener.dispose(drawable); + listenersToBeInit.add(listener); + } } } + private final boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { + if(listenersToBeInit.remove(l)) { + l.init(drawable); + if(sendReshape) { + reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */); + } + return true; + } + return false; + } + public void init(GLAutoDrawable drawable) { - for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { - ((GLEventListener) iter.next()).init(drawable); + synchronized(listenersLock) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + GLEventListener listener = (GLEventListener) iter.next() ; + if ( ! init( listener, drawable, false ) ) { + throw new GLException("GLEventListener "+listener+" already initialized: "+drawable); + } + } } } public void display(GLAutoDrawable drawable) { - for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { - ((GLEventListener) iter.next()).display(drawable); + synchronized(listenersLock) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + GLEventListener listener = (GLEventListener) iter.next() ; + // GLEventListener may need to be init, + // in case this one is added after the realization of the GLAutoDrawable + init( listener, drawable, true ) ; + listener.display(drawable); + } } execGLRunnables(drawable); } - public void reshape(GLAutoDrawable drawable, - int x, int y, int width, int height) { - for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { - ((GLEventListener) iter.next()).reshape(drawable, x, y, width, height); + private final void reshape(GLEventListener listener, GLAutoDrawable drawable, + int x, int y, int width, int height, boolean setViewport) { + if(setViewport) { + drawable.getGL().glViewport(x, y, width, height); + } + listener.reshape(drawable, x, y, width, height); + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + synchronized(listenersLock) { + int i=0; + for (Iterator iter = listeners.iterator(); iter.hasNext(); i++) { + reshape((GLEventListener) iter.next(), drawable, x, y, width, height, 0==i); + } } } private void execGLRunnables(GLAutoDrawable drawable) { if(glRunnables.size()>0) { + // swap one-shot list asap ArrayList _glRunnables = null; - synchronized(glRunnables) { + synchronized(glRunnablesLock) { if(glRunnables.size()>0) { _glRunnables = glRunnables; glRunnables = new ArrayList(); @@ -128,23 +176,38 @@ public class GLDrawableHelper { } } - private void invokeLater(GLRunnable glRunnable) { - synchronized(glRunnables) { - glRunnables.add(glRunnable); - glRunnables.notifyAll(); + public void setAnimator(Thread animator) throws GLException { + synchronized(glRunnablesLock) { + if(animator!=animatorThread && null!=animator && null!=animatorThread) { + throw new GLException("Trying to register animator thread "+animator+", where "+animatorThread+" is already registered. Unregister first."); + } + animatorThread = animator; + } + } + + public Thread getAnimator() { + synchronized(glRunnablesLock) { + return animatorThread; } } - public void invoke(boolean wait, GLRunnable glRunnable) { - if(glRunnable == null) { + public void invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) { + if( null == drawable || null == glRunnable ) { return; } - Object lock = new Object(); - GLRunnableTask rTask = new GLRunnableTask(glRunnable, wait?lock:null/*, true*/); Throwable throwable = null; + Object lock = new Object(); + GLRunnableTask rTask = null; synchronized(lock) { - invokeLater(rTask); - if( wait ) { + boolean callDisplay; + synchronized(glRunnablesLock) { + callDisplay = null == animatorThread || animatorThread == Thread.currentThread() ; + rTask = new GLRunnableTask(glRunnable, ( !callDisplay && wait ) ? lock : null); + glRunnables.add(rTask); + } + if( callDisplay ) { + drawable.display(); + } else if( wait ) { try { lock.wait(); } catch (InterruptedException ie) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java index 071ac1378..c2efb3f4e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java @@ -138,8 +138,16 @@ public class GLPbufferImpl implements GLPbuffer { drawableHelper.removeGLEventListener(listener); } + public void setAnimator(Thread animator) { + drawableHelper.setAnimator(animator); + } + + public Thread getAnimator() { + return drawableHelper.getAnimator(); + } + public void invoke(boolean wait, GLRunnable glRunnable) { - drawableHelper.invoke(wait, glRunnable); + drawableHelper.invoke(this, wait, glRunnable); } public void setContext(GLContext ctx) { diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java index 15b9d5eb9..66d3d5b88 100755 --- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -218,6 +218,9 @@ public class Animator { } else { thread = new Thread(threadGroup, runnable); } + for(Iterator iter = drawables.iterator(); iter.hasNext(); ) { + ((GLAutoDrawable) iter.next()).setAnimator(thread); + } thread.start(); } @@ -241,15 +244,16 @@ public class Animator { // dependencies on the Animator's internal thread. Currently we // use a couple of heuristics to determine whether we should do // the blocking wait(). - if (impl.skipWaitForStop(thread)) { - return; - } - - while (shouldStop && thread != null) { - try { - wait(); - } catch (InterruptedException ie) { + if (!impl.skipWaitForStop(thread)) { + while (shouldStop && thread != null) { + try { + wait(); + } catch (InterruptedException ie) { + } } } + for(Iterator iter = drawables.iterator(); iter.hasNext(); ) { + ((GLAutoDrawable) iter.next()).setAnimator(null); + } } } |