summaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-09-27 17:33:39 +0200
committerSven Gothel <[email protected]>2012-09-27 17:33:39 +0200
commitfbe331f013608eb31ff0d8675f4e4c9881c9c48b (patch)
tree535aae61f299884ce6b61d026a60ed0546e9703b /src/nativewindow/classes
parentba846a478d616327817dd530dbdcd9a786be5b7a (diff)
Fix Bug 616: X11: Remove XInitThreads() dependency while cleaning up device locking, resulting in a native-lock-free impl.
The X11 implementation details of NativeWindow and NEWT used the X11 implicit locking facility XLockDisplay/XUnlockDisplay, enabled via XInitThreads(). The latter useage is complicated within an unsure environment where the initialization point of JOGL is unknown, but XInitThreads() requires to be called once and before any other X11 calls. The solution is simple and thorough, replace native X11 locking w/ 'application level' locking. Following this pattern actually cleans up a pretty messy part of X11 NativeWindow and NEWT, since the generalization of platform independent locking simplifies code. Simply using our RecursiveLock also speeds up locking, since it doesn't require JNI calls down to X11 anymore. It allows us to get rid of X11ToolkitLock and X11JAWTToolkitLock. Using the RecursiveLock also allows us to remove the shortcut of explicitly createing a NullToolkitLocked device for 'private' display connections. All devices use proper locking as claimed in their toolkit util 'requiresToolkitLock()' in X11Util, OSXUtil, .. Further more a bug has been fixed of X11ErrorHandler usage, i.e. we need to keep our handler alive at all times due to async X11 messaging behavior. This allows to remove the redundant code in X11/NEWT. The AbstractGraphicsDevice lifecycle has been fixed as well, i.e. called when closing NEWT's Display for all driver implementations. On the NEWT side the Display's AbstractGraphicsDevice semantics has been clarified, i.e. it's usage for EDT and lifecycle operations. Hence the X11 Display 2nd device for rendering operations has been moved to X11 Window where it belongs - and the X11 Display's default device used for EDT/lifecycle-ops as it should be. This allows running X11/NEWT properly with the default usage, where the Display instance and hence the EDT thread is shared with many Screen and Window. Rendering using NEWT Window is decoupled from it's shared Display lock via it's own native X11 display. Lock free AbstractGraphicsDevice impl. (Windows, OSX, ..) don't require any attention in this regard since they use NullToolkitLock. Tests: ====== This implementation has been tested manually with Mesa3d (soft, Intel), ATI and Nvidia on X11, Windows and OSX w/o any regressions found in any unit test. Issues on ATI: ============== Only on ATI w/o a composite renderer the unit tests expose a driver or WM bug where XCB claims a lack of locking. Setting env. var 'LIBXCB_ALLOW_SLOPPY_LOCK=true' is one workaround if users refuse to enable compositing. We may investigate this issue in more detail later on.
Diffstat (limited to 'src/nativewindow/classes')
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java2
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java2
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java2
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java3
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java99
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java18
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java9
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java (renamed from src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java)60
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java141
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java3
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java76
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java3
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java119
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java7
14 files changed, 268 insertions, 276 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index 152384980..2e4099c1b 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -73,7 +73,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
/**
* @param display the Display connection
- * @param locker custom {@link javax.media.nativewindow.ToolkitLock}, eg to force null locking in NEWT
+ * @param locker custom {@link javax.media.nativewindow.ToolkitLock}, eg to force null locking w/ private connection
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(String, String, int, long, ToolkitLock)
*/
public X11GraphicsDevice(long display, int unitID, ToolkitLock locker, boolean owner) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
index 5f3c220ca..7ab5bd6aa 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java
@@ -63,7 +63,7 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl
private static int fetchScreen(X11GraphicsDevice device, int screen) {
// It still could be an AWT hold handle ..
- if(X11Util.XineramaIsEnabled(device.getHandle())) {
+ if(X11Util.XineramaIsEnabled(device)) {
screen = 0; // Xinerama -> 1 screen
}
return screen;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
index 756e4451b..5eaaa6613 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
@@ -131,7 +131,7 @@ public interface AbstractGraphicsDevice extends Cloneable {
/**
* Optionally closing the device if handle is not <code>null</code>.
* <p>
- * The default implementation is a <code>NOP</code>, just setting the handle to <code>null</code>.
+ * The default implementation {@link ToolkitLock#dispose() dispose} it's {@link ToolkitLock} and sets the handle to <code>null</code>.
* </p>
* <p>
* Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 583fde07f..b16b0c75c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -153,6 +153,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
@Override
public boolean close() {
+ toolkitLock.dispose();
if(0 != handle) {
handle = 0;
return true;
@@ -162,7 +163,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
@Override
public String toString() {
- return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+"]";
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", "+toolkitLock+"]";
}
/**
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 40aaa8a25..4f4bb629b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -33,7 +33,6 @@
package javax.media.nativewindow;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -43,6 +42,7 @@ import java.util.Map;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NativeWindowFactoryImpl;
+import jogamp.nativewindow.ResourceToolkitLock;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
@@ -93,13 +93,6 @@ public abstract class NativeWindowFactory {
private static ToolkitLock jawtUtilJAWTToolkitLock;
- public static final String X11JAWTToolkitLockClassName = "jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock" ;
- public static final String X11ToolkitLockClassName = "jogamp.nativewindow.x11.X11ToolkitLock" ;
-
- private static Class<?> x11JAWTToolkitLockClass;
- private static Constructor<?> x11JAWTToolkitLockConstructor;
- private static Class<?> x11ToolkitLockClass;
- private static Constructor<?> x11ToolkitLockConstructor;
private static boolean requiresToolkitLock;
private static volatile boolean isJVMShuttingDown = false;
@@ -266,16 +259,6 @@ public abstract class NativeWindowFactory {
// register either our default factory or (if exist) the X11/AWT one -> AWT Component
registerFactory(ReflectionUtil.getClass(ReflectionUtil.AWTNames.ComponentClass, false, cl), factory);
}
-
- if( TYPE_X11 == nativeWindowingTypePure ) {
- // passing through RuntimeException if not exists intended
- x11ToolkitLockClass = ReflectionUtil.getClass(X11ToolkitLockClassName, false, cl);
- x11ToolkitLockConstructor = ReflectionUtil.getConstructor(x11ToolkitLockClass, new Class[] { long.class } );
- if( isAWTAvailable() ) {
- x11JAWTToolkitLockClass = ReflectionUtil.getClass(X11JAWTToolkitLockClassName, false, cl);
- x11JAWTToolkitLockConstructor = ReflectionUtil.getConstructor(x11JAWTToolkitLockClass, new Class[] { long.class } );
- }
- }
if(DEBUG) {
System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock);
@@ -300,6 +283,7 @@ public abstract class NativeWindowFactory {
GraphicsConfigurationFactory.shutdown();
}
shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
+ // SharedResourceToolkitLock.shutdown(DEBUG); // not used yet
if(DEBUG) {
System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
}
@@ -358,16 +342,9 @@ public abstract class NativeWindowFactory {
/**
* Provides the default {@link ToolkitLock} for <code>type</code>, a singleton instance.
- * <br>
* <ul>
- * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li>
- * <ul>
- * <li>If <b>AWT-type</b> and <b>native-X11-type</b> and <b>AWT-available</b></li>
- * <ul>
- * <li> return {@link #getAWTToolkitLock()} </li>
- * </ul>
- * </ul>
- * <li> Otherwise return {@link #getNullToolkitLock()} </li>
+ * <li> JAWT {@link ToolkitLock} if required and AWT available, otherwise</li>
+ * <li> {@link jogamp.nativewindow.NullToolkitLock} </li>
* </ul>
*/
public static ToolkitLock getDefaultToolkitLock(String type) {
@@ -390,84 +367,36 @@ public abstract class NativeWindowFactory {
/**
* Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>.
- * <br>
* <ul>
- * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li>
- * <ul>
- * <li>If <b>X11 type</b> </li>
- * <ul>
- * <li> return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li>
- * </ul>
- * </ul>
- * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li>
+ * <li> {@link jogamp.nativewindow.ResourceToolkitLock} if required, otherwise</li>
+ * <li> {@link jogamp.nativewindow.NullToolkitLock} </li>
* </ul>
*/
public static ToolkitLock createDefaultToolkitLock(String type, long deviceHandle) {
if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- return createX11ToolkitLock(deviceHandle);
- }
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
/**
* Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>.
- * <br>
* <ul>
- * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li>
- * <ul>
- * <li>If <b>X11 type</b> </li>
- * <ul>
- * <li> If <b>shared-AWT-type</b> and <b>AWT available</b> </li>
- * <ul>
- * <li> return {@link jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock} </li>
- * </ul>
- * <li> else return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li>
- * </ul>
- * </ul>
- * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li>
+ * <li> JAWT {@link ToolkitLock} if required and AWT available,</li>
+ * <li> {@link jogamp.nativewindow.ResourceToolkitLock} if required, otherwise</li>
+ * <li> {@link jogamp.nativewindow.NullToolkitLock} </li>
* </ul>
*/
public static ToolkitLock createDefaultToolkitLock(String type, String sharedType, long deviceHandle) {
if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- if( TYPE_AWT == sharedType && isAWTAvailable() ) {
- return createX11AWTToolkitLock(deviceHandle);
- }
- return createX11ToolkitLock(deviceHandle);
+ if( TYPE_AWT == sharedType && isAWTAvailable() ) {
+ return getAWTToolkitLock();
}
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
-
- protected static ToolkitLock createX11AWTToolkitLock(long deviceHandle) {
- try {
- if(DEBUG) {
- System.err.println("NativeWindowFactory.createX11AWTToolkitLock(0x"+Long.toHexString(deviceHandle)+")");
- // Thread.dumpStack();
- }
- return (ToolkitLock) x11JAWTToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- protected static ToolkitLock createX11ToolkitLock(long deviceHandle) {
- try {
- return (ToolkitLock) x11ToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
-
+
/** Returns the appropriate NativeWindowFactory to handle window
objects of the given type. The windowClass might be {@link
NativeWindow NativeWindow}, in which case the client has
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
index 30f9660f0..18b7cf5d9 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
@@ -33,12 +33,26 @@ import jogamp.nativewindow.Debug;
/**
* Marker for a singleton global recursive blocking lock implementation,
* optionally locking a native windowing toolkit as well.
- * <br>
- * One use case is the AWT locking on X11, see {@link jogamp.nativewindow.jawt.JAWTToolkitLock}.
+ * <p>
+ * Toolkit locks are created solely via {@link NativeWindowFactory}.
+ * </p>
+ * <p>
+ * One use case is the AWT locking on X11, see {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}.
+ * </p>
*/
public interface ToolkitLock {
public static final boolean TRACE_LOCK = Debug.isPropertyDefined("nativewindow.debug.ToolkitLock.TraceLock", true);
public void lock();
public void unlock();
+
+ /**
+ * Dispose this instance.
+ * <p>
+ * Shall be called when instance is no more required.
+ * </p>
+ * This allows implementations sharing a lock via resources
+ * to decrease the reference counter.
+ */
+ public void dispose();
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
index 1af6bf279..e59910138 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
@@ -50,4 +50,13 @@ public class NullToolkitLock implements ToolkitLock {
public final void unlock() {
if(TRACE_LOCK) { System.err.println("NullToolkitLock.unlock()"); }
}
+
+ public final void dispose() {
+ // nop
+ }
+
+ public String toString() {
+ return "NullToolkitLock[]";
+ }
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java
index 5166ef577..a3b0804fa 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,7 +25,8 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package jogamp.nativewindow.x11;
+
+package jogamp.nativewindow;
import javax.media.nativewindow.ToolkitLock;
@@ -33,38 +34,41 @@ import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
/**
- * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock}
- * utilizing {@link X11Util#XLockDisplay(long)}.
- * <br>
- * This strategy should not be used in case XInitThreads() is being used,
- * or a higher level toolkit lock is required, ie AWT lock.
+ * Implementing a resource based recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * A resource handle maybe used within a unique object
+ * and can be synchronized across threads via an instance of ResourceToolkitLock.
+ * </p>
*/
-public class X11ToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
-
- public X11ToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
+public class ResourceToolkitLock implements ToolkitLock {
+ public static final boolean DEBUG = Debug.debug("ToolkitLock");
+
+ public static final ResourceToolkitLock create() {
+ return new ResourceToolkitLock();
}
+ private final RecursiveLock lock;
+
+ private ResourceToolkitLock() {
+ this.lock = LockFactory.createRecursiveLock();
+ }
+
+
public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
- }
+ if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.lock()"); }
+ lock.lock();
}
public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
+ if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.unlock()"); }
+ lock.unlock();
+ }
+
+ public final void dispose() {
+ // nop
+ }
+
+ public String toString() {
+ return "ResourceToolkitLock[obj 0x"+Integer.toHexString(hashCode())+", isOwner "+lock.isOwner(Thread.currentThread())+", "+lock.toString()+"]";
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
new file mode 100644
index 000000000..5d7ae8abb
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
@@ -0,0 +1,141 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import java.util.Iterator;
+
+import javax.media.nativewindow.ToolkitLock;
+
+import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+/**
+ * Implementing a shared resource based recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * A resource handle maybe used within many objects
+ * and can be synchronized across threads via an unique instance of SharedResourceToolkitLock.
+ * </p>
+ * <p>
+ * Implementation holds a synchronized map from handle to reference counted {@link SharedResourceToolkitLock}.
+ * New elements are added via {@link #get(long)} if new
+ * and removed via {@link #dispose()} if no more referenced.
+ * </p>
+ */
+public class SharedResourceToolkitLock implements ToolkitLock {
+ public static final boolean DEBUG = Debug.debug("ToolkitLock");
+ private static final LongObjectHashMap handle2Lock;
+ static {
+ handle2Lock = new LongObjectHashMap();
+ handle2Lock.setKeyNotFoundValue(null);
+ }
+
+ /**
+ * @return number of unclosed EGL Displays.<br>
+ */
+ public static int shutdown(boolean verbose) {
+ if(DEBUG || verbose || handle2Lock.size() > 0 ) {
+ System.err.println("SharedResourceToolkitLock: Shutdown (open: "+handle2Lock.size()+")");
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ if( handle2Lock.size() > 0) {
+ dumpOpenDisplayConnections();
+ }
+ }
+ return handle2Lock.size();
+ }
+
+ public static void dumpOpenDisplayConnections() {
+ System.err.println("SharedResourceToolkitLock: Open ResourceToolkitLock's: "+handle2Lock.size());
+ int i=0;
+ for(Iterator<LongObjectHashMap.Entry> iter = handle2Lock.iterator(); iter.hasNext(); i++) {
+ final LongObjectHashMap.Entry e = iter.next();
+ System.err.println("SharedResourceToolkitLock: Open["+i+"]: "+e.value);
+ }
+ }
+
+ public static final SharedResourceToolkitLock get(long handle) {
+ SharedResourceToolkitLock res;
+ synchronized(handle2Lock) {
+ res = (SharedResourceToolkitLock) handle2Lock.get(handle);
+ if( null == res ) {
+ res = new SharedResourceToolkitLock(handle);
+ res.refCount++;
+ handle2Lock.put(handle, res);
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.get() * NEW *: "+res); }
+ } else {
+ res.refCount++;
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.get() * EXIST *: "+res); }
+ }
+ }
+ return res;
+ }
+
+ private final RecursiveLock lock;
+ private final long handle;
+ private volatile int refCount;
+
+ private SharedResourceToolkitLock(long handle) {
+ this.lock = LockFactory.createRecursiveLock();
+ this.handle = handle;
+ this.refCount = 0;
+ }
+
+
+ public final void lock() {
+ if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.lock()"); }
+ lock.lock();
+ }
+
+ public final void unlock() {
+ if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.unlock()"); }
+ lock.unlock();
+ }
+
+ public final void dispose() {
+ if(0 < refCount) { // volatile OK
+ synchronized(handle2Lock) {
+ refCount--;
+ if(0 == refCount) {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * REMOV *: "+this); }
+ handle2Lock.remove(handle);
+ } else {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * DOWN *: "+this); }
+ }
+ }
+ } else {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * NULL *: "+this); }
+ }
+ }
+
+ public String toString() {
+ return "SharedResourceToolkitLock[refCount "+refCount+", handle 0x"+Long.toHexString(handle)+", obj 0x"+Integer.toHexString(hashCode())+", isOwner "+lock.isOwner(Thread.currentThread())+", "+lock.toString()+"]";
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
index f1e8a786a..7c934b154 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
@@ -237,6 +237,9 @@ public class JAWTUtil {
public final void unlock() {
JAWTUtil.unlockToolkit();
}
+ public final void dispose() {
+ // nop
+ }
};
// trigger native AWT toolkit / properties initialization
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java
deleted file mode 100644
index 743d371b7..000000000
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package jogamp.nativewindow.jawt.x11;
-
-import jogamp.nativewindow.jawt.*;
-import jogamp.nativewindow.x11.X11Lib;
-import jogamp.nativewindow.x11.X11Util;
-import javax.media.nativewindow.ToolkitLock;
-
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-
-/**
- * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock}
- * utilizing JAWT's AWT lock via {@link JAWTUtil#lockToolkit()} and {@link X11Util#XLockDisplay(long)}.
- * <br>
- * This strategy should only be used if AWT is using the underlying native windowing toolkit
- * in a not intrinsic thread safe manner, e.g. under X11 where no XInitThreads() call
- * is issued before any other X11 usage. This is the current situation for e.g. Webstart or Applets.
- */
-public class X11JAWTToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
-
- public X11JAWTToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
- }
-
- public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.lock() - native: "+(null==lock)); }
- JAWTUtil.lockToolkit();
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
- }
- }
-
- public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
- JAWTUtil.unlockToolkit();
- }
-}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
index 736718de8..467809284 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
@@ -127,7 +127,8 @@ public class X11JAWTWindow extends JAWTWindow {
}
protected Point getLocationOnScreenNativeImpl(int x, int y) {
- return X11Lib.GetRelativeLocation( getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ // surface is locked and hence the device
+ return X11Lib.GetRelativeLocation(getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
}
// Variables for lockSurface/unlockSurface
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 2ea75c7fb..60f54eb3c 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -42,8 +42,8 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
-
import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
/**
* Contains a thread safe X11 utility to retrieve display connections.
@@ -80,25 +80,15 @@ public class X11Util {
*/
public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
- /** Value is <code>true</code>, best 'stable' results if always using XInitThreads(). */
- public static final boolean XINITTHREADS_ALWAYS_ENABLED = true;
-
- /** Value is <code>true</code>, best 'stable' results if not using XLockDisplay/XUnlockDisplay at all. */
- public static final boolean HAS_XLOCKDISPLAY_BUG = true;
-
public static final boolean DEBUG = Debug.debug("X11Util");
public static final boolean XSYNC_ENABLED = Debug.isPropertyDefined("nativewindow.debug.X11Util.XSync", true);
public static final boolean XERROR_STACKDUMP = DEBUG || Debug.isPropertyDefined("nativewindow.debug.X11Util.XErrorStackDump", true);
private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.isPropertyDefined("nativewindow.debug.X11Util.TraceDisplayLifecycle", true);
private static String nullDisplayName = null;
- private static boolean isX11LockAvailable = false;
- private static boolean requiresX11Lock = true;
private static volatile boolean isInit = false;
private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues
- private static int setX11ErrorHandlerRecCount = 0;
private static Object setX11ErrorHandlerLock = new Object();
-
/**
* Called by {@link NativeWindowFactory#initSingleton()}
@@ -115,9 +105,7 @@ public class X11Util {
throw new NativeWindowException("NativeWindow X11 native library load error.");
}
- final boolean callXInitThreads = XINITTHREADS_ALWAYS_ENABLED ;
- final boolean isXInitThreadsOK = initialize0( callXInitThreads, XERROR_STACKDUMP);
- isX11LockAvailable = isXInitThreadsOK && !HAS_XLOCKDISPLAY_BUG ;
+ final boolean isInitOK = initialize0( XERROR_STACKDUMP );
final long dpy = X11Lib.XOpenDisplay(null);
if(0 != dpy) {
@@ -134,9 +122,7 @@ public class X11Util {
}
if(DEBUG) {
- System.err.println("X11Util requiresX11Lock "+requiresX11Lock+
- ", XInitThreads [called "+callXInitThreads+", OK "+isXInitThreadsOK+"]"+
- ", isX11LockAvailable "+isX11LockAvailable+
+ System.err.println("X11Util init OK "+isInitOK+"]"+
", X11 Display(NULL) <"+nullDisplayName+">"+
", XSynchronize Enabled: "+XSYNC_ENABLED);
// Thread.dumpStack();
@@ -199,31 +185,14 @@ public class X11Util {
}
}
}
-
- public static synchronized boolean isNativeLockAvailable() {
- return isX11LockAvailable;
- }
-
- public static synchronized boolean requiresToolkitLock() {
- return requiresX11Lock;
+
+ public static boolean requiresToolkitLock() {
+ return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock.
}
-
+
public static void setX11ErrorHandler(boolean onoff, boolean quiet) {
synchronized(setX11ErrorHandlerLock) {
- if(onoff) {
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(true, quiet);
- }
- setX11ErrorHandlerRecCount++;
- } else {
- if(0 >= setX11ErrorHandlerRecCount) {
- throw new InternalError();
- }
- setX11ErrorHandlerRecCount--;
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(false, false);
- }
- }
+ setX11ErrorHandler0(onoff, quiet);
}
}
@@ -492,52 +461,50 @@ public class X11Util {
*******************************/
public static long XOpenDisplay(String arg0) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
- try {
- long handle = X11Lib.XOpenDisplay(arg0);
- if(XSYNC_ENABLED && 0 != handle) {
- X11Lib.XSynchronize(handle, true);
- }
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
- // Thread.dumpStack();
- }
- return handle;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ long handle = X11Lib.XOpenDisplay(arg0);
+ if(XSYNC_ENABLED && 0 != handle) {
+ X11Lib.XSynchronize(handle, true);
+ }
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
+ // Thread.dumpStack();
}
+ return handle;
}
public static int XCloseDisplay(long display) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
+ // Thread.dumpStack();
+ }
+ int res = -1;
try {
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
- // Thread.dumpStack();
- }
- int res = -1;
- X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
- try {
- res = X11Lib.XCloseDisplay(display);
- } catch (Exception ex) {
- System.err.println("X11Util: Catched Exception:");
- ex.printStackTrace();
- } finally {
- X11Util.setX11ErrorHandler(false, false);
- }
- return res;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ res = X11Lib.XCloseDisplay(display);
+ } catch (Exception ex) {
+ System.err.println("X11Util: Catched Exception:");
+ ex.printStackTrace();
}
+ return res;
}
static volatile boolean XineramaFetched = false;
static long XineramaLibHandle = 0;
static long XineramaQueryFunc = 0;
- public static boolean XineramaIsEnabled(long display) {
- if(0==display) {
- throw new IllegalArgumentException("Display NULL");
+ public static boolean XineramaIsEnabled(X11GraphicsDevice device) {
+ if(null == device) {
+ throw new IllegalArgumentException("X11 Display device is NULL");
+ }
+ device.lock();
+ try {
+ return XineramaIsEnabled(device.getHandle());
+ } finally {
+ device.unlock();
+ }
+ }
+ public static boolean XineramaIsEnabled(long displayHandle) {
+ if( 0 == displayHandle ) {
+ throw new IllegalArgumentException("X11 Display handle is NULL");
}
if(!XineramaFetched) { // volatile: ok
synchronized(X11Util.class) {
@@ -551,9 +518,9 @@ public class X11Util {
}
}
if(0!=XineramaQueryFunc) {
- final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, display);
+ final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, displayHandle);
if(DEBUG) {
- System.err.println("XineramaIsEnabled: "+res);
+ System.err.println("XineramaIsEnabled: 0x"+Long.toHexString(displayHandle)+": "+res);
}
return res;
} else if(DEBUG) {
@@ -566,7 +533,7 @@ public class X11Util {
private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
- private static native boolean initialize0(boolean firstUIActionOnProcess, boolean debug);
+ private static native boolean initialize0(boolean debug);
private static native void shutdown0();
private static native void setX11ErrorHandler0(boolean onoff, boolean quiet);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
index 1de03e8be..b152f0f97 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
@@ -91,7 +91,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device);
final long displayHandle;
- boolean owner = false;
+ final boolean owner;
if(0==displayHandleAWT) {
displayHandle = X11Util.openDisplay(null);
owner = true;
@@ -112,9 +112,8 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
System.err.println(getThreadName()+" - X11AWTGraphicsConfigurationFactory: AWT dpy "+displayName+" / "+toHexString(displayHandleAWT)+", create X11 display "+toHexString(displayHandle));
}
}
- final ToolkitLock lock = owner ?
- NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT) : // own non-shared X11 display connection, no X11 lock
- NativeWindowFactory.createDefaultToolkitLock(NativeWindowFactory.TYPE_X11, NativeWindowFactory.TYPE_AWT, displayHandle);
+ // Global JAWT lock required - No X11 resource locking due to private display connection
+ final ToolkitLock lock = NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT);
final X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, lock, owner);
final X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex());
if(DEBUG) {