aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-04-13 20:48:50 +0200
committerSven Gothel <[email protected]>2010-04-13 20:48:50 +0200
commit1c1053c6a8b669c067ae1316b9770871e213ea05 (patch)
treeaf4ed7ea0b41ea6626cc0ad2208b495733b4056e
parent98de1d96e77a1c1aad237a8e5c6c63e21bcb5fc2 (diff)
NEWT X11 Fix (mainly ATI and multithreading)
- EventDispatchThread -> EDTUtil Since the name leads to the assumptions that an instance is the EDT. EDTUtil manages the EDT within. - EDTUtil, no more reference to Display, but use a Runnable for the pumpMessage() - Window.destroy() check if already done - X11Window: Added XErrorHandler to catch BadWindow and BadAtom while dispatching events - it is possible that the resource is already freed. Also added an XIOErrorHandler to identify the fatal Display* inaccessibility. Tests: - New junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java Testing creation/destruction and double destruction (error case) - Fix: src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java Properly holding all NEWT references .. Misc: - Reduced redundant NEWT 'toString()' output (*Capabilities, ..) -
-rwxr-xr-xsrc/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java82
-rwxr-xr-xsrc/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java67
-rwxr-xr-xsrc/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java174
-rwxr-xr-xsrc/newt/classes/com/jogamp/newt/Display.java47
-rwxr-xr-xsrc/newt/classes/com/jogamp/newt/Window.java63
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java6
-rw-r--r--src/newt/classes/com/jogamp/newt/util/EDTUtil.java (renamed from src/newt/classes/com/jogamp/newt/util/EventDispatchThread.java)92
-rwxr-xr-xsrc/newt/native/X11Window.c75
8 files changed, 443 insertions, 163 deletions
diff --git a/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java b/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java
index 277b41af3..436167dbf 100755
--- a/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java
+++ b/src/junit/com/jogamp/test/junit/jogl/offscreen/TestOffscreen01NEWT.java
@@ -66,38 +66,102 @@ public class TestOffscreen01NEWT {
@Test
public void test01OffscreenWindow() {
- GLWindow windowOffscreen = WindowUtilNEWT.createGLWindow(caps, width, height, false, true, false);
- GLEventListener demo = new RedSquare();
+ GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false);
+
+ Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ Window window = NewtFactory.createWindow(screen, caps2, false /* undecorated */);
+ Assert.assertNotNull(window);
+ window.setSize(width, height);
+ GLWindow windowOffScreen = GLWindow.create(window);
+ Assert.assertNotNull(windowOffScreen);
+ windowOffScreen.setVisible(true);
+
GLWindow windowOnScreen = null;
WindowListener wl=null;
MouseListener ml=null;
SurfaceUpdatedListener ul=null;
- WindowUtilNEWT.run(windowOffscreen, null, windowOnScreen, wl, ml, ul, 2, false /*snapshot*/, false /*debug*/);
+ WindowUtilNEWT.run(windowOffScreen, null, windowOnScreen, wl, ml, ul, 2, false /*snapshot*/, false /*debug*/);
try {
Thread.sleep(1000); // 1000 ms
} catch (Exception e) {}
- WindowUtilNEWT.shutdown(windowOffscreen, windowOnScreen);
+
+ if(null!=windowOnScreen) {
+ windowOnScreen.destroy();
+ }
+ if(null!=windowOffScreen) {
+ windowOffScreen.destroy();
+ }
+ if(null!=screen) {
+ screen.destroy();
+ }
+ if(null!=display) {
+ display.destroy();
+ }
}
@Test
public void test02OffscreenSnapshotWithDemo() {
- GLWindow windowOffscreen = WindowUtilNEWT.createGLWindow(caps, width, height, false, true, false);
- GLEventListener demo = new RedSquare();
+ GLCapabilities caps2 = WindowUtilNEWT.fixCaps(caps, false, true, false);
+
+ Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+ Window window = NewtFactory.createWindow(screen, caps2, false /* undecorated */);
+ Assert.assertNotNull(window);
+ window.setSize(width, height);
+ GLWindow windowOffScreen = GLWindow.create(window);
+ Assert.assertNotNull(windowOffScreen);
+ windowOffScreen.setVisible(true);
+
GLWindow windowOnScreen = null;
WindowListener wl=null;
MouseListener ml=null;
SurfaceUpdatedListener ul=null;
- WindowUtilNEWT.run(windowOffscreen, demo, windowOnScreen, wl, ml, ul, 2, true /*snapshot*/, false /*debug*/);
+ GLEventListener demo = new RedSquare();
+ Assert.assertNotNull(demo);
+
+ WindowUtilNEWT.run(windowOffScreen, demo, windowOnScreen, wl, ml, ul, 2, true /*snapshot*/, false /*debug*/);
try {
Thread.sleep(1000); // 1000 ms
} catch (Exception e) {}
- WindowUtilNEWT.shutdown(windowOffscreen, windowOnScreen);
+
+ if(null!=windowOnScreen) {
+ windowOnScreen.destroy();
+ }
+ if(null!=windowOffScreen) {
+ windowOffScreen.destroy();
+ }
+ if(null!=screen) {
+ screen.destroy();
+ }
+ if(null!=display) {
+ display.destroy();
+ }
}
public static void main(String args[]) {
- org.junit.runner.JUnitCore.main(TestOffscreen01NEWT.class.getName());
+ String tstname = TestOffscreen01NEWT.class.getName();
+ try {
+ 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" } );
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
}
diff --git a/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java b/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java
index 26b13cf7d..f6a6dc4be 100755
--- a/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java
+++ b/src/junit/com/jogamp/test/junit/jogl/offscreen/WindowUtilNEWT.java
@@ -34,6 +34,8 @@ package com.jogamp.test.junit.jogl.offscreen;
import com.jogamp.test.junit.util.*;
+import org.junit.Assert;
+
import java.lang.reflect.*;
import javax.media.opengl.*;
import javax.media.nativewindow.*;
@@ -42,52 +44,29 @@ import com.jogamp.newt.opengl.*;
public class WindowUtilNEWT {
- public static Window createWindow(GLCapabilities caps, int w, int h, boolean onscreen, boolean pbuffer, boolean undecorated) {
- GLCapabilities caps2 = (GLCapabilities) caps.clone();
- caps2.setOnscreen(onscreen);
- caps2.setPBuffer(!onscreen && pbuffer);
- caps2.setDoubleBuffered(!onscreen);
-
- Display display = NewtFactory.createDisplay(null); // local display
- Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- Window window = NewtFactory.createWindow(screen, caps2, onscreen && undecorated);
-
- GLCapabilities glCaps = (GLCapabilities) window.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities();
-
- GLDrawableFactory factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
- GLDrawable drawable = factory.createGLDrawable(window);
- drawable.setRealized(true);
- GLContext context = drawable.createContext(null);
-
- window.setSize(w, h);
- window.setVisible(true);
- return window;
- }
-
- public static GLWindow createGLWindow(GLCapabilities caps, int w, int h, boolean onscreen, boolean pbuffer, boolean undecorated) {
+ public static GLCapabilities fixCaps(GLCapabilities caps, boolean onscreen, boolean pbuffer, boolean undecorated) {
GLCapabilities caps2 = (GLCapabilities) caps.clone();
caps2.setOnscreen(onscreen);
caps2.setPBuffer(!onscreen && pbuffer);
caps2.setDoubleBuffered(!onscreen);
- GLWindow window = GLWindow.create(caps2, onscreen && undecorated);
- window.setSize(w, h);
- window.setVisible(true);
- return window;
+ return caps2;
}
- public static void run(GLWindow windowOffscreen, GLEventListener demo,
+ public static void run(GLWindow windowOffScreen, GLEventListener demo,
GLWindow windowOnScreen, WindowListener wl, MouseListener ml,
SurfaceUpdatedListener ul, int frames, boolean snapshot, boolean debug) {
try {
+ Assert.assertNotNull(windowOffScreen);
+
if(debug && null!=demo) {
MiscUtils.setField(demo, "glDebug", new Boolean(true));
MiscUtils.setField(demo, "glTrace", new Boolean(true));
}
if(null!=demo) {
- if(!MiscUtils.setField(demo, "window", windowOffscreen)) {
- MiscUtils.setField(demo, "glWindow", windowOffscreen);
+ if(!MiscUtils.setField(demo, "window", windowOffScreen)) {
+ MiscUtils.setField(demo, "glWindow", windowOffScreen);
}
- windowOffscreen.addGLEventListener(demo);
+ windowOffScreen.addGLEventListener(demo);
}
if ( null != windowOnScreen ) {
@@ -100,47 +79,35 @@ public class WindowUtilNEWT {
windowOnScreen.setVisible(true);
}
- GLDrawable readDrawable = windowOffscreen.getContext().getGLDrawable() ;
+ GLDrawable readDrawable = windowOffScreen.getContext().getGLDrawable() ;
if ( null == windowOnScreen ) {
if(snapshot) {
Surface2File s2f = new Surface2File();
- windowOffscreen.addSurfaceUpdatedListener(s2f);
+ windowOffScreen.addSurfaceUpdatedListener(s2f);
}
} else {
ReadBuffer2Screen readDemo = new ReadBuffer2Screen( readDrawable ) ;
windowOnScreen.addGLEventListener(readDemo);
}
if(null!=ul) {
- windowOffscreen.addSurfaceUpdatedListener(ul);
+ windowOffScreen.addSurfaceUpdatedListener(ul);
}
if(debug) {
System.out.println("+++++++++++++++++++++++++++");
- System.out.println(windowOffscreen);
+ System.out.println(windowOffScreen);
System.out.println("+++++++++++++++++++++++++++");
}
- while ( windowOffscreen.getTotalFrames() < frames) {
- windowOffscreen.display();
+ while ( windowOffScreen.getTotalFrames() < frames) {
+ windowOffScreen.display();
}
- windowOffscreen.removeAllSurfaceUpdatedListener();
+ windowOffScreen.removeAllSurfaceUpdatedListener();
} catch (GLException e) {
e.printStackTrace();
}
}
- public static void shutdown(GLWindow windowOffscreen, GLWindow windowOnscreen) {
- // Shut things down cooperatively
- if(null!=windowOnscreen) {
- windowOnscreen.destroy();
- }
- if(null!=windowOffscreen) {
- windowOffscreen.destroy();
- }
- if(null!=windowOnscreen) {
- windowOnscreen.getFactory().shutdown();
- }
- }
}
diff --git a/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java
new file mode 100755
index 000000000..91760ae80
--- /dev/null
+++ b/src/junit/com/jogamp/test/junit/newt/TestWindows01NEWT.java
@@ -0,0 +1,174 @@
+/*
+ * 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 com.jogamp.newt.*;
+
+public class TestWindows01NEWT {
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ width = 640;
+ height = 480;
+ }
+
+ static Window createWindow(Screen screen, Capabilities caps, int width, int height, boolean onscreen, boolean undecorated) {
+ Assert.assertNotNull(caps);
+ caps.setOnscreen(onscreen);
+ // System.out.println("Requested: "+caps);
+
+ //
+ // Create native windowing resources .. X11/Win/OSX
+ //
+ Window window = NewtFactory.createWindow(screen, caps, onscreen && undecorated);
+ Assert.assertNotNull(window);
+ window.setSize(width, height);
+ Assert.assertTrue(false==window.isVisible());
+ window.setVisible(true);
+ Assert.assertTrue(true==window.isVisible());
+ Assert.assertTrue(width==window.getWidth());
+ Assert.assertTrue(height==window.getHeight());
+ // System.out.println("Created: "+window);
+
+ //
+ // Create native OpenGL resources .. XGL/WGL/CGL ..
+ // equivalent to GLAutoDrawable methods: setVisible(true)
+ //
+ caps = (Capabilities) window.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities();
+ Assert.assertNotNull(caps);
+ Assert.assertTrue(caps.getGreenBits()>5);
+ Assert.assertTrue(caps.getBlueBits()>5);
+ Assert.assertTrue(caps.getRedBits()>5);
+ Assert.assertTrue(caps.isOnscreen()==onscreen);
+
+ return window;
+ }
+
+ static void destroyWindow(Display display, Screen screen, Window window) {
+ if(null!=window) {
+ window.destroy();
+ }
+ if(null!=screen) {
+ screen.destroy();
+ }
+ if(null!=display) {
+ display.destroy();
+ }
+ }
+
+ @Test
+ public void testWindowDecor01Simple() {
+ Capabilities caps = new Capabilities();
+ Assert.assertNotNull(caps);
+ Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+
+ Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ try {
+ Thread.sleep(1000); // 1000 ms
+ } catch (Exception e) {}
+ destroyWindow(display, screen, window);
+ }
+
+ @Test
+ public void testWindowDecor02DestroyWinTwiceA() {
+ Capabilities caps = new Capabilities();
+ Assert.assertNotNull(caps);
+ Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+
+ Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ try {
+ Thread.sleep(1000); // 1000 ms
+ } catch (Exception e) {}
+ destroyWindow(null, null, window);
+ destroyWindow(display, screen, window);
+ }
+
+ @Test
+ public void testWindowDecor03TwoWin() {
+ Capabilities caps = new Capabilities();
+ Assert.assertNotNull(caps);
+ Display display = NewtFactory.createDisplay(null); // local display
+ Assert.assertNotNull(display);
+ Screen screen = NewtFactory.createScreen(display, 0); // screen 0
+ Assert.assertNotNull(screen);
+
+ Window window1 = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ Window window2 = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */);
+ try {
+ Thread.sleep(1000); // 1000 ms
+ } catch (Exception e) {}
+ destroyWindow(null, null, window2);
+ destroyWindow(display, screen, window1);
+ }
+
+ public static void main(String args[]) {
+ String tstname = TestWindows01NEWT.class.getName();
+ try {
+ 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" } );
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 88f6dd34b..2bc99475c 100755
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -35,7 +35,7 @@ package com.jogamp.newt;
import javax.media.nativewindow.*;
import com.jogamp.newt.impl.Debug;
-import com.jogamp.newt.util.EventDispatchThread;
+import com.jogamp.newt.util.EDTUtil;
import java.util.*;
public abstract class Display {
@@ -141,11 +141,16 @@ public abstract class Display {
display.refCount=1;
if(NewtFactory.useEDT()) {
- Thread current = Thread.currentThread();
- display.eventDispatchThread = new EventDispatchThread(display, current.getThreadGroup(), current.getName());
- display.eventDispatchThread.start();
final Display f_dpy = display;
- display.eventDispatchThread.invokeAndWait(new Runnable() {
+ Thread current = Thread.currentThread();
+ display.edtUtil = new EDTUtil(current.getThreadGroup(),
+ "Display_"+display.getName()+"-"+current.getName(),
+ new Runnable() {
+ public void run() {
+ f_dpy.pumpMessagesImpl();
+ } } );
+ display.edt = display.edtUtil.start();
+ display.edtUtil.invokeAndWait(new Runnable() {
public void run() {
f_dpy.createNative();
}
@@ -189,7 +194,7 @@ public abstract class Display {
}
}
- public EventDispatchThread getEDT() { return eventDispatchThread; }
+ public EDTUtil getEDTUtil() { return edtUtil; }
public synchronized void destroy() {
if(DEBUG) {
@@ -201,10 +206,10 @@ public abstract class Display {
if(DEBUG) {
System.err.println("Display.destroy("+name+") REMOVE: "+this+" "+Thread.currentThread());
}
- if(null!=eventDispatchThread) {
+ if(null!=edtUtil) {
final Display f_dpy = this;
- final EventDispatchThread f_edt = eventDispatchThread;
- eventDispatchThread.invokeAndWait(new Runnable() {
+ final EDTUtil f_edt = edtUtil;
+ edtUtil.invokeAndWait(new Runnable() {
public void run() {
f_dpy.closeNative();
f_edt.stop();
@@ -213,9 +218,9 @@ public abstract class Display {
} else {
closeNative();
}
- if(null!=eventDispatchThread) {
- eventDispatchThread.waitUntilStopped();
- eventDispatchThread=null;
+ if(null!=edtUtil) {
+ edtUtil.waitUntilStopped();
+ edtUtil=null;
}
aDevice = null;
} else {
@@ -246,14 +251,13 @@ public abstract class Display {
return aDevice;
}
- public void pumpMessages() {
- if(null!=eventDispatchThread) {
- dispatchMessages();
- } else {
- synchronized(this) {
- dispatchMessages();
- }
- }
+ public synchronized void pumpMessages() {
+ pumpMessagesImpl();
+ }
+
+ private void pumpMessagesImpl() {
+ if(0==refCount) return;
+ dispatchMessages();
}
public String toString() {
@@ -268,7 +272,8 @@ public abstract class Display {
/** Default impl. nop - Currently only X11 needs a Display lock */
protected void unlockDisplay() { }
- protected EventDispatchThread eventDispatchThread = null;
+ protected EDTUtil edtUtil = null;
+ protected Thread edt = null;
protected String name;
protected int refCount;
protected AbstractGraphicsDevice aDevice;
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index 171bb2468..8f09ae364 100755
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -34,7 +34,7 @@
package com.jogamp.newt;
import com.jogamp.newt.impl.Debug;
-import com.jogamp.newt.util.EventDispatchThread;
+import com.jogamp.newt.util.EDTUtil;
import javax.media.nativewindow.*;
import com.jogamp.nativewindow.impl.NWReflection;
@@ -98,10 +98,10 @@ public abstract class Window implements NativeWindow
window.invalidate();
window.screen = screen;
window.setUndecorated(undecorated||0!=parentWindowHandle);
- EventDispatchThread edt = screen.getDisplay().getEDT();
- if(null!=edt) {
+ EDTUtil edtUtil = screen.getDisplay().getEDTUtil();
+ if(null!=edtUtil) {
final Window f_win = window;
- edt.invokeAndWait(new Runnable() {
+ edtUtil.invokeAndWait(new Runnable() {
public void run() {
f_win.createNative(parentWindowHandle, caps);
}
@@ -131,10 +131,10 @@ public abstract class Window implements NativeWindow
window.invalidate();
window.screen = screen;
window.setUndecorated(undecorated);
- EventDispatchThread edt = screen.getDisplay().getEDT();
- if(null!=edt) {
+ EDTUtil edtUtil = screen.getDisplay().getEDTUtil();
+ if(null!=edtUtil) {
final Window f_win = window;
- edt.invokeAndWait(new Runnable() {
+ edtUtil.invokeAndWait(new Runnable() {
public void run() {
f_win.createNative(0, caps);
}
@@ -212,15 +212,15 @@ public abstract class Window implements NativeWindow
public String toString() {
StringBuffer sb = new StringBuffer();
- sb.append(getClass().getName()+"[config "+config+
- ", windowHandle "+toHexString(getWindowHandle())+
- ", surfaceHandle "+toHexString(getSurfaceHandle())+
- ", pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
- ", visible "+isVisible()+
- ", undecorated "+undecorated+
- ", fullscreen "+fullscreen+
+ sb.append(getClass().getName()+"[Config "+config+
+ ", WindowHandle "+toHexString(getWindowHandle())+
+ ", SurfaceHandle "+toHexString(getSurfaceHandle())+
+ ", Pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
+ ", Visible "+isVisible()+
+ ", Undecorated "+undecorated+
+ ", Fullscreen "+fullscreen+
", "+screen+
- ", wrappedWindow "+getWrappedWindow());
+ ", WrappedWindow "+getWrappedWindow());
sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedListeners.size()+" [");
for (Iterator iter = surfaceUpdatedListeners.iterator(); iter.hasNext(); ) {
@@ -343,25 +343,28 @@ public abstract class Window implements NativeWindow
keyListeners = new ArrayList();
}
synchronized(this) {
- destructionLock.lock();
try {
- Screen scr = screen;
- Display dpy = (null!=screen) ? screen.getDisplay() : null;
- EventDispatchThread edt = (null!=dpy) ? dpy.getEDT() : null;
- if(null!=edt) {
- final Window f_win = this;
- edt.invokeAndWait(new Runnable() {
- public void run() {
- f_win.closeNative();
- }
- } );
- } else {
- closeNative();
+ destructionLock.lock();
+ Display dpy = null;
+ if( null != screen && 0 != windowHandle ) {
+ Screen scr = screen;
+ dpy = (null!=screen) ? screen.getDisplay() : null;
+ EDTUtil edtUtil = (null!=dpy) ? dpy.getEDTUtil() : null;
+ if(null!=edtUtil) {
+ final Window f_win = this;
+ edtUtil.invokeAndWait(new Runnable() {
+ public void run() {
+ f_win.closeNative();
+ }
+ } );
+ } else {
+ closeNative();
+ }
}
invalidate();
if(deep) {
- if(null!=scr) {
- scr.destroy();
+ if(null!=screen) {
+ screen.destroy();
}
if(null!=dpy) {
dpy.destroy();
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 4a7f27f3a..fec70c99c 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -65,7 +65,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
this.ownerOfWinScrDpy = ownerOfWinScrDpy;
this.window = window;
this.window.setAutoDrawableClient(true);
- this.runPumpMessages = ( null == getScreen().getDisplay().getEDT() ) ;
+ this.runPumpMessages = ( null == getScreen().getDisplay().getEDTUtil() ) ;
window.addWindowListener(new WindowListener() {
public void windowResized(WindowEvent e) {
sendReshape = true;
@@ -152,7 +152,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
* @deprecated EXPERIMENTAL, semantic is about to be removed after further verification.
*/
public void setRunPumpMessages(boolean onoff) {
- if( onoff && null!=getScreen().getDisplay().getEDT() ) {
+ if( onoff && null!=getScreen().getDisplay().getEDTUtil() ) {
throw new GLException("GLWindow.setRunPumpMessages(true) - Can't do with EDT on");
}
runPumpMessages = onoff;
@@ -382,7 +382,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
}
public String toString() {
- return "NEWT-GLWindow[ \n\tDrawable: "+drawable+", \n\tWindow: "+window+", \n\tHelper: "+helper+", \n\tFactory: "+factory+"]";
+ return "NEWT-GLWindow[ \n\tHelper: "+helper+", \n\tDrawable: "+drawable + /** ", \n\tWindow: "+window+", \n\tFactory: "+factory+ */ "]";
}
//----------------------------------------------------------------------
diff --git a/src/newt/classes/com/jogamp/newt/util/EventDispatchThread.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
index 675c6f322..f852bcf5c 100644
--- a/src/newt/classes/com/jogamp/newt/util/EventDispatchThread.java
+++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
@@ -40,30 +40,30 @@ import com.jogamp.newt.Display;
import com.jogamp.newt.impl.Debug;
import java.util.*;
-public class EventDispatchThread {
+public class EDTUtil {
public static final boolean DEBUG = Debug.debug("EDT");
private ThreadGroup threadGroup;
private volatile boolean shouldStop = false;
- private TaskWorker taskWorker = null;
- private Object taskWorkerLock = new Object();
+ private EventDispatchThread edt = null;
+ private Object edtLock = new Object();
private ArrayList tasks = new ArrayList(); // one shot tasks
- private Display display = null;
private String name;
- private long edtPollGranularity = 10;
+ private Runnable pumpMessages;
+ private long edtPollGranularity = 10; // 10ms, 1/100s
- public EventDispatchThread(Display display, ThreadGroup tg, String name) {
- this.display = display;
+ public EDTUtil(ThreadGroup tg, String name, Runnable pumpMessages) {
this.threadGroup = tg;
- this.name=new String("EDT-Display_"+display.getName()+"-"+name);
+ this.name=new String("EDT-"+name);
+ this.pumpMessages=pumpMessages;
}
public String getName() { return name; }
public ThreadGroup getThreadGroup() { return threadGroup; }
- public void start() {
- start(false);
+ public Thread start() {
+ return start(false);
}
/**
@@ -75,52 +75,56 @@ public class EventDispatchThread {
* Usefull in combination with externalStimuli=true,
* so an external stimuli can call it.
*/
- public Runnable start(boolean externalStimuli) {
- synchronized(taskWorkerLock) {
- if(null==taskWorker) {
- taskWorker = new TaskWorker(threadGroup, name);
+ public Thread start(boolean externalStimuli) {
+ synchronized(edtLock) {
+ if(null==edt) {
+ edt = new EventDispatchThread(threadGroup, name);
}
- if(!taskWorker.isRunning()) {
+ if(!edt.isRunning()) {
shouldStop = false;
- taskWorker.start(externalStimuli);
+ edt.start(externalStimuli);
}
- taskWorkerLock.notifyAll();
+ edtLock.notifyAll();
}
- return taskWorker;
+ return edt;
}
public void stop() {
- synchronized(taskWorkerLock) {
- if(null!=taskWorker && taskWorker.isRunning()) {
+ synchronized(edtLock) {
+ if(null!=edt && edt.isRunning()) {
shouldStop = true;
}
- taskWorkerLock.notifyAll();
+ edtLock.notifyAll();
if(DEBUG) {
System.out.println(Thread.currentThread()+": EDT signal STOP");
}
}
}
+ public Thread getEDT() {
+ return edt;
+ }
+
public boolean isThreadEDT(Thread thread) {
- return null!=taskWorker && taskWorker == thread;
+ return null!=edt && edt == thread;
}
public boolean isCurrentThreadEDT() {
- return null!=taskWorker && taskWorker == Thread.currentThread();
+ return null!=edt && edt == Thread.currentThread();
}
public boolean isRunning() {
- return null!=taskWorker && taskWorker.isRunning() ;
+ return null!=edt && edt.isRunning() ;
}
public void invokeLater(Runnable task) {
if(task == null) {
return;
}
- synchronized(taskWorkerLock) {
- if(null!=taskWorker && taskWorker.isRunning() && taskWorker != Thread.currentThread() ) {
+ synchronized(edtLock) {
+ if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) {
tasks.add(task);
- taskWorkerLock.notifyAll();
+ edtLock.notifyAll();
} else {
// if !running or isEDTThread, do it right away
task.run();
@@ -137,10 +141,10 @@ public class EventDispatchThread {
}
public void waitOnWorker() {
- synchronized(taskWorkerLock) {
- if(null!=taskWorker && taskWorker.isRunning() && tasks.size()>0 && taskWorker != Thread.currentThread() ) {
+ synchronized(edtLock) {
+ if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) {
try {
- taskWorkerLock.wait();
+ edtLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
@@ -149,10 +153,10 @@ public class EventDispatchThread {
}
public void waitUntilStopped() {
- synchronized(taskWorkerLock) {
- while(null!=taskWorker && taskWorker.isRunning() && taskWorker != Thread.currentThread() ) {
+ synchronized(edtLock) {
+ while(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) {
try {
- taskWorkerLock.wait();
+ edtLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
@@ -160,11 +164,11 @@ public class EventDispatchThread {
}
}
- class TaskWorker extends Thread {
+ class EventDispatchThread extends Thread {
boolean isRunning = false;
boolean externalStimuli = false;
- public TaskWorker(ThreadGroup tg, String name) {
+ public EventDispatchThread(ThreadGroup tg, String name) {
super(tg, name);
}
@@ -183,7 +187,7 @@ public class EventDispatchThread {
}
/**
- * Utilizing taskWorkerLock only for local resources and task execution,
+ * Utilizing edtLock only for local resources and task execution,
* not for event dispatching.
*/
public void run() {
@@ -194,26 +198,26 @@ public class EventDispatchThread {
try {
// wait for something todo
while(!shouldStop && tasks.size()==0) {
- synchronized(taskWorkerLock) {
+ synchronized(edtLock) {
if(!shouldStop && tasks.size()==0) {
try {
- taskWorkerLock.wait(edtPollGranularity);
+ edtLock.wait(edtPollGranularity);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- display.pumpMessages(); // event dispatch
+ pumpMessages.run(); // event dispatch
}
if(!shouldStop && tasks.size()>0) {
- synchronized(taskWorkerLock) {
+ synchronized(edtLock) {
if(!shouldStop && tasks.size()>0) {
Runnable task = (Runnable) tasks.remove(0);
task.run();
- taskWorkerLock.notifyAll();
+ edtLock.notifyAll();
}
}
- display.pumpMessages(); // event dispatch
+ pumpMessages.run(); // event dispatch
}
} catch (Throwable t) {
// handle errors ..
@@ -227,8 +231,8 @@ public class EventDispatchThread {
isRunning = !shouldStop;
}
if(!isRunning) {
- synchronized(taskWorkerLock) {
- taskWorkerLock.notifyAll();
+ synchronized(edtLock) {
+ edtLock.notifyAll();
}
}
if(DEBUG) {
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 11f7d0f6c..0fccc94bb 100755
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -186,6 +186,57 @@ static void _throwNewRuntimeException(Display * unlockDisplay, JNIEnv *env, cons
* Display
*/
+
+static XErrorHandler origErrorHandler = NULL ;
+
+static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e)
+{
+ fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X\n", dpy, e->error_code);
+
+ if (e->error_code == BadAtom)
+ {
+ fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", e->resourceid);
+ } else if (e->error_code == BadWindow)
+ {
+ fprintf(stderr, " BadWindow (%p): Window probably already removed\n", e->resourceid);
+ } else {
+ return origErrorHandler(dpy, e);
+ }
+
+ return 0;
+}
+
+static void displayDispatchErrorHandlerEnable(int onoff) {
+ if(onoff) {
+ if(NULL==origErrorHandler) {
+ origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler);
+ }
+ } else {
+ XSetErrorHandler(origErrorHandler);
+ origErrorHandler = NULL;
+ }
+}
+
+static XIOErrorHandler origIOErrorHandler = NULL;
+
+static int displayDispatchIOErrorHandler(Display *dpy)
+{
+ fprintf(stderr, "Fatal: NEWT X11 IOError: Display %p not available\n", dpy);
+ return 0;
+}
+
+static void displayDispatchIOErrorHandlerEnable(int onoff) {
+ if(onoff) {
+ if(NULL==origIOErrorHandler) {
+ origIOErrorHandler = XSetIOErrorHandler(displayDispatchIOErrorHandler);
+ }
+ } else {
+ XSetIOErrorHandler(origIOErrorHandler);
+ origIOErrorHandler = NULL;
+ }
+}
+
+
/*
* Class: com_jogamp_newt_x11_X11Display
* Method: initIDs
@@ -197,7 +248,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_x11_X11Display_initIDs
jclass c;
if( 0 == XInitThreads() ) {
- fprintf(stderr, "Warning: XInitThreads() failed\n");
+ fprintf(stderr, "Warning: NEWT X11Window: XInitThreads() failed\n");
}
displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
@@ -249,6 +300,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_LockDisplay
_throwNewRuntimeException(NULL, env, "given display connection is NULL\n");
}
XLockDisplay(dpy) ;
+ DBG_PRINT1( "X11: LockDisplay 0x%X\n", dpy);
}
@@ -265,6 +317,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_UnlockDisplay
_throwNewRuntimeException(NULL, env, "given display connection is NULL\n");
}
XUnlockDisplay(dpy) ;
+ DBG_PRINT1( "X11: UnlockDisplay 0x%X\n", dpy);
}
@@ -356,14 +409,13 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j
&nitems_return, &bytes_after_return, &jogl_java_object_data_pp);
if ( Success != res ) {
- _throwNewRuntimeException(dpy, env, "could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, bail out!\n",
- res, nitems_return, bytes_after_return);
+ fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, result 0!\n", res, nitems_return, bytes_after_return);
return NULL;
}
if(actual_type_return!=(Atom)javaObjectAtom || nitems_return<nitems_32 || NULL==jogl_java_object_data_pp) {
XFree(jogl_java_object_data_pp);
- _throwNewRuntimeException(dpy, env, "could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, actual_type_return %ld, JOGL_JAVA_OBJECT %ld, bail out!\n",
+ fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, actual_type_return %ld, JOGL_JAVA_OBJECT %ld, result 0!\n",
res, nitems_return, bytes_after_return, (long)actual_type_return, javaObjectAtom);
return NULL;
}
@@ -374,7 +426,7 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j
#ifdef VERBOSE_ON
if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, newtWindowClz)) {
- _throwNewRuntimeException(NULL, env, "fetched Atom JOGL_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !\n", jwindow);
+ _throwNewRuntimeException(dpy, env, "fetched Atom JOGL_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !\n", jwindow);
}
#endif
return jwindow;
@@ -395,6 +447,8 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_DispatchMessages
return;
}
+ displayDispatchIOErrorHandlerEnable(1);
+
// Periodically take a break
while( num_events > 0 ) {
jobject jwindow = NULL;
@@ -408,6 +462,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_DispatchMessages
// num_events = XPending(dpy); // XEventsQueued(dpy, QueuedAfterFlush); // I/O Flush ..
// num_events = XEventsQueued(dpy, QueuedAlready); // Better, no I/O ..
if ( 0 >= XEventsQueued(dpy, QueuedAlready) ) {
+ displayDispatchIOErrorHandlerEnable(0);
XUnlockDisplay(dpy) ;
return;
}
@@ -415,6 +470,8 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_DispatchMessages
XNextEvent(dpy, &evt);
num_events--;
+ displayDispatchIOErrorHandlerEnable(0);
+
if( 0==evt.xany.window ) {
_throwNewRuntimeException(dpy, env, "event window NULL, bail out!\n");
return ;
@@ -424,10 +481,16 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_x11_X11Display_DispatchMessages
_throwNewRuntimeException(dpy, env, "wrong display, bail out!\n");
return ;
}
+
+ displayDispatchErrorHandlerEnable(1);
+
jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom);
+ displayDispatchErrorHandlerEnable(0);
+
if(NULL==jwindow) {
- // just leave .. _throwNewRuntimeException(env, "could not fetch Java Window object, bail out!\n");
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for invalid X11 window %p\n",
+ dpy, evt.type, evt.xany.window);
XUnlockDisplay(dpy) ;
return;
}