From 34fffab0bb25bbf8a4cd2bf372e018748982b9bc Mon Sep 17 00:00:00 2001
From: Sven Gothel An Animator can be attached to one or more {@link
GLAutoDrawable}s to drive their display() methods in a loop.
FPSAnimator(null, fps)
. */
- 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 FPSAnimator(null, fps,
- scheduleAtFixedRate)
. */
- 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
- FPSAnimator(null, fps, false)
. */
- 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 FPSAnimator(null, fps)
. */
+ 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 FPSAnimator(null, fps,
+ scheduleAtFixedRate)
. */
+ 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
+ FPSAnimator(null, fps, false)
. */
+ 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.
+ *
+ * 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 getCurrentTime() - getStartTime()
.
+ *
+ * @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 getStartTime()
.
+ * 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.
+ *
+ * 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. + *
+ * 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. + *
+ * 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. + *
+ * 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. + *
+ * 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. + *
+ * 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 { /** *
- * Indicates whether a running animator thread is periodically issuing {@link #display()} calls or not.
* This method shall be called by an animator implementation only,
- * e.g. {@link com.jogamp.opengl.util.Animator#start()}, passing the animator thread,
- * and {@link com.jogamp.opengl.util.Animator#stop()}, passing null
.
null
.* Impacts {@link #display()} and {@link #invoke(boolean, GLRunnable)} semantics.
null
reference indicates no running animator thread
- * issues {@link #display()} calls on this GLAutoDrawable
,null
reference indicates no animator is using
+ * this GLAutoDrawable
,GLAutoDrawable
.
*
- * @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 GLAutoDrawable
.
*
- * @see #setAnimator(Thread)
+ * @see #setAnimator(javax.media.opengl.GLAnimatorControl)
+ * @see javax.media.opengl.GLAnimatorControl
*/
- public Thread getAnimator();
+ public GLAnimatorControl getAnimator();
/**
* * Enqueues a one-shot {@link javax.media.opengl.GLRunnable}, - * which will be executed with the next {@link #display()} call.
- * If {@link #setAnimator(Thread)} has not registered no running animator thread, the default,
+ * If a {@link javax.media.opengl.GLAnimatorControl} is registered, or if it's not animating, the default situation,
* or if the current thread is the animator thread,
- * a {@link #display()} call has to be issued after enqueueing the GLRunnable
.
- * No extra synchronization must be performed in case wait
is true, since it is executed in the current thread.
GLRunnable
.wait
is true, since it is executed in the current thread.
*
- * If {@link #setAnimator(Thread)} has registered a valid animator thread,
- * no call of {@link #display()} must be issued, since the animator thread performs it.
- * If wait
is true, the implementation must wait until the GLRunnable
is excecuted.
wait
is true, the implementation must wait until the GLRunnable
is executed.- * Called automatically by the - * window system toolkit upon receiving a repaint() request, - * except a running animator thread is registered with {@link #setAnimator(Thread)}.
- * Maybe called periodically by a running animator thread,
- * which must register itself with {@link #setAnimator(Thread)}.
+ * Called automatically by the window system toolkit upon receiving a repaint() request,
+ * except an {@link javax.media.opengl.GLAnimatorControl} implementation {@link javax.media.opengl.GLAnimatorControl#isAnimating()}.
- * 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.
@@ -254,7 +240,7 @@ public interface GLAutoDrawable extends GLDrawable { * actual {@link GLEventListener#display display(..)} calls, * in case this has not been done yet. * - * @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; -/** 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.
A GLRunnable maybe used to inject OpenGL commands via I/O event listener, - via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}.
- */ +/** + *
+ * Declares one-shot OpenGL commands usable for injection into a {@link GLAutoDrawable},
+ * via {@link GLAutoDrawable#invoke(boolean, javax.media.opengl.GLRunnable)}.
+ * {@link GLAutoDrawable} executes these commands within it's {@link GLAutoDrawable#display()}
+ * method while the OpenGL context is current.
+ *
+ * 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(); } -- cgit v1.2.3