summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-09-23 14:53:25 +0200
committerSven Gothel <[email protected]>2010-09-23 14:53:25 +0200
commit34fffab0bb25bbf8a4cd2bf372e018748982b9bc (patch)
tree11b2967f39afde7547d820f069e706a71cef4338 /src
parente62a91e26ba01a8970658681891edebcee7461e1 (diff)
NEWT: Animator API Change - Changed Lifecycle of Display/Screen (part 4)
Change GLAutoDrawable interface: setAnimator(Thread) -> setAnimator(GLAnimatorControl) to minimize the setAnimator(..) calls and to allow fine grained control over the animation, ie in case of reparenting where the animation shall pause while changing the window(s). Introducing GLAnimatorControl interface: - abstract class AnimatorBase implements GLAnimatorControl - class Animator extends AnimatorBase - class FPSAnimator extends AnimatorBase This also changes FPSAnimator, since it is no more derived from Animator, use it's superclass or superinterface instead. +++ - Fix GLJPanel.paintComponent(): Don't issue reshape/display in case an external animator thread is animating. - Fix: Documentation [API]
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java51
-rw-r--r--src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java41
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java7
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/Animator.java266
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java145
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java7
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java199
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAnimatorControl.java180
-rw-r--r--src/jogl/classes/javax/media/opengl/GLAutoDrawable.java76
-rw-r--r--src/jogl/classes/javax/media/opengl/GLRunnable.java24
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java10
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java11
13 files changed, 731 insertions, 292 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java
index 1e954af1d..1596f0baf 100644
--- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java
+++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -54,13 +55,14 @@ public class GLDrawableHelper {
private boolean autoSwapBufferMode = true;
private Object glRunnablesLock = new Object();
private ArrayList glRunnables = new ArrayList(); // one shot GL tasks
- private Thread animatorThread = null; // default
+ private GLAnimatorControl animatorCtrl = null; // default
public GLDrawableHelper() {
}
public String toString() {
StringBuffer sb = new StringBuffer();
+ sb.append("GLAnimatorControl: "+animatorCtrl+", ");
synchronized(listenersLock) {
sb.append("GLEventListeners num "+listeners.size()+" [");
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
@@ -176,51 +178,60 @@ public class GLDrawableHelper {
}
}
- public void setAnimator(Thread animator) throws GLException {
+ public void setAnimator(GLAnimatorControl 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.");
+ if(animatorCtrl!=animator && null!=animator && null!=animatorCtrl) {
+ throw new GLException("Trying to register GLAnimatorControl "+animator+", where "+animatorCtrl+" is already registered. Unregister first.");
}
- animatorThread = animator;
+ animatorCtrl = animator;
}
}
- public Thread getAnimator() {
+ public GLAnimatorControl getAnimator() {
synchronized(glRunnablesLock) {
- return animatorThread;
+ return animatorCtrl;
}
}
+ public final boolean isExternalAnimatorAnimating() {
+ return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() && animatorCtrl.getThread() != Thread.currentThread() : false ;
+ }
+
public void invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) {
if( null == drawable || null == glRunnable ) {
return;
}
Throwable throwable = null;
- Object lock = new Object();
GLRunnableTask rTask = null;
- synchronized(lock) {
- boolean callDisplay;
+ Object rTaskLock = new Object();
+ synchronized(rTaskLock) {
+ boolean deferred;
synchronized(glRunnablesLock) {
- callDisplay = null == animatorThread || animatorThread == Thread.currentThread() ;
- rTask = new GLRunnableTask(glRunnable, ( !callDisplay && wait ) ? lock : null);
+ deferred = isExternalAnimatorAnimating();
+ if(!deferred) {
+ wait = false; // don't wait if exec immediatly
+ }
+ rTask = new GLRunnableTask(glRunnable,
+ wait ? rTaskLock : null,
+ wait /* catch Exceptions if waiting for result */);
glRunnables.add(rTask);
}
- if( callDisplay ) {
+ if( !deferred ) {
drawable.display();
} else if( wait ) {
try {
- lock.wait();
+ rTaskLock.wait(); // free lock, allow execution of rTask
} catch (InterruptedException ie) {
throwable = ie;
}
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
}
}
- if(null==throwable) {
- throwable = rTask.getThrowable();
- }
- if(null!=throwable) {
- throw new RuntimeException(throwable);
- }
}
public void setAutoSwapBufferMode(boolean onOrOff) {
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java
index c2efb3f4e..dcfb2e3f5 100644
--- a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java
@@ -138,11 +138,11 @@ public class GLPbufferImpl implements GLPbuffer {
drawableHelper.removeGLEventListener(listener);
}
- public void setAnimator(Thread animator) {
- drawableHelper.setAnimator(animator);
+ public void setAnimator(GLAnimatorControl animatorControl) {
+ drawableHelper.setAnimator(animatorControl);
}
- public Thread getAnimator() {
+ public GLAnimatorControl getAnimator() {
return drawableHelper.getAnimator();
}
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java b/src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java
index ea1e63b8b..a2a6939cd 100644
--- a/src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java
+++ b/src/jogl/classes/com/jogamp/opengl/impl/GLRunnableTask.java
@@ -38,27 +38,52 @@ import javax.media.opengl.GLAutoDrawable;
public class GLRunnableTask implements GLRunnable {
GLRunnable runnable;
Object notifyObject;
+ boolean catchExceptions;
+ boolean isExecuted;
Throwable runnableException;
- public GLRunnableTask(GLRunnable runnable, Object notifyObject) {
+ public GLRunnableTask(GLRunnable runnable, Object notifyObject, boolean catchExceptions) {
this.runnable = runnable ;
this.notifyObject = notifyObject ;
+ this.catchExceptions = catchExceptions;
+ isExecuted = false;
}
public void run(GLAutoDrawable drawable) {
- try {
- runnable.run(drawable);
- } catch (Throwable t) {
- runnableException = t;
- }
- if(null != notifyObject) {
+ if(null == notifyObject) {
+ try {
+ runnable.run(drawable);
+ } catch (Throwable t) {
+ runnableException = t;
+ if(catchExceptions) {
+ runnableException.printStackTrace();
+ } else {
+ throw new RuntimeException(runnableException);
+ }
+ } finally {
+ isExecuted=true;
+ }
+ } else {
synchronized (notifyObject) {
- notifyObject.notifyAll();
+ try {
+ runnable.run(drawable);
+ } catch (Throwable t) {
+ runnableException = t;
+ if(catchExceptions) {
+ runnableException.printStackTrace();
+ } else {
+ throw new RuntimeException(runnableException);
+ }
+ } finally {
+ isExecuted=true;
+ notifyObject.notifyAll();
+ }
}
}
}
+ public boolean isExecuted() { return isExecuted; }
public Throwable getThrowable() { return runnableException; }
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
index d8e1cf080..e3aff61c6 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -51,11 +52,11 @@ class AWTAnimatorImpl extends AnimatorImpl {
private Map repaintManagers = new IdentityHashMap();
private Map dirtyRegions = new IdentityHashMap();
- public void display(Animator animator,
+ public void display(AnimatorBase animator,
boolean ignoreExceptions,
boolean printExceptions) {
Iterator iter = animator.drawableIterator();
- while (iter.hasNext()) {
+ while (animator.isAnimating() && !animator.getShouldStop() && !animator.getShouldPause() && iter.hasNext()) {
GLAutoDrawable drawable = (GLAutoDrawable) iter.next();
if (drawable instanceof JComponent) {
// Lightweight components need a more efficient drawing
@@ -157,7 +158,7 @@ class AWTAnimatorImpl extends AnimatorImpl {
}
};
- public boolean skipWaitForStop(Thread thread) {
+ public boolean skipWaitForCompletion(Thread thread) {
return ((Thread.currentThread() == thread) || EventQueue.isDispatchThread());
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
index 66d3d5b88..5d48405e2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -39,12 +40,16 @@
package com.jogamp.opengl.util;
-import java.util.*;
-
-import javax.media.opengl.*;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
import com.jogamp.opengl.impl.Debug;
+import java.util.*;
+
+
/** <P> An Animator can be attached to one or more {@link
GLAutoDrawable}s to drive their display() methods in a loop. </P>
@@ -54,44 +59,34 @@ import com.jogamp.opengl.impl.Debug;
CPU, unless {@link #setRunAsFastAsPossible} has been called. </P>
*/
-public class Animator {
- protected static final boolean DEBUG = Debug.debug("Animator");
+public class Animator extends AnimatorBase {
- private volatile ArrayList/*<GLAutoDrawable>*/ drawables = new ArrayList();
- private AnimatorImpl impl;
+ protected ThreadGroup threadGroup;
private Runnable runnable;
private boolean runAsFastAsPossible;
- protected ThreadGroup threadGroup;
- protected Thread thread;
+ protected volatile boolean isAnimating;
+ protected volatile boolean shouldPause;
protected volatile boolean shouldStop;
- protected boolean ignoreExceptions;
- protected boolean printExceptions;
-
- /** Creates a new, empty Animator. */
- public Animator(ThreadGroup tg) {
- if(GLProfile.isAWTAvailable()) {
- try {
- impl = (AnimatorImpl) Class.forName("com.jogamp.opengl.util.awt.AWTAnimatorImpl").newInstance();
- } catch (Exception e) { }
- }
- if(null==impl) {
- impl = new AnimatorImpl();
+ public Animator() {
+ super();
+ if(DEBUG) {
+ System.err.println("Animator created");
}
+ }
+
+ public Animator(ThreadGroup tg) {
+ super();
threadGroup = tg;
if(DEBUG) {
- System.out.println("Animator created, ThreadGroup: "+threadGroup);
+ System.err.println("Animator created, ThreadGroup: "+threadGroup);
}
}
- public Animator() {
- this((ThreadGroup)null);
- }
-
/** Creates a new Animator for a particular drawable. */
public Animator(GLAutoDrawable drawable) {
- this((ThreadGroup)null);
+ super();
add(drawable);
}
@@ -101,142 +96,131 @@ public class Animator {
add(drawable);
}
- /** Adds a drawable to the list managed by this Animator. */
- public synchronized void add(GLAutoDrawable drawable) {
- ArrayList newList = (ArrayList) drawables.clone();
- newList.add(drawable);
- drawables = newList;
- notifyAll();
- }
-
- /** Removes a drawable from the list managed by this Animator. */
- public synchronized void remove(GLAutoDrawable drawable) {
- ArrayList newList = (ArrayList) drawables.clone();
- newList.remove(drawable);
- drawables = newList;
- }
-
- /** Returns an iterator over the drawables managed by this
- Animator. */
- public Iterator/*<GLAutoDrawable>*/ drawableIterator() {
- return drawables.iterator();
+ protected String getBaseName(String prefix) {
+ return prefix + "Animator" ;
}
- /** Sets a flag causing this Animator to ignore exceptions produced
- while redrawing the drawables. By default this flag is set to
- false, causing any exception thrown to halt the Animator. */
- public void setIgnoreExceptions(boolean ignoreExceptions) {
- this.ignoreExceptions = ignoreExceptions;
- }
-
- /** Sets a flag indicating that when exceptions are being ignored by
- this Animator (see {@link #setIgnoreExceptions}), to print the
- exceptions' stack traces for diagnostic information. Defaults to
- false. */
- public void setPrintExceptions(boolean printExceptions) {
- this.printExceptions = printExceptions;
- }
-
- /** Sets a flag in this Animator indicating that it is to run as
- fast as possible. By default there is a brief pause in the
- animation loop which prevents the CPU from getting swamped.
- This method may not have an effect on subclasses. */
+ /**
+ * Sets a flag in this Animator indicating that it is to run as
+ * fast as possible. By default there is a brief pause in the
+ * animation loop which prevents the CPU from getting swamped.
+ * This method may not have an effect on subclasses.
+ */
public final void setRunAsFastAsPossible(boolean runFast) {
runAsFastAsPossible = runFast;
}
- /** Called every frame to cause redrawing of all of the
- GLAutoDrawables this Animator manages. Subclasses should call
- 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 void display() {
- impl.display(this, ignoreExceptions, printExceptions);
- }
-
- private long startTime = 0;
- private long curTime = 0;
- private int totalFrames = 0;
-
class MainLoop implements Runnable {
public void run() {
try {
if(DEBUG) {
- System.out.println("Animator started: "+Thread.currentThread());
+ System.err.println("Animator started: "+Thread.currentThread());
}
startTime = System.currentTimeMillis();
curTime = startTime;
+ totalFrames = 0;
+
+ synchronized (Animator.this) {
+ isAnimating = true;
+ Animator.this.notifyAll();
+ }
while (!shouldStop) {
- // Don't consume CPU unless there is work to be done
- if (drawables.size() == 0) {
+ // Don't consume CPU unless there is work to be done and not paused
+ if ( !shouldStop && ( shouldPause || drawables.size() == 0 ) ) {
synchronized (Animator.this) {
- while (drawables.size() == 0 && !shouldStop) {
+ boolean wasPaused = false;
+ while ( !shouldStop && ( shouldPause || drawables.size() == 0 ) ) {
+ if(DEBUG) {
+ System.err.println("Animator paused: "+Thread.currentThread());
+ }
+ isAnimating = false;
+ wasPaused = true;
+ Animator.this.notifyAll();
try {
Animator.this.wait();
} catch (InterruptedException e) {
}
}
+ if ( wasPaused ) {
+ startTime = System.currentTimeMillis();
+ curTime = startTime;
+ totalFrames = 0;
+ if(DEBUG) {
+ System.err.println("Animator resumed: "+Thread.currentThread());
+ }
+ isAnimating = true;
+ Animator.this.notifyAll();
+ }
}
}
- display();
- curTime = System.currentTimeMillis();
- totalFrames++;
- if (!runAsFastAsPossible) {
- // Avoid swamping the CPU
- Thread.yield();
+ if ( !shouldStop ) {
+ display();
+ if (!runAsFastAsPossible) {
+ // Avoid swamping the CPU
+ Thread.yield();
+ }
}
}
- if(DEBUG) {
- System.out.println("Animator stopped: "+Thread.currentThread());
- }
} finally {
- shouldStop = false;
synchronized (Animator.this) {
+ if(DEBUG) {
+ System.err.println("Animator stopped: "+Thread.currentThread());
+ }
+ shouldStop = false;
+ shouldPause = false;
thread = null;
- Animator.this.notify();
+ isAnimating = false;
+ Animator.this.notifyAll();
}
}
}
}
- public long getStartTime() { return startTime; }
- public long getCurrentTime() { return curTime; }
- public long getDuration() { return curTime-startTime; }
- public int getTotalFrames() { return totalFrames; }
+ public final synchronized boolean isStarted() {
+ return (thread != null);
+ }
+
+ public final synchronized boolean isAnimating() {
+ return (thread != null) && isAnimating;
+ }
+
+ public final synchronized boolean isPaused() {
+ return (thread != null) && shouldPause;
+ }
- /** Starts this animator. */
public synchronized void start() {
- if (thread != null) {
- throw new GLException("Already started");
+ boolean started = null != thread;
+ if ( started || isAnimating ) {
+ throw new GLException("Already running (started "+started+" (false), animating "+isAnimating+" (false))");
}
if (runnable == null) {
runnable = new MainLoop();
}
+ int id;
+ String threadName = Thread.currentThread().getName()+"-"+baseName;
if(null==threadGroup) {
- thread = new Thread(runnable);
+ thread = new Thread(runnable, threadName);
} else {
- thread = new Thread(threadGroup, runnable);
- }
- for(Iterator iter = drawables.iterator(); iter.hasNext(); ) {
- ((GLAutoDrawable) iter.next()).setAnimator(thread);
+ thread = new Thread(threadGroup, runnable, threadName);
}
thread.start();
- }
- /** Indicates whether this animator is currently running. This
- should only be used as a heuristic to applications because in
- some circumstances the Animator may be in the process of
- shutting down and this method will still return true. */
- public synchronized boolean isAnimating() {
- return (thread != null);
+ if (!impl.skipWaitForCompletion(thread)) {
+ while (!isAnimating && thread != null) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
}
- /** Stops this animator. In most situations this method blocks until
- completion, except when called from the animation thread itself
- or in some cases from an implementation-internal thread like the
- AWT event queue thread. */
public synchronized void stop() {
+ boolean started = null != thread;
+ if ( !started || !isAnimating ) {
+ throw new GLException("Not running (started "+started+" (true), animating "+isAnimating+" (true) )");
+ }
shouldStop = true;
notifyAll();
@@ -244,16 +228,58 @@ 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)) {
- while (shouldStop && thread != null) {
+ if (!impl.skipWaitForCompletion(thread)) {
+ while (isAnimating && thread != null) {
try {
wait();
} catch (InterruptedException ie) {
}
}
}
- for(Iterator iter = drawables.iterator(); iter.hasNext(); ) {
- ((GLAutoDrawable) iter.next()).setAnimator(null);
+ }
+
+ public synchronized void pause() {
+ boolean started = null != thread;
+ if ( !started || !isAnimating || shouldPause ) {
+ throw new GLException("Invalid state (started "+started+" (true), animating "+isAnimating+" (true), paused "+shouldPause+" (false) )");
+ }
+ shouldPause = true;
+ notifyAll();
+
+ if (!impl.skipWaitForCompletion(thread)) {
+ while (isAnimating && thread != null) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ }
+
+ public synchronized void resume() {
+ boolean started = null != thread;
+ if ( !started || !shouldPause ) {
+ throw new GLException("Invalid state (started "+started+" (true), paused "+shouldPause+" (true) )");
+ }
+ shouldPause = false;
+ notifyAll();
+
+ if (!impl.skipWaitForCompletion(thread)) {
+ while (!isAnimating && thread != null) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ }
+ }
}
}
+
+ protected final boolean getShouldPause() {
+ return shouldPause;
+ }
+
+ protected final boolean getShouldStop() {
+ return shouldStop;
+ }
+
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
new file mode 100644
index 000000000..279fe33ef
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
@@ -0,0 +1,145 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.util;
+
+import com.jogamp.opengl.impl.Debug;
+import java.util.ArrayList;
+import java.util.Iterator;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLProfile;
+
+/**
+ * Base implementation of GLAnimatorControl
+ */
+public abstract class AnimatorBase implements GLAnimatorControl {
+ protected static final boolean DEBUG = Debug.debug("Animator");
+
+ private static int animatorCount = 0;
+
+ protected volatile ArrayList/*<GLAutoDrawable>*/ drawables = new ArrayList();
+ protected AnimatorImpl impl;
+ protected String baseName;
+ protected Thread thread;
+ protected boolean ignoreExceptions;
+ protected boolean printExceptions;
+ protected long startTime = 0;
+ protected long curTime = 0;
+ protected int totalFrames = 0;
+
+ /** Creates a new, empty Animator. */
+ public AnimatorBase() {
+ if(GLProfile.isAWTAvailable()) {
+ try {
+ impl = (AnimatorImpl) Class.forName("com.jogamp.opengl.util.awt.AWTAnimatorImpl").newInstance();
+ baseName = "AWTAnimator";
+ } catch (Exception e) { }
+ }
+ if(null==impl) {
+ impl = new AnimatorImpl();
+ baseName = "Animator";
+ }
+ synchronized (Animator.class) {
+ animatorCount++;
+ baseName = baseName.concat("-"+animatorCount);
+ }
+ }
+
+ protected abstract String getBaseName(String prefix);
+
+ public synchronized void add(GLAutoDrawable drawable) {
+ ArrayList newList = (ArrayList) drawables.clone();
+ newList.add(drawable);
+ drawables = newList;
+ drawable.setAnimator(this);
+ notifyAll();
+ }
+
+ public synchronized void remove(GLAutoDrawable drawable) {
+ ArrayList newList = (ArrayList) drawables.clone();
+ newList.remove(drawable);
+ drawables = newList;
+ drawable.setAnimator(null);
+ notifyAll();
+ }
+
+ /** Called every frame to cause redrawing of all of the
+ GLAutoDrawables this Animator manages. Subclasses should call
+ 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 void display() {
+ impl.display(this, ignoreExceptions, printExceptions);
+ curTime = System.currentTimeMillis();
+ totalFrames++;
+ }
+
+ public Iterator drawableIterator() {
+ return drawables.iterator();
+ }
+
+ public long getCurrentTime() {
+ return curTime;
+ }
+
+ public long getDuration() {
+ return curTime - startTime;
+ }
+
+ protected abstract boolean getShouldPause();
+
+ protected abstract boolean getShouldStop();
+
+ public long getStartTime() {
+ return startTime;
+ }
+
+ public int getTotalFrames() {
+ return totalFrames;
+ }
+
+ public final synchronized Thread getThread() {
+ return thread;
+ }
+
+ /** Sets a flag causing this Animator to ignore exceptions produced
+ while redrawing the drawables. By default this flag is set to
+ false, causing any exception thrown to halt the Animator. */
+ public void setIgnoreExceptions(boolean ignoreExceptions) {
+ this.ignoreExceptions = ignoreExceptions;
+ }
+
+ /** Sets a flag indicating that when exceptions are being ignored by
+ this Animator (see {@link #setIgnoreExceptions}), to print the
+ exceptions' stack traces for diagnostic information. Defaults to
+ false. */
+ public void setPrintExceptions(boolean printExceptions) {
+ this.printExceptions = printExceptions;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java
index 50b91b729..e4bf8d711 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -40,11 +41,11 @@ import javax.media.opengl.*;
up this behavior if desired. */
class AnimatorImpl {
- public void display(Animator animator,
+ public void display(AnimatorBase animator,
boolean ignoreExceptions,
boolean printExceptions) {
Iterator iter = animator.drawableIterator();
- while (iter.hasNext()) {
+ while (animator.isAnimating() && !animator.getShouldStop() && !animator.getShouldPause() && iter.hasNext()) {
GLAutoDrawable drawable = (GLAutoDrawable) iter.next();
try {
drawable.display();
@@ -60,7 +61,7 @@ class AnimatorImpl {
}
}
- public boolean skipWaitForStop(Thread thread) {
+ public boolean skipWaitForCompletion(Thread thread) {
return (Thread.currentThread() == thread);
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
index 75c4cdff7..d098cf1a3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -36,88 +37,142 @@
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
-
package com.jogamp.opengl.util;
import java.util.*;
import javax.media.opengl.*;
/** An Animator subclass which attempts to achieve a target
- frames-per-second rate to avoid using all CPU time. The target FPS
- is only an estimate and is not guaranteed. */
-
-public class FPSAnimator extends Animator {
- private Timer timer;
- private int fps;
- private boolean scheduleAtFixedRate;
-
- /** Creates an FPSAnimator with a given target frames-per-second
- value. Equivalent to <code>FPSAnimator(null, fps)</code>. */
- public FPSAnimator(int fps) {
- this(null, fps);
- }
-
- /** Creates an FPSAnimator with a given target frames-per-second
- value and a flag indicating whether to use fixed-rate
- scheduling. Equivalent to <code>FPSAnimator(null, fps,
- scheduleAtFixedRate)</code>. */
- public FPSAnimator(int fps, boolean scheduleAtFixedRate) {
- this(null, fps, scheduleAtFixedRate);
- }
-
- /** Creates an FPSAnimator with a given target frames-per-second
- value and an initial drawable to animate. Equivalent to
- <code>FPSAnimator(null, fps, false)</code>. */
- public FPSAnimator(GLAutoDrawable drawable, int fps) {
- this(drawable, fps, false);
- }
-
- /** Creates an FPSAnimator with a given target frames-per-second
- value, an initial drawable to animate, and a flag indicating
- whether to use fixed-rate scheduling. */
- public FPSAnimator(GLAutoDrawable drawable, int fps, boolean scheduleAtFixedRate) {
- this.fps = fps;
- if (drawable != null) {
- add(drawable);
+frames-per-second rate to avoid using all CPU time. The target FPS
+is only an estimate and is not guaranteed. */
+public class FPSAnimator extends AnimatorBase {
+ private Timer timer = null;
+ private TimerTask task = null;
+ private int fps;
+ private boolean scheduleAtFixedRate;
+ private volatile boolean shouldRun;
+
+ protected String getBaseName(String prefix) {
+ return "FPS" + prefix + "Animator" ;
+ }
+
+ /** Creates an FPSAnimator with a given target frames-per-second
+ value. Equivalent to <code>FPSAnimator(null, fps)</code>. */
+ public FPSAnimator(int fps) {
+ this(null, fps);
+ }
+
+ /** Creates an FPSAnimator with a given target frames-per-second
+ value and a flag indicating whether to use fixed-rate
+ scheduling. Equivalent to <code>FPSAnimator(null, fps,
+ scheduleAtFixedRate)</code>. */
+ public FPSAnimator(int fps, boolean scheduleAtFixedRate) {
+ this(null, fps, scheduleAtFixedRate);
+ }
+
+ /** Creates an FPSAnimator with a given target frames-per-second
+ value and an initial drawable to animate. Equivalent to
+ <code>FPSAnimator(null, fps, false)</code>. */
+ public FPSAnimator(GLAutoDrawable drawable, int fps) {
+ this(drawable, fps, false);
+ }
+
+ /** Creates an FPSAnimator with a given target frames-per-second
+ value, an initial drawable to animate, and a flag indicating
+ whether to use fixed-rate scheduling. */
+ public FPSAnimator(GLAutoDrawable drawable, int fps, boolean scheduleAtFixedRate) {
+ this.fps = fps;
+ if (drawable != null) {
+ add(drawable);
+ }
+ this.scheduleAtFixedRate = scheduleAtFixedRate;
+ }
+
+ public long getStartTime() { return startTime; }
+ public long getCurrentTime() { return curTime; }
+ public long getDuration() { return curTime-startTime; }
+ public int getTotalFrames() { return totalFrames; }
+
+ public final synchronized boolean isStarted() {
+ return (timer != null);
+ }
+
+ public final synchronized boolean isAnimating() {
+ return (timer != null) && (task != null);
+ }
+
+ public final synchronized boolean isPaused() {
+ return (timer != null) && (task == null);
}
- this.scheduleAtFixedRate = scheduleAtFixedRate;
- }
- /** Starts this FPSAnimator. */
- public synchronized void start() {
- if (timer != null) {
- throw new GLException("Already started");
+ private void startTask() {
+ long delay = (long) (1000.0f / (float) fps);
+ task = new TimerTask() {
+ public void run() {
+ if(FPSAnimator.this.shouldRun) {
+ FPSAnimator.this.thread = Thread.currentThread();
+ display();
+ }
+ }
+ };
+
+ startTime = System.currentTimeMillis();
+ curTime = startTime;
+ totalFrames = 0;
+ shouldRun = true;
+
+ if (scheduleAtFixedRate) {
+ timer.scheduleAtFixedRate(task, 0, delay);
+ } else {
+ timer.schedule(task, 0, delay);
+ }
}
- timer = new Timer();
- long delay = (long) (1000.0f / (float) fps);
- TimerTask task = new TimerTask() {
- public void run() {
- display();
+
+ public synchronized void start() {
+ if (timer != null) {
+ throw new GLException("Already started");
}
- };
- if (scheduleAtFixedRate) {
- timer.scheduleAtFixedRate(task, 0, delay);
- } else {
- timer.schedule(task, 0, delay);
+ timer = new Timer();
+ startTask();
}
- }
-
- /** Indicates whether this FPSAnimator is currently running. This
- should only be used as a heuristic to applications because in
- some circumstances the FPSAnimator may be in the process of
- shutting down and this method will still return true. */
- public synchronized boolean isAnimating() {
- return (timer != null);
- }
-
- /** Stops this FPSAnimator. Due to the implementation of the
- FPSAnimator it is not guaranteed that the FPSAnimator will be
- completely stopped by the time this method returns. */
- public synchronized void stop() {
- if (timer == null) {
- throw new GLException("Already stopped");
+
+ /** Stops this FPSAnimator. Due to the implementation of the
+ FPSAnimator it is not guaranteed that the FPSAnimator will be
+ completely stopped by the time this method returns. */
+ public synchronized void stop() {
+ if (timer == null) {
+ throw new GLException("Already stopped");
+ }
+ shouldRun = false;
+ task.cancel();
+ task = null;
+ timer.cancel();
+ timer = null;
+ thread = null;
+ }
+
+ public synchronized void pause() {
+ if (timer == null) {
+ throw new GLException("Not running");
+ }
+ shouldRun = false;
+ task.cancel();
+ task = null;
+ thread = null;
+ }
+
+ public synchronized void resume() {
+ if (timer == null) {
+ throw new GLException("Not running");
+ }
+ startTask();
+ }
+
+ protected final boolean getShouldPause() {
+ return (timer != null) && (task == null);
+ }
+
+ protected final boolean getShouldStop() {
+ return (timer == null);
}
- timer.cancel();
- timer = null;
- }
}
diff --git a/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
new file mode 100644
index 000000000..13788fe53
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.opengl;
+
+/**
+ * An animator control interface,
+ * which implementation may drive a {@link javax.media.opengl.GLAutoDrawable} animation.
+ * <P>
+ * Note that the methods {@link #start()}, {@link #stop()}, {@link #pause()} and {@link #resume()}
+ * shall be implemented to fail-fast, ie {@link #start()} fails if not started, etc.
+ * This way an implementation can find implementation errors faster.
+ */
+public interface GLAnimatorControl {
+
+ /**
+ * @return Time of the first display call in milliseconds.
+ * This value is reset if started or resumed.
+ *
+ * @see #start()
+ * @see #resume()
+ */
+ long getStartTime();
+
+ /**
+ * @return Time of the last display call in milliseconds.
+ * This value is reset if started or resumed.
+ *
+ * @see #start()
+ * @see #resume()
+ */
+ long getCurrentTime();
+
+ /**
+ * @return Duration <code>getCurrentTime() - getStartTime()</code>.
+ *
+ * @see #getStartTime()
+ * @see #getCurrentTime()
+ */
+ long getDuration();
+
+
+ /**
+ * @return Number of frames issued to all registered GLAutoDrawables registered
+ */
+ /**
+ * @return Number of frame cycles displayed by all registered {@link javax.media.opengl.GLAutoDrawable}
+ * since the first display call, ie <code>getStartTime()</code>.
+ * This value is reset if started or resumed.
+ *
+ * @see #start()
+ * @see #resume()
+ */
+ int getTotalFrames();
+
+ /**
+ * Indicates whether this animator is currently running, ie started.
+ *
+ * @see #start()
+ * @see #stop()
+ * @see #pause()
+ * @see #resume()
+ */
+ boolean isStarted();
+
+ /**
+ * Indicates whether this animator is currently running and not paused.
+ *
+ * @see #start()
+ * @see #stop()
+ * @see #pause()
+ * @see #resume()
+ */
+ boolean isAnimating();
+
+ /**
+ * Indicates whether this animator is currently running and paused.
+ *
+ * @see #start()
+ * @see #stop()
+ * @see #pause()
+ * @see #resume()
+ */
+ boolean isPaused();
+
+ /**
+ * @return The animation thread if started, ie running.
+ *
+ * @see #start()
+ * @see #stop()
+ */
+ Thread getThread();
+
+ /**
+ * Starts this animator, if not running.
+ * <P>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ * <P>
+ * If started, all counters (time, frames, ..) are reset to zero.
+ *
+ * @see #stop()
+ * @see #isAnimating()
+ * @see #getThread()
+ * @throws GLException if started and animating already
+ */
+ void start();
+
+ /**
+ * Stops this animator.
+ * <P>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ *
+ * @see #start()
+ * @see #isAnimating()
+ * @see #getThread()
+ * @throws GLException if not started or not animating
+ */
+ void stop();
+
+ /**
+ * Pauses this animator.
+ * <P>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ *
+ * @see #resume()
+ * @see #isAnimating()
+ * @throws GLException if not started or not animating or already paused
+ */
+ void pause();
+
+ /**
+ * Resumes animation if paused.
+ * <P>
+ * In most situations this method blocks until
+ * completion, except when called from the animation thread itself
+ * or in some cases from an implementation-internal thread like the
+ * AWT event queue thread.
+ * <P>
+ * If resumed, all counters (time, frames, ..) are reset to zero.
+ *
+ * @see #pause()
+ * @see #isAnimating()
+ * @throws GLException if not started or not paused
+ */
+ void resume();
+}
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 10a32fd1d..bc2f633ce 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -115,17 +116,6 @@ public interface GLAutoDrawable extends GLDrawable {
* where you drag the window to another monitor. */
public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true, AccessController.getContext());
- /** FIXME:
- ** Invalid state, the resources are not yet ready to render. *
- public static final int STATE_INVALID = 0;
-
- ** Valid state, all resources are ready to render,
- and all registered {@link GLEventListener#init init(..)} are called. *
- public static final int STATE_VALID = 1;
-
- ** Destroying state, currently executing the {@link #destroy()} method. *
- public static final int STATE_DESTROYING = 2; */
-
/**
* Returns the context associated with this drawable. The returned
* context will be synchronized.
@@ -163,58 +153,55 @@ public interface GLAutoDrawable extends GLDrawable {
/**
* <p>
- * Indicates whether a running animator thread is periodically issuing {@link #display()} calls or not.</p><br>
+ * Registers the usage of an animator, an {@link javax.media.opengl.GLAnimatorControl} implementation.
+ * The animator will be queried whether it's animating, ie periodically issuing {@link #display()} calls or not.</p><br>
* <p>
* This method shall be called by an animator implementation only,<br>
- * e.g. {@link com.jogamp.opengl.util.Animator#start()}, passing the animator thread,<br>
- * and {@link com.jogamp.opengl.util.Animator#stop()}, passing <code>null</code>.</p><br>
+ * e.g. {@link com.jogamp.opengl.util.Animator#add(javax.media.opengl.GLAutoDrawable)}, passing it's control implementation,<br>
+ * and {@link com.jogamp.opengl.util.Animator#remove(javax.media.opengl.GLAutoDrawable)}, passing <code>null</code>.</p><br>
* <p>
* Impacts {@link #display()} and {@link #invoke(boolean, GLRunnable)} semantics.</p><br>
*
- * @param animator <code>null</code> reference indicates no running animator thread
- * issues {@link #display()} calls on this <code>GLAutoDrawable</code>,<br>
- * a valid reference indicates a running animator thread
- * periodically issuing {@link #display()} calls.
+ * @param animator <code>null</code> reference indicates no animator is using
+ * this <code>GLAutoDrawable</code>,<br>
+ * a valid reference indicates an animator is using this <code>GLAutoDrawable</code>.
*
- * @throws GLException if a running animator thread is already registered and you try to register a different one without unregistering the previous one.
+ * @throws GLException if an animator is already registered.
* @see #display()
* @see #invoke(boolean, GLRunnable)
+ * @see javax.media.opengl.GLAnimatorControl
*/
- public void setAnimator(Thread animator) throws GLException;
+ public abstract void setAnimator(GLAnimatorControl animatorControl) throws GLException;
/**
- * @return the value of the registered animator thread
+ * @return the registered {@link javax.media.opengl.GLAnimatorControl} implementation, using this <code>GLAutoDrawable</code>.
*
- * @see #setAnimator(Thread)
+ * @see #setAnimator(javax.media.opengl.GLAnimatorControl)
+ * @see javax.media.opengl.GLAnimatorControl
*/
- public Thread getAnimator();
+ public GLAnimatorControl getAnimator();
/**
* <p>
* Enqueues a one-shot {@link javax.media.opengl.GLRunnable},
- * which will be executed with the next {@link #display()} call.</p><br>
+ * which will be executed with the next {@link #display()} call.</p>
* <p>
- * If {@link #setAnimator(Thread)} has not registered no running animator thread, the default,<br>
+ * If a {@link javax.media.opengl.GLAnimatorControl} is registered, or if it's not animating, the default situation,<br>
* or if the current thread is the animator thread,<br>
- * a {@link #display()} call has to be issued after enqueueing the <code>GLRunnable</code>.<br>
- * No extra synchronization must be performed in case <code>wait</code> is true, since it is executed in the current thread.</p><br>
+ * a {@link #display()} call has to be issued after enqueue the <code>GLRunnable</code>.<br>
+ * No extra synchronization must be performed in case <code>wait</code> is true, since it is executed in the current thread.</p>
* <p>
- * If {@link #setAnimator(Thread)} has registered a valid animator thread,<br>
- * no call of {@link #display()} must be issued, since the animator thread performs it.<br>
- * If <code>wait</code> is true, the implementation must wait until the <code>GLRunnable</code> is excecuted.</p><br>
+ * If {@link javax.media.opengl.GLAnimatorControl} is registered and is animating,<br>
+ * no call of {@link #display()} must be issued, since the animator thread will performs it.<br>
+ * If <code>wait</code> is true, the implementation must wait until the <code>GLRunnable</code> is executed.<br>
+ * </p><br>
*
- * @see #setAnimator(Thread)
+ * @see #setAnimator(javax.media.opengl.GLAnimatorControl)
* @see #display()
* @see javax.media.opengl.GLRunnable
*/
public void invoke(boolean wait, GLRunnable glRunnable);
- /** FIXME: Returns the current state,
- {@link #STATE_INVALID}, {@link #STATE_VALID} or {@link #STATE_DESTROYING}.
- Tool to determine, e.g. if a {@link GLEventListener#dispose dispose(..)}
- event is send in the context of the destruction of this GLAutoDrawable.
- public int getCurrentState(); */
-
/** Destroys all resources associated with this GLAutoDrawable,
inclusive the GLContext.
If a window is attached to it's implementation, it shall be closed.
@@ -236,14 +223,13 @@ public interface GLAutoDrawable extends GLDrawable {
* enqueued via {@link #invoke(boolean, GLRunnable)}.</li>
* </ul></p>
* <p>
- * Called automatically by the
- * window system toolkit upon receiving a repaint() request,
- * except a running animator thread is registered with {@link #setAnimator(Thread)}.</p> <br>
- * <p>
- * Maybe called periodically by a running animator thread,<br>
- * which must register itself with {@link #setAnimator(Thread)}.</p> <br>
+ * May be called periodically by a running {@link javax.media.opengl.GLAnimatorControl} implementation,<br>
+ * which must register itself with {@link #setAnimator(javax.media.opengl.GLAnimatorControl)}.</p>
+ * <p>
+ * Called automatically by the window system toolkit upon receiving a repaint() request, <br>
+ * except an {@link javax.media.opengl.GLAnimatorControl} implementation {@link javax.media.opengl.GLAnimatorControl#isAnimating()}.</p>
* <p>
- * This routine may be called manually for better control over the
+ * This routine may also be called manually for better control over the
* rendering process. It is legal to call another GLAutoDrawable's
* display method from within the {@link GLEventListener#display
* display(..)} callback.</p>
@@ -254,7 +240,7 @@ public interface GLAutoDrawable extends GLDrawable {
* actual {@link GLEventListener#display display(..)} calls,
* in case this has not been done yet.</p>
*
- * @see #setAnimator(Thread)
+ * @see #setAnimator(javax.media.opengl.GLAnimatorControl)
*/
public void display();
diff --git a/src/jogl/classes/javax/media/opengl/GLRunnable.java b/src/jogl/classes/javax/media/opengl/GLRunnable.java
index 9d8345fb4..de0f5df48 100644
--- a/src/jogl/classes/javax/media/opengl/GLRunnable.java
+++ b/src/jogl/classes/javax/media/opengl/GLRunnable.java
@@ -28,16 +28,20 @@
package javax.media.opengl;
-/** <p> Declares one-shot OpenGL commands, which client code can use to manage OpenGL
- commands into a {@link GLAutoDrawable}. At the time any of these
- methods is called, the drawable has made its associated OpenGL
- context current, so it is valid to make OpenGL calls.<br></p>
- <p> A GLRunnable maybe used to inject OpenGL commands via I/O event listener,
- via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}.</p>
- */
+/**
+ * <p>
+ * Declares one-shot OpenGL commands usable for injection into a {@link GLAutoDrawable},<br>
+ * via {@link GLAutoDrawable#invoke(boolean, javax.media.opengl.GLRunnable)}.<br>
+ * {@link GLAutoDrawable} executes these commands within it's {@link GLAutoDrawable#display()}
+ * method while the OpenGL context is current.<br>
+ * <p>
+ * This might be useful to inject OpenGL commands from an I/O event listener.
+ */
public interface GLRunnable {
- /** Called by the drawable to initiate one-shot OpenGL commands by the
- client, like {@link GLEventListener#display(GLAutoDrawable)}. */
- public void run(GLAutoDrawable drawable);
+ /**
+ * Called by the drawable to initiate one-shot OpenGL commands by the
+ * client, like {@link GLEventListener#display(GLAutoDrawable)}.
+ */
+ void run(GLAutoDrawable drawable);
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index f150b2507..705b12783 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -377,8 +378,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
(int) ((getHeight() + bounds.getHeight()) / 2));
return;
}
-
- if( null == getAnimator() ) {
+ if( this.drawableHelper.isExternalAnimatorAnimating() ) {
display();
}
}
@@ -494,11 +494,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
drawableHelper.removeGLEventListener(listener);
}
- public void setAnimator(Thread animator) {
- drawableHelper.setAnimator(animator);
+ public void setAnimator(GLAnimatorControl animatorControl) {
+ drawableHelper.setAnimator(animatorControl);
}
- public Thread getAnimator() {
+ public GLAnimatorControl getAnimator() {
return drawableHelper.getAnimator();
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index d0d97fe31..72b782f9a 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -286,6 +287,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
return;
}
+ if ( drawableHelper.isExternalAnimatorAnimating() ) {
+ return;
+ }
+
if (backend == null || !isInitialized) {
createAndInitializeBackend();
}
@@ -380,11 +385,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable {
drawableHelper.removeGLEventListener(listener);
}
- public void setAnimator(Thread animator) {
- drawableHelper.setAnimator(animator);
+ public void setAnimator(GLAnimatorControl animatorControl) {
+ drawableHelper.setAnimator(animatorControl);
}
- public Thread getAnimator() {
+ public GLAnimatorControl getAnimator() {
return drawableHelper.getAnimator();
}