diff options
author | Sven Gothel <[email protected]> | 2012-09-30 19:47:46 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-09-30 19:47:46 +0200 |
commit | 92398025abdabb2fdef0d78edd41e730991a6f94 (patch) | |
tree | 8d209c588d1246aa126c29465206ba1f8167c0e2 /src/nativewindow/classes/javax/media | |
parent | 43891be36e8485353ac74f329fd2f7438303a846 (diff) |
Workaround for Bug 623: Sporadic XCB assertion failures w/ ATI proprietary driver and w/o native X11 locking
The proprietary ATI X11 driver does not handle multi-threaded [GL] clients well,
i.e. triggers an XCB assertion 'from time to time'.
It almost seems like that the driver either:
- aliases all display connections to it's connection name, i.e. server; or
- utilizes a build-in display connection w/o locking, used for some reason
+++
- X11Lib: Add QueryExtension(dpy, name) allowing early driver determination w/o GL
- X11Util detects 'requiresGlobalToolkitLock' and 'markAllDisplaysUnclosable' via
X11 extensions. In case certain ATI extensions are available, both are set to true.
- X11GLXDrawableFactory: Dropped setting 'markAllDisplaysUnclosable', using X11Util's detection (see above).
- New GlobalToolkitLock to satisfy certain driver restrictions (ATI's XCB multithreading bug)
- NativeWindowFactory handles new property requiresGlobalToolkitLock,
in which case the new GlobalToolkitLock is being used instead of ResourceToolkitLock.
- JAWTUtil ToolkitLock locks GlobalToolkitLock 1st to match new 'requiresGlobalToolkitLock' property.
- Document static method requirement of X11Util, GDIUtil and OSXUtil via marker interface ToolkitProperties
- ToolkitLock: New method 'validateLocked()', allowing use to validate whether the device/toolkit
is properly locked and hence to detect implementation bugs. See unit test class: ValidateLockListener
Diffstat (limited to 'src/nativewindow/classes/javax/media')
4 files changed, 107 insertions, 48 deletions
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index 5eaaa6613..8ecd5242d 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -102,17 +102,24 @@ public interface AbstractGraphicsDevice extends Cloneable { public long getHandle(); /** - * Optionally locking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}. + * Optionally locking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock#lock()}. * The lock implementation must be recursive. */ public void lock(); /** - * Optionally unlocking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}. + * Optionally unlocking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock#unlock()}. * The lock implementation must be recursive. + * + * @throws RuntimeException in case the lock is not acquired by this thread. */ public void unlock(); + /** + * @throws RuntimeException if current thread does not hold the lock + */ + public void validateLocked() throws RuntimeException; + /** * Optionally [re]opening the device if handle is <code>null</code>. * <p> diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index b16b0c75c..9288652d9 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -60,7 +60,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice /** * Create an instance with the system default {@link ToolkitLock}. - * gathered via {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}. + * gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. * @param type * @param handle */ @@ -70,7 +70,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice this.unitID = unitID; this.uniqueID = getUniqueID(type, connection, unitID); this.handle = handle; - this.toolkitLock = NativeWindowFactory.createDefaultToolkitLock(type, handle); + this.toolkitLock = NativeWindowFactory.getDefaultToolkitLock(type, handle); } /** @@ -123,8 +123,10 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } /** - * No lock is performed on the graphics device per default, - * instead the aggregated recursive {@link ToolkitLock#lock()} is invoked. + * {@inheritDoc} + * <p> + * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}. + * </p> * * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) @@ -134,9 +136,16 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice toolkitLock.lock(); } + @Override + public final void validateLocked() throws RuntimeException { + toolkitLock.validateLocked(); + } + /** - * No lock is performed on the graphics device per default, - * instead the aggregated recursive {@link ToolkitLock#unlock()} is invoked. + * {@inheritDoc} + * <p> + * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}. + * </p> * * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index 4f4bb629b..af8008f0f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -42,6 +42,7 @@ import java.util.Map; import jogamp.nativewindow.Debug; import jogamp.nativewindow.NativeWindowFactoryImpl; +import jogamp.nativewindow.ToolkitProperties; import jogamp.nativewindow.ResourceToolkitLock; import com.jogamp.common.os.Platform; @@ -87,13 +88,17 @@ public abstract class NativeWindowFactory { private static boolean isAWTAvailable; private static final String JAWTUtilClassName = "jogamp.nativewindow.jawt.JAWTUtil" ; + /** {@link jogamp.nativewindow.x11.X11Util} implements {@link ToolkitProperties}. */ private static final String X11UtilClassName = "jogamp.nativewindow.x11.X11Util"; + /** {@link jogamp.nativewindow.macosx.OSXUtil} implements {@link ToolkitProperties}. */ private static final String OSXUtilClassName = "jogamp.nativewindow.macosx.OSXUtil"; + /** {@link jogamp.nativewindow.windows.GDIUtil} implements {@link ToolkitProperties}. */ private static final String GDIClassName = "jogamp.nativewindow.windows.GDIUtil"; private static ToolkitLock jawtUtilJAWTToolkitLock; private static boolean requiresToolkitLock; + private static boolean requiresGlobalToolkitLock; private static volatile boolean isJVMShuttingDown = false; @@ -156,11 +161,18 @@ public abstract class NativeWindowFactory { if( null != clazzName ) { ReflectionUtil.callStaticMethod(clazzName, "initSingleton", null, null, cl ); - final Boolean res = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl); - requiresToolkitLock = res.booleanValue(); + final Boolean res1 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl); + requiresToolkitLock = res1.booleanValue(); + if(requiresToolkitLock) { + final Boolean res2 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresGlobalToolkitLock", null, null, cl); + requiresGlobalToolkitLock = res2.booleanValue(); + } else { + requiresGlobalToolkitLock = false; + } } else { requiresToolkitLock = false; - } + requiresGlobalToolkitLock = false; + } } private static void shutdownNativeImpl(final ClassLoader cl) { @@ -261,7 +273,7 @@ public abstract class NativeWindowFactory { } if(DEBUG) { - System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock); + System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock+", requiresGlobalToolkitLock "+requiresGlobalToolkitLock); System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+", defaultFactory "+factory); } @@ -295,7 +307,12 @@ public abstract class NativeWindowFactory { /** @return true if the underlying toolkit requires locking, otherwise false. */ public static boolean requiresToolkitLock() { return requiresToolkitLock; - } + } + + /** @return true if the underlying toolkit requires global locking, otherwise false. */ + public static boolean requiresGlobalToolkitLock() { + return requiresGlobalToolkitLock; + } /** @return true if not headless, AWT Component and NativeWindow's AWT part available */ public static boolean isAWTAvailable() { return isAWTAvailable; } @@ -331,9 +348,28 @@ public abstract class NativeWindowFactory { return defaultFactory; } + /** + * Returns the AWT {@link ToolkitLock} (JAWT based) if {@link #isAWTAvailable}, otherwise null. + * <p> + * The JAWT based {@link ToolkitLock} also locks the global lock, + * which matters if the latter is required. + * </p> + */ + public static ToolkitLock getAWTToolkitLock() { + return jawtUtilJAWTToolkitLock; + } + + public static ToolkitLock getNullToolkitLock() { + return NativeWindowFactoryImpl.getNullToolkitLock(); + } + + public static ToolkitLock getGlobalToolkitLock() { + return NativeWindowFactoryImpl.getGlobalToolkitLock(); + } + /** - * Provides the system default {@link ToolkitLock}, a singleton instance. - * <br> + * Provides the system default {@link ToolkitLock} for the default system windowing type. + * @see #getNativeWindowType(boolean) * @see #getDefaultToolkitLock(java.lang.String) */ public static ToolkitLock getDefaultToolkitLock() { @@ -341,57 +377,44 @@ public abstract class NativeWindowFactory { } /** - * Provides the default {@link ToolkitLock} for <code>type</code>, a singleton instance. + * Provides the default {@link ToolkitLock} for <code>type</code>. * <ul> - * <li> JAWT {@link ToolkitLock} if required and AWT available, otherwise</li> + * <li> JAWT {@link ToolkitLock} if required and <code>type</code> is of {@link #TYPE_AWT} and AWT available,</li> + * <li> {@link jogamp.nativewindow.GlobalToolkitLock} if required, otherwise</li> + * <li> {@link jogamp.nativewindow.ResourceToolkitLock} if required, otherwise</li> * <li> {@link jogamp.nativewindow.NullToolkitLock} </li> * </ul> */ public static ToolkitLock getDefaultToolkitLock(String type) { - if( requiresToolkitLock() ) { - if( TYPE_AWT == type && TYPE_X11 == getNativeWindowType(false) && isAWTAvailable() ) { + if( requiresToolkitLock ) { + if( TYPE_AWT == type && isAWTAvailable() ) { return getAWTToolkitLock(); } - } - return NativeWindowFactoryImpl.getNullToolkitLock(); - } - - /** Returns the AWT Toolkit (JAWT based) if {@link #isAWTAvailable}, otherwise null. */ - public static ToolkitLock getAWTToolkitLock() { - return jawtUtilJAWTToolkitLock; - } - - public static ToolkitLock getNullToolkitLock() { - return NativeWindowFactoryImpl.getNullToolkitLock(); - } - - /** - * Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>. - * <ul> - * <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( requiresGlobalToolkitLock ) { + return NativeWindowFactoryImpl.getGlobalToolkitLock(); + } return ResourceToolkitLock.create(); } return NativeWindowFactoryImpl.getNullToolkitLock(); } - + /** - * Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>. + * Provides the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>. * <ul> - * <li> JAWT {@link ToolkitLock} if required and AWT available,</li> + * <li> JAWT {@link ToolkitLock} if required and <code>type</code> is of {@link #TYPE_AWT} and AWT available,</li> + * <li> {@link jogamp.nativewindow.GlobalToolkitLock} if required, otherwise</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_AWT == sharedType && isAWTAvailable() ) { + public static ToolkitLock getDefaultToolkitLock(String type, long deviceHandle) { + if( requiresToolkitLock ) { + if( TYPE_AWT == type && isAWTAvailable() ) { return getAWTToolkitLock(); } + if( requiresGlobalToolkitLock ) { + return NativeWindowFactoryImpl.getGlobalToolkitLock(); + } return ResourceToolkitLock.create(); } return NativeWindowFactoryImpl.getNullToolkitLock(); diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java index 18b7cf5d9..eccfcfa4f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java @@ -37,15 +37,35 @@ import jogamp.nativewindow.Debug; * 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)}. + * One use case is the AWT locking on X11, see {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. * </p> */ public interface ToolkitLock { + public static final boolean DEBUG = Debug.debug("ToolkitLock"); public static final boolean TRACE_LOCK = Debug.isPropertyDefined("nativewindow.debug.ToolkitLock.TraceLock", true); + /** + * Blocking until the lock is acquired by this Thread or a timeout is reached. + * <p> + * Timeout is implementation specific, if used at all. + * </p> + * + * @throws RuntimeException in case of a timeout + */ public void lock(); + + /** + * Release the lock. + * + * @throws RuntimeException in case the lock is not acquired by this thread. + */ public void unlock(); + /** + * @throws RuntimeException if current thread does not hold the lock + */ + public void validateLocked() throws RuntimeException; + /** * Dispose this instance. * <p> |