diff options
5 files changed, 118 insertions, 79 deletions
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index bbc915f2c..adc946f70 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -195,10 +195,9 @@ public abstract class NativeWindowFactory { final ClassLoader cl = NativeWindowFactory.class.getClassLoader(); - if(firstUIActionOnProcess) { - // X11 initialization before possible AWT initialization - initNativeImpl(true, cl); - } + // X11 initialization before possible AWT initialization + initNativeImpl(firstUIActionOnProcess, cl); + isAWTAvailable = false; // may be set to true below if( !Debug.getBooleanProperty("java.awt.headless", true, acc) && @@ -230,10 +229,6 @@ public abstract class NativeWindowFactory { } } } - if(!firstUIActionOnProcess) { - // X11 initialization after possible AWT initialization - initNativeImpl(false, cl); - } registeredFactories = Collections.synchronizedMap(new HashMap<Class<?>, NativeWindowFactory>()); // register our default factory -> NativeWindow @@ -324,31 +319,30 @@ public abstract class NativeWindowFactory { * <ul> * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li> * <ul> - * <li>If native <b>X11 type</b> with or w/o AWT</li> - * <ul> - * <li> If <b>AWT available</b> </li> + * <li>If <b>AWT-type</b> and <b>native-X11-type</b> and <b>AWT-available</b></li> * <ul> * <li> return {@link jogamp.nativewindow.jawt.JAWTToolkitLock} </li> * </ul> - * </ul> * </ul> * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li> * </ul> */ - /* package */ static ToolkitLock getDefaultToolkitLock(String type) { + public static ToolkitLock getDefaultToolkitLock(String type) { if( requiresToolkitLock() ) { - if( TYPE_X11 == type || TYPE_AWT == type && TYPE_X11 == getNativeWindowType(false) ) { - if( isAWTAvailable() ) { - return getAWTToolkitLock(); - } + if( TYPE_AWT == type && TYPE_X11 == getNativeWindowType(false) && isAWTAvailable() ) { + return getAWTToolkitLock(); } } return NativeWindowFactoryImpl.getNullToolkitLock(); } - /* package */ static ToolkitLock getAWTToolkitLock() { + private static ToolkitLock getAWTToolkitLock() { Object resO = ReflectionUtil.callMethod(null, jawtUtilGetJAWTToolkitMethod); + if(DEBUG) { + System.err.println("NativeWindowFactory.getAWTToolkitLock()"); + Thread.dumpStack(); + } if(resO instanceof ToolkitLock) { return (ToolkitLock) resO; } else { @@ -368,26 +362,49 @@ public abstract class NativeWindowFactory { * <ul> * <li>If <b>X11 type</b> </li> * <ul> - * <li> If <b>AWT available</b> </li> + * <li> return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li> + * </ul> + * </ul> + * <li> Otherwise return {@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 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> If <b>AWT not available</b> </li> - * <ul> - * <li> return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li> - * </ul> + * <li> else return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li> * </ul> * </ul> * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li> * </ul> */ - public static ToolkitLock createDefaultToolkitLock(String type, long deviceHandle) { + 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( isAWTAvailable() ) { + if( TYPE_AWT == sharedType && isAWTAvailable() ) { return createX11AWTToolkitLock(deviceHandle); } return createX11ToolkitLock(deviceHandle); @@ -398,6 +415,10 @@ public abstract class NativeWindowFactory { 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); diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java index 5d4fa0dad..94a71f5e6 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java @@ -31,6 +31,9 @@ import jogamp.nativewindow.jawt.*; 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)}. @@ -41,20 +44,32 @@ import javax.media.nativewindow.ToolkitLock; */ 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()"); } + if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.lock() - native: "+(null==lock)); } JAWTUtil.lockToolkit(); - X11Util.XLockDisplay(displayHandle); + if(null == lock) { + X11Util.XLockDisplay(displayHandle); + } else { + lock.lock(); + } } public final void unlock() { - if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.unlock()"); } - X11Util.XUnlockDisplay(displayHandle); + if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.unlock() - native: "+(null==lock)); } + if(null == lock) { + X11Util.XUnlockDisplay(displayHandle); + } else { + lock.unlock(); + } JAWTUtil.unlockToolkit(); } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java index fb0aff10d..974211261 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java @@ -29,6 +29,9 @@ package jogamp.nativewindow.x11; 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 {@link X11Util#XLockDisplay(long)}. @@ -38,18 +41,30 @@ import javax.media.nativewindow.ToolkitLock; */ public class X11ToolkitLock implements ToolkitLock { long displayHandle; + RecursiveLock lock; public X11ToolkitLock(long displayHandle) { this.displayHandle = displayHandle; + if(!X11Util.isNativeLockAvailable()) { + lock = LockFactory.createRecursiveLock(); + } } public final void lock() { - if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock()"); } - X11Util.XLockDisplay(displayHandle); + if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock() - native: "+(null==lock)); } + if(null == lock) { + X11Util.XLockDisplay(displayHandle); + } else { + lock.lock(); + } } public final void unlock() { - if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock()"); } - X11Util.XUnlockDisplay(displayHandle); + if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock() - native: "+(null==lock)); } + if(null == lock) { + X11Util.XUnlockDisplay(displayHandle); + } else { + lock.unlock(); + } } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java index 0fd14bc6e..211967b5c 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java @@ -34,6 +34,7 @@ package jogamp.nativewindow.x11; import com.jogamp.common.util.LongObjectHashMap; + import jogamp.nativewindow.Debug; import jogamp.nativewindow.NWJNILibLoader; @@ -66,13 +67,12 @@ public class X11Util { */ public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = true; - public static final boolean XINITTHREADS_ALWAYS_ENABLED = true; - private static final boolean DEBUG = Debug.debug("X11Util"); private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.getBooleanProperty("nativewindow.debug.X11Util.TraceDisplayLifecycle", true, AccessController.getContext()); private static volatile String nullDisplayName = null; - private static boolean requiresX11Lock = false; + private static boolean isX11LockAvailable = false; + private static boolean requiresX11Lock = true; private static boolean isInit = false; private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues @@ -84,25 +84,22 @@ public class X11Util { if(!isInit) { NWJNILibLoader.loadNativeWindow("x11"); - /** - * Always issue XInitThreads() since we have independent - * off-thread created Display connections able to utilize multithreading, - * ie NEWT (jogamp.newt.x11.X11Display.createNativeImpl()) !! - */ - initialize0( XINITTHREADS_ALWAYS_ENABLED ? true : firstX11ActionOnProcess ); + isX11LockAvailable = initialize0( firstX11ActionOnProcess ); - requiresX11Lock = !firstX11ActionOnProcess ; - if(DEBUG) { System.err.println("X11Util firstX11ActionOnProcess: "+firstX11ActionOnProcess+ - ", XINITTHREADS_ALWAYS_ENABLED "+XINITTHREADS_ALWAYS_ENABLED+ - ", requiresX11Lock "+requiresX11Lock); - // Thread.dumpStack(); + ", requiresX11Lock "+requiresX11Lock+ + ", isX11LockAvailable "+isX11LockAvailable); + Thread.dumpStack(); } isInit = true; } } + public static synchronized boolean isNativeLockAvailable() { + return isX11LockAvailable; + } + public static synchronized boolean requiresToolkitLock() { return requiresX11Lock; } @@ -127,16 +124,18 @@ public class X11Util { } public static void lockDefaultToolkit(long dpyHandle) { - NativeWindowFactory.getDefaultToolkitLock().lock(); - if(requiresX11Lock) { - X11Util.XLockDisplay(dpyHandle); + if(ToolkitLock.TRACE_LOCK) { + System.out.println("+++ X11 Display lockDefaultToolkit [x11Lock: "+isX11LockAvailable+"] get 0x"+Long.toHexString(dpyHandle)); } + NativeWindowFactory.getDefaultToolkitLock().lock(); + X11Util.XLockDisplay(dpyHandle); } public static void unlockDefaultToolkit(long dpyHandle) { - if(requiresX11Lock) { - X11Util.XUnlockDisplay(dpyHandle); + if(ToolkitLock.TRACE_LOCK) { + System.out.println("+++ X11 Display lockDefaultToolkit [x11Lock: "+isX11LockAvailable+"] rel 0x"+Long.toHexString(dpyHandle)); } + X11Util.XUnlockDisplay(dpyHandle); NativeWindowFactory.getDefaultToolkitLock().unlock(); } @@ -225,7 +224,6 @@ public class X11Util { public final void setUncloseable(boolean v) { unCloseable = v; } public final boolean isUncloseable() { return unCloseable; } - public final Throwable getCreationStack() { return creationStack; } @Override @@ -245,14 +243,11 @@ public class X11Util { public static int shutdown(boolean realXCloseOpenAndPendingDisplays, boolean verbose) { int num=0; if(DEBUG||verbose||pendingDisplayList.size() > 0) { - String msg = "X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+ - ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+ - ", pending (not closed, marked uncloseable): "+pendingDisplayList.size()+")" ; + System.err.println("X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+ + ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+ + ", pending (not closed, marked uncloseable): "+pendingDisplayList.size()+")"); if(DEBUG) { - Exception e = new Exception(msg); - e.printStackTrace(); - } else { - System.err.println(msg); + Thread.dumpStack(); } if( openDisplayList.size() > 0) { X11Util.dumpOpenDisplayConnections(); @@ -385,8 +380,8 @@ public class X11Util { } } if(DEBUG) { - Exception e = new Exception("X11Util.Display: openDisplay [reuse "+reused+"] "+namedDpy+". Thread "+Thread.currentThread().getName()); - e.printStackTrace(); + System.err.println("X11Util.Display: openDisplay [reuse "+reused+"] "+namedDpy+". Thread "+Thread.currentThread().getName()); + // Thread.dumpStack(); } return namedDpy.getHandle(); } @@ -409,10 +404,6 @@ public class X11Util { if(!openDisplayList.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); } if(!namedDpy.isUncloseable()) { - if(DEBUG) { - System.err.println("X11Util.Display: XCloseDisplay "+namedDpy+". Thread "+Thread.currentThread().getName()); - Thread.dumpStack(); - } XCloseDisplay(namedDpy.getHandle()); } else { // for reuse @@ -456,8 +447,8 @@ public class X11Util { try { long handle = X11Lib.XOpenDisplay(arg0); if(TRACE_DISPLAY_LIFECYCLE) { - Throwable t = new Throwable(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle)); - t.printStackTrace(); + System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle)); + // Thread.dumpStack(); } return handle; } finally { @@ -469,8 +460,8 @@ public class X11Util { NativeWindowFactory.getDefaultToolkitLock().lock(); try { if(TRACE_DISPLAY_LIFECYCLE) { - Throwable t = new Throwable(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display)); - t.printStackTrace(); + System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display)); + // Thread.dumpStack(); } int res = -1; X11Util.setX11ErrorHandler(true, DEBUG ? false : true); @@ -678,19 +669,13 @@ public class X11Util { } public static void XLockDisplay(long handle) { - if(ToolkitLock.TRACE_LOCK) { - System.out.println("+++ X11 Display Lock get 0x"+Long.toHexString(handle)); - } X11Lib.XLockDisplay(handle); - } + } public static void XUnlockDisplay(long handle) { - if(ToolkitLock.TRACE_LOCK) { - System.out.println("--- X11 Display Lock rel 0x"+Long.toHexString(handle)); - } X11Lib.XUnlockDisplay(handle); } - private static native void initialize0(boolean firstUIActionOnProcess); + private static native boolean initialize0(boolean firstUIActionOnProcess); private static native void setX11ErrorHandler0(boolean onoff, boolean quiet); } diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c index d481343f9..8b56bca90 100644 --- a/src/nativewindow/native/x11/Xmisc.c +++ b/src/nativewindow/native/x11/Xmisc.c @@ -293,14 +293,16 @@ static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) { } static int _initialized=0; +static jboolean _xinitThreadsOK=JNI_FALSE; -JNIEXPORT void JNICALL +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass _unused, jboolean firstUIActionOnProcess) { if(0==_initialized) { if( JNI_TRUE == firstUIActionOnProcess ) { if( 0 == XInitThreads() ) { fprintf(stderr, "Warning: XInitThreads() failed\n"); } else { + _xinitThreadsOK=JNI_TRUE; fprintf(stderr, "Info: XInitThreads() called for concurrent Thread support\n"); } } else { @@ -311,6 +313,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass _unused, jb x11IOErrorHandlerEnable(1, env); _initialized=1; } + return _xinitThreadsOK; } JNIEXPORT void JNICALL |