40package com.jogamp.opengl.util;
42import java.util.Timer;
43import java.util.TimerTask;
45import com.jogamp.opengl.GLAutoDrawable;
46import com.jogamp.opengl.GLException;
47import com.jogamp.opengl.GLProfile;
48import com.jogamp.common.ExceptionUtils;
61 private Timer timer =
null;
62 private MainTask task =
null;
64 private final boolean scheduleAtFixedRate;
65 private boolean isAnimating;
66 private volatile boolean pauseIssued;
67 private volatile boolean stopIssued;
71 return "FPS" + prefix +
"Animator" ;
115 public FPSAnimator(
final int fps,
final boolean scheduleAtFixedRate) {
168 if (drawable !=
null) {
171 this.scheduleAtFixedRate = scheduleAtFixedRate;
180 throw new GLException(
"Animator already started.");
184 public final int getFPS() {
return fps; }
186 class MainTask
extends TimerTask {
187 private boolean justStarted;
188 private boolean alreadyStopped;
189 private boolean alreadyPaused;
194 public void start(
final Timer timer) {
201 alreadyStopped =
false;
202 alreadyPaused =
false;
204 final long period = 0 < fps ? (long) (1000.0f / fps) : 1;
205 if (scheduleAtFixedRate) {
206 timer.scheduleAtFixedRate(
this, 0, period);
208 timer.schedule(
this, 0, period);
212 public boolean isActive() {
return !alreadyStopped && !alreadyPaused; }
216 return "Task[thread "+
animThread+
", stopped "+alreadyStopped+
", paused "+alreadyPaused+
" pauseIssued "+pauseIssued+
", stopIssued "+stopIssued+
" -- started "+
isStarted()+
", animating "+isAnimatingImpl()+
", paused "+
isPaused()+
", drawable "+
drawables.size()+
", drawablesEmpty "+
drawablesEmpty+
"]";
221 UncaughtAnimatorException caughtException =
null;
228 System.err.println(
"FPSAnimator start/resume:" + Thread.currentThread() +
": " +
toString());
239 System.err.println(
"FPSAnimator P1:" + Thread.currentThread() +
": " +
toString());
243 if( !pauseIssued && !stopIssued ) {
246 }
catch (
final UncaughtAnimatorException dre) {
247 caughtException = dre;
250 }
else if( pauseIssued && !stopIssued ) {
252 System.err.println(
"FPSAnimator pausing: "+alreadyPaused+
", "+ Thread.currentThread() +
": " +
toString());
256 if( !alreadyPaused ) {
257 alreadyPaused =
true;
262 }
catch (
final UncaughtAnimatorException dre) {
263 caughtException = dre;
267 if(
null == caughtException ) {
270 System.err.println(
"FPSAnimator pause " + Thread.currentThread() +
": " +
toString());
280 System.err.println(
"FPSAnimator stopping: "+alreadyStopped+
", "+ Thread.currentThread() +
": " +
toString());
284 if( !alreadyStopped ) {
285 alreadyStopped =
true;
290 }
catch (
final UncaughtAnimatorException dre) {
291 if(
null == caughtException ) {
292 caughtException = dre;
294 System.err.println(
"FPSAnimator.setExclusiveContextThread: caught: "+dre.getMessage());
295 dre.printStackTrace();
300 boolean throwCaughtException =
false;
303 System.err.println(
"FPSAnimator stop " + Thread.currentThread() +
": " +
toString());
304 if(
null != caughtException ) {
305 System.err.println(
"Animator caught: "+caughtException.getMessage());
306 caughtException.printStackTrace();
310 if(
null != caughtException ) {
320 if( throwCaughtException ) {
321 throw caughtException;
327 private final boolean isAnimatingImpl() {
340 static int timerNo = 0;
343 public final synchronized boolean start() {
344 if (
null != timer ||
null != task ||
isStarted() ) {
348 task =
new MainTask();
350 System.err.println(
"FPSAnimator.start() START: "+task+
", "+ Thread.currentThread() +
": " +
toString());
357 System.err.println(
"FPSAnimator.start() END: "+task+
", "+ Thread.currentThread() +
": " +
toString());
365 private final Condition waitForStartedAddedCondition =
new Condition() {
367 public boolean eval() {
370 private final Condition waitForStartedEmptyCondition =
new Condition() {
372 public boolean eval() {
380 public final synchronized boolean stop() {
385 System.err.println(
"FPSAnimator.stop() START: "+task+
", "+ Thread.currentThread() +
": " +
toString());
397 System.err.println(
"FPSAnimator.stop() END: "+task+
", "+ Thread.currentThread() +
": " +
toString());
410 private final Condition waitForStoppedCondition =
new Condition() {
412 public boolean eval() {
417 public final synchronized boolean pause() {
422 System.err.println(
"FPSAnimator.pause() START: "+task+
", "+ Thread.currentThread() +
": " +
toString());
434 System.err.println(
"FPSAnimator.pause() END: "+task+
", "+ Thread.currentThread() +
": " +
toString());
442 private final Condition waitForPausedCondition =
new Condition() {
444 public boolean eval() {
450 public final synchronized boolean resume() {
455 System.err.println(
"FPSAnimator.resume() START: "+ Thread.currentThread() +
": " +
toString());
463 System.err.println(
"FPSAnimator.resume() Ops: !pauseIssued, but task != null: "+
toString());
464 ExceptionUtils.dumpStack(System.err);
469 task =
new MainTask();
474 System.err.println(
"FPSAnimator.resume() END: "+task+
", "+ Thread.currentThread() +
": " +
toString());
478 private final Condition waitForResumeCondition =
new Condition() {
480 public boolean eval() {
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Base implementation of GLAnimatorControl
static String getThreadName()
static final boolean DEBUG
final synchronized void setDrawablesExclCtxState(final boolean enable)
Should be called at start() and stop() from within the animator thread.
static final int MODE_EXPECT_AWT_RENDERING_THREAD
If present in modeBits field and AWT is available, implementation is aware of the AWT EDT,...
final void display()
Called every frame to cause redrawing of all of the GLAutoDrawables this Animator manages.
final void flushGLRunnables()
Should be called in case of an uncaught exception from within the animator thread to flush all animat...
final synchronized boolean handleUncaughtException(final UncaughtAnimatorException ue)
Should be called in case of an uncaught exception from within the animator thread,...
ArrayList< GLAutoDrawable > drawables
final synchronized boolean finishLifecycleAction(final Condition waitCondition, long pollPeriod)
final synchronized void add(final GLAutoDrawable drawable)
Adds a drawable to this animator's list of rendering drawables.
FPSCounterImpl fpsCounter
static final long POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION
synchronized boolean isStarted()
Indicates whether this animator has been started.
An Animator subclass which attempts to achieve a target frames-per-second rate to avoid using all CPU...
FPSAnimator(final int modeBits, final int fps)
Creates an FPSAnimator with modeBits, see AnimatorBase#AnimatorBase(int) and a given target frames-pe...
final synchronized boolean isPaused()
Indicates whether this animator is started and either manually paused or paused automatically due to ...
FPSAnimator(final GLAutoDrawable drawable, final int fps, final boolean scheduleAtFixedRate)
Creates an FPSAnimator with a given target frames-per-second value, an initial drawable to animate,...
FPSAnimator(final int fps, final boolean scheduleAtFixedRate)
Creates an FPSAnimator with a given target frames-per-second value and a flag indicating whether to u...
String getBaseName(final String prefix)
final synchronized boolean start()
Starts this animator, if not running.
FPSAnimator(final int fps)
Creates an FPSAnimator with a given target frames-per-second value.
FPSAnimator(final GLAutoDrawable drawable, final int fps)
Creates an FPSAnimator with a given target frames-per-second value and an initial drawable to animate...
final synchronized boolean pause()
Pauses this animator.
FPSAnimator(final int modeBits, final GLAutoDrawable drawable, final int fps, final boolean scheduleAtFixedRate)
Creates an FPSAnimator with modeBits, see AnimatorBase#AnimatorBase(int), a given target frames-per-s...
final synchronized boolean isAnimating()
Indicates whether this animator is started and is not paused.
final void setFPS(final int fps)
final synchronized boolean resume()
Resumes animation if paused.
final synchronized boolean stop()
Stops this FPSAnimator.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...