diff options
45 files changed, 993 insertions, 505 deletions
diff --git a/make/scripts/java-run-all.sh b/make/scripts/java-run-all.sh index 16353dff2..0d7e5b21d 100755 --- a/make/scripts/java-run-all.sh +++ b/make/scripts/java-run-all.sh @@ -46,6 +46,7 @@ uname -a | grep -i Darwin && MOSX=1 # D_ARGS="-Dnewt.debug=all" # D_ARGS="-Dnewt.debug.Window" # D_ARGS="-Dnewt.debug.Display" +# D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display" # D_ARGS="-Dnewt.debug.Window -Dnewt.debug.TestEDTMainThread" # D_ARGS="-Dnewt.debug.TestEDTMainThread" # D_ARGS="-Djogl.debug=all -Djogl.debug.DynamicLookup=true -Djogamp.debug.NativeLibrary=true" diff --git a/src/junit/com/jogamp/test/junit/newt/TestDisplayLifecycle01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestDisplayLifecycle01NEWT.java new file mode 100644 index 000000000..f0ceba606 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestDisplayLifecycle01NEWT.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2010 Sven Gothel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name Sven Gothel or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.test.junit.newt; + +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Test; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +import com.jogamp.newt.*; +import com.jogamp.newt.event.*; +import com.jogamp.newt.opengl.*; +import java.io.IOException; + +import com.jogamp.test.junit.util.MiscUtils; +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; + +public class TestDisplayLifecycle01NEWT { + static { + GLProfile.initSingleton(); + } + + static GLProfile glp; + static GLCapabilities caps; + static int width, height; + static long durationPerTest = 100; // ms + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glp = GLProfile.getDefault(); + caps = new GLCapabilities(glp); + } + + static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height) + throws InterruptedException + { + Assert.assertNotNull(caps); + + // + // Create native windowing resources .. X11/Win/OSX + // + GLWindow glWindow; + if(null!=screen) { + Window window = NewtFactory.createWindow(screen, caps, false); + Assert.assertNotNull(window); + glWindow = GLWindow.create(window); + } else { + glWindow = GLWindow.create(caps, false); + } + + GLEventListener demo = new Gears(); + setDemoFields(demo, glWindow); + glWindow.addGLEventListener(demo); + glWindow.addWindowListener(new TraceWindowAdapter()); + glWindow.setSize(width, height); + return glWindow; + } + + private void testDisplayCreate01(Display display, Screen screen, boolean destroyWhenUnused) throws InterruptedException { + // start-state == end-state + Assert.assertEquals(0,Display.getActiveDisplayNumber()); + Assert.assertEquals(0,display.getReferenceCount()); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertNotNull(display.getEDTUtil()); + Assert.assertEquals(false,display.getEDTUtil().isRunning()); + Assert.assertEquals(0,screen.getReferenceCount()); + Assert.assertEquals(false,screen.isNativeValid()); + + // Setup/Verify default DestroyWhenUnused behavior + if(destroyWhenUnused) { + screen.setDestroyWhenUnused(true); + } + Assert.assertEquals(destroyWhenUnused,display.getDestroyWhenUnused()); + Assert.assertEquals(destroyWhenUnused,screen.getDestroyWhenUnused()); + + // Create Window, pending lazy native creation + GLWindow window = createWindow(screen, caps, width, height); + Assert.assertEquals(screen,window.getScreen()); + Assert.assertEquals(0,Display.getActiveDisplayNumber()); + Assert.assertEquals(0,display.getReferenceCount()); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertEquals(false,display.getEDTUtil().isRunning()); + Assert.assertEquals(0,screen.getReferenceCount()); + Assert.assertEquals(false,screen.isNativeValid()); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + + // lazy native creation sequence: Display, Screen and Window + window.setVisible(true); + window.display(); + int wait=0; + while(wait<10 && window.getTotalFrames()<1) { Thread.sleep(100); wait++; } + System.out.println("Frames for setVisible(true) 1: "+window.getTotalFrames()); + + Assert.assertEquals(screen,window.getScreen()); + Assert.assertEquals(1,Display.getActiveDisplayNumber()); + Assert.assertEquals(1,display.getReferenceCount()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(1,screen.getReferenceCount()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + + while(window.getDuration()<1*durationPerTest) { + window.display(); + Thread.sleep(100); + } + System.out.println("duration: "+window.getDuration()); + + // just make the Window invisible + window.setVisible(false); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + + // just make the Window visible again + window.setVisible(true); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + + while(window.getDuration()<2*durationPerTest) { + window.display(); + Thread.sleep(100); + } + System.out.println("duration: "+window.getDuration()); + + // recoverable destruction, ie Display/Screen untouched + window.destroy(false); + Assert.assertEquals(screen,window.getScreen()); + Assert.assertEquals(1,Display.getActiveDisplayNumber()); + Assert.assertEquals(1,display.getReferenceCount()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertNotNull(display.getEDTUtil()); + Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(1,screen.getReferenceCount()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + + // a display call shall not change a thing + window.display(); + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + + // recover Window + window.setVisible(true); + window.display(); + wait=0; + while(wait<10 && window.getTotalFrames()<1) { Thread.sleep(100); wait++; } + System.out.println("Frames for setVisible(true) 2: "+window.getTotalFrames()); + + Assert.assertEquals(screen,window.getScreen()); + Assert.assertEquals(1,Display.getActiveDisplayNumber()); + Assert.assertEquals(1,display.getReferenceCount()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(1,screen.getReferenceCount()); + Assert.assertEquals(true,screen.isNativeValid()); + Assert.assertEquals(true,window.isNativeValid()); + Assert.assertEquals(true,window.isVisible()); + + while(window.getDuration()<1*durationPerTest) { + window.display(); + Thread.sleep(100); + } + System.out.println("duration: "+window.getDuration()); + + // unrecoverable destruction, ie Display/Screen will be unreferenced + window.destroy(true); + Assert.assertEquals(null,window.getScreen()); + Display.dumpDisplayList("Post destroy(true)"); + if(!destroyWhenUnused) { + // display/screen untouched when unused, default + Assert.assertEquals(1,Display.getActiveDisplayNumber()); + Assert.assertEquals(1,display.getReferenceCount()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertNotNull(display.getEDTUtil()); + Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(0,screen.getReferenceCount()); + Assert.assertEquals(true,screen.isNativeValid()); + + // manual destruction: Screen + screen.destroy(); + Assert.assertEquals(1,Display.getActiveDisplayNumber()); + Assert.assertEquals(0,display.getReferenceCount()); + Assert.assertEquals(true,display.isNativeValid()); + Assert.assertNotNull(display.getEDTUtil()); + Assert.assertEquals(true,display.getEDTUtil().isRunning()); + Assert.assertEquals(0,screen.getReferenceCount()); + Assert.assertEquals(false,screen.isNativeValid()); + + // manual destruction: Display + display.destroy(); + } else { + // display/screen destroyed when unused + } + + // end-state == start-state + Assert.assertEquals(0,Display.getActiveDisplayNumber()); + Assert.assertEquals(0,display.getReferenceCount()); + Assert.assertEquals(false,display.isNativeValid()); + Assert.assertNotNull(display.getEDTUtil()); + Assert.assertEquals(false,display.getEDTUtil().isRunning()); + Assert.assertEquals(0,screen.getReferenceCount()); + Assert.assertEquals(false,screen.isNativeValid()); + + Assert.assertEquals(false,window.isNativeValid()); + Assert.assertEquals(false,window.isVisible()); + } + + @Test + public void testDisplayCreate01_DestroyWhenUnused_False() throws InterruptedException { + Assert.assertEquals(0,Display.getActiveDisplayNumber()); + + // Create Display/Screen, pending lazy native creation + Display display = NewtFactory.createDisplay(null); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + testDisplayCreate01(display, screen, false); + testDisplayCreate01(display, screen, false); + + Assert.assertEquals(0,Display.getActiveDisplayNumber()); + } + + @Test + public void testDisplayCreate01_DestroyWhenUnused_True() throws InterruptedException { + Assert.assertEquals(0,Display.getActiveDisplayNumber()); + + // Create Display/Screen, pending lazy native creation + Display display = NewtFactory.createDisplay(null); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + testDisplayCreate01(display, screen, true); + testDisplayCreate01(display, screen, true); + + Assert.assertEquals(0,Display.getActiveDisplayNumber()); + } + + public static void setDemoFields(GLEventListener demo, GLWindow glWindow) { + Assert.assertNotNull(demo); + Assert.assertNotNull(glWindow); + if(!MiscUtils.setFieldIfExists(demo, "window", glWindow.getInnerWindow())) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + durationPerTest = atoi(args[++i]); + } + } + System.out.println("durationPerTest: "+durationPerTest); + String tstname = TestDisplayLifecycle01NEWT.class.getName(); + org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { + tstname, + "filtertrace=true", + "haltOnError=false", + "haltOnFailure=false", + "showoutput=true", + "outputtoformatters=true", + "logfailedtests=true", + "logtestlistenerevents=true", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + } + +} diff --git a/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java index 1a6863a31..9586ad936 100644 --- a/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestGLWindows01NEWT.java @@ -89,7 +89,7 @@ public class TestGLWindows01NEWT { } Assert.assertNotNull(glWindow); Assert.assertEquals(false,glWindow.isVisible()); - Assert.assertEquals(false,glWindow.isNativeWindowValid()); + Assert.assertEquals(false,glWindow.isNativeValid()); GLEventListener demo = new Gears(); setDemoFields(demo, glWindow); @@ -102,7 +102,7 @@ public class TestGLWindows01NEWT { glWindow.setVisible(true); Assert.assertEquals(true,glWindow.isVisible()); - Assert.assertEquals(true,glWindow.isNativeWindowValid()); + Assert.assertEquals(true,glWindow.isNativeValid()); int wait=0; while(wait<10 && glWindow.getTotalFrames()<1) { Thread.sleep(100); wait++; } System.out.println("Frames for initial setVisible(true): "+glWindow.getTotalFrames()); @@ -133,7 +133,7 @@ public class TestGLWindows01NEWT { static void destroyWindow(GLWindow glWindow, boolean deep) { if(null!=glWindow) { glWindow.destroy(deep); - Assert.assertEquals(false,glWindow.isNativeWindowValid()); + Assert.assertEquals(false,glWindow.isNativeValid()); } } @@ -145,22 +145,22 @@ public class TestGLWindows01NEWT { true /* onscreen */, false /* undecorated */, false /*addGLEventListenerAfterVisible*/); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); window.destroy(false); - Assert.assertEquals(false,window.isNativeWindowValid()); + Assert.assertEquals(false,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); window.display(); - Assert.assertEquals(false,window.isNativeWindowValid()); + Assert.assertEquals(false,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); window.setVisible(true); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); window.setVisible(false); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); destroyWindow(window, true); @@ -174,22 +174,22 @@ public class TestGLWindows01NEWT { true /* onscreen */, false /* undecorated */, true /*addGLEventListenerAfterVisible*/); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); window.destroy(false); - Assert.assertEquals(false,window.isNativeWindowValid()); + Assert.assertEquals(false,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); window.display(); - Assert.assertEquals(false,window.isNativeWindowValid()); + Assert.assertEquals(false,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); window.setVisible(true); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); window.setVisible(false); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); destroyWindow(window, true); diff --git a/src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java b/src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java index 60fadb7d6..62bb5b7f9 100644 --- a/src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java +++ b/src/junit/com/jogamp/test/junit/newt/TestGLWindows02NEWTAnimated.java @@ -89,13 +89,13 @@ public class TestGLWindows02NEWTAnimated { setDemoFields(demo, glWindow); glWindow.addGLEventListener(demo); glWindow.addWindowListener(new TraceWindowAdapter()); - Assert.assertEquals(false,glWindow.isNativeWindowValid()); + Assert.assertEquals(false,glWindow.isNativeValid()); glWindow.setSize(width, height); Assert.assertEquals(false,glWindow.isVisible()); glWindow.setVisible(true); Assert.assertEquals(true,glWindow.isVisible()); - Assert.assertEquals(true,glWindow.isNativeWindowValid()); + Assert.assertEquals(true,glWindow.isNativeValid()); // Assert.assertEquals(width,glWindow.getWidth()); // Assert.assertEquals(height,glWindow.getHeight()); // System.out.println("Created: "+glWindow); diff --git a/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java index d729b2718..be917ecea 100644 --- a/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java @@ -65,11 +65,11 @@ public class TestWindows01NEWT { Window window = NewtFactory.createWindow(screen, caps, onscreen && undecorated); Assert.assertNotNull(window); window.setSize(width, height); - Assert.assertEquals(false,window.isNativeWindowValid()); + Assert.assertEquals(false,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); window.setVisible(true); Assert.assertEquals(true,window.isVisible()); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); // Assert.assertEquals(width,window.getWidth()); // Assert.assertEquals(height,window.getHeight()); // System.out.println("Created: "+window); @@ -111,11 +111,11 @@ public class TestWindows01NEWT { Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); window.destroy(); - Assert.assertEquals(false,window.isNativeWindowValid()); + Assert.assertEquals(false,window.isNativeValid()); Assert.assertEquals(false,window.isVisible()); window.setVisible(true); - Assert.assertEquals(true,window.isNativeWindowValid()); + Assert.assertEquals(true,window.isNativeValid()); Assert.assertEquals(true,window.isVisible()); Thread.sleep(100); // 100 ms diff --git a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01NEWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01NEWT.java index fc6a30bd6..ad03f010c 100644 --- a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01NEWT.java @@ -83,7 +83,7 @@ public class TestParenting01NEWT { GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); glWindow1.setSize(640, 480); @@ -94,7 +94,7 @@ public class TestParenting01NEWT { GLWindow glWindow2 = GLWindow.create(glWindow1, glCaps); Assert.assertNotNull(glWindow2); Assert.assertEquals(false, glWindow2.isVisible()); - Assert.assertEquals(false, glWindow2.isNativeWindowValid()); + Assert.assertEquals(false, glWindow2.isNativeValid()); Assert.assertEquals(glWindow1,glWindow2.getParentNativeWindow()); glWindow2.setSize(320, 240); GLEventListener demo2 = new Gears(); @@ -104,19 +104,19 @@ public class TestParenting01NEWT { // visible test glWindow1.setVisible(true); Assert.assertEquals(true, glWindow1.isVisible()); - Assert.assertEquals(true, glWindow1.isNativeWindowValid()); + Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(true, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(true, glWindow2.isNativeValid()); glWindow1.setVisible(false); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(true, glWindow1.isNativeWindowValid()); + Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(false, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(true, glWindow2.isNativeValid()); glWindow1.setVisible(true); Assert.assertEquals(true, glWindow1.isVisible()); - Assert.assertEquals(true, glWindow1.isNativeWindowValid()); + Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(true, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(true, glWindow2.isNativeValid()); Animator animator1 = new Animator(glWindow1); animator1.start(); @@ -133,20 +133,20 @@ public class TestParenting01NEWT { glWindow1.destroy(); // false Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertEquals(true, glWindow1.isValid()); Assert.assertEquals(false, glWindow2.isVisible()); - Assert.assertEquals(false, glWindow2.isNativeWindowValid()); - Assert.assertEquals(false, glWindow2.isDestroyed()); + Assert.assertEquals(false, glWindow2.isNativeValid()); + Assert.assertEquals(true, glWindow2.isValid()); glWindow1.destroy(true); - Assert.assertEquals(true, glWindow1.isDestroyed()); - Assert.assertEquals(true, glWindow2.isDestroyed()); + Assert.assertEquals(false, glWindow1.isValid()); + Assert.assertEquals(false, glWindow2.isValid()); // test double destroy .. glWindow2.destroy(true); - Assert.assertEquals(true, glWindow2.isDestroyed()); + Assert.assertEquals(false, glWindow2.isValid()); } @Test @@ -185,14 +185,14 @@ public class TestParenting01NEWT { Assert.assertEquals(true, glWindow2.isVisible()); glWindow2.reparentWindow(glWindow1, null); Assert.assertEquals(true, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertEquals(glWindow1,glWindow2.getParentNativeWindow()); break; case 1: Assert.assertEquals(true, glWindow2.isVisible()); glWindow2.reparentWindow(null, null); Assert.assertEquals(true, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertNull(glWindow2.getParentNativeWindow()); break; } @@ -204,11 +204,11 @@ public class TestParenting01NEWT { Assert.assertEquals(false, animator2.isAnimating()); glWindow1.destroy(true); - Assert.assertEquals(true, glWindow1.isDestroyed()); - Assert.assertEquals(false, glWindow2.isDestroyed()); + Assert.assertEquals(false, glWindow1.isValid()); + Assert.assertEquals(true , glWindow2.isValid()); glWindow2.destroy(true); - Assert.assertEquals(true, glWindow1.isDestroyed()); - Assert.assertEquals(true, glWindow2.isDestroyed()); + Assert.assertEquals(false, glWindow1.isValid()); + Assert.assertEquals(false, glWindow2.isValid()); } @Test @@ -246,14 +246,14 @@ public class TestParenting01NEWT { Assert.assertEquals(true, glWindow2.isVisible()); glWindow2.reparentWindow(null, null); Assert.assertEquals(true, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertNull(glWindow2.getParentNativeWindow()); break; case 1: Assert.assertEquals(true, glWindow2.isVisible()); glWindow2.reparentWindow(glWindow1, null); Assert.assertEquals(true, glWindow2.isVisible()); - Assert.assertEquals(true, glWindow2.isNativeWindowValid()); + Assert.assertEquals(true, glWindow2.isNativeValid()); Assert.assertEquals(glWindow1,glWindow2.getParentNativeWindow()); break; } @@ -265,11 +265,11 @@ public class TestParenting01NEWT { Assert.assertEquals(false, animator2.isAnimating()); glWindow1.destroy(true); - Assert.assertEquals(true, glWindow1.isDestroyed()); - Assert.assertEquals(true, glWindow2.isDestroyed()); + Assert.assertEquals(false, glWindow1.isValid()); + Assert.assertEquals(false, glWindow2.isValid()); glWindow2.destroy(true); - Assert.assertEquals(true, glWindow1.isDestroyed()); - Assert.assertEquals(true, glWindow2.isDestroyed()); + Assert.assertEquals(false, glWindow1.isValid()); + Assert.assertEquals(false, glWindow2.isValid()); } public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { diff --git a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01aAWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01aAWT.java index af28c8236..5d4ddc153 100644 --- a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01aAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01aAWT.java @@ -89,7 +89,7 @@ public class TestParenting01aAWT { GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new RedSquare(); @@ -99,7 +99,7 @@ public class TestParenting01aAWT { NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); Frame frame1 = new Frame("AWT Parent Frame"); @@ -133,20 +133,20 @@ public class TestParenting01aAWT { Assert.assertEquals(false, animator1.isAnimating()); frame1.setVisible(false); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); frame1.setVisible(true); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); frame1.remove(newtCanvasAWT); // Assert.assertNull(glWindow1.getParentNativeWindow()); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); frame1.dispose(); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); glWindow1.destroy(true); - //Assert.assertEquals(true, glWindow1.isDestroyed()); + //Assert.assertEquals(false, glWindow1.isValid()); } @Test @@ -159,7 +159,7 @@ public class TestParenting01aAWT { GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, glWindow1, false); @@ -168,7 +168,7 @@ public class TestParenting01aAWT { NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); Frame frame = new Frame("AWT Parent Frame"); @@ -259,12 +259,12 @@ public class TestParenting01aAWT { switch(state) { case 0: glWindow1.reparentWindow(null, null); - Assert.assertEquals(true, glWindow1.isNativeWindowValid()); + Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); break; case 1: glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), null); - Assert.assertEquals(true, glWindow1.isNativeWindowValid()); + Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); break; } @@ -314,12 +314,12 @@ public class TestParenting01aAWT { switch(state) { case 0: glWindow1.reparentWindow(null, null); - Assert.assertEquals(true, glWindow1.isNativeWindowValid()); + Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); break; case 1: glWindow1.reparentWindow(newtCanvasAWT.getNativeWindow(), null); - Assert.assertEquals(true, glWindow1.isNativeWindowValid()); + Assert.assertEquals(true, glWindow1.isNativeValid()); Assert.assertEquals(newtCanvasAWT.getNativeWindow(),glWindow1.getParentNativeWindow()); break; } diff --git a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cAWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cAWT.java index 15dd8a5c6..669ff0a42 100644 --- a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cAWT.java @@ -88,7 +88,7 @@ public class TestParenting01cAWT { GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new RedSquare(); @@ -98,7 +98,7 @@ public class TestParenting01cAWT { NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); Frame frame1 = new Frame("AWT Parent Frame"); @@ -128,20 +128,20 @@ public class TestParenting01cAWT { } frame1.setVisible(false); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); frame1.setVisible(true); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); frame1.remove(newtCanvasAWT); // Assert.assertNull(glWindow1.getParentNativeWindow()); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); frame1.dispose(); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); glWindow1.destroy(true); - //Assert.assertEquals(true, glWindow1.isDestroyed()); + //Assert.assertEquals(false, glWindow1.isValid()); } @Test diff --git a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cSwingAWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cSwingAWT.java index 7342b4169..3277999e2 100644 --- a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cSwingAWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting01cSwingAWT.java @@ -95,7 +95,7 @@ public class TestParenting01cSwingAWT { GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new RedSquare(); @@ -123,7 +123,7 @@ public class TestParenting01cSwingAWT { NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); Container container1 = new Container(); @@ -169,14 +169,14 @@ public class TestParenting01cSwingAWT { System.out.println("Demos: 3 - !Visible"); _jFrame1.setVisible(false); } }); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { System.out.println("Demos: 4 - Visible"); _jFrame1.setVisible(true); } }); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -184,16 +184,16 @@ public class TestParenting01cSwingAWT { _jPanel1.remove(_container1); } }); // Assert.assertNull(glWindow1.getParentNativeWindow()); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { _jFrame1.dispose(); } }); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); glWindow1.destroy(true); - //Assert.assertEquals(true, glWindow1.isDestroyed()); + //Assert.assertEquals(false, glWindow1.isValid()); } @Test @@ -209,7 +209,7 @@ public class TestParenting01cSwingAWT { GLWindow glWindow1 = GLWindow.create(glCaps); Assert.assertNotNull(glWindow1); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new RedSquare(); @@ -236,7 +236,7 @@ public class TestParenting01cSwingAWT { NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow1); Assert.assertNotNull(newtCanvasAWT); Assert.assertEquals(false, glWindow1.isVisible()); - Assert.assertEquals(false, glWindow1.isNativeWindowValid()); + Assert.assertEquals(false, glWindow1.isNativeValid()); Assert.assertNull(glWindow1.getParentNativeWindow()); Container container1 = new Container(); @@ -318,17 +318,17 @@ public class TestParenting01cSwingAWT { _jFrame1.setVisible(false); _jFrame2.setVisible(false); } }); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); SwingUtilities.invokeAndWait(new Runnable() { public void run() { _jFrame1.dispose(); _jFrame2.dispose(); } }); - Assert.assertEquals(false, glWindow1.isDestroyed()); + Assert.assertEquals(true, glWindow1.isValid()); glWindow1.destroy(true); - //Assert.assertEquals(true, glWindow1.isDestroyed()); + //Assert.assertEquals(false, glWindow1.isValid()); } public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) { diff --git a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02AWT.java b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02AWT.java index 736967d21..f67d93da3 100644 --- a/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02AWT.java +++ b/src/junit/com/jogamp/test/junit/newt/parenting/TestParenting02AWT.java @@ -113,7 +113,7 @@ public class TestParenting02AWT { NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); Assert.assertNotNull(newtCanvasAWT); Assert.assertEquals(false, glWindow.isVisible()); - Assert.assertEquals(false, glWindow.isNativeWindowValid()); + Assert.assertEquals(false, glWindow.isNativeValid()); Assert.assertNull(glWindow.getParentNativeWindow()); Frame frame = new Frame("AWT Parent Frame"); @@ -154,9 +154,9 @@ public class TestParenting02AWT { Thread.yield(); // 1st display .. creation glWindow.display(); - } while(!glWindow.isNativeWindowValid()) ; + } while(!glWindow.isNativeValid()) ; - Assert.assertEquals(true, glWindow.isNativeWindowValid()); + Assert.assertEquals(true, glWindow.isNativeValid()); Assert.assertNotNull(glWindow.getParentNativeWindow()); if(verbose) { System.out.println("+++++++++++++++++++ 1st ADDED"); @@ -167,7 +167,7 @@ public class TestParenting02AWT { // test some fancy re-layout .. frame.remove(newtCanvasAWT); Assert.assertEquals(false, glWindow.isVisible()); - Assert.assertEquals(true, glWindow.isNativeWindowValid()); + Assert.assertEquals(true, glWindow.isNativeValid()); Assert.assertNull(glWindow.getParentNativeWindow()); if(verbose) { System.out.println("+++++++++++++++++++ REMOVED!"); @@ -178,7 +178,7 @@ public class TestParenting02AWT { frame.add(newtCanvasAWT, BorderLayout.CENTER); glWindow.display(); Assert.assertEquals(true, glWindow.isVisible()); - Assert.assertEquals(true, glWindow.isNativeWindowValid()); + Assert.assertEquals(true, glWindow.isNativeValid()); Assert.assertNotNull(glWindow.getParentNativeWindow()); if(verbose) { System.out.println("+++++++++++++++++++ 2nd ADDED"); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java index 924185210..a0936de15 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -277,6 +277,44 @@ public class X11Util { ** *******************************/ + /** Returns this created named display. */ + public static long createDisplay(String name) { + name = validateDisplayName(name); + long dpy = X11Lib.XOpenDisplay(name); + if(0==dpy) { + throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection. Thread "+Thread.currentThread().getName()); + } + // if you like to debug and synchronize X11 commands .. + // setSynchronizeDisplay(dpy, true); + NamedDisplay namedDpy = new NamedDisplay(name, dpy); + synchronized(globalLock) { + globalNamedDisplayMap.put(dpy, namedDpy); + } + if(DEBUG) { + Exception e = new Exception("X11Util.Display: Created new global "+namedDpy+". Thread "+Thread.currentThread().getName()); + e.printStackTrace(); + } + return namedDpy.getHandle(); + } + + public static void closeDisplay(long handle) { + NamedDisplay namedDpy; + + synchronized(globalLock) { + namedDpy = (NamedDisplay) globalNamedDisplayMap.remove(handle); + } + if(null==namedDpy) { + throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped. Thread "+Thread.currentThread().getName()); + } + if(namedDpy.getHandle()!=handle) { + throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") Mapping error: "+namedDpy+". Thread "+Thread.currentThread().getName()); + } + + if(!namedDpy.isUncloseable()) { + X11Lib.XCloseDisplay(namedDpy.getHandle()); + } + } + /** * @return If name is null, it returns the previous queried NULL display name, * otherwise the name. */ diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index b9ef93572..1c1fdd7ec 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -69,111 +69,54 @@ public abstract class Display { return displayClass; } - // Unique Display for each thread - private static ThreadLocal currentDisplayMap = new ThreadLocal(); - - /** Returns the thread local display map */ - public static Map getCurrentDisplayMap() { - Map displayMap = (Map) currentDisplayMap.get(); - if(null==displayMap) { - displayMap = new HashMap(); - currentDisplayMap.set( displayMap ); + // Global Displays + private static ArrayList displayList = new ArrayList(); + private static int displaysActive = 0; + private static int serialno = 1; + + public static void dumpDisplayList(String prefix) { + synchronized(displayList) { + Iterator i = displayList.iterator(); + System.err.println(prefix+" DisplayList[] entries: "+displayList.size()+" - "+getThreadName()); + for(int j=0; i.hasNext(); j++) { + Display d = (Display) i.next(); + System.err.println(" ["+j+"] : "+d); + } } - return displayMap; } - /** maps the given display to the thread local display map - * and notifies all threads synchronized to this display map. */ - protected static Display setCurrentDisplay(Display display) { - Map displayMap = getCurrentDisplayMap(); - Display oldDisplay = null; - synchronized(displayMap) { - oldDisplay = (Display) displayMap.put(display.getFQName(), display); - displayMap.notifyAll(); + /** Returns the global display collection */ + public static Collection getAllDisplays() { + ArrayList list; + synchronized(displayList) { + list = (ArrayList) displayList.clone(); } - return oldDisplay; + return list; } - /** removes the mapping of the given name from the thread local display map - * and notifies all threads synchronized to this display map. */ - protected static Display removeCurrentDisplay(String type, String name) { - Map displayMap = getCurrentDisplayMap(); - Display oldDisplay = null; - synchronized(displayMap) { - oldDisplay = (Display) displayMap.remove(getFQName(type,name)); - displayMap.notifyAll(); + public static int getActiveDisplayNumber() { + synchronized(displayList) { + return displaysActive; } - return oldDisplay; - } - - /** Returns the thread local display mapped to the given name */ - public static Display getCurrentDisplay(String type, String name) { - Map displayMap = getCurrentDisplayMap(); - Display display = (Display) displayMap.get(getFQName(type,name)); - return display; - } - - public static void dumpDisplayMap(String prefix) { - Map displayMap = getCurrentDisplayMap(); - Set entrySet = displayMap.entrySet(); - Iterator i = entrySet.iterator(); - System.err.println(prefix+" DisplayMap[] entries: "+entrySet.size()+" - "+getThreadName()); - for(int j=0; i.hasNext(); j++) { - Map.Entry entry = (Map.Entry) i.next(); - System.err.println(" ["+j+"] "+entry.getKey()+" -> "+entry.getValue()); - } - } - - /** Returns the thread local display collection */ - public static Collection getCurrentDisplays() { - return getCurrentDisplayMap().values(); } /** Make sure to reuse a Display with the same name */ - protected static synchronized Display create(String type, String name, final long handle) { + protected static Display create(String type, String name, final long handle) { try { Class displayClass = getDisplayClass(type); - Display tmpDisplay = (Display) displayClass.newInstance(); - name = tmpDisplay.validateDisplayName(name, handle); - - if(DEBUG) { - dumpDisplayMap("Display.create("+getFQName(type, name)+") BEGIN"); - } - Display display = getCurrentDisplay(type, name); - if(null==display) { - display = tmpDisplay; - tmpDisplay = null; - display.name = name; - display.type=type; - display.refCount=0; - if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") NEW: refCount "+display.refCount+", "+display+" "+getThreadName()); - } - } else { - tmpDisplay = null; - if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") REUSE: refCount "+display.refCount+", "+display+" "+getThreadName()); - } - } - synchronized(display) { - display.refCount++; - if(null==display.aDevice) { - final Display f_dpy = display; - display.runOnEDTIfAvail(true, new Runnable() { - public void run() { - f_dpy.createNative(); - }}); - if(null==display.aDevice) { - throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); - } - setCurrentDisplay(display); - if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") CreateNative: "+display+" "+getThreadName()); - } - } + Display display = (Display) displayClass.newInstance(); + name = display.validateDisplayName(name, handle); + display.name = name; + display.type=type; + display.destroyWhenUnused=false; + synchronized(displayList) { + display.id = serialno++; + display.fqname = getFQName(display.id, display.type, display.name); + displayList.add(display); } + display.createEDTUtil(); if(DEBUG) { - dumpDisplayMap("Display.create("+getFQName(type, name)+") END"); + System.err.println("Display.create() NEW: "+display+" "+getThreadName()); } return display; } catch (Exception e) { @@ -181,98 +124,138 @@ public abstract class Display { } } + protected synchronized final void createNative() { + if(null==aDevice) { + if(DEBUG) { + System.out.println("Display.createNative() START ("+getThreadName()+", "+this+")"); + } + final Display f_dpy = this; + runOnEDTIfAvail(true, new Runnable() { + public void run() { + f_dpy.createNativeImpl(); + }}); + if(null==aDevice) { + throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); + } + if(DEBUG) { + System.out.println("Display.createNative() END ("+getThreadName()+", "+this+")"); + } + synchronized(displayList) { + displaysActive++; + } + } + } + protected boolean getShallRunOnEDT() { return true; } - public EDTUtil getEDTUtil() { - if( null == edtUtil ) { - synchronized (this) { - if( null == edtUtil ) { - if(NewtFactory.useEDT()) { - final Display f_dpy = this; - if ( ! DEBUG_TEST_EDT_MAINTHREAD ) { - Thread current = Thread.currentThread(); - edtUtil = new DefaultEDTUtil(current.getThreadGroup(), - "Display_"+getFQName(), - new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } } ); - } else { - // Begin JAU EDT Test .. - MainThread.addPumpMessage(this, - new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } } ); - edtUtil = MainThread.getSingleton(); - System.err.println("Display.getEDTUtil("+getFQName()+") Test EDT MainThread: "+edtUtil.getClass().getName()); - // End JAU EDT Test .. - } - edtUtil.start(); - } - } + protected void createEDTUtil() { + if(NewtFactory.useEDT()) { + if ( ! DEBUG_TEST_EDT_MAINTHREAD ) { + Thread current = Thread.currentThread(); + edtUtil = new DefaultEDTUtil(current.getThreadGroup(), "Display_"+getFQName(), dispatchMessagesRunnable); + } else { + // Begin JAU EDT Test .. + MainThread.addPumpMessage(this, dispatchMessagesRunnable); + edtUtil = MainThread.getSingleton(); + // End JAU EDT Test .. + } + if(DEBUG) { + System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); } } - return edtUtil; } - protected void releaseEDTUtil() { - if(null!=edtUtil) { - if ( DEBUG_TEST_EDT_MAINTHREAD ) { - MainThread.removePumpMessage(this); // JAU EDT Test .. - } - edtUtil.waitUntilStopped(); - edtUtil=null; - } + public final EDTUtil getEDTUtil() { + return edtUtil; } public void runOnEDTIfAvail(boolean wait, final Runnable task) { - EDTUtil _edtUtil = getEDTUtil(); - if(getShallRunOnEDT() && null!=_edtUtil) { - _edtUtil.invoke(wait, task); + if( getShallRunOnEDT() && null!=edtUtil ) { + edtUtil.invoke(wait, task); } else { task.run(); } } - public synchronized void destroy() { - if(DEBUG) { - dumpDisplayMap("Display.destroy("+getFQName()+") BEGIN"); - } - refCount--; - if(0==refCount) { - removeCurrentDisplay(type, name); + public synchronized final void destroy() { + if ( null != aDevice ) { + if(DEBUG) { + dumpDisplayList("Display.destroy("+getFQName()+") BEGIN"); + } + synchronized(displayList) { + displayList.remove(this); + displaysActive--; + } if(DEBUG) { - System.err.println("Display.destroy("+getFQName()+") REMOVE: "+this+" "+getThreadName()); + System.err.println("Display.destroy(): "+this+" "+getThreadName()); } final Display f_dpy = this; final EDTUtil f_edtUtil = edtUtil; runOnEDTIfAvail(true, new Runnable() { public void run() { - f_dpy.closeNative(); + f_dpy.closeNativeImpl(); if(null!=f_edtUtil) { f_edtUtil.stop(); } } } ); - releaseEDTUtil(); + if(null!=edtUtil) { + if ( DEBUG_TEST_EDT_MAINTHREAD ) { + MainThread.removePumpMessage(this); // JAU EDT Test .. + } + edtUtil.waitUntilStopped(); + edtUtil.reset(); + } aDevice = null; - } else { if(DEBUG) { - System.err.println("Display.destroy("+getFQName()+") KEEP: refCount "+refCount+", "+this+" "+getThreadName()); + dumpDisplayList("Display.destroy("+getFQName()+") END"); } } + } + + protected synchronized final int addReference() { if(DEBUG) { - dumpDisplayMap("Display.destroy("+getFQName()+") END"); + System.out.println("Display.addReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount+1)); + } + if ( 0 == refCount ) { + createNative(); + } + if(null == aDevice) { + throw new RuntimeException("Display.addReference() (refCount "+refCount+") null AbstractGraphicsDevice"); } + return ++refCount; } - protected abstract void createNative(); - protected abstract void closeNative(); + + protected synchronized final int removeReference() { + if(DEBUG) { + System.out.println("Display.removeReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount-1)); + } + refCount--; + if(0==refCount && destroyWhenUnused) { + destroy(); + } + return refCount; + } + + /** + * @return number of references by Screen + */ + public synchronized final int getReferenceCount() { + return refCount; + } + + public final boolean getDestroyWhenUnused() { return destroyWhenUnused; } + public final void setDestroyWhenUnused(boolean v) { destroyWhenUnused=v; } + + protected abstract void createNativeImpl(); + protected abstract void closeNativeImpl(); + + public final int getId() { + return id; + } public final String getType() { return type; @@ -283,35 +266,45 @@ public abstract class Display { } public final String getFQName() { - return getFQName(type, name); + return fqname; } - static final String nilString = "nil" ; + public static final String nilString = "nil" ; - protected String validateDisplayName(String name, long handle) { + public String validateDisplayName(String name, long handle) { if(null==name && 0!=handle) { name="wrapping-"+toHexString(handle); } return ( null == name ) ? nilString : name ; } - public static final String getFQName(String type, String name) { + public static final String getFQName(int id, String type, String name) { if(null==type) type=nilString; if(null==name) name=nilString; - return type+"_"+name; + StringBuffer sb = new StringBuffer(); + sb.append(type); + sb.append("_"); + sb.append(name); + sb.append("_"); + sb.append(id); + return sb.toString(); } - public long getHandle() { + public final long getHandle() { if(null!=aDevice) { return aDevice.getHandle(); } return 0; } - public AbstractGraphicsDevice getGraphicsDevice() { + public final AbstractGraphicsDevice getGraphicsDevice() { return aDevice; } + public final boolean isNativeValid() { + return null != aDevice; + } + public synchronized void pumpMessages() { dispatchMessages(); } @@ -338,8 +331,16 @@ public abstract class Display { private Object eventsLock = new Object(); private LinkedList/*<NEWTEvent>*/ events = new LinkedList(); + class DispatchMessagesRunnable implements Runnable { + public void run() { + Display.this.dispatchMessages(); + } + } + DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); + public void dispatchMessages() { - if(0==refCount) return; // in destruction .. + if(0==refCount) return; // no screens + if(null==getGraphicsDevice()) return; // no native device LinkedList/*<NEWTEvent>*/ _events = null; @@ -405,9 +406,12 @@ public abstract class Display { } protected EDTUtil edtUtil = null; + protected int id; protected String name; protected String type; - protected int refCount; + protected String fqname; + protected int refCount; // number of Display references by Screen + protected boolean destroyWhenUnused; protected AbstractGraphicsDevice aDevice; } diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index 3959c6a8d..12dadc310 100644 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -145,12 +145,13 @@ public abstract class NewtFactory { if(null!=nParentConfig) { AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); - Display display = NewtFactory.wrapDisplay(type, nParentDevice.getHandle()); + Display display = NewtFactory.createDisplay(type, nParentDevice.getHandle()); screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); } else { Display display = NewtFactory.createDisplay(type, null); // local display screen = NewtFactory.createScreen(type, display, 0); // screen 0 } + screen.setDestroyWhenUnused(true); final Window win = createWindowImpl(type, nParentWindow, screen, caps, undecorated); win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); @@ -177,6 +178,7 @@ public abstract class NewtFactory { protected static Window createWindowImpl(String type, Capabilities caps, boolean undecorated) { Display display = NewtFactory.createDisplay(type, null); // local display Screen screen = NewtFactory.createScreen(type, display, 0); // screen 0 + screen.setDestroyWhenUnused(true); return Window.create(type, null, 0, screen, caps, undecorated); } @@ -217,7 +219,7 @@ public abstract class NewtFactory { /** * Instantiate a Display entity using the native handle. */ - public static Display wrapDisplay(String type, long handle) { + public static Display createDisplay(String type, long handle) { return Display.create(type, null, handle); } diff --git a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java index e85714d4f..d17f8df07 100644 --- a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java @@ -62,7 +62,7 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { } } - protected void closeNative() { + protected void closeNativeImpl() { // nop } diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java index 26342519e..e9697647d 100644 --- a/src/newt/classes/com/jogamp/newt/Screen.java +++ b/src/newt/classes/com/jogamp/newt/Screen.java @@ -40,6 +40,8 @@ import java.security.*; public abstract class Screen { + public static final boolean DEBUG = Debug.debug("Display"); + private static Class getScreenClass(String type) throws ClassNotFoundException { @@ -62,7 +64,7 @@ public abstract class Screen { return screenClass; } - protected static Screen create(String type, Display display, int idx) { + protected static Screen create(String type, Display display, final int idx) { try { if(usrWidth<0 || usrHeight<0) { usrWidth = Debug.getIntProperty("newt.ws.swidth", true, localACC); @@ -74,48 +76,105 @@ public abstract class Screen { Class screenClass = getScreenClass(type); Screen screen = (Screen) screenClass.newInstance(); screen.display = display; - screen.createNative(idx); - if(null==screen.aScreen) { - throw new RuntimeException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); - } + screen.idx = idx; return screen; } catch (Exception e) { throw new RuntimeException(e); } } - public synchronized void destroy() { - closeNative(); - display = null; - aScreen = null; + protected synchronized final void createNative() { + if(null == aScreen) { + if(DEBUG) { + System.out.println("Screen.createNative() START ("+Display.getThreadName()+", "+this+")"); + } + display.addReference(); + createNativeImpl(); + if(null == aScreen) { + throw new RuntimeException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); + } + if(DEBUG) { + System.out.println("Screen.createNative() END ("+Display.getThreadName()+", "+this+")"); + } + } + } + + public synchronized final void destroy() { + if ( null != aScreen ) { + closeNativeImpl(); + display.removeReference(); + aScreen = null; + } + } + + protected synchronized final int addReference() { + if(DEBUG) { + System.out.println("Screen.addReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount+1)); + } + if ( 0 == refCount ) { + createNative(); + } + if(null == aScreen) { + throw new RuntimeException("Screen.addReference() (refCount "+refCount+") null AbstractGraphicsScreen"); + } + return ++refCount; + } + + protected synchronized final int removeReference() { + if(DEBUG) { + System.out.println("Screen.removeReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount-1)); + } + refCount--; + if(0==refCount && getDestroyWhenUnused()) { + destroy(); + } + return refCount; + } + + /** + * @return number of references by Window + */ + public synchronized final int getReferenceCount() { + return refCount; } - protected abstract void createNative(int index); - protected abstract void closeNative(); + public final boolean getDestroyWhenUnused() { + return display.getDestroyWhenUnused(); + } + public final void setDestroyWhenUnused(boolean v) { + display.setDestroyWhenUnused(v); + } + + protected abstract void createNativeImpl(); + protected abstract void closeNativeImpl(); protected void setScreenSize(int w, int h) { System.out.println("Detected screen size "+w+"x"+h); width=w; height=h; } - public Display getDisplay() { + public final Display getDisplay() { return display; } - public int getIndex() { - return aScreen.getIndex(); + public final int getIndex() { + return idx; } - public AbstractGraphicsScreen getGraphicsScreen() { + public final AbstractGraphicsScreen getGraphicsScreen() { return aScreen; } + public final boolean isNativeValid() { + return null != aScreen; + } + /** * The actual implementation shall return the detected display value, * if not we return 800. * This can be overwritten with the user property 'newt.ws.swidth', */ - public int getWidth() { + public final int getWidth() { return (usrWidth>0) ? usrWidth : (width>0) ? width : 480; } @@ -124,12 +183,14 @@ public abstract class Screen { * if not we return 480. * This can be overwritten with the user property 'newt.ws.sheight', */ - public int getHeight() { + public final int getHeight() { return (usrHeight>0) ? usrHeight : (height>0) ? height : 480; } protected Display display; + protected int idx; protected AbstractGraphicsScreen aScreen; + protected int refCount; // number of Screen references by Window protected int width=-1, height=-1; // detected values: set using setScreenSize protected static int usrWidth=-1, usrHeight=-1; // property values: newt.ws.swidth and newt.ws.sheight private static AccessControlContext localACC = AccessController.getContext(); diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index d002791ca..3f07e63de 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -150,8 +150,9 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer protected String title = "Newt Window"; protected boolean undecorated = false; + protected boolean screenRefAdded = false; - private boolean createNative() { + private final boolean createNative() { if( null==screen || 0!=windowHandle || !visible ) { return 0 != windowHandle ; } @@ -159,7 +160,11 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer System.out.println("Window.createNative() START ("+getThreadName()+", "+this+")"); } if(validateParentWindowHandle()) { - Display dpy = getScreen().getDisplay(); + if(!screenRefAdded) { + // only once .. at 1st creation + screenRefAdded = true; + getScreen().addReference(); + } createNativeImpl(); setVisibleImpl(true); } @@ -219,7 +224,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer */ protected abstract void createNativeImpl(); - protected abstract void closeNative(); + protected abstract void closeNativeImpl(); public Capabilities getRequestedCapabilities() { return (Capabilities)caps.clone(); @@ -348,7 +353,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer windowLock.lock(); // if(windowLock.getRecursionCount() == 0) { // allow recursion to lock again, always - if(isDestroyed() || !isNativeWindowValid()) { + if(!isNativeValid()) { windowLock.unlock(); return LOCK_SURFACE_NOT_READY; } @@ -381,7 +386,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer * windowing related resources.<br></p> * <p> * all other resources and states are kept intact, - * ie listeners, parent handles and size, position etc.<br></p> + * ie listeners, parent handles, size, position and Screen reference.<br></p> * * @see #destroy(boolean) * @see #invalidate() @@ -391,49 +396,51 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } /** - * @param deep If true, all resources, ie listeners, parent handles, size, position - * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call - * this method with deep = true, you will not be able to regenerate the Window. + * Destroys the Window and it's children. + * @param unrecoverable If true, all resources, ie listeners, parent handles, + * size, position and reference to it's Screen will be destroyed as well. + * Otherwise you can recreate the window, via <code>setVisible(true)</code>. * @see #destroy() * @see #invalidate(boolean) + * @see #setVisible(boolean) */ - public void destroy(boolean deep) { - if(!isDestroyed()) { - runOnEDTIfAvail(true, new DestroyAction(deep)); + public void destroy(boolean unrecoverable) { + if(isValid()) { + runOnEDTIfAvail(true, new DestroyAction(unrecoverable)); } } class DestroyAction implements Runnable { - boolean deep; - public DestroyAction(boolean deep) { - this.deep = deep; + boolean unrecoverable; + public DestroyAction(boolean unrecoverable) { + this.unrecoverable = unrecoverable; } public void run() { windowLock(); try { if(DEBUG_IMPLEMENTATION) { - System.out.println("Window.destroy(deep: "+deep+") START "+getThreadName()+", "+Window.this); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") START "+getThreadName()+", "+Window.this); } // Childs first .. synchronized(childWindowsLock) { for(Iterator i = childWindows.iterator(); i.hasNext(); ) { NativeWindow nw = (NativeWindow) i.next(); - System.out.println("Window.destroy(deep: "+deep+") CHILD BEGIN"); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") CHILD BEGIN"); if(nw instanceof Window) { ((Window)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - if(deep) { - ((Window)nw).destroy(deep); + if(unrecoverable) { + ((Window)nw).destroy(unrecoverable); } } else { nw.destroy(); } - System.out.println("Window.destroy(deep: "+deep+") CHILD END"); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") CHILD END"); } } // Now us .. - if(deep) { + if(unrecoverable) { synchronized(childWindowsLock) { childWindows = new ArrayList(); } @@ -444,24 +451,20 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer mouseListeners = new ArrayList(); keyListeners = new ArrayList(); } - Display dpy = null; Screen scr = null; if( null != screen && 0 != windowHandle ) { scr = screen; - dpy = screen.getDisplay(); - closeNative(); + closeNativeImpl(); } - invalidate(deep); - if(deep) { + invalidate(unrecoverable); + if(unrecoverable) { if(null!=scr) { - scr.destroy(); - } - if(null!=dpy) { - dpy.destroy(); + // only once .. at final destruction + scr.removeReference(); } } if(DEBUG_IMPLEMENTATION) { - System.out.println("Window.destroy(deep: "+deep+") END "+getThreadName()+", "+Window.this); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") END "+getThreadName()+", "+Window.this); } } finally { windowUnlock(); @@ -486,18 +489,18 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } /** - * @param deep if false only the native window handle is invalidated, otherwise all - * states (references and properties) are reset. Be aware that if you call - * this method with deep = true, you will not be able to regenerate the Window. + * @param unrecoverable If true, all states, size, position, parent handles, + * reference to it's Screen are reset. + * Otherwise you can recreate the window, via <code>setVisible(true)</code>. * @see #invalidate() * @see #destroy() * @see #destroy(boolean) */ - public void invalidate(boolean deep) { + public void invalidate(boolean unrecoverable) { windowLock(); try{ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - String msg = new String("!!! Window Invalidate(deep: "+deep+") "+getThreadName()); + String msg = new String("!!! Window Invalidate(unrecoverable: "+unrecoverable+") "+getThreadName()); //System.out.println(msg); Exception e = new Exception(msg); e.printStackTrace(); @@ -506,7 +509,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer visible = false; fullscreen = false; - if(deep) { + if(unrecoverable) { screen = null; parentWindowHandle = 0; parentNativeWindow = null; @@ -523,13 +526,24 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } } - /** @return true if the native window handle is valid and ready to operate */ - public boolean isNativeWindowValid() { - return 0 != windowHandle ; + /** @return true if the native window handle is valid and ready to operate, ie + * if the native window has been created, otherwise false. + * + * @see #setVisible(boolean) + * @see #destroy(boolean) + */ + public boolean isNativeValid() { + return null != screen && 0 != windowHandle ; } - public boolean isDestroyed() { - return null == screen ; + /** @return True if native window is valid, can be created or recovered. + * Otherwise false, ie this window is unrecoverable due to a <code>destroy(true)</code> call. + * + * @see #destroy(boolean) + * @see #setVisible(boolean) + */ + public boolean isValid() { + return null != screen ; } public boolean surfaceSwap() { @@ -713,7 +727,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer * this Screen is being used. */ public void reparentWindow(NativeWindow newParent, Screen newScreen) { - if(!isDestroyed()) { + if(isValid()) { runOnEDTIfAvail(true, new ReparentAction(newParent, newScreen)); if( isVisible() ) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener @@ -730,7 +744,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer public void run() { windowLock(); try{ - if( !isDestroyed() ) { + if( isValid() ) { if(!visible && childWindows.size()>0) { synchronized(childWindowsLock) { for(Iterator i = childWindows.iterator(); i.hasNext(); ) { @@ -805,7 +819,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer Exception ee = new Exception(msg); ee.printStackTrace(); } - if(!isDestroyed()) { + if(isValid()) { runOnEDTIfAvail(true, new VisibleAction(visible)); } } @@ -985,7 +999,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { - if(!getInnerWindow().isDestroyed()) { + if(getInnerWindow().isValid()) { getInnerWindow().getScreen().getDisplay().enqueueEvent(wait, event); } } @@ -1523,7 +1537,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - if(handleDestroyNotify && !isDestroyed()) { + if(handleDestroyNotify && isValid()) { destroy(); } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 0c28eca40..a342f9ba6 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -52,7 +52,7 @@ import com.jogamp.newt.Window; import com.jogamp.newt.impl.Debug; public class NewtCanvasAWT extends java.awt.Canvas { - public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + public static final boolean DEBUG = Debug.debug("Window"); NativeWindow parent = null; Window newtChild = null; @@ -90,7 +90,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { class FocusActionImpl implements Runnable { public final boolean result = false; // NEWT shall always proceed requesting the native focus public void run() { - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { System.out.println("FocusActionImpl.run() "+Window.getThreadName()); } NewtCanvasAWT.this.requestFocusAWTParent(); @@ -147,7 +147,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { super.addNotify(); disableBackgroundErase(); java.awt.Container cont = getContainer(this); - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { // if ( isShowing() == false ) -> Container was not visible yet. // if ( isShowing() == true ) -> Container is already visible. System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+ @@ -158,7 +158,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { public void removeNotify() { java.awt.Container cont = getContainer(this); - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont); } reparentWindow(false, cont); @@ -175,15 +175,19 @@ public class NewtCanvasAWT extends java.awt.Canvas { parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); } if(null!=parent) { - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { System.err.println("NewtCanvasAWT.reparentWindow: "+newtChild); } setSize(cont.getWidth(), cont.getHeight()); newtChild.setSize(cont.getWidth(), cont.getHeight()); Screen screen = null; - if( !newtChild.isNativeWindowValid() ) { - screen = NewtFactoryAWT.createCompatibleScreen(parent); + if( !newtChild.isNativeValid() ) { + Screen currentScreen = newtChild.getScreen(); + screen = NewtFactoryAWT.createCompatibleScreen(parent, currentScreen); + if( currentScreen != screen ) { + screen.setDestroyWhenUnused(true); + } } newtChild.reparentWindow(parent, screen); newtChild.setVisible(true); diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java index 05f346192..5c28f8452 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java @@ -83,15 +83,57 @@ public class NewtFactoryAWT extends NewtFactory { } public static Screen createCompatibleScreen(NativeWindow parent) { + return createCompatibleScreen(parent, null); + } + + public static Screen createCompatibleScreen(NativeWindow parent, Screen childScreen) { // Get parent's NativeWindow details AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); AWTGraphicsDevice parentDevice = (AWTGraphicsDevice) parentScreen.getDevice(); - // Prep NEWT's Display and Screen according to the parent final String type = NativeWindowFactory.getNativeWindowType(true); - Display display = NewtFactory.wrapDisplay(type, parentDevice.getHandle()); + + if(null != childScreen) { + // check if child Display/Screen is compatible already + Display childDisplay = childScreen.getDisplay(); + String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle()); + String childDisplayName = childDisplay.getName(); + boolean displayEqual = parentDisplayName.equals( childDisplayName ); + boolean screenEqual = parentScreen.getIndex() == childScreen.getIndex(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("NewtFactoryAWT.createCompatibleScreen: Display: "+ + parentDisplayName+" =? "+childDisplayName+" : "+displayEqual+"; Screen: "+ + parentScreen.getIndex()+" =? "+childScreen.getIndex()+" : "+screenEqual); + } + if( displayEqual && screenEqual ) { + // match: display/screen + return childScreen; + } + } + + // Prep NEWT's Display and Screen according to the parent + Display display = NewtFactory.createDisplay(type, parentDevice.getHandle()); return NewtFactory.createScreen(type, display, parentScreen.getIndex()); } + + public static boolean isScreenCompatible(NativeWindow parent, Screen childScreen) { + // Get parent's NativeWindow details + AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); + AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); + AWTGraphicsDevice parentDevice = (AWTGraphicsDevice) parentScreen.getDevice(); + + Display childDisplay = childScreen.getDisplay(); + String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle()); + String childDisplayName = childDisplay.getName(); + if( ! parentDisplayName.equals( childDisplayName ) ) { + return false; + } + + if( parentScreen.getIndex() != childScreen.getIndex() ) { + return false; + } + return true; + } } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 8015cff16..32452d6ee 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -101,7 +101,7 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.out.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); } - if(!newtWindow.isDestroyed()) { + if(newtWindow.isValid()) { newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { newtWindow.setVisible(showing); diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index 59f5b7b4f..dd58ad1c8 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -128,7 +128,7 @@ public class AWTWindowAdapter } /** if(null==newtListener) { - if(!newtWindow.isDestroyed()) { + if(newtWindow.isValid()) { newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { newtWindow.setVisible(true); @@ -145,7 +145,7 @@ public class AWTWindowAdapter } /** if(null==newtListener) { - if(!newtWindow.isDestroyed()) { + if(newtWindow.isValid()) { newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { newtWindow.setVisible(false); diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java index 92c4e53eb..c9c6c63fc 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java @@ -44,7 +44,7 @@ public class AWTDisplay extends Display { public AWTDisplay() { } - protected void createNative() { + protected void createNativeImpl() { aDevice = (AWTGraphicsDevice) AWTGraphicsDevice.createDevice(null); // default } @@ -52,7 +52,7 @@ public class AWTDisplay extends Display { aDevice = d; } - protected void closeNative() { } + protected void closeNativeImpl() { } protected boolean getShallRunOnEDT() { return false; diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java index 8702686c0..eec83d721 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java @@ -42,7 +42,7 @@ public class AWTScreen extends Screen { public AWTScreen() { } - protected void createNative(int index) { + protected void createNativeImpl() { aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice()); DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); @@ -60,6 +60,6 @@ public class AWTScreen extends Screen { super.setScreenSize(w, h); } - protected void closeNative() { } + protected void closeNativeImpl() { } } diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index db55aee6f..9da1eb860 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -148,7 +148,7 @@ public class AWTWindow extends Window { this.windowHandle = 1; // just a marker .. } - protected void closeNative() { + protected void closeNativeImpl() { this.windowHandle = 0; // just a marker .. if(null!=container) { runOnEDT(true, new Runnable() { diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java index d19aaf796..c8e69dac6 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java @@ -58,7 +58,7 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative() { + protected void createNativeImpl() { synchronized(Display.class) { if(0==initCounter) { displayHandle = CreateDisplay(); @@ -71,7 +71,7 @@ public class Display extends com.jogamp.newt.Display { aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, displayHandle); } - protected void closeNative() { + protected void closeNativeImpl() { if(0==displayHandle) { throw new NativeWindowException("displayHandle null; initCnt "+initCounter); } diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java index 3d9a5a309..3aded5df3 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java @@ -45,13 +45,13 @@ public class Screen extends com.jogamp.newt.Screen { public Screen() { } - protected void createNative(int index) { + protected void createNativeImpl() { AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice(); - GetScreenInfo(adevice.getHandle(), index); - aScreen = new DefaultGraphicsScreen(adevice, index); + GetScreenInfo(adevice.getHandle(), idx); + aScreen = new DefaultGraphicsScreen(adevice, idx); } - protected void closeNative() { } + protected void closeNativeImpl() { } //---------------------------------------------------------------------- // Internals only diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java index 14621807a..5f40a35ae 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java @@ -67,7 +67,7 @@ public class Window extends com.jogamp.newt.Window { } } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=surfaceHandle) { synchronized(Window.class) { CloseSurface(getDisplayHandle(), surfaceHandle); diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java index 11f825282..9b8689114 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java @@ -65,31 +65,24 @@ public class MacDisplay extends Display { dispatchMessages0(); } - protected void createNative() { + protected void createNativeImpl() { aDevice = new MacOSXGraphicsDevice(); } - protected void closeNative() { } + protected void closeNativeImpl() { } - public EDTUtil getEDTUtil() { - if( null == edtUtil ) { - synchronized (this) { - if( null == edtUtil ) { - if(NewtFactory.useEDT()) { - final Display f_dpy = this; - MainThread.addPumpMessage(this, - new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } } ); - edtUtil = MainThread.getSingleton(); - edtUtil.start(); - } - } - } + protected void createEDTUtil() { + if(NewtFactory.useEDT()) { + final Display f_dpy = this; + MainThread.addPumpMessage(this, + new Runnable() { + public void run() { + if(null!=f_dpy.getGraphicsDevice()) { + f_dpy.dispatchMessages(); + } } } ); + edtUtil = MainThread.getSingleton(); + edtUtil.start(); } - return edtUtil; } protected void releaseEDTUtil() { diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java index d7deb13ee..317a3161c 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java @@ -44,12 +44,12 @@ public class MacScreen extends Screen { public MacScreen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); - setScreenSize(getWidthImpl0(getIndex()), getHeightImpl0(getIndex())); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); + setScreenSize(getWidthImpl0(idx), getHeightImpl0(idx)); } - protected void closeNative() { } + protected void closeNativeImpl() { } private static native int getWidthImpl0(int scrn_idx); private static native int getHeightImpl0(int scrn_idx); diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index a8e6febf5..7571c05be 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -149,7 +149,7 @@ public class MacWindow extends Window { } } - protected void closeNative() { + protected void closeNativeImpl() { nsViewLock.lock(); try { if(DEBUG_IMPLEMENTATION) { System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java index c2d323e56..8b8ce1f41 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java @@ -56,7 +56,7 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative() { + protected void createNativeImpl() { long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight); if (handle == EGL.EGL_NO_DISPLAY) { throw new NativeWindowException("BC EGL CreateDisplay failed"); @@ -64,7 +64,7 @@ public class Display extends com.jogamp.newt.Display { aDevice = new EGLGraphicsDevice(handle); } - protected void closeNative() { + protected void closeNativeImpl() { if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { DestroyDisplay(aDevice.getHandle()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java index e30896468..f38e7b4dc 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java @@ -45,12 +45,12 @@ public class Screen extends com.jogamp.newt.Screen { public Screen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); setScreenSize(fixedWidth, fixedHeight); } - protected void closeNative() { } + protected void closeNativeImpl() { } //---------------------------------------------------------------------- // Internals only diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java index ca06699f5..d6b802a85 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java @@ -64,7 +64,7 @@ public class Window extends com.jogamp.newt.Window { } } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=windowHandleClose) { CloseWindow(getDisplayHandle(), windowHandleClose); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java index 2ab30773f..1845342a0 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java @@ -57,7 +57,7 @@ public class KDDisplay extends Display { public KDDisplay() { } - protected void createNative() { + protected void createNativeImpl() { // FIXME: map name to EGL_*_DISPLAY long handle = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); if (handle == EGL.EGL_NO_DISPLAY) { @@ -69,7 +69,7 @@ public class KDDisplay extends Display { aDevice = new EGLGraphicsDevice(handle); } - protected void closeNative() { + protected void closeNativeImpl() { if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { EGL.eglTerminate(aDevice.getHandle()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java index d570d9f5b..c7db047f6 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java @@ -44,11 +44,11 @@ public class KDScreen extends Screen { public KDScreen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); } - protected void closeNative() { } + protected void closeNativeImpl() { } // elevate access to this package .. protected void setScreenSize(int w, int h) { diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index 2f534548b..43e4ac021 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -78,7 +78,7 @@ public class KDWindow extends Window { windowHandleClose = eglWindowHandle; } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=windowHandleClose) { CloseWindow(windowHandleClose, windowUserData); windowUserData=0; diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java index ef033d1c8..cfc35e1f8 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java @@ -60,11 +60,11 @@ public class WindowsDisplay extends Display { public WindowsDisplay() { } - protected void createNative() { + protected void createNativeImpl() { aDevice = new WindowsGraphicsDevice(); } - protected void closeNative() { + protected void closeNativeImpl() { // Can't do .. only at application shutdown // UnregisterWindowClass0(getWindowClassAtom(), getHInstance()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java index 1b4be0d55..2197667cd 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java @@ -45,12 +45,12 @@ public class WindowsScreen extends Screen { public WindowsScreen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); - setScreenSize(getWidthImpl0(getIndex()), getHeightImpl0(getIndex())); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); + setScreenSize(getWidthImpl0(idx), getHeightImpl0(idx)); } - protected void closeNative() { } + protected void closeNativeImpl() { } private native int getWidthImpl0(int scrn_idx); private native int getHeightImpl0(int scrn_idx); diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index 69cd62201..15d9ac8b0 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -115,14 +115,14 @@ public class WindowsWindow extends Window { } } - protected void closeNative() { + protected void closeNativeImpl() { if (hdc != 0) { if(windowHandleClose != 0) { try { ReleaseDC0(windowHandleClose, hdc); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + Exception e = new Exception("closeNativeImpl failed - "+Thread.currentThread().getName(), t); e.printStackTrace(); } } @@ -134,7 +134,7 @@ public class WindowsWindow extends Window { DestroyWindow0(windowHandleClose); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + Exception e = new Exception("closeNativeImpl failed - "+Thread.currentThread().getName(), t); e.printStackTrace(); } } finally { diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java index 6701d6c8e..22b5e8470 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java @@ -61,26 +61,26 @@ public class X11Display extends Display { public X11Display() { } - protected String validateDisplayName(String name, long handle) { + public String validateDisplayName(String name, long handle) { return X11Util.validateDisplayName(name, handle); } - protected void createNative() { - long handle = X11Util.createThreadLocalDisplay(name); + protected void createNativeImpl() { + long handle = X11Util.createDisplay(name); if( 0 == handle ) { throw new RuntimeException("Error creating display: "+name); } try { CompleteDisplay0(handle); } catch(RuntimeException e) { - X11Util.closeThreadLocalDisplay(name); + X11Util.closeDisplay(handle); throw e; } aDevice = new X11GraphicsDevice(handle); } - protected void closeNative() { - X11Util.closeThreadLocalDisplay(name); + protected void closeNativeImpl() { + X11Util.closeDisplay(getHandle()); } protected void dispatchMessagesNative() { diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java index 453d8e5e1..aa53ea5d0 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java @@ -46,17 +46,17 @@ public class X11Screen extends Screen { public X11Screen() { } - protected void createNative(int index) { - long handle = GetScreen0(display.getHandle(), index); + protected void createNativeImpl() { + long handle = GetScreen0(display.getHandle(), idx); if (handle == 0 ) { - throw new RuntimeException("Error creating screen: "+index); + throw new RuntimeException("Error creating screen: "+idx); } - aScreen = new X11GraphicsScreen((X11GraphicsDevice)getDisplay().getGraphicsDevice(), index); - setScreenSize(getWidth0(display.getHandle(), index), - getHeight0(display.getHandle(), index)); + aScreen = new X11GraphicsScreen((X11GraphicsDevice)getDisplay().getGraphicsDevice(), idx); + setScreenSize(getWidth0(display.getHandle(), idx), + getHeight0(display.getHandle(), idx)); } - protected void closeNative() { } + protected void closeNativeImpl() { } //---------------------------------------------------------------------- // Internals only diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index 7a770f770..894de9ae5 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -67,7 +67,7 @@ public class X11Window extends Window { windowHandleClose = windowHandle; } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=windowHandleClose && null!=getScreen() ) { X11Display display = (X11Display) getScreen().getDisplay(); try { @@ -75,7 +75,7 @@ public class X11Window extends Window { display.getJavaObjectAtom(), display.getWindowDeleteAtom()); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + Exception e = new Exception("closeNativeImpl failed - "+Thread.currentThread().getName(), t); e.printStackTrace(); } } finally { diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 99b4314a3..2aca37cab 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -82,8 +82,8 @@ public class GLWindow extends Window implements GLAutoDrawable { if( !windowIsLocked() && null == getAnimator() ) { destroy(); } else { - sendDestroy = true; - } + sendDestroy = true; + } } }); } @@ -125,12 +125,12 @@ public class GLWindow extends Window implements GLAutoDrawable { return new GLWindow(window); } - public boolean isNativeWindowValid() { - return (null!=window)?window.isNativeWindowValid():false; + public boolean isNativeValid() { + return (null!=window)?window.isNativeValid():false; } - public boolean isDestroyed() { - return (null!=window)?window.isDestroyed():true; + public boolean isValid() { + return (null!=window)?window.isValid():true; } public final Window getInnerWindow() { @@ -145,7 +145,7 @@ public class GLWindow extends Window implements GLAutoDrawable { shouldNotCallThis(); } - protected void closeNative() { + protected void closeNativeImpl() { shouldNotCallThis(); } @@ -158,23 +158,23 @@ public class GLWindow extends Window implements GLAutoDrawable { private DisposeAction disposeAction = new DisposeAction(); class DestroyAction implements Runnable { - boolean deep; - public DestroyAction(boolean deep) { - this.deep = deep; + boolean unrecoverable; + public DestroyAction(boolean unrecoverable) { + this.unrecoverable = unrecoverable; } public void run() { // Lock: Have to cover whole workflow (dispose all, context, drawable and window) windowLock(); try { - if( isDestroyed() ) { + if( !isValid() ) { return; // nop } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - Exception e1 = new Exception("GLWindow.destroy("+deep+") "+Thread.currentThread()+", start: "+GLWindow.this); + Exception e1 = new Exception("GLWindow.destroy("+unrecoverable+") "+Thread.currentThread()+", start: "+GLWindow.this); e1.printStackTrace(); } - if( window.isNativeWindowValid() && null != drawable && drawable.isRealized() ) { + if( window.isNativeValid() && null != drawable && drawable.isRealized() ) { if( null != context && context.isCreated() ) { // Catch dispose GLExceptions by GLEventListener, just 'print' them // so we can continue with the destruction. @@ -193,14 +193,14 @@ public class GLWindow extends Window implements GLAutoDrawable { } if(null!=window) { - window.destroy(deep); + window.destroy(unrecoverable); } - if(deep) { + if(unrecoverable) { helper=null; } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - System.out.println("GLWindow.destroy("+deep+") "+Thread.currentThread()+", fin: "+GLWindow.this); + System.out.println("GLWindow.destroy("+unrecoverable+") "+Thread.currentThread()+", fin: "+GLWindow.this); } } finally { windowUnlock(); @@ -208,15 +208,9 @@ public class GLWindow extends Window implements GLAutoDrawable { } } - /** - * @param deep If true, all resources, ie listeners, parent handles, size, position - * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call - * this method with deep = true, you will not be able to regenerate the Window. - * @see #destroy() - */ - public void destroy(boolean deep) { - if( !isDestroyed() ) { - runOnEDTIfAvail(true, new DestroyAction(deep)); + public void destroy(boolean unrecoverable) { + if( isValid() ) { + runOnEDTIfAvail(true, new DestroyAction(unrecoverable)); } } @@ -269,7 +263,7 @@ public class GLWindow extends Window implements GLAutoDrawable { } public void setVisible(boolean visible) { - if(!isDestroyed()) { + if(isValid()) { runOnEDTIfAvail(true, new VisibleAction(visible)); } } @@ -512,17 +506,17 @@ public class GLWindow extends Window implements GLAutoDrawable { if( null == window ) { return; } if(sendDestroy || ( null!=window && window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) ) { - sendDestroy=false; - destroy(); - return; - } + sendDestroy=false; + destroy(); + return; + } if( null == context && window.isVisible() ) { // retry native window and drawable/context creation setVisible(true); } - if( window.isVisible() && window.isNativeWindowValid() && null != context ) { + if( window.isVisible() && window.isNativeValid() && null != context ) { if(forceReshape) { sendReshape = true; } diff --git a/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java b/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java index 87dfdb9d8..96bfc50e0 100644 --- a/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java @@ -47,8 +47,8 @@ public class DefaultEDTUtil implements EDTUtil { private ThreadGroup threadGroup; private volatile boolean shouldStop = false; private EventDispatchThread edt = null; - private Object edtLock = new Object(); - private ArrayList tasks = new ArrayList(); // one shot tasks + private Object edtLock = new Object(); // locking the EDT start/stop state + private ArrayList edtTasks = new ArrayList(); // one shot tasks private String name; private Runnable pumpMessages; @@ -56,123 +56,137 @@ public class DefaultEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=new String(Thread.currentThread().getName()+"-"+"EDT-"+name); this.pumpMessages=pumpMessages; + this.edt = new EventDispatchThread(threadGroup, name); } - public void start() { + public final void reset() { synchronized(edtLock) { - if(null==edt) { - edt = new EventDispatchThread(threadGroup, name); + waitUntilStopped(); + if(edtTasks.size()>0) { + throw new RuntimeException("Remaining EDTTasks: "+edtTasks.size()); } + this.edt = new EventDispatchThread(threadGroup, name); + } + } + + public final void start() { + synchronized(edtLock) { if(!edt.isRunning()) { shouldStop = false; edt.start(); + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT START"); + } } - edtLock.notifyAll(); } } - public void stop() { + public final void stop() { synchronized(edtLock) { - if(null!=edt && edt.isRunning()) { + if(edt.isRunning()) { shouldStop = true; + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT signal STOP"); + } } edtLock.notifyAll(); - if(DEBUG) { - System.out.println(Thread.currentThread()+": EDT signal STOP"); - } } } - public boolean isCurrentThreadEDT() { - return null!=edt && edt == Thread.currentThread(); - } - - public boolean isRunning() { - return null!=edt && edt.isRunning() ; + public final boolean isCurrentThreadEDT() { + return edt == Thread.currentThread(); } - private void invokeLater(Runnable task) { - synchronized(edtLock) { - if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { - tasks.add(task); - edtLock.notifyAll(); - } else { - // if !running or isEDTThread, do it right away - task.run(); - } - } + public final boolean isRunning() { + return !shouldStop && edt.isRunning() ; } public void invoke(boolean wait, Runnable task) { if(task == null) { return; } - boolean doWait = wait && null!=edt && edt.isRunning() && edt != Thread.currentThread(); - Object lock = new Object(); - RunnableTask rTask = new RunnableTask(task, doWait?lock:null, true); Throwable throwable = null; - synchronized(lock) { - invokeLater(rTask); - if( doWait ) { + RunnableTask rTask = null; + Object rTaskLock = new Object(); + synchronized(rTaskLock) { // lock the optional task execution + synchronized(edtLock) { // lock the EDT status + start(); // start if not started yet + if(isRunning() && edt != Thread.currentThread() ) { + rTask = new RunnableTask(task, wait?rTaskLock:null, true); + synchronized(edtTasks) { + edtTasks.add(rTask); + edtTasks.notifyAll(); + } + } else { + // if !running or isEDTThread, do it right away + wait = false; + task.run(); + } + } + // wait until task finished, if requested + // and no stop() call slipped through. + if( wait && !shouldStop ) { try { - lock.wait(); + rTaskLock.wait(); } catch (InterruptedException ie) { throwable = ie; } + if(null==throwable) { + throwable = rTask.getThrowable(); + } + if(null!=throwable) { + throw new RuntimeException(throwable); + } } } - if(null==throwable) { - throwable = rTask.getThrowable(); - } - if(null!=throwable) { - throw new RuntimeException(throwable); - } } public void waitUntilIdle() { - synchronized(edtLock) { - if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) { - try { - edtLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); + if(edt.isRunning() && edt != Thread.currentThread()) { + synchronized(edtTasks) { + while(edt.isRunning() && edtTasks.size()>0) { + try { + edtTasks.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } } } public void waitUntilStopped() { - synchronized(edtLock) { - while(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { - try { - edtLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); + if(edt.isRunning() && edt != Thread.currentThread() ) { + synchronized(edtLock) { + while(edt.isRunning()) { + try { + edtLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } } } class EventDispatchThread extends Thread { - boolean isRunning = false; + volatile boolean isRunning = false; public EventDispatchThread(ThreadGroup tg, String name) { super(tg, name); } - public synchronized boolean isRunning() { + public final boolean isRunning() { return isRunning; } public void start() throws IllegalThreadStateException { - synchronized(this) { - isRunning = true; - } + isRunning = true; super.start(); } /** - * Utilizing edtLock only for local resources and task execution, + * Utilizing locking only on edtTasks and its execution, * not for event dispatching. */ public void run() { @@ -180,41 +194,39 @@ public class DefaultEDTUtil implements EDTUtil { System.out.println(Thread.currentThread()+": EDT run() START"); } try { - while(!shouldStop) { - // wait for something todo - while(!shouldStop && tasks.size()==0) { - synchronized(edtLock) { - if(!shouldStop && tasks.size()==0) { - try { - edtLock.wait(defaultEDTPollGranularity); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - pumpMessages.run(); // event dispatch + do { + // event dispatch + if(!shouldStop) { + pumpMessages.run(); } - if(!shouldStop && tasks.size()>0) { - synchronized(edtLock) { - if(!shouldStop && tasks.size()>0) { - Runnable task = (Runnable) tasks.remove(0); - task.run(); // FIXME: could be run outside of lock - edtLock.notifyAll(); + // wait and work on tasks + synchronized(edtTasks) { + // wait for tasks + while(!shouldStop && edtTasks.size()==0) { + try { + edtTasks.wait(defaultEDTPollGranularity); + } catch (InterruptedException e) { + e.printStackTrace(); } } - pumpMessages.run(); // event dispatch + // execute one task, if available + if(edtTasks.size()>0) { + Runnable task = (Runnable) edtTasks.remove(0); + task.run(); + edtTasks.notifyAll(); + } } - } + } while(!shouldStop || edtTasks.size()>0) ; } catch (Throwable t) { // handle errors .. shouldStop = true; throw new RuntimeException(t); } finally { - synchronized(this) { + // check for tasks + // sync for waitUntilStopped() + synchronized(edtLock) { isRunning = !shouldStop; - } - if(!isRunning) { - synchronized(edtLock) { + if(!isRunning) { edtLock.notifyAll(); } } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index 1af102f43..91f35459b 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -44,6 +44,8 @@ public interface EDTUtil { public static final long defaultEDTPollGranularity = 10; // 10ms, 1/100s + public void reset(); + public void start(); public void stop(); @@ -52,6 +54,7 @@ public interface EDTUtil { public boolean isRunning(); + /** Shall start the thread if not running */ public void invoke(boolean wait, Runnable task); public void waitUntilIdle(); diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index ba886ade8..cb5c87a89 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -243,6 +243,10 @@ public class MainThread implements EDTUtil { } } + public void reset() { + // nop + } + public void start() { // nop } |