Skip to content

Commit

Permalink
Fix Bug 642 TestJSplitPaneMixHwLw01AWT (AWT-GLCanvas); Robustness GLC…
Browse files Browse the repository at this point in the history
…ontext/GLDrawable

- Fix Bug 642 TestJSplitPaneMixHwLw01AWT
  On Windows platform when mixing hw/lw JSplitPanel,
  the GLCanvas is removed and added when splitter is moved.
  The lack of robustness (see below) lead to an exception.

  Note: Only w/ GLJPanel (no hw/lw mixing) the splitter can be moved
  in both direction. Only here it is guaranteed that the GL component
  will survive the action.

- Fix AWT-GLCanvas EDT Runnable: swapBuffer().. / display(..)
  - Check drawable.isRealized() within the lock on the performing thread.
    This is not possible before issuing the EDT Runnable action
    since we cannot hold the lock beforehand.

- Robustness GLDrawableImpl
  - boolean realized -> volatile boolean realized
  - remove 'synchronized' on isRealized() and setRealized(..)
  - Use dbl-checked locking on 'realized' test for swapBuffers() and setRealized(..)

- Robustness GLContextImpl
  - Catch createImpl(..) exception and properly return CONTEXT_NOT_CURRENT
  • Loading branch information
sgothel committed Dec 22, 2012
1 parent 99b7993 commit 1ae0737
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 33 deletions.
3 changes: 2 additions & 1 deletion make/scripts/java-win64-dbg.bat
Expand Up @@ -21,7 +21,8 @@ echo CP_ALL %CP_ALL%
REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject"
REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery"
REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK"
set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.GLContext" "-Djogl.debug.GLCanvas"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery"
REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile"
REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
Expand Down
5 changes: 3 additions & 2 deletions make/scripts/tests-x64.bat
Expand Up @@ -10,7 +10,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedCon
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT -time 5000
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 %*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT %*
scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile02NEWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT %*

Expand All @@ -22,7 +22,8 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug551A
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT03GLCanvasRecreate01
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestJScrollPaneMixHwLw01AWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT %*
scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestIsRealizedConcurrency01AWT %*

REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000
Expand Down
8 changes: 5 additions & 3 deletions make/scripts/tests.sh
Expand Up @@ -100,8 +100,9 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing"
#D_ARGS="-Djogamp.debug=all"
#D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
#D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
#D_ARGS="-Djogl.debug=all -Dnewt.debug=all"
D_ARGS="-Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLCanvas"
#D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration"
#D_ARGS="-Djogl.debug.GLDrawable"
#D_ARGS="-Djogl.fbo.force.none"
Expand Down Expand Up @@ -264,7 +265,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix02NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $*
testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestInitConcurrent01NEWT $*
Expand Down Expand Up @@ -353,7 +354,8 @@ testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT03GLCanvasRecreate01 $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT02WindowClosing
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestJScrollPaneMixHwLw01AWT $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT $*
testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestIsRealizedConcurrency01AWT $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.text.TestAWTTextRendererUseVertexArrayBug464
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
Expand Down
6 changes: 4 additions & 2 deletions src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
Expand Up @@ -1024,7 +1024,9 @@ public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
try {
helper.invokeGL(drawable, context, displayAction, initAction);
if( drawable.isRealized() ) {
helper.invokeGL(drawable, context, displayAction, initAction);
}
} finally {
_lock.unlock();
}
Expand All @@ -1037,7 +1039,7 @@ public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
try {
if(null != drawable) {
if(null != drawable && drawable.isRealized() ) {
drawable.swapBuffers();
}
} finally {
Expand Down
9 changes: 8 additions & 1 deletion src/jogl/classes/jogamp/opengl/GLContextImpl.java
Expand Up @@ -567,7 +567,8 @@ private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
if (null != shareWith) {
shareWith.getDrawableImpl().lockSurface();
}
final boolean created;
Throwable exception = null;
boolean created;
try {
created = createImpl(shareWith); // may throws exception if fails!
if( created && isGL3core() && ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=2 ) ) {
Expand All @@ -580,6 +581,9 @@ private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
defaultVAO = tmp[0];
gl.getGL2GL3().glBindVertexArray(defaultVAO);
}
} catch (Throwable t) {
exception = t;
created = false;
} finally {
if (null != shareWith) {
shareWith.getDrawableImpl().unlockSurface();
Expand All @@ -591,6 +595,9 @@ private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
// Thread.dumpStack();
} else {
System.err.println(getThreadName() + ": Create GL context FAILED obj " + toHexString(hashCode()) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName());
if(null != exception) {
exception.printStackTrace();
}
}
}
if(!created) {
Expand Down
49 changes: 27 additions & 22 deletions src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
Expand Up @@ -76,7 +76,7 @@ public final GLDrawableFactoryImpl getFactoryImpl() {

@Override
public final void swapBuffers() throws GLException {
if( !realized ) {
if( !realized ) { // volatile OK (locked below)
return; // destroyed already
}
int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
Expand All @@ -87,17 +87,19 @@ public final void swapBuffers() throws GLException {
if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
updateHandle();
}
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
if ( caps.getDoubleBuffered() ) {
if(!surface.surfaceSwap()) {
swapBuffersImpl(true);
}
} else {
final GLContext ctx = GLContext.getCurrent();
if(null!=ctx && ctx.getGLDrawable()==this) {
ctx.getGL().glFlush();
if( realized ) { // volatile OK
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
if ( caps.getDoubleBuffered() ) {
if(!surface.surfaceSwap()) {
swapBuffersImpl(true);
}
} else {
final GLContext ctx = GLContext.getCurrent();
if(null!=ctx && ctx.getGLDrawable()==this) {
ctx.getGL().glFlush();
}
swapBuffersImpl(false);
}
swapBuffersImpl(false);
}
} finally {
unlockSurface();
Expand Down Expand Up @@ -160,12 +162,11 @@ public final GLDrawableFactory getFactory() {
}

@Override
public final synchronized void setRealized(boolean realizedArg) {
if ( realized != realizedArg ) {
public final void setRealized(boolean realizedArg) {
if ( realized != realizedArg ) { // volatile: OK (locked below)
if(DEBUG) {
System.err.println(getThreadName() + ": setRealized: "+getClass().getSimpleName()+" "+realized+" -> "+realizedArg);
}
realized = realizedArg;
AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice();
if(realizedArg) {
if(surface instanceof ProxySurface) {
Expand All @@ -178,12 +179,15 @@ public final synchronized void setRealized(boolean realizedArg) {
aDevice.lock();
}
try {
if(realizedArg) {
setRealizedImpl();
updateHandle();
} else {
destroyHandle();
setRealizedImpl();
if ( realized != realizedArg ) { // volatile: OK
realized = realizedArg;
if(realizedArg) {
setRealizedImpl();
updateHandle();
} else {
destroyHandle();
setRealizedImpl();
}
}
} finally {
if(realizedArg) {
Expand All @@ -199,6 +203,7 @@ public final synchronized void setRealized(boolean realizedArg) {
System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg);
}
}

/**
* Platform specific realization of drawable
*/
Expand Down Expand Up @@ -256,7 +261,7 @@ protected int getDefaultReadBuffer(GL gl) {
}

@Override
public final synchronized boolean isRealized() {
public final boolean isRealized() {
return realized;
}

Expand Down Expand Up @@ -306,6 +311,6 @@ protected static String getThreadName() {
// result of calling show() on the main thread. To work around this
// we prevent any JAWT or OpenGL operations from being done until
// addNotify() is called on the surface.
protected boolean realized;
protected volatile boolean realized;

}
Expand Up @@ -77,7 +77,8 @@ public void setOpaque(boolean isOpaque) {
}

protected void runTestGL(GLCapabilities caps, boolean useGLJPanel) throws InterruptedException {
final JFrame frame = new JFrame("JSplitPane Mix Hw/Lw Swing");
final String typeS = useGLJPanel ? "LW" : "HW";
final JFrame frame = new JFrame("Mix Hw/Lw Swing - Canvas "+typeS);
Assert.assertNotNull(frame);

final Dimension f_sz = new Dimension(824,568);
Expand Down
@@ -0,0 +1,101 @@
/**
* Copyright 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/

package com.jogamp.opengl.test.junit.jogl.awt;

import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.Animator;

import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;

import com.jogamp.opengl.test.junit.util.MiscUtils;

import java.awt.Dimension;
import java.awt.Frame;
import java.lang.reflect.InvocationTargetException;

import org.junit.Assert;
import org.junit.Test;


public class TestIsRealizedConcurrency01AWT extends UITestCase {
static long durationPerTest = 1000; // ms

@Test
public void testAddRemove() throws InterruptedException, InvocationTargetException {
final Dimension f_sz = new Dimension(512, 512);

final GLCanvas glCanvas = new GLCanvas();
Assert.assertNotNull(glCanvas);
glCanvas.addGLEventListener(new GearsES2());

final Animator animator = new Animator(glCanvas);
animator.start();

final Frame frame = new Frame("Frame");
Assert.assertNotNull(frame);
frame.add(glCanvas);

javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.setLocation(0, 0);
frame.setPreferredSize(f_sz);
frame.setSize(f_sz);
frame.pack();
frame.setVisible(true);
}});
Thread.sleep(durationPerTest/2);

javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame.remove(glCanvas);
frame.validate();
frame.add(glCanvas);
frame.validate();
}});
Thread.sleep(durationPerTest/2);

javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
glCanvas.destroy();
frame.dispose();
}});

animator.stop();
}

public static void main(String args[]) {
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
}
}
org.junit.runner.JUnitCore.main(TestIsRealizedConcurrency01AWT.class.getName());
}
}
Expand Up @@ -77,7 +77,8 @@ public void setOpaque(boolean isOpaque) {
}

protected void runTestGL(GLCapabilities caps, boolean useJScroll) throws InterruptedException {
final JFrame frame = new JFrame("JScrollPane Mix Hw/Lw Swing");
final String typeS = useJScroll ? "LW" : "HW";
final JFrame frame = new JFrame("Mix Hw/Lw Swing - ScrollPane "+typeS);
Assert.assertNotNull(frame);

final Dimension f_sz = new Dimension(600,400);
Expand Down

0 comments on commit 1ae0737

Please sign in to comment.