diff options
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 > <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()); } - + } |