aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/scripts/tests.sh5
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/Animator.java94
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java92
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java57
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java374
5 files changed, 260 insertions, 362 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 1f4ca9fc7..468672325 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -462,11 +462,10 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestAWTCloseX11DisplayBug565 $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimatorGLWindow01NEWT $*
+testnoawt com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimatorGLWindow01NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimatorGLJPanel01AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimatorGLCanvas01AWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.anim.TestAWTCardLayoutAnimatorStartStopBug532 $*
-testawt com.jogamp.opengl.test.junit.jogl.acore.anim.Bug898AnimatorFromEDTAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.anim.Bug898AnimatorFromEDTAWT $*
#
# NEWT
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
index 27b9427eb..799069292 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
@@ -110,7 +110,7 @@ public class Animator extends AnimatorBase {
}
@Override
- protected String getBaseName(String prefix) {
+ protected final String getBaseName(String prefix) {
return prefix + "Animator" ;
}
@@ -120,40 +120,28 @@ public class Animator extends AnimatorBase {
* animation loop which prevents the CPU from getting swamped.
* This method may not have an effect on subclasses.
*/
- public final void setRunAsFastAsPossible(boolean runFast) {
- stateSync.lock();
- try {
- runAsFastAsPossible = runFast;
- } finally {
- stateSync.unlock();
- }
- }
-
- private final void setIsAnimatingSynced(boolean v) {
- stateSync.lock();
- try {
- isAnimating = v;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized void setRunAsFastAsPossible(boolean runFast) {
+ runAsFastAsPossible = runFast;
}
class MainLoop implements Runnable {
@Override
public String toString() {
- return "[started "+isStartedImpl()+", animating "+isAnimatingImpl()+", paused "+isPausedImpl()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
+ return "[started "+isStarted()+", animating "+isAnimating()+", paused "+isPaused()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
}
@Override
public void run() {
try {
- if(DEBUG) {
- System.err.println("Animator start on " + getThreadName() + ": " + toString());
+ synchronized (Animator.this) {
+ if(DEBUG) {
+ System.err.println("Animator start on " + getThreadName() + ": " + toString());
+ }
+ fpsCounter.resetFPSCounter();
+ animThread = Thread.currentThread();
+ isAnimating = false;
+ // 'waitForStartedCondition' wake-up is handled below!
}
- fpsCounter.resetFPSCounter();
- animThread = Thread.currentThread();
- setIsAnimatingSynced(false); // barrier
- // 'waitForStartedCondition' wake-up is handled below!
while (!stopIssued) {
synchronized (Animator.this) {
@@ -172,7 +160,7 @@ public class Animator extends AnimatorBase {
setDrawablesExclCtxState(false);
display(); // propagate exclusive change!
}
- setIsAnimatingSynced(false); // barrier
+ isAnimating = false;
Animator.this.notifyAll();
try {
Animator.this.wait();
@@ -191,7 +179,7 @@ public class Animator extends AnimatorBase {
// - and -
// Resume from pause or drawablesEmpty,
// implies !pauseIssued and !drawablesEmpty
- setIsAnimatingSynced(true); // barrier
+ isAnimating = true;
setDrawablesExclCtxState(exclusiveContext);
Animator.this.notifyAll();
}
@@ -221,37 +209,21 @@ public class Animator extends AnimatorBase {
stopIssued = false;
pauseIssued = false;
animThread = null;
- setIsAnimatingSynced(false); // barrier
+ isAnimating = false;
Animator.this.notifyAll();
}
}
}
}
- private final boolean isAnimatingImpl() {
- return animThread != null && isAnimating ;
- }
@Override
- public final boolean isAnimating() {
- stateSync.lock();
- try {
- return animThread != null && isAnimating ;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized boolean isAnimating() {
+ return animThread != null && isAnimating ;
}
- private final boolean isPausedImpl() {
- return animThread != null && pauseIssued ;
- }
@Override
- public final boolean isPaused() {
- stateSync.lock();
- try {
- return animThread != null && pauseIssued ;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized boolean isPaused() {
+ return animThread != null && pauseIssued ;
}
/**
@@ -260,16 +232,16 @@ public class Animator extends AnimatorBase {
* @param tg the {@link ThreadGroup}
* @throws GLException if the animator has already been started
*/
- public synchronized void setThreadGroup(ThreadGroup tg) throws GLException {
- if ( isStartedImpl() ) {
+ public final synchronized void setThreadGroup(ThreadGroup tg) throws GLException {
+ if ( isStarted() ) {
throw new GLException("Animator already started.");
}
threadGroup = tg;
}
@Override
- public synchronized boolean start() {
- if ( isStartedImpl() ) {
+ public final synchronized boolean start() {
+ if ( isStarted() ) {
return false;
}
if (runnable == null) {
@@ -294,12 +266,12 @@ public class Animator extends AnimatorBase {
private final Condition waitForStartedCondition = new Condition() {
@Override
public boolean eval() {
- return !isStartedImpl() || (!drawablesEmpty && !isAnimating) ;
+ return !isStarted() || (!drawablesEmpty && !isAnimating) ;
} };
@Override
- public synchronized boolean stop() {
- if ( !isStartedImpl() ) {
+ public final synchronized boolean stop() {
+ if ( !isStarted() ) {
return false;
}
stopIssued = true;
@@ -308,12 +280,12 @@ public class Animator extends AnimatorBase {
private final Condition waitForStoppedCondition = new Condition() {
@Override
public boolean eval() {
- return isStartedImpl();
+ return isStarted();
} };
@Override
- public synchronized boolean pause() {
- if ( !isStartedImpl() || pauseIssued ) {
+ public final synchronized boolean pause() {
+ if ( !isStarted() || pauseIssued ) {
return false;
}
pauseIssued = true;
@@ -323,12 +295,12 @@ public class Animator extends AnimatorBase {
@Override
public boolean eval() {
// end waiting if stopped as well
- return isStartedImpl() && isAnimating;
+ return isStarted() && isAnimating;
} };
@Override
- public synchronized boolean resume() {
- if ( !isStartedImpl() || !pauseIssued ) {
+ public final synchronized boolean resume() {
+ if ( !isStarted() || !pauseIssued ) {
return false;
}
pauseIssued = false;
@@ -338,6 +310,6 @@ public class Animator extends AnimatorBase {
@Override
public boolean eval() {
// end waiting if stopped as well
- return isStartedImpl() && ( !drawablesEmpty && !isAnimating || drawablesEmpty && !pauseIssued ) ;
+ return isStarted() && ( !drawablesEmpty && !isAnimating || drawablesEmpty && !pauseIssued ) ;
} };
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
index ee2754bdf..39643744a 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
@@ -28,8 +28,6 @@
package com.jogamp.opengl.util;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
import jogamp.opengl.Debug;
import jogamp.opengl.FPSCounterImpl;
@@ -86,7 +84,6 @@ public abstract class AnimatorBase implements GLAnimatorControl {
protected boolean exclusiveContext;
protected Thread userExclusiveContextThread;
protected FPSCounterImpl fpsCounter = new FPSCounterImpl();
- protected RecursiveLock stateSync = LockFactory.createRecursiveLock();
private final static Class<?> awtAnimatorImplClazz;
static {
@@ -129,7 +126,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
*
* @throws GLException if Animator is {@link #isStarted()}
*/
- protected synchronized void initImpl(boolean force) {
+ protected final synchronized void initImpl(boolean force) {
if( force || null == impl ) {
if( useAWTAnimatorImpl( modeBits ) ) {
try {
@@ -157,7 +154,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
* @throws GLException if Animator is {@link #isStarted()} and {@link #MODE_EXPECT_AWT_RENDERING_THREAD} about to change
* @see AnimatorBase#MODE_EXPECT_AWT_RENDERING_THREAD
*/
- public synchronized void setModeBits(boolean enable, int bitValues) throws GLException {
+ public final synchronized void setModeBits(boolean enable, int bitValues) throws GLException {
final int _oldModeBits = modeBits;
if(enable) {
modeBits |= bitValues;
@@ -175,7 +172,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
@Override
- public synchronized void add(final GLAutoDrawable drawable) {
+ public final synchronized void add(final GLAutoDrawable drawable) {
if(DEBUG) {
System.err.println("Animator add: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName());
}
@@ -207,7 +204,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
}
@Override
- public synchronized void remove(final GLAutoDrawable drawable) {
+ public final synchronized void remove(final GLAutoDrawable drawable) {
if(DEBUG) {
System.err.println("Animator remove: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName());
}
@@ -270,17 +267,11 @@ public abstract class AnimatorBase implements GLAnimatorControl {
* @see #isExclusiveContextEnabled()
*/
// @Override
- public final Thread setExclusiveContext(Thread t) {
- final Thread old;
+ public final synchronized Thread setExclusiveContext(Thread t) {
final boolean enable = null != t;
- stateSync.lock();
- try {
- old = userExclusiveContextThread;
- if( enable && t != animThread ) { // disable: will be cleared at end after propagation && filter out own animThread usae
- userExclusiveContextThread=t;
- }
- } finally {
- stateSync.unlock();
+ final Thread old = userExclusiveContextThread;
+ if( enable && t != animThread ) { // disable: will be cleared at end after propagation && filter out own animThread usae
+ userExclusiveContextThread=t;
}
setExclusiveContext(enable);
return old;
@@ -340,11 +331,8 @@ public abstract class AnimatorBase implements GLAnimatorControl {
pause();
}
}
- stateSync.lock();
- try {
+ synchronized(AnimatorBase.this) {
userExclusiveContextThread=null;
- } finally {
- stateSync.unlock();
}
}
}
@@ -361,13 +349,8 @@ public abstract class AnimatorBase implements GLAnimatorControl {
* @see #setExclusiveContext(Thread)
*/
// @Override
- public final boolean isExclusiveContextEnabled() {
- stateSync.lock();
- try {
- return exclusiveContext;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized boolean isExclusiveContextEnabled() {
+ return exclusiveContext;
}
/**
@@ -384,13 +367,8 @@ public abstract class AnimatorBase implements GLAnimatorControl {
* @see #setExclusiveContext(Thread)
*/
// @Override
- public final Thread getExclusiveContextThread() {
- stateSync.lock();
- try {
- return ( isStartedImpl() && exclusiveContext ) ? ( null != userExclusiveContextThread ? userExclusiveContextThread : animThread ) : null ;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized Thread getExclusiveContextThread() {
+ return ( isStarted() && exclusiveContext ) ? ( null != userExclusiveContextThread ? userExclusiveContextThread : animThread ) : null ;
}
/**
@@ -425,13 +403,8 @@ public abstract class AnimatorBase implements GLAnimatorControl {
}
@Override
- public final Thread getThread() {
- stateSync.lock();
- try {
- return animThread;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized Thread getThread() {
+ return animThread;
}
/** Called every frame to cause redrawing of all of the
@@ -439,7 +412,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
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() {
+ protected final void display() {
impl.display(drawables, ignoreExceptions, printExceptions);
fpsCounter.tickFPS();
}
@@ -497,7 +470,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
/** 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) {
+ public final void setIgnoreExceptions(boolean ignoreExceptions) {
this.ignoreExceptions = ignoreExceptions;
}
@@ -505,7 +478,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
this Animator (see {@link #setIgnoreExceptions}), to print the
exceptions' stack traces for diagnostic information. Defaults to
false. */
- public void setPrintExceptions(boolean printExceptions) {
+ public final void setPrintExceptions(boolean printExceptions) {
this.printExceptions = printExceptions;
}
@@ -522,7 +495,7 @@ public abstract class AnimatorBase implements GLAnimatorControl {
* if &gt; <code>0</code>, method will wait for the given <code>pollPeriod</code> in milliseconds.
* @return <code>true</code> if {@link Condition#eval() waitCondition.eval()} returned <code>false</code>, otherwise <code>false</code>.
*/
- protected synchronized boolean finishLifecycleAction(Condition waitCondition, long pollPeriod) {
+ protected final synchronized boolean finishLifecycleAction(Condition waitCondition, long pollPeriod) {
/**
* It's hard to tell whether the thread which changes the lifecycle has
* dependencies on the Animator's internal thread. Currently we
@@ -570,16 +543,11 @@ public abstract class AnimatorBase implements GLAnimatorControl {
if( blocking && remaining<=0 && nok ) {
System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): ++++++ timeout reached ++++++ " + getThreadName());
}
- stateSync.lock(); // avoid too many lock/unlock ops
- try {
- System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): OK "+(!nok)+
- "- pollPeriod "+pollPeriod+", blocking "+blocking+
- ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION +
- " - " + getThreadName());
- System.err.println(" - "+toString());
- } finally {
- stateSync.unlock();
- }
+ System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): OK "+(!nok)+
+ "- pollPeriod "+pollPeriod+", blocking "+blocking+
+ ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION +
+ " - " + getThreadName());
+ System.err.println(" - "+toString());
if(nok) {
Thread.dumpStack();
}
@@ -587,17 +555,9 @@ public abstract class AnimatorBase implements GLAnimatorControl {
return !nok;
}
- protected final boolean isStartedImpl() {
- return animThread != null ;
- }
@Override
- public boolean isStarted() {
- stateSync.lock();
- try {
- return animThread != null ;
- } finally {
- stateSync.unlock();
- }
+ public synchronized boolean isStarted() {
+ return animThread != null ;
}
protected static String getThreadName() { return Thread.currentThread().getName(); }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
index 351c47e7e..65fed17f2 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
@@ -59,7 +59,7 @@ public class FPSAnimator extends AnimatorBase {
private Timer timer = null;
private MainTask task = null;
private int fps;
- private boolean scheduleAtFixedRate;
+ private final boolean scheduleAtFixedRate;
private boolean isAnimating; // MainTask feedback
private volatile boolean shouldRun; // MainTask trigger
private volatile boolean shouldStop; // MainTask trigger
@@ -107,7 +107,7 @@ public class FPSAnimator extends AnimatorBase {
* @throws GLException if the animator has already been started
*/
public final synchronized void setFPS(int fps) throws GLException {
- if ( isStartedImpl() ) {
+ if ( isStarted() ) {
throw new GLException("Animator already started.");
}
this.fps = fps;
@@ -131,7 +131,7 @@ public class FPSAnimator extends AnimatorBase {
alreadyStopped = false;
alreadyPaused = false;
- final long period = 0 < fps ? (long) (1000.0f / (float) fps) : 1; // 0 -> 1: IllegalArgumentException: Non-positive period
+ final long period = 0 < fps ? (long) (1000.0f / fps) : 1; // 0 -> 1: IllegalArgumentException: Non-positive period
if (scheduleAtFixedRate) {
timer.scheduleAtFixedRate(this, 0, period);
} else {
@@ -142,8 +142,8 @@ public class FPSAnimator extends AnimatorBase {
public boolean isActive() { return !alreadyStopped && !alreadyPaused; }
@Override
- public String toString() {
- return "Task[thread "+animThread+", stopped "+alreadyStopped+", paused "+alreadyPaused+" shouldRun "+shouldRun+", shouldStop "+shouldStop+" -- started "+isStartedImpl()+", animating "+isAnimatingImpl()+", paused "+isPausedImpl()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
+ public final String toString() {
+ return "Task[thread "+animThread+", stopped "+alreadyStopped+", paused "+alreadyPaused+" shouldRun "+shouldRun+", shouldStop "+shouldStop+" -- started "+isStarted()+", animating "+isAnimatingImpl()+", paused "+isPaused()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
}
@Override
@@ -212,33 +212,20 @@ public class FPSAnimator extends AnimatorBase {
return animThread != null && isAnimating ;
}
@Override
- public final boolean isAnimating() {
- stateSync.lock();
- try {
- return animThread != null && isAnimating ;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized boolean isAnimating() {
+ return animThread != null && isAnimating ;
}
- private final boolean isPausedImpl() {
- return animThread != null && ( !shouldRun && !shouldStop ) ;
- }
@Override
- public final boolean isPaused() {
- stateSync.lock();
- try {
- return animThread != null && ( !shouldRun && !shouldStop ) ;
- } finally {
- stateSync.unlock();
- }
+ public final synchronized boolean isPaused() {
+ return animThread != null && ( !shouldRun && !shouldStop ) ;
}
static int timerNo = 0;
@Override
- public synchronized boolean start() {
- if ( null != timer || null != task || isStartedImpl() ) {
+ public final synchronized boolean start() {
+ if ( null != timer || null != task || isStarted() ) {
return false;
}
timer = new Timer( getThreadName()+"-"+baseName+"-Timer"+(timerNo++) );
@@ -262,20 +249,20 @@ public class FPSAnimator extends AnimatorBase {
private final Condition waitForStartedAddedCondition = new Condition() {
@Override
public boolean eval() {
- return !isStartedImpl() || !isAnimating ;
+ return !isStarted() || !isAnimating ;
} };
private final Condition waitForStartedEmptyCondition = new Condition() {
@Override
public boolean eval() {
- return !isStartedImpl() || isAnimating ;
+ return !isStarted() || isAnimating ;
} };
/** 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. */
@Override
- public synchronized boolean stop() {
- if ( null == timer || !isStartedImpl() ) {
+ public final synchronized boolean stop() {
+ if ( null == timer || !isStarted() ) {
return false;
}
if(DEBUG) {
@@ -308,12 +295,12 @@ public class FPSAnimator extends AnimatorBase {
private final Condition waitForStoppedCondition = new Condition() {
@Override
public boolean eval() {
- return isStartedImpl();
+ return isStarted();
} };
@Override
- public synchronized boolean pause() {
- if ( !isStartedImpl() || ( null != task && isPausedImpl() ) ) {
+ public final synchronized boolean pause() {
+ if ( !isStarted() || ( null != task && isPaused() ) ) {
return false;
}
if(DEBUG) {
@@ -341,12 +328,12 @@ public class FPSAnimator extends AnimatorBase {
@Override
public boolean eval() {
// end waiting if stopped as well
- return isAnimating && isStartedImpl();
+ return isAnimating && isStarted();
} };
@Override
- public synchronized boolean resume() {
- if ( null != task || !isStartedImpl() || !isPausedImpl() ) {
+ public final synchronized boolean resume() {
+ if ( null != task || !isStarted() || !isPaused() ) {
return false;
}
if(DEBUG) {
@@ -369,6 +356,6 @@ public class FPSAnimator extends AnimatorBase {
@Override
public boolean eval() {
// end waiting if stopped as well
- return !drawablesEmpty && !isAnimating && isStartedImpl();
+ return !drawablesEmpty && !isAnimating && isStarted();
} };
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
index 2587f8d50..605f97fe3 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,7 +20,7 @@
* 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.
@@ -63,12 +63,12 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
- * Sample program that relies on JOGL's mechanism to handle the OpenGL context
+ * Sample program that relies on JOGL's mechanism to handle the OpenGL context
* and rendering loop when using an AWT canvas attached to an Applet.
* <p>
- * BUG on OSX/CALayer w/ Java6:
+ * BUG on OSX/CALayer w/ Java6:
* If frame.setTitle() is issued right after initialization the call hangs in
- * <pre>
+ * <pre>
* at apple.awt.CWindow._setTitle(Native Method)
* at apple.awt.CWindow.setTitle(CWindow.java:765) [1.6.0_37, build 1.6.0_37-b06-434-11M3909]
* </pre>
@@ -81,7 +81,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
* e.g. setResizable*().
* </p>
* <p>
- * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) !
+ * Users shall make sure all mutable AWT calls are performed on the EDT, even before 1st setVisible(true) !
* </p>
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -90,89 +90,89 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
static class MiniPApplet extends Applet implements MouseMotionListener, KeyListener {
private static final long serialVersionUID = 1L;
-
+
/////////////////////////////////////////////////////////////
//
- // Test parameters
-
+ // Test parameters
+
public int frameRate = 120;
public int numSamples = 4;
-
- public boolean fullScreen = false;
+
+ public boolean fullScreen = false;
public boolean useAnimator = true;
public boolean resizeableFrame = true;
-
+
public boolean restartCanvas = true;
public int restartTimeout = 100; // in number of frames.
-
+
public boolean printThreadInfo = false;
public boolean printEventInfo = false;
-
+
/////////////////////////////////////////////////////////////
//
// Internal variables
-
+
int width;
int height;
-
- String OPENGL_VENDOR;
+
+ String OPENGL_VENDOR;
String OPENGL_RENDERER;
- String OPENGL_VERSION;
- String OPENGL_EXTENSIONS;
-
+ String OPENGL_VERSION;
+ String OPENGL_EXTENSIONS;
+
int currentSamples = -1;
-
+
private Frame frame;
private GLProfile profile;
private GLCapabilities capabilities;
private GLCanvas canvas;
-
+
private SimpleListener listener;
private CustomAnimator animator;
-
+
private long beforeTime;
private long overSleepTime;
- private long frameRatePeriod = 1000000000L / frameRate;
-
- private boolean initialized = false;
+ private final long frameRatePeriod = 1000000000L / frameRate;
+
+ private boolean initialized = false;
private boolean osxCALayerAWTModBug = false;
boolean justInitialized = true;
private double theta = 0;
private double s = 0;
- private double c = 0;
-
+ private double c = 0;
+
private long millisOffset;
private int fcount, lastm;
private float frate;
- private int fint = 3;
-
+ private final int fint = 3;
+
private boolean setFramerate = false;
private boolean restarted = false;
-
+
private int frameCount = 0;
-
+
void run() throws InterruptedException, InvocationTargetException {
// Thread loop = new Thread("Animation Thread") {
- // public void run() {
+ // public void run() {
frameCount = 0;
while ( frameCount < framesPerTest ) {
if (!initialized) {
- setup();
+ setup();
}
-
+
if (restartCanvas && restartTimeout == frameCount) {
restart();
}
-
+
if (useAnimator) {
animator.requestRender();
} else {
- canvas.display();
+ canvas.display();
}
-
+
clock();
-
+
frameCount++;
if( null == frame ) {
break;
@@ -181,32 +181,32 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
dispose();
// }
// };
- // loop.start();
+ // loop.start();
}
-
+
void setup() throws InterruptedException, InvocationTargetException {
if (printThreadInfo) System.out.println("Current thread at setup(): " + Thread.currentThread());
-
- millisOffset = System.currentTimeMillis();
-
+
+ millisOffset = System.currentTimeMillis();
+
final VersionNumber version170 = new VersionNumber(1, 7, 0);
- osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
+ osxCALayerAWTModBug = Platform.OSType.MACOS == Platform.getOSType() &&
0 > Platform.getJavaVersionNumber().compareTo(version170);
System.err.println("OSX CALayer AWT-Mod Bug "+osxCALayerAWTModBug);
System.err.println("OSType "+Platform.getOSType());
System.err.println("Java Version "+Platform.getJavaVersionNumber());
-
+
// Frame setup ----------------------------------------------------------
-
+
width = 300;
- height = 300;
+ height = 300;
final MiniPApplet applet = this;
-
+
GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
frame = new Frame(displayDevice.getDefaultConfiguration());
-
+
final Rectangle fullScreenRect;
if (fullScreen) {
DisplayMode mode = displayDevice.getDisplayMode();
@@ -231,7 +231,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
} catch (Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
- }
+ }
}
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
@@ -252,25 +252,25 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
applet.width, applet.height);
} else {
Insets insets = frame.getInsets();
-
+
int windowW = applet.width + insets.left + insets.right;
int windowH = applet.height + insets.top + insets.bottom;
- int locationX = 100;
+ int locationX = 100;
int locationY = 100;
-
+
frame.setSize(windowW, windowH);
frame.setLocation(locationX, locationY);
-
+
int usableWindowH = windowH - insets.top - insets.bottom;
- applet.setBounds((windowW - width)/2, insets.top + (usableWindowH - height)/2, width, height);
+ applet.setBounds((windowW - width)/2, insets.top + (usableWindowH - height)/2, width, height);
}
}});
} catch (Throwable t) {
t.printStackTrace();
Assume.assumeNoException(t);
}
-
-
+
+
frame.add(this);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
@@ -280,63 +280,63 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
Assume.assumeNoException(ex);
}
}
- });
-
+ });
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.setVisible(true);
} } );
-
+
// Canvas setup ----------------------------------------------------------
-
+
profile = GLProfile.getDefault();
- capabilities = new GLCapabilities(profile);
+ capabilities = new GLCapabilities(profile);
capabilities.setSampleBuffers(true);
capabilities.setNumSamples(numSamples);
capabilities.setDepthBits(24);
// capabilities.setStencilBits(8); // No Stencil on OSX w/ hw-accel !
capabilities.setAlphaBits(8);
-
+
canvas = new GLCanvas(capabilities);
canvas.setBounds(0, 0, width, height);
-
+
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
MiniPApplet.this.setLayout(new BorderLayout());
MiniPApplet.this.add(canvas, BorderLayout.CENTER);
MiniPApplet.this.validate();
} } );
- canvas.addMouseMotionListener(this);
+ canvas.addMouseMotionListener(this);
canvas.addKeyListener(this);
-
+
// Setting up animation
listener = new SimpleListener();
canvas.addGLEventListener(listener);
if (useAnimator) {
animator = new CustomAnimator(canvas);
animator.start();
- }
- initialized = true;
+ }
+ initialized = true;
}
-
+
void restart() throws InterruptedException, InvocationTargetException {
System.out.println("Restarting surface...");
-
+
// Stopping animation, removing current canvas.
if (useAnimator) {
animator.stop();
animator.remove(canvas);
}
canvas.disposeGLEventListener(listener, true);
- this.remove(canvas);
-
- capabilities = new GLCapabilities(profile);
+ this.remove(canvas);
+
+ capabilities = new GLCapabilities(profile);
capabilities.setSampleBuffers(true);
capabilities.setNumSamples(numSamples);
-
+
canvas = new GLCanvas(capabilities);
canvas.setBounds(0, 0, width, height);
-
+
// Setting up animation again
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -346,24 +346,24 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
} } );
canvas.addMouseMotionListener(this);
canvas.addKeyListener(this);
-
+
canvas.addGLEventListener(listener);
if (useAnimator) {
animator.add(canvas);
animator.start();
- }
-
+ }
+
setFramerate = false;
restarted = true;
-
+
System.out.println("Done");
}
-
+
void dispose() throws InterruptedException, InvocationTargetException {
if( null == frame ) {
return;
}
-
+
// Stopping animation, removing current canvas.
if (useAnimator) {
animator.stop();
@@ -387,7 +387,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
}});
}
}
-
+
void draw(GL2 gl) {
if( !osxCALayerAWTModBug || !justInitialized ) {
AWTEDTExecutor.singleton.invoke(true, new Runnable() {
@@ -395,19 +395,19 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
frame.setTitle("frame " + frameCount);
} } );
}
-
- if (printThreadInfo) System.out.println("Current thread at draw(): " + Thread.currentThread());
-
+
+ if (printThreadInfo) System.out.println("Current thread at draw(): " + Thread.currentThread());
+
if (OPENGL_VENDOR == null) {
- OPENGL_VENDOR = gl.glGetString(GL.GL_VENDOR);
+ OPENGL_VENDOR = gl.glGetString(GL.GL_VENDOR);
OPENGL_RENDERER = gl.glGetString(GL.GL_RENDERER);
- OPENGL_VERSION = gl.glGetString(GL.GL_VERSION);
+ OPENGL_VERSION = gl.glGetString(GL.GL_VERSION);
OPENGL_EXTENSIONS = gl.glGetString(GL.GL_EXTENSIONS);
System.out.println(OPENGL_VENDOR);
System.out.println(OPENGL_RENDERER);
System.out.println(OPENGL_VERSION);
System.out.println(OPENGL_EXTENSIONS);
-
+
int[] temp = { 0 };
gl.glGetIntegerv(GL2.GL_MAX_SAMPLES, temp, 0);
System.out.println("Maximum number of samples supported by the hardware: " + temp[0]);
@@ -416,43 +416,43 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
System.out.println("GLCanvas: "+canvas);
System.out.println("GLDrawable: "+canvas.getDelegatedDrawable());
}
-
+
if (currentSamples == -1) {
int[] temp = { 0 };
gl.glGetIntegerv(GL.GL_SAMPLES, temp, 0);
currentSamples = temp[0];
if (numSamples != currentSamples) {
System.err.println("Requested sampling level " + numSamples + " not supported. Using " + currentSamples + " samples instead.");
- }
+ }
}
-
- if (!setFramerate) {
+
+ if (!setFramerate) {
if (60 < frameRate) {
// Disables vsync
- gl.setSwapInterval(0);
- } else if (30 < frameRate) {
- gl.setSwapInterval(1);
+ gl.setSwapInterval(0);
+ } else if (30 < frameRate) {
+ gl.setSwapInterval(1);
} else {
gl.setSwapInterval(2);
- }
- setFramerate = true;
+ }
+ setFramerate = true;
}
-
+
if (restarted) {
int[] temp = { 0 };
- gl.glGetIntegerv(GL.GL_SAMPLES, temp, 0);
+ gl.glGetIntegerv(GL.GL_SAMPLES, temp, 0);
if (numSamples != temp[0]) {
System.err.println("Multisampling level requested " + numSamples + " not supported. Using " + temp[0] + "samples instead.");
- }
+ }
}
-
+
gl.glClearColor(0, 0, 0, 1);
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
-
+
theta += 0.01;
s = Math.sin(theta);
- c = Math.cos(theta);
-
+ c = Math.cos(theta);
+
gl.glBegin(GL.GL_TRIANGLES);
gl.glColor3f(1, 0, 0);
gl.glVertex2d(-c, -c);
@@ -460,135 +460,125 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
gl.glVertex2d(0, c);
gl.glColor3f(0, 0, 1);
gl.glVertex2d(s, -s);
- gl.glEnd();
-
+ gl.glEnd();
+
gl.glFlush();
-
+
fcount += 1;
int m = (int) (System.currentTimeMillis() - millisOffset);
if (m - lastm > 1000 * fint) {
frate = (float)(fcount) / fint;
fcount = 0;
lastm = m;
- System.err.println("fps: " + frate);
- }
+ System.err.println("fps: " + frate);
+ }
}
-
+
void clock() {
long afterTime = System.nanoTime();
long timeDiff = afterTime - beforeTime;
long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
-
+
if (sleepTime > 0) { // some time left in this cycle
try {
Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
} catch (InterruptedException ex) { }
-
+
overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
-
+
} else { // sleepTime <= 0; the frame took longer than the period
overSleepTime = 0L;
}
-
- beforeTime = System.nanoTime();
- }
-
+
+ beforeTime = System.nanoTime();
+ }
+
class SimpleListener implements GLEventListener {
@Override
public void display(GLAutoDrawable drawable) {
draw(drawable.getGL().getGL2());
justInitialized = false;
}
-
+
@Override
public void dispose(GLAutoDrawable drawable) { }
-
+
@Override
public void init(GLAutoDrawable drawable) {
justInitialized = true;
}
-
+
@Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { }
}
-
+
public void mouseDragged(MouseEvent ev) {
if (printEventInfo) {
System.err.println("Mouse dragged event: " + ev);
}
}
-
+
public void mouseMoved(MouseEvent ev) {
if (printEventInfo) {
System.err.println("Mouse moved event: " + ev);
}
- }
-
- public void keyPressed(KeyEvent ev) {
+ }
+
+ public void keyPressed(KeyEvent ev) {
if (printEventInfo) {
System.err.println("Key pressed event: " + ev);
}
}
-
- public void keyReleased(KeyEvent ev) {
+
+ public void keyReleased(KeyEvent ev) {
if (printEventInfo) {
System.err.println("Key released event: " + ev);
- }
+ }
}
-
- public void keyTyped(KeyEvent ev) {
+
+ public void keyTyped(KeyEvent ev) {
if (printEventInfo) {
System.err.println("Key typed event: " + ev);
- }
+ }
}
-
+
/** An Animator subclass which renders one frame at the time
- * upon calls to the requestRender() method.
+ * upon calls to the requestRender() method.
**/
- public class CustomAnimator extends AnimatorBase {
+ public class CustomAnimator extends AnimatorBase {
private Timer timer = null;
private TimerTask task = null;
private volatile boolean shouldRun;
-
+
protected String getBaseName(String prefix) {
return "Custom" + prefix + "Animator" ;
}
-
- /** Creates an CustomAnimator with an initial drawable to
+
+ /** Creates an CustomAnimator with an initial drawable to
* animate. */
public CustomAnimator(GLAutoDrawable drawable) {
if (drawable != null) {
add(drawable);
}
}
-
+
public synchronized void requestRender() {
shouldRun = true;
}
-
- public final boolean isStarted() {
- stateSync.lock();
- try {
- return (timer != null);
- } finally {
- stateSync.unlock();
- }
+
+ public final synchronized boolean isStarted() {
+ return (timer != null);
}
-
- public final boolean isAnimating() {
- stateSync.lock();
- try {
- return (timer != null) && (task != null);
- } finally {
- stateSync.unlock();
- }
+
+ public final synchronized boolean isAnimating() {
+ return (timer != null) && (task != null);
}
-
+
private void startTask() {
if(null != task) {
return;
}
-
+
task = new TimerTask() {
private boolean firstRun = true;
public void run() {
@@ -599,67 +589,57 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
if(CustomAnimator.this.shouldRun) {
CustomAnimator.this.animThread = Thread.currentThread();
// display impl. uses synchronized block on the animator instance
- display();
+ display();
synchronized (this) {
// done with current frame.
shouldRun = false;
- }
+ }
}
}
};
-
+
fpsCounter.resetFPSCounter();
shouldRun = false;
-
+
timer.schedule(task, 0, 1);
}
-
+
public synchronized boolean start() {
if (timer != null) {
return false;
}
- stateSync.lock();
- try {
- timer = new Timer();
- startTask();
- } finally {
- stateSync.unlock();
- }
+ timer = new Timer();
+ startTask();
return true;
}
-
+
/** Stops this CustomAnimator. */
public synchronized boolean stop() {
if (timer == null) {
return false;
}
- stateSync.lock();
- try {
- shouldRun = false;
- if(null != task) {
- task.cancel();
- task = null;
- }
- if(null != timer) {
- timer.cancel();
- timer = null;
- }
- animThread = null;
- try {
- Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads
- } catch (InterruptedException e) { }
- } finally {
- stateSync.unlock();
+ shouldRun = false;
+ if(null != task) {
+ task.cancel();
+ task = null;
}
+ if(null != timer) {
+ timer.cancel();
+ timer = null;
+ }
+ animThread = null;
+ try {
+ Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads
+ } catch (InterruptedException e) { }
return true;
}
-
- public final boolean isPaused() { return false; }
+
+ public final synchronized boolean isPaused() { return false; }
public synchronized boolean resume() { return false; }
- public synchronized boolean pause() { return false; }
+ public synchronized boolean pause() { return false; }
}
}
-
+
@Test
public void test00() {
TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet mini;
@@ -668,7 +648,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
mini = (TestGLCanvasAWTActionDeadlock02AWT.MiniPApplet) c.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
- }
+ }
if (mini != null) {
try {
mini.run();
@@ -677,7 +657,7 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
}
}
}
-
+
public static void main(String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-frames")) {
@@ -686,5 +666,5 @@ public class TestGLCanvasAWTActionDeadlock02AWT extends UITestCase {
}
org.junit.runner.JUnitCore.main(TestGLCanvasAWTActionDeadlock02AWT.class.getName());
}
-
+
}