diff options
author | Sven Gothel <[email protected]> | 2012-09-27 17:33:39 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-09-27 17:33:39 +0200 |
commit | fbe331f013608eb31ff0d8675f4e4c9881c9c48b (patch) | |
tree | 535aae61f299884ce6b61d026a60ed0546e9703b /src/nativewindow/classes/javax | |
parent | ba846a478d616327817dd530dbdcd9a786be5b7a (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/javax')
4 files changed, 33 insertions, 89 deletions
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(); } |