From 601d6c46df61853fb61df087327a055550316b1d Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Thu, 29 Nov 2012 00:08:06 +0100
Subject: SWT GLCanvas: Fix dispose bug, check for isDisposed() and add
DisposeListener; Run GL tasks on current thread w/o restrictions
Fix dispose bug, check for isDisposed() and add DisposeListener
- Don't issue SWTAccessor.setRealized(..), since it's called implicit via super.dispose()
- Check isDisposed() ..
- add DisposeListener to act on parent's disposal (Shell, Composition, ..)
Run GL tasks on current thread w/o restrictions
+ * The current thread seems to be valid for all platforms,
+ * since no SWT lifecycle tasks are being performed w/ this call.
+ * Only GL task, which are independent from the SWT threading model.
---
make/scripts/tests.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'make/scripts/tests.sh')
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index a732d78fa..2d8f3e1a8 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -370,9 +370,9 @@ function testawtswt() {
#
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $*
-#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
+testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $*
-testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock $*
+#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock $*
#
# newt.awt (testawt)
--
cgit v1.2.3
From 0bb202f2883e1eb82256140f13310046f7b13c62 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Thu, 29 Nov 2012 18:21:02 +0100
Subject: Bug628: Adding unit-test 'TestNewtCanvasSWTBug628ResizeDeadlock'
exposing NewtCanvasSWT asyncExec(..) bug w/ native parenting
The unit test shows, that while using JOGL's SWT GLCanvas Display's asyncExec(..) works properly,
but w/ NewtCanvasSWT on Windows does not.
NewtCanvasSWT differs w/:
- Using native parenting [Newt GLWindow to SWT Canvas]
- Processing native events in own NEWT EDT, w/ own Windows dispatch hook [For the child GLWindow only]
---
make/scripts/tests-x64.bat | 3 +-
make/scripts/tests.sh | 3 +-
.../swt/TestNewtCanvasSWTBug628ResizeDeadlock.java | 12 +-
.../junit/jogl/swt/TestSWTBug643AsyncExec.java | 283 +++++++++++++++++++++
4 files changed, 292 insertions(+), 9 deletions(-)
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
(limited to 'make/scripts/tests.sh')
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat
index f340af552..7a2946d31 100755
--- a/make/scripts/tests-x64.bat
+++ b/make/scripts/tests-x64.bat
@@ -54,9 +54,10 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestP
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn %*
-scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock %*
+scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 2d8f3e1a8..0669efb37 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -370,9 +370,10 @@ function testawtswt() {
#
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $*
-testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
+#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock $*
+testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec $*
#
# newt.awt (testawt)
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java
index 9c0762c12..834261d22 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java
@@ -65,7 +65,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase {
- static int duration = 1000;
+ static int duration = 500;
static class BigFlashingX implements GLEventListener
{
@@ -262,7 +262,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase {
shell = new Shell( display );
Assert.assertNotNull( shell );
shell.setLayout( new FillLayout() );
- composite = new Composite( shell, SWT.NONE );
+ composite = new Composite( shell, SWT.NO_BACKGROUND );
composite.setLayout( new FillLayout() );
Assert.assertNotNull( composite );
}});
@@ -301,10 +301,9 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase {
dsc.init();
final GLWindow glWindow;
- final NewtCanvasSWT canvas;
{
final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ;
- GLCapabilities caps = new GLCapabilities( gl2Profile ) ;
+ final GLCapabilities caps = new GLCapabilities( gl2Profile ) ;
glWindow = GLWindow.create( caps ) ;
glWindow.addGLEventListener( new BigFlashingX() ) ;
glWindow.addKeyListener(new KeyAdapter() {
@@ -314,7 +313,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase {
glWindow.display();
}
});
- canvas = NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ;
+ NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ;
}
dsc.display.syncExec( new Runnable() {
@@ -374,8 +373,7 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase {
Assert.assertTrue("Deadlock @ dispatch: "+e0, false);
}
- System.err.println("NewtCanvasAWT Dispose");
- canvas.dispose();
+ // canvas is disposed implicit, due to it's disposed listener !
dsc.dispose();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
new file mode 100644
index 000000000..ccea76c02
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
@@ -0,0 +1,283 @@
+/**
+ * Copyright 2012 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.swt;
+
+import java.awt.AWTException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.SWT ;
+
+import org.eclipse.swt.layout.FillLayout ;
+
+import org.eclipse.swt.widgets.Composite ;
+import org.eclipse.swt.widgets.Display ;
+import org.eclipse.swt.widgets.Shell ;
+import org.junit.Assume;
+import org.junit.Test;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities ;
+import javax.media.opengl.GLProfile;
+
+import junit.framework.Assert;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.opengl.GLWindow ;
+import com.jogamp.newt.swt.NewtCanvasSWT ;
+import com.jogamp.opengl.swt.GLCanvas;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+public class TestSWTBug643AsyncExec extends UITestCase {
+
+ static int duration = 500;
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static void resetAsyncExecCount() {
+ synchronized(asyncExecCountSync) {
+ asyncExecCount=0;
+ }
+ }
+ static int incrAsyncExecCount() {
+ synchronized(asyncExecCountSync) {
+ asyncExecCount++;
+ return asyncExecCount;
+ }
+ }
+ static int getAsyncExecCount() {
+ synchronized(asyncExecCountSync) {
+ return asyncExecCount;
+ }
+ }
+ static Object asyncExecCountSync = new Object();
+ static int asyncExecCount = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ static class AsyncExecFeederThread extends Thread {
+ volatile boolean shallStop = false;
+ private Display display ;
+ private int n ;
+
+ public AsyncExecFeederThread( Display display )
+ {
+ super();
+ this.display = display ;
+ }
+
+ final Runnable asyncAction = new Runnable() {
+ public void run()
+ {
+ ++n ;
+ System.err.println("[A-i shallStop "+shallStop+", disposed "+display.isDisposed()+"]: Counter[loc "+n+", glob: "+incrAsyncExecCount()+"]");
+ } };
+
+ public void run()
+ {
+ System.err.println("[A-0 shallStop "+shallStop+", disposed "+display.isDisposed()+"]");
+
+ // final Display d = Display.getDefault();
+ final Display d = this.display;
+
+ while( !shallStop && !d.isDisposed() )
+ {
+ try
+ {
+ System.err.println("[A-n shallStop "+shallStop+", disposed "+d.isDisposed()+"]");
+ d.asyncExec( asyncAction );
+ d.wake();
+
+ Thread.sleep( 50L ) ;
+ } catch( InterruptedException e ) {
+ break ;
+ }
+ }
+ System.err.println("*R-Exit* shallStop "+shallStop+", disposed "+d.isDisposed());
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+ private volatile boolean shallStop = false;
+
+ static class SWT_DSC {
+ Display display;
+ Shell shell;
+ Composite composite;
+
+ public void init() {
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display = new Display();
+ Assert.assertNotNull( display );
+ }});
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ shell = new Shell( display );
+ Assert.assertNotNull( shell );
+ shell.setLayout( new FillLayout() );
+ composite = new Composite( shell, SWT.NO_BACKGROUND );
+ composite.setLayout( new FillLayout() );
+ Assert.assertNotNull( composite );
+ }});
+ }
+
+ public void dispose() {
+ Assert.assertNotNull( display );
+ Assert.assertNotNull( shell );
+ Assert.assertNotNull( composite );
+ try {
+ display.syncExec(new Runnable() {
+ public void run() {
+ composite.dispose();
+ shell.dispose();
+ }});
+ SWTAccessor.invoke(true, new Runnable() {
+ public void run() {
+ display.dispose();
+ }});
+ }
+ catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ display = null;
+ shell = null;
+ composite = null;
+ }
+ }
+
+ private void testImpl(boolean useJOGLGLCanvas, boolean useNewtCanvasSWT) throws InterruptedException, AWTException, InvocationTargetException {
+ resetAsyncExecCount();
+
+ final SWT_DSC dsc = new SWT_DSC();
+ dsc.init();
+
+ {
+ final GLProfile gl2Profile = GLProfile.get( GLProfile.GL2 ) ;
+ final GLCapabilities caps = new GLCapabilities( gl2Profile ) ;
+
+ final GLAutoDrawable glad;
+ if( useJOGLGLCanvas ) {
+ glad = GLCanvas.create(dsc.composite, 0, caps, null, null);
+ } else if( useNewtCanvasSWT ) {
+ final GLWindow glWindow = GLWindow.create( caps ) ;
+ glad = glWindow;
+ NewtCanvasSWT.create( dsc.composite, 0, glWindow ) ;
+ } else {
+ throw new InternalError("XXX");
+ }
+ glad.addGLEventListener( new GearsES2() ) ;
+ }
+
+ dsc.display.syncExec( new Runnable() {
+ public void run() {
+ dsc.shell.setText( "NewtCanvasSWT Resize Bug Demo" ) ;
+ dsc.shell.setSize( 400, 450 ) ;
+ dsc.shell.open() ;
+ } } );
+
+ shallStop = false;
+
+ final int[] ayncExecCountBeforeExit = new int[] { 0 };
+
+ final AsyncExecFeederThread asyncExecFeeder;
+ {
+ asyncExecFeeder = new AsyncExecFeederThread( dsc.display) ;
+ asyncExecFeeder.start() ;
+ }
+
+ {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(duration);
+ } catch (InterruptedException e) {}
+
+ ayncExecCountBeforeExit[0] = getAsyncExecCount();
+ asyncExecFeeder.shallStop = true;
+ try
+ {
+ asyncExecFeeder.join();
+ } catch( InterruptedException e ) { }
+ shallStop = true;
+ dsc.display.wake();
+ } } ).start();
+ }
+
+ try {
+ final Display d = dsc.display;
+ while( !shallStop && !d.isDisposed() ) {
+ final boolean r = d.readAndDispatch();
+ System.err.print(",");
+ if( !r ) {
+ dsc.display.sleep();
+ }
+ }
+ } catch (Exception e0) {
+ e0.printStackTrace();
+ Assert.assertTrue("Deadlock @ dispatch: "+e0, false);
+ }
+
+ // canvas is disposed implicit, due to it's disposed listener !
+
+ dsc.dispose();
+
+ System.err.println("AsyncExecCount before exit: " + ayncExecCountBeforeExit[0]);
+ Assert.assertTrue("AsyncExecCount not greater zero before dispose!", 0 < ayncExecCountBeforeExit[0]);
+ }
+
+ @Test
+ public void test01JOGLGLCanvas() throws InterruptedException, AWTException, InvocationTargetException {
+ testImpl(true /* useJOGLGLCanvas */, false /* useNewtCanvasSWT */);
+ }
+
+ @Test
+ public void test02NewtCanvasSWT() throws InterruptedException, AWTException, InvocationTargetException {
+ testImpl(false /* useJOGLGLCanvas */, true /* useNewtCanvasSWT */);
+ }
+
+ public static void main( String[] args ) {
+ for(int i=0; i
Date: Tue, 4 Dec 2012 07:10:59 +0100
Subject: SWT GLCanvas: Fix sporadic drop of redraw on X11 _and_ allow using
custom GLCapabilities on X11 (feature complete)
To allow custom GLCapabilities, we had to use native parenting on X11 w/ a new child window.
The desired visualID chosen by the users GLCapabilities is passed to the new child window.
The redraw drops must be caused by the original GDK or the new child GDK window.
Now we use a plain X11 child window similar to NEWT's X11 window and NewtCanvasSWT,
which doesn't expose this bug.
(Note: SWTAccessor/GLCanvas still contains the uncommented GDK code path for further inspection, if desired)
Also added SWTNewtEventFactory to test event handling on the SWT GLCanvas w/ GearsES2.
TestSWTJOGLGLCanvas01GLn tests custom GLCapabilities now.
SWTEDTUtil has been moved to private: com.jogamp.newt.swt -> jogamp.newt.swt.
---
make/build-common.xml | 1 +
make/build-newt.xml | 2 +-
make/config/nativewindow/x11-CustomJavaCode.java | 5 +-
make/scripts/tests-x32.sh | 2 +
make/scripts/tests-x64.bat | 4 +-
make/scripts/tests.sh | 6 +-
.../classes/com/jogamp/opengl/swt/GLCanvas.java | 350 ++++++++++++++-------
.../com/jogamp/nativewindow/swt/SWTAccessor.java | 345 +++++++++++++-------
.../x11/X11DummyUpstreamSurfaceHook.java | 4 +-
src/nativewindow/native/x11/Xmisc.c | 123 +++++++-
.../classes/com/jogamp/newt/swt/NewtCanvasSWT.java | 82 +++--
.../classes/com/jogamp/newt/swt/SWTEDTUtil.java | 313 ------------------
src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java | 313 ++++++++++++++++++
.../jogamp/newt/swt/event/SWTNewtEventFactory.java | 249 +++++++++++++++
.../opengl/test/junit/jogl/demos/es2/GearsES2.java | 8 +-
.../swt/TestNewtCanvasSWTBug628ResizeDeadlock.java | 5 +-
.../junit/jogl/swt/TestSWTBug643AsyncExec.java | 26 +-
.../junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java | 16 +-
18 files changed, 1236 insertions(+), 618 deletions(-)
delete mode 100644 src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
create mode 100644 src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
create mode 100644 src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
(limited to 'make/scripts/tests.sh')
diff --git a/make/build-common.xml b/make/build-common.xml
index a718ae09a..414b0eba2 100644
--- a/make/build-common.xml
+++ b/make/build-common.xml
@@ -428,6 +428,7 @@
+
diff --git a/make/build-newt.xml b/make/build-newt.xml
index 7b9a51863..c3b51141f 100644
--- a/make/build-newt.xml
+++ b/make/build-newt.xml
@@ -112,7 +112,7 @@
value="com/jogamp/newt/awt/** com/jogamp/newt/event/awt/** jogamp/newt/awt/** ${java.part.driver.awt}"/>
+ value="com/jogamp/newt/swt/** jogamp/newt/swt/**"/>
diff --git a/make/config/nativewindow/x11-CustomJavaCode.java b/make/config/nativewindow/x11-CustomJavaCode.java
index 8e5da3b2d..4240c5e2f 100644
--- a/make/config/nativewindow/x11-CustomJavaCode.java
+++ b/make/config/nativewindow/x11-CustomJavaCode.java
@@ -28,8 +28,9 @@
public static native int DefaultVisualID(long display, int screen);
- public static native long CreateDummyWindow(long display, int screen_index, int visualID, int width, int height);
- public static native void DestroyDummyWindow(long display, long window);
+ public static native long CreateWindow(long parent, long display, int screen_index, int visualID, int width, int height, boolean input, boolean visible);
+ public static native void DestroyWindow(long display, long window);
+ public static native void SetWindowPosSize(long display, long window, int x, int y, int width, int height);
public static Point GetRelativeLocation(long display, int screen_index, long src_win, long dest_win, int src_x, int src_y) {
return (Point) GetRelativeLocation0(display, screen_index, src_win, dest_win, src_x, src_y);
diff --git a/make/scripts/tests-x32.sh b/make/scripts/tests-x32.sh
index a3aed84c3..858ed5fd8 100755
--- a/make/scripts/tests-x32.sh
+++ b/make/scripts/tests-x32.sh
@@ -6,6 +6,8 @@ if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86.sh ] ; then
. $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86.sh
fi
+export SWT_CLASSPATH=`pwd`/lib/swt/gtk-linux-x86/swt-debug.jar
+
. $SDIR/tests.sh `which java` -d32 ../build-x86 $*
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat
index 7a2946d31..db7e27264 100755
--- a/make/scripts/tests-x64.bat
+++ b/make/scripts/tests-x64.bat
@@ -54,10 +54,10 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestP
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
+scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock %*
-scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec %*
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 0669efb37..628ab706b 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -113,7 +113,7 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLProfile"
#D_ARGS="-Djogl.debug.GLProfile"
#D_ARGS="-Dnativewindow.debug.NativeWindow"
- #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT"
+ D_ARGS="-Djogl.debug.GLCanvas -Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.Animator"
#D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window -Djogl.debug.GLContext"
#D_ARGS="-Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util"
#D_ARGS="-Dnativewindow.debug.X11Util -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnewt.debug=all"
@@ -370,10 +370,10 @@ function testawtswt() {
#
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $*
-#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
+testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock $*
-testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec $*
+#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec $*
#
# newt.awt (testawt)
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index a080a7045..0320c63ae 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -29,10 +29,16 @@ package com.jogamp.opengl.swt;
import java.util.List;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.opengl.GL;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
@@ -48,23 +54,20 @@ import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.Threading;
+import jogamp.nativewindow.x11.X11Util;
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableImpl;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.jogamp.common.GlueGenVersion;
@@ -73,13 +76,14 @@ import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.opengl.JoglVersion;
/**
* Native SWT Canvas implementing GLAutoDrawable
- *
- *
Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.
- *
+ *
+ * Implementation allows use of custom {@link GLCapabilities}.
+ *
*/
public class GLCanvas extends Canvas implements GLAutoDrawable {
private static final boolean DEBUG = Debug.debug("GLCanvas");
@@ -103,11 +107,15 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
private final GLCapabilitiesImmutable capsRequested;
private final GLCapabilitiesChooser capsChooser;
+ private volatile Rectangle clientArea;
private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
- private GLContextImpl context;
+ private volatile GLContextImpl context;
/* Native window surface */
- private AbstractGraphicsDevice device;
+ private final boolean useX11GTK;
+ private volatile long gdkWindow; // either GDK child window ..
+ private volatile long x11Window; // .. or X11 child window (for GL rendering)
+ private final AbstractGraphicsScreen screen;
/* Construction parameters stored for GLAutoDrawable accessor methods */
private int additionalCtxCreationFlags = 0;
@@ -135,7 +143,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public void run() {
if (sendReshape) {
- helper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight());
+ helper.reshape(GLCanvas.this, 0, 0, clientArea.width, clientArea.height);
sendReshape = false;
}
helper.display(GLCanvas.this);
@@ -143,7 +151,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Action to make specified context current prior to running displayAction */
- private final Runnable makeCurrentAndDisplayOnEDTAction = new Runnable() {
+ private final Runnable makeCurrentAndDisplayOnGLAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
@@ -159,13 +167,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
};
/* Swaps buffers, assuming the GLContext is current */
- private final Runnable swapBuffersOnEDTAction = new Runnable() {
+ private final Runnable swapBuffersOnGLAction = new Runnable() {
@Override
public void run() {
final RecursiveLock _lock = lock;
_lock.lock();
try {
- if(null != drawable && !GLCanvas.this.isDisposed() ) {
+ final boolean drawableOK = null != drawable && drawable.isRealized();
+ if( drawableOK && !GLCanvas.this.isDisposed() ) {
drawable.swapBuffers();
}
} finally {
@@ -212,10 +221,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
drawable.setRealized(false);
drawable = null;
}
- if (null != device) {
- device.close();
- device = null;
+ if( 0 != x11Window) {
+ SWTAccessor.destroyX11Window(screen.getDevice(), x11Window);
+ x11Window = 0;
+ } else if( 0 != gdkWindow) {
+ SWTAccessor.destroyGDKWindow(gdkWindow);
+ gdkWindow = 0;
}
+ screen.getDevice().close();
if (animatorPaused) {
animator.resume();
@@ -249,11 +262,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
};
- /**
- * Storage for the client area rectangle so that it may be accessed from outside of the SWT thread.
- */
- private volatile Rectangle clientArea;
-
/**
* Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)}
* on the SWT thread.
@@ -293,72 +301,80 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
* @param style
* Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
* Canvas constructor, so OpenGL handles the background.
- * @param caps
+ * @param capsReqUser
* Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
* graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
* actually used may differ based on the capabilities of the graphics device.
- * @param chooser
+ * @param capsChooser
* Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
* requested GLCapabilities, and the available capabilities of the graphics device.
* @param shareWith
* Optional GLContext to share state (textures, vbos, shaders, etc.) with.
*/
- public GLCanvas(final Composite parent, final int style, GLCapabilitiesImmutable caps,
- final GLCapabilitiesChooser chooser, final GLContext shareWith) {
+ public GLCanvas(final Composite parent, final int style, GLCapabilitiesImmutable capsReqUser,
+ final GLCapabilitiesChooser capsChooser, final GLContext shareWith) {
/* NO_BACKGROUND required to avoid clearing bg in native SWT widget (we do this in the GL display) */
super(parent, style | SWT.NO_BACKGROUND);
GLProfile.initSingleton(); // ensure JOGL is completly initialized
SWTAccessor.setRealized(this, true);
-
+
clientArea = GLCanvas.this.getClientArea();
/* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
* Note: SWT is owner of the native handle, hence closing operation will be a NOP. */
- device = SWTAccessor.getDevice(this);
+ final AbstractGraphicsDevice swtDevice = SWTAccessor.getDevice(this);
+
+ useX11GTK = SWTAccessor.useX11GTK();
+ if(useX11GTK) {
+ // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering
+ final long x11DeviceHandle = X11Util.openDisplay(swtDevice.getConnection());
+ if( 0 == x11DeviceHandle ) {
+ throw new RuntimeException("Error creating display(EDT): "+swtDevice.getConnection());
+ }
+ final AbstractGraphicsDevice x11Device = new X11GraphicsDevice(x11DeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
+ screen = SWTAccessor.getScreen(x11Device, -1 /* default */);
+ } else {
+ screen = SWTAccessor.getScreen(swtDevice, -1 /* default */);
+ }
/* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */
- if(null == caps) {
- caps = new GLCapabilities(GLProfile.getDefault(device));
+ if(null == capsReqUser) {
+ capsReqUser = new GLCapabilities(GLProfile.getDefault(screen.getDevice()));
}
- this.capsRequested = caps;
- this.capsChooser = chooser;
+
+ this.capsRequested = capsReqUser;
+ this.capsChooser = capsChooser;
this.shareWith = shareWith;
// post create .. when ready
+ gdkWindow = 0;
+ x11Window = 0;
drawable = null;
context = null;
- /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
- /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
- addPaintListener(new PaintListener() {
- @Override
- public void paintControl(final PaintEvent arg0) {
- if ( !helper.isAnimatorAnimatingOnOtherThread() ) {
- display(); // checks: null != drawable
- }
- }
- });
-
- addControlListener(new ControlListener() {
- @Override
- public void controlMoved(ControlEvent e) {
- }
-
- @Override
- public void controlResized(final ControlEvent arg0) {
- updateSizeCheck();
- }
- });
-
- addDisposeListener(new DisposeListener() {
- @Override
- public void widgetDisposed(DisposeEvent e) {
- GLCanvas.this.dispose();
- }
- });
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (Event event) {
+ switch (event.type) {
+ case SWT.Paint:
+ displayIfNoAnimatorNoCheck();
+ break;
+ case SWT.Resize:
+ updateSizeCheck();
+ break;
+ case SWT.Dispose:
+ GLCanvas.this.dispose();
+ break;
+ }
+ }
+ };
+ addListener (SWT.Resize, listener);
+ addListener (SWT.Paint, listener);
+ addListener (SWT.Dispose, listener);
}
+
private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() {
@Override
public final void create(ProxySurface s) { /* nop */ }
@@ -390,11 +406,13 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
) {
clientArea = nClientArea; // write back new value
- GLDrawableImpl _drawable = drawable;
- if( null != _drawable ) {
- if(DEBUG) {
- System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
- }
+ final GLDrawableImpl _drawable = drawable;
+ final boolean drawableOK = null != _drawable && _drawable.isRealized();
+ if(DEBUG) {
+ final long dh = drawableOK ? _drawable.getHandle() : 0;
+ System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - drawableHandle 0x"+Long.toHexString(dh));
+ }
+ if( drawableOK ) {
if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
final RecursiveLock _lock = lock;
_lock.lock();
@@ -407,66 +425,154 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
} finally {
_lock.unlock();
}
- }
- sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
- }
+ }
+ }
+ if(0 != x11Window) {
+ SWTAccessor.resizeX11Window(screen.getDevice(), clientArea, x11Window);
+ } else if(0 != gdkWindow) {
+ SWTAccessor.resizeGDKWindow(clientArea, gdkWindow);
+ }
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
}
}
- @Override
- public void display() {
- if( null != drawable || validateDrawableAndContext() ) {
- runInGLThread(makeCurrentAndDisplayOnEDTAction);
- }
+ private boolean isValidAndVisibleOnEDTActionResult;
+ private final Runnable isValidAndVisibleOnEDTAction = new Runnable() {
+ @Override
+ public void run() {
+ isValidAndVisibleOnEDTActionResult = !GLCanvas.this.isDisposed() && GLCanvas.this.isVisible();
+ } };
+
+ private final boolean isValidAndVisibleOnEDT() {
+ synchronized(isValidAndVisibleOnEDTAction) {
+ runOnEDTIfAvail(true, isValidAndVisibleOnEDTAction);
+ return isValidAndVisibleOnEDTActionResult;
+ }
}
-
- /** assumes drawable == null ! */
- protected final boolean validateDrawableAndContext() {
- if( isDisposed() || !isVisible() ) {
+ /** assumes drawable == null || !drawable.isRealized() ! Checks of !isDispose() and isVisible() */
+ protected final boolean validateDrawableAndContextWithCheck() {
+ if( !isValidAndVisibleOnEDT() ) {
return false;
}
+ return validateDrawableAndContextPostCheck();
+ }
+
+ /** assumes drawable == null || !drawable.isRealized() ! No check of !isDispose() and isVisible() */
+ protected final boolean validateDrawableAndContextPostCheck() {
final Rectangle nClientArea = clientArea;
if(0 >= nClientArea.width || 0 >= nClientArea.height) {
return false;
}
+ final boolean res;
final RecursiveLock _lock = lock;
_lock.lock();
try {
- final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
-
- /* Native handle for the control, used to associate with GLContext */
- final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
-
- /* Create a NativeWindow proxy for the SWT canvas */
- ProxySurface proxySurface = null;
- try {
- proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle,
- capsRequested, capsChooser, swtCanvasUpStreamHook);
- } catch (GLException gle) {
- // not ready yet ..
- if(DEBUG) { System.err.println(gle.getMessage()); }
+ if(null == drawable) {
+ createDrawableAndContext();
}
-
- if(null != proxySurface) {
- /* Associate a GL surface with the proxy */
- drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
+ if(null != drawable) {
drawable.setRealized(true);
-
- context = (GLContextImpl) drawable.createContext(shareWith);
+ res = drawable.isRealized();
+ } else {
+ res = false;
}
} finally {
_lock.unlock();
+ }
+
+ if(res) {
+ sendReshape = true;
+ if(DEBUG) {
+ System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
+ // Thread.dumpStack();
+ }
}
- final boolean res = null != drawable;
- if(DEBUG && res) {
- System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
- Thread.dumpStack();
- }
- return res;
+ return res;
+ }
+
+ private final void createDrawableAndContext() {
+ final AbstractGraphicsDevice device = screen.getDevice();
+ device.open();
+
+ final long nativeWindowHandle;
+ if( useX11GTK ) {
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(device, capsRequested);
+ final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capsChooser, screen, VisualIDHolder.VID_UNDEFINED);
+ if(DEBUG) {
+ System.err.println("SWT.GLCanvas.X11 factory: "+factory+", chosen config: "+cfg);
+ }
+ if (null == cfg) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ final int visualID = cfg.getVisualID(VIDType.NATIVE);
+ if( VisualIDHolder.VID_UNDEFINED != visualID ) {
+ // gdkWindow = SWTAccessor.createCompatibleGDKChildWindow(this, visualID, clientArea.width, clientArea.height);
+ // nativeWindowHandle = SWTAccessor.gdk_window_get_xwindow(gdkWindow);
+ x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientArea.width, clientArea.height);
+ nativeWindowHandle = x11Window;
+ } else {
+ throw new GLException("Could not choose valid visualID: 0x"+Integer.toHexString(visualID)+", "+this);
+ }
+ } else {
+ nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+ }
+ final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
+
+ // Create a NativeWindow proxy for the SWT canvas
+ ProxySurface proxySurface = glFactory.createProxySurface(device, screen.getIndex(), nativeWindowHandle,
+ capsRequested, capsChooser, swtCanvasUpStreamHook);
+ // Associate a GL surface with the proxy
+ drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
+ context = (GLContextImpl) drawable.createContext(shareWith);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ }
+
+ @Override
+ public void update() {
+ // don't paint background etc .. nop avoids flickering
+ // super.update();
+ }
+
+ /**
+ @Override
+ public boolean forceFocus() {
+ final boolean r = super.forceFocus();
+ if(r && 0 != gdkWindow) {
+ SWTGTKUtil.focusGDKWindow(gdkWindow);
+ }
+ return r;
+ } */
+
+ @Override
+ public void dispose() {
+ runInGLThread(disposeOnEDTGLAction);
+ super.dispose();
+ }
+
+ private final void displayIfNoAnimatorNoCheck() {
+ if ( !helper.isAnimatorAnimatingOnOtherThread() ) {
+ final boolean drawableOK = null != drawable && drawable.isRealized();
+ if( drawableOK || validateDrawableAndContextPostCheck() ) {
+ runInGLThread(makeCurrentAndDisplayOnGLAction);
+ }
+ }
}
+ //
+ // GL[Auto]Drawable
+ //
+
+ @Override
+ public void display() {
+ final boolean drawableOK = null != drawable && drawable.isRealized();
+ if( drawableOK || validateDrawableAndContextWithCheck() ) {
+ runInGLThread(makeCurrentAndDisplayOnGLAction);
+ }
+ }
+
@Override
public final Object getUpstreamWidget() {
return this;
@@ -692,18 +798,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
@Override
public void swapBuffers() throws GLException {
- runInGLThread(swapBuffersOnEDTAction);
- }
-
- @Override
- public void update() {
- // don't paint background etc .. nop avoids flickering
- }
-
- @Override
- public void dispose() {
- runInGLThread(disposeOnEDTGLAction);
- super.dispose();
+ runInGLThread(swapBuffersOnGLAction);
}
/**
@@ -746,7 +841,32 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
} */
action.run();
}
+
+ private void runOnEDTIfAvail(boolean wait, final Runnable action) {
+ final Display d = isDisposed() ? null : getDisplay();
+ if( null == d || d.isDisposed() || d.getThread() == Thread.currentThread() ) {
+ action.run();
+ } else if(wait) {
+ d.syncExec(action);
+ } else {
+ d.asyncExec(action);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final GLDrawable _drawable = drawable;
+ final int dw = (null!=_drawable) ? _drawable.getWidth() : -1;
+ final int dh = (null!=_drawable) ? _drawable.getHeight() : -1;
+ return "SWT-GLCanvas[Realized "+isRealized()+
+ ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
+ ",\n\tFactory "+getFactory()+
+ ",\n\thandle 0x"+Long.toHexString(getHandle())+
+ ",\n\tDrawable size "+dw+"x"+dh+
+ ",\n\tSWT size "+getWidth()+"x"+getHeight()+"]";
+ }
+
public static void main(final String[] args) {
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index e208cfb28..eba26c7d3 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -34,6 +34,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -59,12 +60,22 @@ public class SWTAccessor {
private static final Field swt_control_handle;
private static final boolean swt_uses_long_handles;
+ private static Object swt_osx_init = new Object();
+ private static Field swt_osx_control_view = null;
+ private static Field swt_osx_view_id = null;
+
+ private static final String nwt;
+ private static final boolean isOSX;
+ private static final boolean isWindows;
+ private static final boolean isX11;
+ private static final boolean isX11GTK;
+
// X11/GTK, Windows/GDI, ..
private static final String str_handle = "handle";
// OSX/Cocoa
- private static final String str_view = "view"; // OSX
- private static final String str_id = "id"; // OSX
+ private static final String str_osx_view = "view"; // OSX
+ private static final String str_osx_id = "id"; // OSX
// static final String str_NSView = "org.eclipse.swt.internal.cocoa.NSView";
private static final Method swt_control_internal_new_GC;
@@ -73,9 +84,10 @@ public class SWTAccessor {
private static final String str_internal_dispose_GC = "internal_dispose_GC";
private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS";
- private static final Class> OS_gtk_class;
+ public static final Class> OS_gtk_class;
private static final String str_OS_gtk_version = "GTK_VERSION";
- private static final VersionNumber OS_gtk_version;
+ public static final VersionNumber OS_gtk_version;
+
private static final Method OS_gtk_widget_realize;
private static final Method OS_gtk_widget_unrealize; // optional (removed in SWT 4.3)
private static final Method OS_GTK_WIDGET_WINDOW;
@@ -85,6 +97,8 @@ public class SWTAccessor {
private static final Method OS_gdk_window_get_display;
private static final Method OS_gdk_x11_drawable_get_xid;
private static final Method OS_gdk_x11_window_get_xid;
+ private static final Method OS_gdk_window_set_back_pixmap;
+
private static final String str_gtk_widget_realize = "gtk_widget_realize";
private static final String str_gtk_widget_unrealize = "gtk_widget_unrealize";
private static final String str_GTK_WIDGET_WINDOW = "GTK_WIDGET_WINDOW";
@@ -94,6 +108,7 @@ public class SWTAccessor {
private static final String str_gdk_window_get_display = "gdk_window_get_display";
private static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid";
private static final String str_gdk_x11_window_get_xid = "gdk_x11_window_get_xid";
+ private static final String str_gdk_window_set_back_pixmap = "gdk_window_set_back_pixmap";
private static final VersionNumber GTK_VERSION_2_14_0 = new VersionNumber(2, 14, 0);
private static final VersionNumber GTK_VERSION_2_24_0 = new VersionNumber(2, 24, 0);
@@ -108,23 +123,25 @@ public class SWTAccessor {
}
static {
- Field f = null;
-
AccessController.doPrivileged(new PrivilegedAction
*/
public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
private static final boolean DEBUG = Debug.debug("Window");
@@ -126,54 +126,44 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
clientArea = getClientArea();
final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
- screen = SWTAccessor.getScreen(device, 0);
+ screen = SWTAccessor.getScreen(device, -1 /* default */);
nativeWindow = null;
if(null != child) {
setNEWTChild(child);
}
-
- /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
- /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
- addPaintListener(new PaintListener() {
+
+ final Listener listener = new Listener () {
@Override
- public void paintControl(final PaintEvent arg0) {
- if( null != nativeWindow || validateNative() ) {
- if( newtChildReady ) {
- if( postSetSize ) {
- newtChild.setSize(clientArea.width, clientArea.height);
- postSetSize = false;
+ public void handleEvent (Event event) {
+ switch (event.type) {
+ case SWT.Paint:
+ if( null != nativeWindow || validateNative() ) {
+ if( newtChildReady ) {
+ if( postSetSize ) {
+ newtChild.setSize(clientArea.width, clientArea.height);
+ postSetSize = false;
+ }
+ newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
}
- newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
}
+ break;
+ case SWT.Resize:
+ updateSizeCheck();
+ break;
+ case SWT.Dispose:
+ NewtCanvasSWT.this.dispose();
+ break;
}
}
- });
-
- addControlListener(new ControlListener() {
- @Override
- public void controlMoved(ControlEvent e) {
- }
- @Override
- public void controlResized(final ControlEvent arg0) {
- updateSizeCheck();
- }
- });
-
- addDisposeListener(new DisposeListener() {
- @Override
- public void widgetDisposed(DisposeEvent e) {
- NewtCanvasSWT.this.dispose();
- }
- });
-
+ };
+ addListener (SWT.Resize, listener);
+ addListener (SWT.Paint, listener);
+ addListener (SWT.Dispose, listener);
}
/** assumes nativeWindow == null ! */
protected final boolean validateNative() {
- if( isDisposed() || !isVisible() ) {
- return false;
- }
updateSizeCheck();
final Rectangle nClientArea = clientArea;
if(0 >= nClientArea.width || 0 >= nClientArea.height) {
@@ -216,6 +206,10 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
) {
clientArea = nClientArea; // write back new value
+ if(DEBUG) {
+ final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
+ System.err.println("NewtCanvasSWT.sizeChanged: ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(nsh));
+ }
if( newtChildReady ) {
newtChild.setSize(clientArea.width, clientArea.height);
} else {
@@ -223,7 +217,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
}
}
}
-
+
@Override
public void update() {
// don't paint background etc .. nop avoids flickering
@@ -261,11 +255,11 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
public NativeWindow getNativeWindow() { return nativeWindow; }
public WindowClosingMode getDefaultCloseOperation() {
- return newtChildCloseOp; // FIXME
+ return newtChildCloseOp; // TODO: implement ?!
}
public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
- return newtChildCloseOp = op; // FIXME
+ return newtChildCloseOp = op; // TODO: implement ?!
}
diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
deleted file mode 100644
index 1c20fe524..000000000
--- a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/**
- * Copyright 2012 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.newt.swt;
-
-import javax.media.nativewindow.NativeWindowException;
-
-import jogamp.newt.Debug;
-
-import com.jogamp.common.util.RunnableTask;
-import com.jogamp.newt.util.EDTUtil;
-
-/**
- * Simple {@link EDTUtil} implementation utilizing the SWT UI thread
- * of the given {@link Display}.
- */
-public class SWTEDTUtil implements EDTUtil {
- public static final boolean DEBUG = Debug.debug("EDT");
-
- private final Object edtLock = new Object(); // locking the EDT start/stop state
- private final ThreadGroup threadGroup;
- private final String name;
- private final Runnable dispatchMessages;
- private final org.eclipse.swt.widgets.Display swtDisplay;
- private NewtEventDispatchThread nedt = null;
- private int start_iter=0;
- private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
-
- public SWTEDTUtil(final com.jogamp.newt.Display newtDisplay, org.eclipse.swt.widgets.Display swtDisplay) {
- this.threadGroup = Thread.currentThread().getThreadGroup();
- this.name=Thread.currentThread().getName()+"-SWTDisplay-"+newtDisplay.getFQName()+"-EDT-";
- this.dispatchMessages = new Runnable() {
- public void run() {
- ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages();
- } };
- this.swtDisplay = swtDisplay;
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
- this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
- }
-
- public final org.eclipse.swt.widgets.Display getDisplay() {
- return swtDisplay;
- }
-
- @Override
- public long getPollPeriod() {
- return pollPeriod;
- }
-
- @Override
- public void setPollPeriod(long ms) {
- pollPeriod = ms;
- }
-
- @Override
- public void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt);
- }
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
- this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
- }
- }
-
- private final void startImpl() {
- if(nedt.isAlive()) {
- throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
- }
- start_iter++;
- nedt.setName(name+start_iter);
- nedt.shouldStop = false;
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": SWT-EDT START - edt: "+nedt);
- // Thread.dumpStack();
- }
- nedt.start();
- }
-
- @Override
- public boolean isCurrentThreadEDT() {
- return swtDisplay.getThread() == Thread.currentThread();
- }
-
- @Override
- public final boolean isCurrentThreadNEDT() {
- return nedt == Thread.currentThread();
- }
-
- @Override
- public final boolean isCurrentThreadEDTorNEDT() {
- final Thread ct = Thread.currentThread();
- return ct == swtDisplay.getThread() || ct == nedt ;
- }
-
- @Override
- public boolean isRunning() {
- return nedt.isRunning() ; // SWT is always running
- }
-
- @Override
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
- }
-
- @Override
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
- }
-
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
- Throwable throwable = null;
- RunnableTask rTask = null;
- Object rTaskLock = new Object();
- synchronized(rTaskLock) { // lock the optional task execution
- synchronized(edtLock) { // lock the EDT status
- if( nedt.shouldStop ) {
- // drop task ..
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
- Thread.dumpStack();
- }
- return;
- }
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- synchronized(nedt.sync) {
- nedt.shouldStop = true;
- nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
- }
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
- // Thread.dumpStack();
- }
- } else if( !nedt.isRunning() ) {
- // start if should not stop && not started yet
- startImpl();
- }
- if( null == task ) {
- wait = false;
- } else if( isCurrentThreadEDT() ) {
- task.run();
- wait = false; // running in same thread (EDT) -> no wait
- } else if( swtDisplay.isDisposed() ) {
- wait = false; // drop task, SWT disposed
- } else {
- rTask = new RunnableTask(task,
- wait ? rTaskLock : null,
- true /* always catch and report Exceptions, don't disturb EDT */);
- swtDisplay.asyncExec(rTask);
- }
- }
- if( wait ) {
- try {
- rTaskLock.wait(); // free lock, allow execution of rTask
- } catch (InterruptedException ie) {
- throwable = ie;
- }
- if(null==throwable) {
- throwable = rTask.getThrowable();
- }
- if(null!=throwable) {
- if(throwable instanceof NativeWindowException) {
- throw (NativeWindowException)throwable;
- }
- throw new RuntimeException(throwable);
- }
- }
- }
- }
-
- @Override
- final public void waitUntilIdle() {
- final NewtEventDispatchThread _nedt;
- synchronized(edtLock) {
- _nedt = nedt;
- }
- final Thread ct = Thread.currentThread();
- if(!_nedt.isRunning() || _nedt == ct || swtDisplay.getThread() == ct) {
- return;
- }
- try {
- swtDisplay.syncExec(new Runnable() {
- public void run() { }
- });
- } catch (Exception e) { }
- }
-
- @Override
- final public void waitUntilStopped() {
- synchronized(edtLock) {
- final Thread ct = Thread.currentThread();
- if(nedt.isRunning() && nedt != ct && swtDisplay.getThread() != ct) {
- while(nedt.isRunning()) {
- try {
- edtLock.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
-
- class NewtEventDispatchThread extends Thread {
- volatile boolean shouldStop = false;
- volatile boolean isRunning = false;
- Object sync = new Object();
-
- public NewtEventDispatchThread(ThreadGroup tg, String name) {
- super(tg, name);
- }
-
- final public boolean isRunning() {
- return isRunning;
- }
-
- @Override
- final public void start() throws IllegalThreadStateException {
- isRunning = true;
- super.start();
- }
-
- /**
- * Utilizing locking only on tasks and its execution,
- * not for event dispatching.
- */
- @Override
- final public void run() {
- if(DEBUG) {
- System.err.println(getName()+": SWT-EDT run() START "+ getName());
- }
- RuntimeException error = null;
- try {
- do {
- // event dispatch
- if(!shouldStop) {
- // EDT invoke thread is SWT-EDT,
- // hence dispatching is required to run on SWT-EDT as well.
- // Otherwise a deadlock may happen due to dispatched event's
- // triggering a locking action.
- if ( !swtDisplay.isDisposed() ) {
- swtDisplay.syncExec(dispatchMessages);
- } else {
- dispatchMessages.run();
- }
- }
- // wait
- synchronized(sync) {
- if(!shouldStop) {
- try {
- sync.wait(pollPeriod);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- } while(!shouldStop) ;
- } catch (Throwable t) {
- // handle errors ..
- shouldStop = true;
- if(t instanceof RuntimeException) {
- error = (RuntimeException) t;
- } else {
- error = new RuntimeException("Within SWT-EDT", t);
- }
- } finally {
- if(DEBUG) {
- System.err.println(getName()+": SWT-EDT run() END "+ getName()+", "+error);
- }
- synchronized(edtLock) {
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
- }
- if(DEBUG) {
- System.err.println(getName()+": SWT-EDT run() EXIT "+ getName()+", exception: "+error);
- }
- if(null!=error) {
- throw error;
- }
- } // finally
- } // run()
- } // EventDispatchThread
-
-}
diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
new file mode 100644
index 000000000..7297e5858
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
@@ -0,0 +1,313 @@
+/**
+ * Copyright 2012 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 jogamp.newt.swt;
+
+import javax.media.nativewindow.NativeWindowException;
+
+import jogamp.newt.Debug;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.newt.util.EDTUtil;
+
+/**
+ * Simple {@link EDTUtil} implementation utilizing the SWT UI thread
+ * of the given {@link Display}.
+ */
+public class SWTEDTUtil implements EDTUtil {
+ public static final boolean DEBUG = Debug.debug("EDT");
+
+ private final Object edtLock = new Object(); // locking the EDT start/stop state
+ private final ThreadGroup threadGroup;
+ private final String name;
+ private final Runnable dispatchMessages;
+ private final org.eclipse.swt.widgets.Display swtDisplay;
+ private NewtEventDispatchThread nedt = null;
+ private int start_iter=0;
+ private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
+
+ public SWTEDTUtil(final com.jogamp.newt.Display newtDisplay, org.eclipse.swt.widgets.Display swtDisplay) {
+ this.threadGroup = Thread.currentThread().getThreadGroup();
+ this.name=Thread.currentThread().getName()+"-SWTDisplay-"+newtDisplay.getFQName()+"-EDT-";
+ this.dispatchMessages = new Runnable() {
+ public void run() {
+ ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages();
+ } };
+ this.swtDisplay = swtDisplay;
+ this.nedt = new NewtEventDispatchThread(threadGroup, name);
+ this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+
+ public final org.eclipse.swt.widgets.Display getDisplay() {
+ return swtDisplay;
+ }
+
+ @Override
+ public long getPollPeriod() {
+ return pollPeriod;
+ }
+
+ @Override
+ public void setPollPeriod(long ms) {
+ pollPeriod = ms;
+ }
+
+ @Override
+ public void reset() {
+ synchronized(edtLock) {
+ waitUntilStopped();
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt);
+ }
+ this.nedt = new NewtEventDispatchThread(threadGroup, name);
+ this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ }
+
+ private final void startImpl() {
+ if(nedt.isAlive()) {
+ throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
+ }
+ start_iter++;
+ nedt.setName(name+start_iter);
+ nedt.shouldStop = false;
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT START - edt: "+nedt);
+ // Thread.dumpStack();
+ }
+ nedt.start();
+ }
+
+ @Override
+ public boolean isCurrentThreadEDT() {
+ return swtDisplay.getThread() == Thread.currentThread();
+ }
+
+ @Override
+ public final boolean isCurrentThreadNEDT() {
+ return nedt == Thread.currentThread();
+ }
+
+ @Override
+ public final boolean isCurrentThreadEDTorNEDT() {
+ final Thread ct = Thread.currentThread();
+ return ct == swtDisplay.getThread() || ct == nedt ;
+ }
+
+ @Override
+ public boolean isRunning() {
+ return nedt.isRunning() ; // SWT is always running
+ }
+
+ @Override
+ public final void invokeStop(Runnable task) {
+ invokeImpl(true, task, true);
+ }
+
+ @Override
+ public final void invoke(boolean wait, Runnable task) {
+ invokeImpl(wait, task, false);
+ }
+
+ private void invokeImpl(boolean wait, Runnable task, boolean stop) {
+ Throwable throwable = null;
+ RunnableTask rTask = null;
+ Object rTaskLock = new Object();
+ synchronized(rTaskLock) { // lock the optional task execution
+ synchronized(edtLock) { // lock the EDT status
+ if( nedt.shouldStop ) {
+ // drop task ..
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
+ Thread.dumpStack();
+ }
+ return;
+ }
+ // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
+ // Thread.dumpStack();
+ if(stop) {
+ synchronized(nedt.sync) {
+ nedt.shouldStop = true;
+ nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+ }
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
+ // Thread.dumpStack();
+ }
+ } else if( !nedt.isRunning() ) {
+ // start if should not stop && not started yet
+ startImpl();
+ }
+ if( null == task ) {
+ wait = false;
+ } else if( isCurrentThreadEDT() ) {
+ task.run();
+ wait = false; // running in same thread (EDT) -> no wait
+ } else if( swtDisplay.isDisposed() ) {
+ wait = false; // drop task, SWT disposed
+ } else {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */);
+ swtDisplay.asyncExec(rTask);
+ }
+ }
+ if( wait ) {
+ try {
+ rTaskLock.wait(); // free lock, allow execution of rTask
+ } catch (InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ if(throwable instanceof NativeWindowException) {
+ throw (NativeWindowException)throwable;
+ }
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ }
+
+ @Override
+ final public void waitUntilIdle() {
+ final NewtEventDispatchThread _nedt;
+ synchronized(edtLock) {
+ _nedt = nedt;
+ }
+ final Thread ct = Thread.currentThread();
+ if(!_nedt.isRunning() || _nedt == ct || swtDisplay.getThread() == ct) {
+ return;
+ }
+ try {
+ swtDisplay.syncExec(new Runnable() {
+ public void run() { }
+ });
+ } catch (Exception e) { }
+ }
+
+ @Override
+ final public void waitUntilStopped() {
+ synchronized(edtLock) {
+ final Thread ct = Thread.currentThread();
+ if(nedt.isRunning() && nedt != ct && swtDisplay.getThread() != ct) {
+ while(nedt.isRunning()) {
+ try {
+ edtLock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ class NewtEventDispatchThread extends Thread {
+ volatile boolean shouldStop = false;
+ volatile boolean isRunning = false;
+ Object sync = new Object();
+
+ public NewtEventDispatchThread(ThreadGroup tg, String name) {
+ super(tg, name);
+ }
+
+ final public boolean isRunning() {
+ return isRunning;
+ }
+
+ @Override
+ final public void start() throws IllegalThreadStateException {
+ isRunning = true;
+ super.start();
+ }
+
+ /**
+ * Utilizing locking only on tasks and its execution,
+ * not for event dispatching.
+ */
+ @Override
+ final public void run() {
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() START "+ getName());
+ }
+ RuntimeException error = null;
+ try {
+ do {
+ // event dispatch
+ if(!shouldStop) {
+ // EDT invoke thread is SWT-EDT,
+ // hence dispatching is required to run on SWT-EDT as well.
+ // Otherwise a deadlock may happen due to dispatched event's
+ // triggering a locking action.
+ if ( !swtDisplay.isDisposed() ) {
+ swtDisplay.syncExec(dispatchMessages);
+ } else {
+ dispatchMessages.run();
+ }
+ }
+ // wait
+ synchronized(sync) {
+ if(!shouldStop) {
+ try {
+ sync.wait(pollPeriod);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } while(!shouldStop) ;
+ } catch (Throwable t) {
+ // handle errors ..
+ shouldStop = true;
+ if(t instanceof RuntimeException) {
+ error = (RuntimeException) t;
+ } else {
+ error = new RuntimeException("Within SWT-EDT", t);
+ }
+ } finally {
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() END "+ getName()+", "+error);
+ }
+ synchronized(edtLock) {
+ isRunning = !shouldStop;
+ if(!isRunning) {
+ edtLock.notifyAll();
+ }
+ }
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() EXIT "+ getName()+", exception: "+error);
+ }
+ if(null!=error) {
+ throw error;
+ }
+ } // finally
+ } // run()
+ } // EventDispatchThread
+
+}
diff --git a/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
new file mode 100644
index 000000000..e238f5d9e
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
@@ -0,0 +1,249 @@
+/**
+ * Copyright 2012 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 jogamp.newt.swt.event;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+import com.jogamp.common.util.IntIntHashMap;
+import com.jogamp.newt.event.InputEvent;
+
+/**
+ * SWT event translator to NEWT, inclusive dispatch listener.
+ *
+ * Disclaimer: This code is merely tested and subject to change.
+ *
+ */
+public class SWTNewtEventFactory {
+
+ protected static final IntIntHashMap eventTypeSWT2NEWT;
+
+ static {
+ IntIntHashMap map = new IntIntHashMap();
+ map.setKeyNotFoundValue(0xFFFFFFFF);
+
+ // map.put(SWT.MouseXXX, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED);
+ map.put(SWT.MouseDown, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
+ map.put(SWT.MouseUp, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
+ map.put(SWT.MouseMove, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED);
+ map.put(SWT.MouseEnter, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED);
+ map.put(SWT.MouseExit, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED);
+ // map.put(SWT.MouseXXX, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED);
+ map.put(SWT.MouseVerticalWheel, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED);
+
+ map.put(SWT.KeyDown, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED);
+ map.put(SWT.KeyUp, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED);
+ // map.put(SWT.KeyXXX, com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED);
+
+ eventTypeSWT2NEWT = map;
+ }
+
+ public static final int swtModifiers2Newt(int awtMods, boolean mouseHint) {
+ int newtMods = 0;
+ if ((awtMods & SWT.SHIFT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ if ((awtMods & SWT.CTRL) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
+ if ((awtMods & SWT.ALT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
+ return newtMods;
+ }
+
+ public static final com.jogamp.newt.event.InputEvent createInputEvent(org.eclipse.swt.widgets.Event event, Object source) {
+ com.jogamp.newt.event.InputEvent res = createMouseEvent(event, source);
+ if(null == res) {
+ res = createKeyEvent(event, source);
+ }
+ return res;
+ }
+
+ public static final com.jogamp.newt.event.MouseEvent createMouseEvent(org.eclipse.swt.widgets.Event event, Object source) {
+ switch(event.type) {
+ case SWT.MouseDown:
+ case SWT.MouseUp:
+ case SWT.MouseMove:
+ case SWT.MouseEnter:
+ case SWT.MouseExit:
+ case SWT.MouseVerticalWheel:
+ break;
+ default:
+ return null;
+ }
+ int type = eventTypeSWT2NEWT.get(event.type);
+ if(0xFFFFFFFF != type) {
+ int rotation = 0;
+ if (SWT.MouseVerticalWheel == event.type) {
+ // SWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up.
+ // rotation = -1 * (int) event.rotation;
+ rotation = (int) event.rotation;
+ }
+
+ int mods = swtModifiers2Newt(event.stateMask, true);
+
+ if( source instanceof com.jogamp.newt.Window) {
+ final com.jogamp.newt.Window newtSource = (com.jogamp.newt.Window)source;
+ if(newtSource.isPointerConfined()) {
+ mods |= InputEvent.CONFINED_MASK;
+ }
+ if(!newtSource.isPointerVisible()) {
+ mods |= InputEvent.INVISIBLE_MASK;
+ }
+ }
+
+ return new com.jogamp.newt.event.MouseEvent(
+ type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time),
+ mods, event.x, event.y, event.count, event.button, rotation);
+ }
+ return null; // no mapping ..
+ }
+
+ public static final com.jogamp.newt.event.KeyEvent createKeyEvent(org.eclipse.swt.widgets.Event event, Object source) {
+ switch(event.type) {
+ case SWT.KeyDown:
+ case SWT.KeyUp:
+ break;
+ default:
+ return null;
+ }
+ int type = eventTypeSWT2NEWT.get(event.type);
+ if(0xFFFFFFFF != type) {
+ return new com.jogamp.newt.event.KeyEvent(
+ type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time),
+ swtModifiers2Newt(event.stateMask, false),
+ event.keyCode, event.character);
+ }
+ return null; // no mapping ..
+ }
+
+ //
+ //
+ //
+
+ int dragButtonDown = 0;
+
+ public SWTNewtEventFactory() {
+ resetButtonsDown();
+ }
+
+ final void resetButtonsDown() {
+ dragButtonDown = 0;
+ }
+
+ public final boolean dispatchMouseEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.MouseListener l) {
+ com.jogamp.newt.event.MouseEvent res = createMouseEvent(event, source);
+ if(null != res) {
+ if(null != l) {
+ switch(event.type) {
+ case SWT.MouseDown:
+ dragButtonDown = event.button;
+ l.mousePressed(res); break;
+ case SWT.MouseUp:
+ dragButtonDown = 0;
+ l.mouseReleased(res);
+ {
+ final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+ com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED,
+ res.getSource(),
+ res.getWhen(), res.getModifiers(),
+ res.getX(), res.getY(), res.getClickCount(),
+ res.getButton(), res.getWheelRotation() );
+ l.mouseClicked(res2);
+ }
+ break;
+ case SWT.MouseMove:
+ if( 0 < dragButtonDown ) {
+ final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+ com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED,
+ res.getSource(),
+ res.getWhen(), res.getModifiers(),
+ res.getX(), res.getY(), res.getClickCount(),
+ dragButtonDown, res.getWheelRotation() );
+ l.mouseDragged( res2 );
+ } else {
+ l.mouseMoved(res);
+ }
+ break;
+ case SWT.MouseEnter:
+ l.mouseEntered(res);
+ break;
+ case SWT.MouseExit:
+ resetButtonsDown();
+ l.mouseExited(res);
+ break;
+ case SWT.MouseVerticalWheel:
+ l.mouseWheelMoved(res);
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public final boolean dispatchKeyEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.KeyListener l) {
+ com.jogamp.newt.event.KeyEvent res = createKeyEvent(event, source);
+ if(null != res) {
+ if(null != l) {
+ switch(event.type) {
+ case SWT.KeyDown:
+ l.keyPressed(res);
+ break;
+ case SWT.KeyUp:
+ l.keyReleased(res);
+ l.keyTyped(res);
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public final void attachDispatchListener(final org.eclipse.swt.widgets.Control ctrl, final Object source,
+ final com.jogamp.newt.event.MouseListener ml,
+ final com.jogamp.newt.event.KeyListener kl) {
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (Event event) {
+ if( dispatchMouseEvent( event, source, ml ) ) {
+ return;
+ }
+ if( dispatchKeyEvent( event, source, kl ) ) {
+ return;
+ }
+ } };
+ ctrl.addListener(SWT.MouseDown, listener);
+ ctrl.addListener(SWT.MouseUp, listener);
+ ctrl.addListener(SWT.MouseMove, listener);
+ ctrl.addListener(SWT.MouseEnter, listener);
+ ctrl.addListener(SWT.MouseExit, listener);
+ ctrl.addListener(SWT.MouseVerticalWheel, listener);
+ ctrl.addListener(SWT.KeyDown, listener);
+ ctrl.addListener(SWT.KeyUp, listener);
+ }
+}
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index e9fe9b401..a3023538f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -60,8 +60,8 @@ public class GearsES2 implements GLEventListener {
private int swapInterval = 0;
private boolean pmvUseBackingArray = true; // the default for PMVMatrix now, since it's faster
// private MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter());
- private MouseListener gearsMouse = new GearsMouseAdapter();
- private KeyListener gearsKeys = new GearsKeyAdapter();
+ public MouseListener gearsMouse = new GearsMouseAdapter();
+ public KeyListener gearsKeys = new GearsKeyAdapter();
private int prevMouseX, prevMouseY;
private boolean doRotate = true;
@@ -352,6 +352,10 @@ public class GearsES2 implements GLEventListener {
window = (Window) source;
width=window.getWidth();
height=window.getHeight();
+ } else if (source instanceof GLAutoDrawable) {
+ GLAutoDrawable glad = (GLAutoDrawable) source;
+ width = glad.getWidth();
+ height = glad.getHeight();
} else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) {
java.awt.Component comp = (java.awt.Component) source;
width=comp.getWidth();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java
index a0874e609..1f3bf3156 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java
@@ -366,8 +366,9 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase {
try {
while( !shallStop && !dsc.display.isDisposed() ) {
- if( !dsc.display.readAndDispatch() ) {
- dsc.display.sleep();
+ if( !dsc.display.readAndDispatch() && !shallStop ) {
+ // blocks on linux .. dsc.display.sleep();
+ Thread.sleep(10);
}
}
} catch (Exception e0) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
index 0a47b96eb..97b3ab243 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
@@ -45,12 +45,13 @@ import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities ;
import javax.media.opengl.GLProfile;
+import jogamp.newt.swt.SWTEDTUtil;
+import jogamp.newt.swt.event.SWTNewtEventFactory;
import junit.framework.Assert;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.newt.opengl.GLWindow ;
import com.jogamp.newt.swt.NewtCanvasSWT ;
-import com.jogamp.newt.swt.SWTEDTUtil;
import com.jogamp.opengl.swt.GLCanvas;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
@@ -121,15 +122,15 @@ public class TestSWTBug643AsyncExec extends UITestCase {
final Runnable swtAsyncAction = new Runnable() {
public void run()
{
- ++swtN ;
- System.err.println("[SWT A-i shallStop "+shallStop+"]: Counter[loc "+swtN+", glob: "+incrSWTCount()+"]");
+ ++swtN ; incrSWTCount();
+ System.err.println("[SWT A-i shallStop "+shallStop+"]: Counter[loc "+swtN+", glob: "+getSWTCount()+"]");
} };
final Runnable newtAsyncAction = new Runnable() {
public void run()
{
- ++newtN ;
- System.err.println("[NEWT A-i shallStop "+shallStop+"]: Counter[loc "+newtN+", glob: "+incrNEWTCount()+"]");
+ ++newtN ; incrNEWTCount();
+ System.err.println("[NEWT A-i shallStop "+shallStop+"]: Counter[loc "+newtN+", glob: "+getNEWTCount()+"]");
} };
public void run()
@@ -219,9 +220,13 @@ public class TestSWTBug643AsyncExec extends UITestCase {
final GLAutoDrawable glad;
if( useJOGLGLCanvas ) {
- glad = GLCanvas.create(dsc.composite, 0, caps, null, null);
- glad.addGLEventListener( new GearsES2() ) ;
- newtDisplay = null;
+ final GearsES2 demo = new GearsES2();
+ final GLCanvas glc = GLCanvas.create(dsc.composite, 0, caps, null, null);
+ final SWTNewtEventFactory swtNewtEventFactory = new SWTNewtEventFactory();
+ swtNewtEventFactory.attachDispatchListener(glc, glc, demo.gearsMouse, demo.gearsKeys);
+ glc.addGLEventListener( demo ) ;
+ glad = glc;
+ newtDisplay = null;
} else if( useNewtCanvasSWT ) {
final GLWindow glWindow = GLWindow.create( caps ) ;
glWindow.addGLEventListener( new GearsES2() ) ;
@@ -287,8 +292,9 @@ public class TestSWTBug643AsyncExec extends UITestCase {
try {
final Display d = dsc.display;
while( !shallStop && !d.isDisposed() ) {
- if( !d.readAndDispatch() ) {
- dsc.display.sleep();
+ if( !d.readAndDispatch() && !shallStop ) {
+ // blocks on linux .. dsc.display.sleep();
+ Thread.sleep(10);
}
}
} catch (Exception e0) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
index a5d2c8012..1822d2eaf 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
@@ -50,6 +50,7 @@ import org.junit.Test;
import com.jogamp.nativewindow.swt.SWTAccessor;
import com.jogamp.opengl.swt.GLCanvas;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
@@ -58,10 +59,9 @@ import com.jogamp.opengl.util.texture.TextureIO;
/**
* Tests that a basic SWT app can open without crashing under different GL profiles.
*
- * Uses JOGL's new SWT GLCanvas.
- *
- *
- * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used.
+ * Uses JOGL's new SWT GLCanvas,
+ * which allows utilizing custom GLCapability settings,
+ * independent from the already instantiated SWT visual.
*
*
* Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
@@ -188,6 +188,14 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() );
}
+ @Test
+ public void test_MultisampleAndAlpha() throws InterruptedException {
+ GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(2);
+ runTestAGL( caps, new MultisampleDemoES2(true) );
+ }
+
static int atoi(String a) {
int i=0;
try {
--
cgit v1.2.3