From 1d333a771ce0bc7c8594e21d031703f698f06a46 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 10 Jun 2010 09:35:06 +0200 Subject: Fix: Locking/Threading; Common IntIntHashMap and Buffers; Fix: glMap*Buffer*; GLX/WGL/CgGL: All runtime dynamic; Misc .. TODO: Compile and test on MacOSX .. Fix: ===== Multithreading/Locking: See jogl/doc/Implementation/MultiThreading.txt - Locking layer is not platform agnostic, ie GLContextImpl, GLDrawableImpl, .. and NEWT: Window/Display - No more use of JAWT global lock necessary, removed. - No need for X11 Display lock, on the contrary, this made the NV driver hang. - Use common window/surface lock - All NativeWindow surfaceLock's are recursive now glMapBuffer: If size is 0, don't do cont with the native call. glMapBufferRange: Fix capacity. glNamedBufferDataEXT: Track the size. glMapNamedBufferEXT: Manual impl. - use the tracked size glXGetVisualFromFBConfig, glXChooseFBConfig, glXChooseVisual: Instead of ignoring and implement a renamed version (*Copied), we just use ManualImplementation for the proper copy-result code. DesktopGLDynamicLookupHelper: Initialize _hasGLBinding* attributes in the determing loadGLJNILibrary() method, which is called by super(). Otherwise static init will overwrite them after the super() call. X11GLXDrawableFactory: Don't release anything at shutdown (removed sharedContext.destroy()), since this caused a freeze/SEGV sometimes. Fixed NEWT's reparentWindow() functionality incl NewtCanvasAWT usage. - Native: if not visible, don't focus, etc - NewtCanvasAWT: Use the container size to start with - Run the command on the EDT Using GlueGen's new DynamicLibraryBundle utility: - X11, Windows and MacOSX OpenGL adapted to DynamicLibraryBundleInfo. - X11GLXDynamicLookupHelper -> X11GLXDynamicLibraryBundleInfo - Remove all path from lib names. - GL order: libGL.so.1, libGL.so, GL - shallLinkGlobal: true -> to server some 'old' DRI systems -> http://dri.sourceforge.net/doc/DRIuserguide.html - shallLookupGlobal: false - Try both : glXGetProcAddressARB and glXGetProcAddress - Using bootstrap: GLX.glXGetProcAddress(long glxGetProcAddressHandle, String glFuncName) Found the issue with LIBGL_DRIVERS_PATH, ie if not set no valid GL instance can be found (ie ATI fglrx/DRI). This may happen if using a differen user than the desktop user for whom the env var is set within some /etc/X11/Xsession.d/ script. Enhancements: ============= GLBufferSizeTracker: Use IntIntHashMap and add DirectState size tracking. GLBufferStateTracker: Use IntIntHashMap. GLStateTracker: Use IntIntHashMap. GLDynamicLookupHelper: More generic (global loading/lookup and GetProcAddress function name list), remove redundant code. FIXME: MacOSXCGLDynamicLookupHelper: - Not tested - Not using NSImage lookup anymore as recommended by OSX API Doc, so dlsym is used always (to be tested) WindowsWGLDynamicLookupHelper: - Not tested GLX/WGL/CgGL is all runtime-dynamic as now, ie loaded and looked-up at runtime, no compile time dependencies to GL anymore, nor a need to specify CgGL. Split up WGL in GDI and WGL, to allow proper dynamic runtime linkage of OpenGL32 while using static binding to GDI32 NEWT events generated by native code are enqueued and not send directly. This should ease locking mechanisms .. if any are necessary. NEWT: More platform specific code moved to *Impl method, simplifying the generic code of the superclass and impl protocol. Cleanup: ========= Replace all InternalBufferUtil's with com.jogamp.common.nio.Buffers Removed all InternalBufferUtil's from repository Removed GLContextImpl notion of 'optimized' surface locking, where the surface gets unlocked during makeCurrent/release. This just makes no sense and would impact multithreading in a horrible way. --- .../nativewindow/impl/InternalBufferUtil.java | 124 ------------------- .../impl/LockingNativeWindowFactory.java | 43 ------- .../nativewindow/impl/NativeWindowFactoryImpl.java | 13 -- .../com/jogamp/nativewindow/impl/NullWindow.java | 19 +-- .../nativewindow/impl/RecursiveToolkitLock.java | 35 +++++- .../jogamp/nativewindow/impl/jawt/JAWTUtil.java | 49 +++----- .../jogamp/nativewindow/impl/jawt/JAWTWindow.java | 34 ++--- .../nativewindow/impl/jawt/x11/X11JAWTWindow.java | 123 +++++++++--------- .../impl/x11/X11GraphicsConfigurationFactory.java | 51 +++----- .../com/jogamp/nativewindow/impl/x11/X11Util.java | 137 ++++++++------------- .../impl/x11/awt/X11AWTNativeWindowFactory.java | 87 ------------- .../media/nativewindow/AbstractGraphicsDevice.java | 4 + .../media/nativewindow/DefaultGraphicsDevice.java | 6 + .../javax/media/nativewindow/NativeWindow.java | 3 + .../media/nativewindow/NativeWindowFactory.java | 109 ++-------------- .../javax/media/nativewindow/ToolkitLock.java | 74 ----------- .../media/nativewindow/x11/X11GraphicsDevice.java | 11 ++ .../media/nativewindow/x11/X11GraphicsScreen.java | 48 ++------ 18 files changed, 251 insertions(+), 719 deletions(-) delete mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/impl/InternalBufferUtil.java delete mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java delete mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java delete mode 100644 src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java (limited to 'src/nativewindow/classes') diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/InternalBufferUtil.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/InternalBufferUtil.java deleted file mode 100644 index f590e9b8b..000000000 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/InternalBufferUtil.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2009 Sun Microsystems, Inc. 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 of Sun Microsystems, Inc. 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 - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package com.jogamp.nativewindow.impl; - -import java.lang.reflect.*; -import java.nio.*; - -/** Internal copy of selected routines from BufferUtil to avoid - outward dependencies on com.jogamp.opengl.util package. */ -public class InternalBufferUtil { - public static final int SIZEOF_BYTE = 1; - public static final int SIZEOF_SHORT = 2; - public static final int SIZEOF_INT = 4; - public static final int SIZEOF_FLOAT = 4; - - //---------------------------------------------------------------------- - // Allocation routines - // - - /** Allocates a new direct ByteBuffer with the specified number of - elements. The returned buffer will have its byte order set to - the host platform's native byte order. */ - public static ByteBuffer newByteBuffer(int numElements) { - ByteBuffer bb = ByteBuffer.allocateDirect(numElements); - nativeOrder(bb); - return bb; - } - - /** Allocates a new direct IntBuffer with the specified number of - elements. The returned buffer will have its byte order set to - the host platform's native byte order. */ - public static IntBuffer newIntBuffer(int numElements) { - ByteBuffer bb = newByteBuffer(numElements * SIZEOF_INT); - return bb.asIntBuffer(); - } - - //---------------------------------------------------------------------- - // Copy routines (type-to-type) - // - - /** Copies the remaining elements (as defined by - limit() - position()) in the passed ByteBuffer into - a newly-allocated direct ByteBuffer. The returned buffer will - have its byte order set to the host platform's native byte - order. The position of the newly-allocated buffer will be zero, - and the position of the passed buffer is unchanged (though its - mark is changed). */ - public static ByteBuffer copyByteBuffer(ByteBuffer orig) { - ByteBuffer dest = newByteBuffer(orig.remaining()); - dest.put(orig); - dest.rewind(); - return dest; - } - - //---------------------------------------------------------------------- - // Conversion routines - // - - public static ByteBuffer nativeOrder(ByteBuffer buf) { - if (!isCDCFP) { - try { - if (byteOrderClass == null) { - byteOrderClass = Class.forName("java.nio.ByteOrder"); - orderMethod = ByteBuffer.class.getMethod("order", new Class[] { byteOrderClass }); - Method nativeOrderMethod = byteOrderClass.getMethod("nativeOrder", null); - nativeOrderObject = nativeOrderMethod.invoke(null, null); - } - } catch (Throwable t) { - // Must be running on CDC / FP - isCDCFP = true; - } - - if (!isCDCFP) { - try { - orderMethod.invoke(buf, new Object[] { nativeOrderObject }); - } catch (Throwable t) { - } - } - } - return buf; - } - - //---------------------------------------------------------------------- - // Internals only below this point - // - - // NOTE that this work must be done reflectively at the present time - // because this code must compile and run correctly on both CDC/FP and J2SE - private static boolean isCDCFP; - private static Class byteOrderClass; - private static Object nativeOrderObject; - private static Method orderMethod; -} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java deleted file mode 100644 index 203ae3d12..000000000 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2009 Sun Microsystems, Inc. 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 of Sun Microsystems, Inc. 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 - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -package com.jogamp.nativewindow.impl; - -import javax.media.nativewindow.*; - -public class LockingNativeWindowFactory extends NativeWindowFactoryImpl { - private ToolkitLock toolkitLock = new RecursiveToolkitLock(); - - public ToolkitLock getToolkitLock() { - return toolkitLock; - } -} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java index 6233bf533..8cf02965b 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java @@ -99,17 +99,4 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory { throw (IllegalArgumentException) new IllegalArgumentException().initCause(ie); } } - - // On most platforms the toolkit lock is a no-op - private ToolkitLock toolkitLock = new ToolkitLock() { - public void lock() { - } - - public void unlock() { - } - }; - - public ToolkitLock getToolkitLock() { - return toolkitLock; - } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/NullWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NullWindow.java index a1c2b594c..7c446addc 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/NullWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NullWindow.java @@ -37,9 +37,10 @@ package com.jogamp.nativewindow.impl; import javax.media.nativewindow.*; +import com.jogamp.nativewindow.impl.RecursiveToolkitLock; public class NullWindow implements NativeWindow, SurfaceChangeable { - private Exception lockedStack = null; + private RecursiveToolkitLock recurLock = new RecursiveToolkitLock(); protected int width, height, scrnIndex; protected long surfaceHandle, displayHandle; protected AbstractGraphicsConfiguration config; @@ -68,28 +69,20 @@ public class NullWindow implements NativeWindow, SurfaceChangeable { } public synchronized int lockSurface() throws NativeWindowException { - if (null!=lockedStack) { - lockedStack.printStackTrace(); - throw new NativeWindowException("Surface already locked - "+this); - } - lockedStack = new Exception("NullWindow previously locked by "+Thread.currentThread().getName()); + recurLock.lock(); return LOCK_SUCCESS; } public synchronized void unlockSurface() { - if (null!=lockedStack) { - lockedStack = null; - } else { - throw new NativeWindowException("NullWindow not locked"); - } + recurLock.unlock(); } public synchronized boolean isSurfaceLocked() { - return null!=lockedStack; + return recurLock.isLocked(); } public Exception getLockedStack() { - return lockedStack; + return recurLock.getLockedStack(); } public boolean surfaceSwap() { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java index 52c211615..236ef0754 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java @@ -5,11 +5,12 @@ import javax.media.nativewindow.*; // // Reentrance locking toolkit // -public class RecursiveToolkitLock implements ToolkitLock { +public class RecursiveToolkitLock { private Thread owner = null; private int recursionCount = 0; private Exception lockedStack = null; private static final long timeout = 3000; // maximum wait 3s + private static final boolean TRACE_LOCK = false; public Exception getLockedStack() { return lockedStack; @@ -35,11 +36,27 @@ public class RecursiveToolkitLock implements ToolkitLock { return recursionCount; } + public synchronized void validateLocked() { + if ( !isLocked() ) { + throw new RuntimeException(Thread.currentThread()+": Not locked"); + } + if ( !isOwner() ) { + getLockedStack().printStackTrace(); + throw new RuntimeException(Thread.currentThread()+": Not owner, owner is "+owner); + } + } + /** Recursive and blocking lockSurface() implementation */ public synchronized void lock() { Thread cur = Thread.currentThread(); + if(TRACE_LOCK) { + System.out.println("... LOCK 0 ["+this+"], recursions "+recursionCount+", "+cur); + } if (owner == cur) { ++recursionCount; + if(TRACE_LOCK) { + System.out.println("+++ LOCK 1 ["+this+"], recursions "+recursionCount+", "+cur); + } return; } @@ -55,6 +72,9 @@ public class RecursiveToolkitLock implements ToolkitLock { lockedStack.printStackTrace(); throw new RuntimeException("Waited "+timeout+"ms for: "+owner+" - "+cur+", with recursionCount "+recursionCount+", lock: "+this); } + if(TRACE_LOCK) { + System.out.println("+++ LOCK X ["+this+"], recursions "+recursionCount+", "+cur); + } owner = cur; lockedStack = new Exception("Previously locked by "+owner+", lock: "+this); } @@ -67,13 +87,13 @@ public class RecursiveToolkitLock implements ToolkitLock { /** Recursive and unblocking unlockSurface() implementation */ public synchronized void unlock(Runnable taskAfterUnlockBeforeNotify) { - Thread cur = Thread.currentThread(); - if (owner != cur) { - lockedStack.printStackTrace(); - throw new RuntimeException(cur+": Not owner, owner is "+owner); - } + validateLocked(); + if (recursionCount > 0) { --recursionCount; + if(TRACE_LOCK) { + System.out.println("--- LOCK 1 ["+this+"], recursions "+recursionCount+", "+Thread.currentThread()); + } return; } owner = null; @@ -81,6 +101,9 @@ public class RecursiveToolkitLock implements ToolkitLock { if(null!=taskAfterUnlockBeforeNotify) { taskAfterUnlockBeforeNotify.run(); } + if(TRACE_LOCK) { + System.out.println("--- LOCK X ["+this+"], recursions "+recursionCount+", "+Thread.currentThread()); + } notifyAll(); } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java index 527d7750d..d7c690fc6 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java @@ -64,7 +64,6 @@ public class JAWTUtil { JAWTJNILibLoader.loadAWTImpl(); JAWTJNILibLoader.loadNativeWindow("awt"); - lockedStack = null; headlessMode = GraphicsEnvironment.isHeadless(); boolean ok=false; @@ -108,11 +107,10 @@ public class JAWTUtil { useSunToolkitAWTLock = false; } - private static Exception lockedStack; + public static void initSingleton() { + // just exist to ensure static init has been run + } - // Just a hook to let this class being initialized, - // ie loading the native libraries .. - public static void init() { } public static final boolean hasJava2D() { return j2dExist; @@ -156,47 +154,36 @@ public class JAWTUtil { } } - public static synchronized void lockToolkit() throws NativeWindowException { - if (isJava2DQueueFlusherThread()) return; + private static RecursiveToolkitLock recurLock = new RecursiveToolkitLock(); - if (null!=lockedStack) { - lockedStack.printStackTrace(); - throw new NativeWindowException("JAWT Toolkit already locked - "+Thread.currentThread().getName()); - } - lockedStack = new Exception("JAWT Toolkit already locked by: "+Thread.currentThread().getName()); + public static synchronized void lockToolkit() throws NativeWindowException { + recurLock.lock(); - if (headlessMode) { - // Workaround for running (to some degree) in headless - // environments but still supporting rendering via pbuffers - // For full correctness, would need to implement a Lock class - return; + if(recurLock.getRecursionCount()==0 && + !isJava2DQueueFlusherThread() && + !headlessMode) { + awtLock(); } - - awtLock(); } public static synchronized void unlockToolkit() { - if (isJava2DQueueFlusherThread()) return; - - if (null!=lockedStack) { - lockedStack = null; - if (headlessMode) { - // Workaround for running (to some degree) in headless - // environments but still supporting rendering via pbuffers - // For full correctness, would need to implement a Lock class - return; - } + recurLock.validateLocked(); + if(recurLock.getRecursionCount()==0 && + !isJava2DQueueFlusherThread() && + !headlessMode) { awtUnlock(); } + + recurLock.unlock(); } public static boolean isToolkitLocked() { - return null!=lockedStack; + return recurLock.isLocked(); } public static Exception getLockedStack() { - return lockedStack; + return recurLock.getLockedStack(); } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java index 68e61cd85..a59b34eb0 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java @@ -101,45 +101,37 @@ public abstract class JAWTWindow implements NativeWindow { bounds.setHeight(jawtBounds.getHeight()); } - private volatile Exception lockedStack = null; + private RecursiveToolkitLock recurLock = new RecursiveToolkitLock(); protected abstract int lockSurfaceImpl() throws NativeWindowException; public final synchronized int lockSurface() throws NativeWindowException { - // We have to be the owner of the JAWT ToolkitLock 'lock' to benefit from it's - // recursive and blocking lock capabitlites. - // Otherwise a followup ToolkitLock would deadlock, - // since we already have locked JAWT with the surface lock. - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - - // recursion not necessary here, due to the blocking ToolkitLock .. - if (null!=lockedStack) { - lockedStack.printStackTrace(); - throw new NativeWindowException("JAWT Surface already locked - "+Thread.currentThread().getName()+" "+this); + recurLock.lock(); + + if(recurLock.getRecursionCount() == 0) { + return lockSurfaceImpl(); } - lockedStack = new Exception("JAWT Surface previously locked by "+Thread.currentThread().getName()); - return lockSurfaceImpl(); + return LOCK_SUCCESS; } protected abstract void unlockSurfaceImpl() throws NativeWindowException; public synchronized void unlockSurface() { - if (null!=lockedStack) { - lockedStack = null; - } else { - throw new NativeWindowException("JAWT Surface not locked"); + recurLock.validateLocked(); + + if(recurLock.getRecursionCount()==0) { + unlockSurfaceImpl(); } - unlockSurfaceImpl(); - NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + recurLock.unlock(); } public synchronized boolean isSurfaceLocked() { - return null!=lockedStack; + return recurLock.isLocked(); } public Exception getLockedStack() { - return lockedStack; + return recurLock.getLockedStack(); } public boolean surfaceSwap() { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java index f7151d9f1..c74a62b7e 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTWindow.java @@ -56,74 +56,83 @@ public class X11JAWTWindow extends JAWTWindow { protected void initNative() throws NativeWindowException { if(0==config.getScreen().getDevice().getHandle()) { AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) config.getScreen().getDevice(); - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - try { - long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(awtDevice.getGraphicsDevice()); - if(0==displayHandle) { - displayHandle = X11Util.createThreadLocalDefaultDisplay(); - } - awtDevice.setHandle(displayHandle); - } finally { - NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(awtDevice.getGraphicsDevice()); + if(0==displayHandle) { + displayHandle = X11Util.createThreadLocalDisplay(null); } + awtDevice.setHandle(displayHandle); } } protected int lockSurfaceImpl() throws NativeWindowException { - int ret = NativeWindow.LOCK_SUCCESS; - ds = JAWT.getJAWT().GetDrawingSurface(component); - if (ds == null) { - // Widget not yet realized - unlockSurface(); - return LOCK_SURFACE_NOT_READY; - } - int res = ds.Lock(); - dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ; - if (!dsLocked) { - unlockSurface(); - throw new NativeWindowException("Unable to lock surface"); - } - // See whether the surface changed and if so destroy the old - // OpenGL context so it will be recreated (NOTE: removeNotify - // should handle this case, but it may be possible that race - // conditions can cause this code to be triggered -- should test - // more) - if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) { - ret = LOCK_SURFACE_CHANGED; - } - dsi = ds.GetDrawingSurfaceInfo(); - if (dsi == null) { - unlockSurface(); - return LOCK_SURFACE_NOT_READY; - } - x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(); - if (x11dsi == null) { - unlockSurface(); - return LOCK_SURFACE_NOT_READY; - } - drawable = x11dsi.getDrawable(); - if (drawable == 0) { - unlockSurface(); - return LOCK_SURFACE_NOT_READY; - } else { - updateBounds(dsi.getBounds()); + // JAWTUtil.lockToolkit(); + // config.getNativeGraphicsConfiguration().getScreen().getDevice().lock(); + try { + int ret = NativeWindow.LOCK_SUCCESS; + ds = JAWT.getJAWT().GetDrawingSurface(component); + if (ds == null) { + // Widget not yet realized + unlockSurface(); + return LOCK_SURFACE_NOT_READY; + } + int res = ds.Lock(); + dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ; + if (!dsLocked) { + unlockSurface(); + throw new NativeWindowException("Unable to lock surface"); + } + // See whether the surface changed and if so destroy the old + // OpenGL context so it will be recreated (NOTE: removeNotify + // should handle this case, but it may be possible that race + // conditions can cause this code to be triggered -- should test + // more) + if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) { + ret = LOCK_SURFACE_CHANGED; + } + dsi = ds.GetDrawingSurfaceInfo(); + if (dsi == null) { + unlockSurface(); + return LOCK_SURFACE_NOT_READY; + } + x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(); + if (x11dsi == null) { + unlockSurface(); + return LOCK_SURFACE_NOT_READY; + } + drawable = x11dsi.getDrawable(); + if (drawable == 0) { + unlockSurface(); + return LOCK_SURFACE_NOT_READY; + } else { + updateBounds(dsi.getBounds()); + } + return ret; + } finally { + // config.getNativeGraphicsConfiguration().getScreen().getDevice().unlock(); + // JAWTUtil.unlockToolkit(); } - return ret; } protected void unlockSurfaceImpl() throws NativeWindowException { - if(null!=ds) { - if (null!=dsi) { - ds.FreeDrawingSurfaceInfo(dsi); - } - if (dsLocked) { - ds.Unlock(); + // JAWTUtil.lockToolkit(); + // config.getNativeGraphicsConfiguration().getScreen().getDevice().lock(); + try { + if(null!=ds) { + if (null!=dsi) { + ds.FreeDrawingSurfaceInfo(dsi); + } + if (dsLocked) { + ds.Unlock(); + } + JAWT.getJAWT().FreeDrawingSurface(ds); } - JAWT.getJAWT().FreeDrawingSurface(ds); + ds = null; + dsi = null; + x11dsi = null; + } finally { + // config.getNativeGraphicsConfiguration().getScreen().getDevice().unlock(); + // JAWTUtil.unlockToolkit(); } - ds = null; - dsi = null; - x11dsi = null; } // Variables for lockSurface/unlockSurface diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java index 0cd02558a..fbf4524a4 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java @@ -58,19 +58,13 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor int num[] = { -1 }; long display = screen.getDevice().getHandle(); - X11Util.XLockDisplay(display); - try { - XVisualInfo[] xvis = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0); + XVisualInfo[] xvis = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0); - if(xvis==null || num[0]<1) { - return null; - } - - return XVisualInfo.create(xvis[0]); - } finally { - X11Util.XUnlockDisplay(display); + if(xvis==null || num[0]<1) { + return null; } + return XVisualInfo.create(xvis[0]); } public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, Capabilities capabilities) @@ -90,29 +84,24 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor vinfo_template.setC_class(c_class); long display = screen.getDevice().getHandle(); - X11Util.XLockDisplay(display); - try { - XVisualInfo[] vinfos = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualScreenMask, vinfo_template, num, 0); - XVisualInfo best=null; - int rdepth = capabilities.getRedBits() + capabilities.getGreenBits() + capabilities.getBlueBits() + capabilities.getAlphaBits(); - for (int i = 0; vinfos!=null && i < num[0]; i++) { - if ( best == null || - best.getDepth() < vinfos[i].getDepth() ) - { - best = vinfos[i]; - if(rdepth <= best.getDepth()) - break; - } - } - if ( null!=best && ( rdepth <= best.getDepth() || 24 == best.getDepth()) ) { - ret = XVisualInfo.create(best); + XVisualInfo[] vinfos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, vinfo_template, num, 0); + XVisualInfo best=null; + int rdepth = capabilities.getRedBits() + capabilities.getGreenBits() + capabilities.getBlueBits() + capabilities.getAlphaBits(); + for (int i = 0; vinfos!=null && i < num[0]; i++) { + if ( best == null || + best.getDepth() < vinfos[i].getDepth() ) + { + best = vinfos[i]; + if(rdepth <= best.getDepth()) + break; } - best = null; - - return ret; - } finally { - X11Util.XUnlockDisplay(display); } + if ( null!=best && ( rdepth <= best.getDepth() || 24 == best.getDepth()) ) { + ret = XVisualInfo.create(best); + } + best = null; + + return ret; } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java index 6e3c62d3b..924185210 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -52,7 +52,6 @@ import com.jogamp.nativewindow.impl.*; */ public class X11Util { private static final boolean DEBUG = Debug.debug("X11Util"); - private static final boolean DEBUG_XDISPLAY_LOCK = false; public static final String nullDisplayName; @@ -62,12 +61,7 @@ public class X11Util { initialize( true ); long dpy = X11Lib.XOpenDisplay(null); - XLockDisplay(dpy); - try { - nullDisplayName = X11Lib.XDisplayString(dpy); - } finally { - XUnlockDisplay(dpy); - } + nullDisplayName = X11Lib.XDisplayString(dpy); X11Lib.XCloseDisplay(dpy); if(DEBUG) { System.out.println("X11 Display(NULL) <"+nullDisplayName+">"); @@ -136,30 +130,17 @@ public class X11Util { return num; } - /** - * @return If name is null, it returns the previous queried NULL display name, - * otherwise the name. */ - public static String validateDisplayName(String name) { - return ( null == name ) ? nullDisplayName : name ; - } - - public static String validateDisplayName(String name, long handle) { - if(null==name && 0!=handle) { - name = getNameOfDisplay(handle); - } - return ( null == name ) ? nullDisplayName : name ; - } + /******************************* + ** + ** TLS Management + ** + *******************************/ /** Returns a clone of the thread local display map, you may {@link Object#wait()} on it */ public static Map getCurrentDisplayMap() { return (Map) ((HashMap)getCurrentDisplayMapImpl()).clone(); } - /** Returns this thread current default display. If it doesn not exist, it is being created, otherwise the reference count is increased */ - public static long createThreadLocalDefaultDisplay() { - return createThreadLocalDisplay(null); - } - /** Returns this thread named display. If it doesn not exist, it is being created, otherwise the reference count is increased */ public static long createThreadLocalDisplay(String name) { name = validateDisplayName(name); @@ -237,65 +218,6 @@ public class X11Util { return closeThreadLocalDisplay(ndpy.getName()); } - public static boolean setSynchronizeDisplay(long handle, boolean onoff) { - boolean res=false; - XLockDisplay(handle); - try { - res = X11Lib.XSynchronize(handle, onoff); - } finally { - XUnlockDisplay(handle); - } - return res; - } - - public static String getNameOfDisplay(long handle) { - String name; - XLockDisplay(handle); - try { - name = X11Lib.XDisplayString(handle); - } finally { - XUnlockDisplay(handle); - } - return name; - } - - public static void XLockDisplay(long handle) { - if(DEBUG_XDISPLAY_LOCK) { - NamedDisplay ndpy; - synchronized(globalLock) { - ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); - } - if(null==ndpy) { - throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, thread "+Thread.currentThread().getName()); - } - ndpy.lock(); - try { - X11Lib.XLockDisplay(handle); - } catch (Throwable t) { - ndpy.unlock(); - throw new RuntimeException(t); - } - } else { - X11Lib.XLockDisplay(handle); - } - } - - public static void XUnlockDisplay(long handle) { - if(DEBUG_XDISPLAY_LOCK) { - NamedDisplay ndpy; - synchronized(globalLock) { - ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle); - } - if(null==ndpy) { - throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, thread "+Thread.currentThread().getName()); - } - X11Lib.XUnlockDisplay(handle); - ndpy.unlock(); - } else { - X11Lib.XUnlockDisplay(handle); - } - } - public static boolean markThreadLocalDisplayUncloseable(long handle) { NamedDisplay ndpy; synchronized(globalLock) { @@ -349,5 +271,52 @@ public class X11Util { return (NamedDisplay) displayMap.get(name); } + /******************************* + ** + ** Non TLS Functions + ** + *******************************/ + + /** + * @return If name is null, it returns the previous queried NULL display name, + * otherwise the name. */ + public static String validateDisplayName(String name) { + return ( null == name ) ? nullDisplayName : name ; + } + + public static String validateDisplayName(String name, long handle) { + if(null==name && 0!=handle) { + name = getNameOfDisplay(handle); + } + return validateDisplayName(name); + } + + public static boolean setSynchronizeDisplay(long handle, boolean onoff) { + boolean res = X11Lib.XSynchronize(handle, onoff); + return res; + } + + public static String getNameOfDisplay(long handle) { + String name = X11Lib.XDisplayString(handle); + return name; + } + + public static void XLockDisplay(long handle) { + if(DEBUG) { + System.out.println("... X11 Display Lock try 0x"+Long.toHexString(handle)); + } + X11Lib.XLockDisplay(handle); + if(DEBUG) { + System.out.println("+++ X11 Display Lock got 0x"+Long.toHexString(handle)); + } + } + + public static void XUnlockDisplay(long handle) { + if(DEBUG) { + System.out.println("--- X11 Display Lock rel 0x"+Long.toHexString(handle)); + } + X11Lib.XUnlockDisplay(handle); + } + private static native void initialize(boolean initConcurrentThreadSupport); } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java deleted file mode 100644 index 616220e14..000000000 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2008-2009 Sun Microsystems, Inc. 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 of Sun Microsystems, Inc. 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 - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -package com.jogamp.nativewindow.impl.x11.awt; - -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import javax.media.nativewindow.*; - -import com.jogamp.nativewindow.impl.*; -import com.jogamp.nativewindow.impl.jawt.*; -import com.jogamp.nativewindow.impl.jawt.x11.*; -import com.jogamp.nativewindow.impl.x11.*; - -public class X11AWTNativeWindowFactory extends NativeWindowFactoryImpl { - - // When running the AWT on X11 platforms, we use the AWT native - // interface (JAWT) to lock and unlock the toolkit - private ToolkitLock toolkitLock = new ToolkitLock() { - private Thread owner; - private int recursionCount; - - public synchronized void lock() { - Thread cur = Thread.currentThread(); - if (owner == cur) { - ++recursionCount; - return; - } - while (owner != null) { - try { - wait(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - owner = cur; - JAWTUtil.lockToolkit(); - } - - public synchronized void unlock() { - if (owner != Thread.currentThread()) { - throw new RuntimeException("Not owner"); - } - if (recursionCount > 0) { - --recursionCount; - return; - } - owner = null; - JAWTUtil.unlockToolkit(); - notifyAll(); - } - }; - - public ToolkitLock getToolkitLock() { - return toolkitLock; - } -} diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index 4240ec81e..c133df5b4 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -55,4 +55,8 @@ public interface AbstractGraphicsDevice extends Cloneable { * if such thing exist. */ public long getHandle(); + + public void lock(); + + public void unlock(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index fdc849d0f..e18b7b2dc 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -62,6 +62,12 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice return handle; } + public void lock() { + } + + public void unlock() { + } + public String toString() { return getClass().toString()+"[type "+getType()+", handle 0x"+Long.toHexString(getHandle())+"]"; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java index 09c605e1c..7d0c52e3b 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java @@ -53,6 +53,9 @@ package javax.media.nativewindow; such as the window handle. */ public interface NativeWindow extends SurfaceUpdatedListener { + /** Unlocked state */ + public static final int LOCK_SURFACE_UNLOCKED = 0; + /** Returned by {@link #lockSurface()} if the surface is not ready to be locked. */ public static final int LOCK_SURFACE_NOT_READY = 1; diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index 14cb830e3..41be6e4b2 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -76,6 +76,7 @@ public abstract class NativeWindowFactory { private static String nativeOSNameCustom; private static final boolean isAWTAvailable; public static final String AWTComponentClassName = "java.awt.Component" ; + public static final String X11UtilClassName = "com.jogamp.nativewindow.impl.x11.X11Util"; /** Creates a new NativeWindowFactory instance. End users do not need to call this method. */ @@ -112,6 +113,10 @@ public abstract class NativeWindowFactory { nativeWindowingTypeCustom = nativeOSNameCustom; } + if( TYPE_X11.equals(nativeWindowingTypePure) ) { + ReflectionUtil.callStaticMethod( X11UtilClassName, "initSingleton", new Class[] { }, new Object[] { } ); + } + registeredFactories = Collections.synchronizedMap(new HashMap()); String factoryClassName = null; @@ -124,87 +129,25 @@ public abstract class NativeWindowFactory { // We break compile-time dependencies on the AWT here to // make it easier to run this code on mobile devices - isAWTAvailable = !Debug.getBooleanProperty("java.awt.headless", true, acc) && ReflectionUtil.isClassAvailable(AWTComponentClassName) && ReflectionUtil.isClassAvailable("javax.media.nativewindow.awt.AWTGraphicsDevice") ; - boolean toolkitLockForced = Debug.getBooleanProperty("nativewindow.locking", true, acc); - boolean awtToolkitLockDisabled = !isAWTAvailable || - Debug.getBooleanProperty("nativewindow.nolocking", true, acc) ; - - NativeWindowFactory _factory = null; - - if( !awtToolkitLockDisabled && TYPE_X11.equals(nativeWindowingTypeCustom) ) { - // There are certain operations that may be done by - // user-level native code which must share the display - // connection with the underlying window toolkit. In JOGL, - // for example, the AWT GLCanvas makes GLX and OpenGL - // calls against an X Drawable that was created by the - // AWT. In this case, the AWT Native Interface ("JAWT") is - // used to lock and unlock this surface, which grabs and - // releases a lock which is also used internally to the - // AWT implementation. This is required because the AWT - // makes X calls from multiple threads: for example, the - // AWT Toolkit thread and one or more Event Dispatch - // Threads. - // - // There are cases where synchronization with the - // toolkit is required in case of a shared resource pattern, - // e.g. with AWT. From recollection, visual selection is - // performed outside of the cover of the - // toolkit's lock, and the toolkit's display connection is - // used for this operation, so for correctness the toolkit - // must be locked during glXChooseFBConfig / - // glXChooseVisual. Synchronization with the toolkit is - // definitely needed for support of external GLDrawables, - // where JOGL creates additional OpenGL contexts on a - // surface that was created by a third party. External - // GLDrawables are the foundation of the Java 2D / JOGL - // bridge. While this bridge may be historical at this - // point, support for external GLDrawables on platforms - // that can support them (namely, WGL and X11 platforms; - // Mac OS X does not currently have the required - // primitives in its OpenGL window system binding) makes - // the JOGL library more powerful. - // - // The X11AWTNativeWindowFactory provides a locking - // mechanism compatible with the AWT. It may be desirable - // to replace this window factory when using third-party - // toolkits like Newt even when running on Java SE when - // the AWT is available. - - try { - Constructor factoryConstructor = - ReflectionUtil.getConstructor("com.jogamp.nativewindow.impl.x11.awt.X11AWTNativeWindowFactory", new Class[] {}); - _factory = (NativeWindowFactory) factoryConstructor.newInstance(null); - } catch (Exception e) { } - } - - if (toolkitLockForced && null==_factory) { - try { - Constructor factoryConstructor = - ReflectionUtil.getConstructor("com.jogamp.nativewindow.impl.LockingNativeWindowFactory", new Class[] {}); - _factory = (NativeWindowFactory) factoryConstructor.newInstance(null); - } catch (Exception e) { } - } - - if (null !=_factory) { - factory = _factory; - } - if ( isAWTAvailable ) { // register either our default factory or (if exist) the X11/AWT one -> AWT Component registerFactory(ReflectionUtil.getClass(AWTComponentClassName, false), factory); } - defaultFactory = factory; if(DEBUG) { - System.err.println("NativeWindowFactory toolkitLockForced "+toolkitLockForced+ - ", awtToolkitLockDisabled "+awtToolkitLockDisabled+", defaultFactory "+factory); + System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+ + ", defaultFactory "+factory); } } + public static void initSingleton() { + // just exist to ensure static init has been run + } + /** @return true if not headless, AWT Component and NativeWindow's AWT part available */ public static boolean isAWTAvailable() { return isAWTAvailable; } @@ -216,32 +159,12 @@ public abstract class NativeWindowFactory { return useCustom?nativeWindowingTypeCustom:nativeWindowingTypePure; } - /** Sets the default NativeWindowFactory. Certain operations on - X11 platforms require synchronization, and the implementation - of this synchronization may be specific to the window toolkit - in use. It is impractical to require that all of the APIs that - might require synchronization receive a {@link ToolkitLock - ToolkitLock} as argument. For this reason the concept of a - default NativeWindowFactory is introduced. The toolkit lock - provided via {@link #getToolkitLock getToolkitLock} from this - default NativeWindowFactory will be used for synchronization - within the Java binding to OpenGL. By default, if the AWT is - available, the default toolkit will support the AWT. */ + /** Sets the default NativeWindowFactory. */ public static void setDefaultFactory(NativeWindowFactory factory) { defaultFactory = factory; } - /** Gets the default NativeWindowFactory. Certain operations on - X11 platforms require synchronization, and the implementation - of this synchronization may be specific to the window toolkit - in use. It is impractical to require that all of the APIs that - might require synchronization receive a {@link ToolkitLock - ToolkitLock} as argument. For this reason the concept of a - default NativeWindowFactory is introduced. The toolkit lock - provided via {@link #getToolkitLock getToolkitLock} from this - default NativeWindowFactory will be used for synchronization - within the Java binding to OpenGL. By default, if the AWT is - available, the default toolkit will support the AWT. */ + /** Gets the default NativeWindowFactory. */ public static NativeWindowFactory getDefaultFactory() { return defaultFactory; } @@ -308,10 +231,4 @@ public abstract class NativeWindowFactory { NativeWindow. Implementors of concrete NativeWindowFactory subclasses should override this method. */ protected abstract NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException; - - /** Returns the object which provides support for synchronizing - with the underlying window toolkit.
- @see ToolkitLock - */ - public abstract ToolkitLock getToolkitLock(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java deleted file mode 100644 index 6f83896fa..000000000 --- a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. 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 of Sun Microsystems, Inc. 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 - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -package javax.media.nativewindow; - -/** Provides an interface for locking and unlocking the underlying - window toolkit, where this is necessary in the OpenGL - implementation. This mechanism is generally only needed on X11 - platforms. Currently it is only used when the AWT is in use. - Implementations of this lock, if they are not no-ops, must support - reentrant locking and unlocking.

- - The ToolkitLock implementation can be aquired by - {@link NativeWindowFactory#getToolkitLock NativeWindowFactory's getToolkitLock()}.

- - All toolkit shared resources shall be accessed by encapsulating the - code with a locking block as follows. -

-    NativeWindowFactory.getDefaultFactory().getToolkitLock().lock();
-    try {
-      long displayHandle = X11Util.getThreadLocalDefaultDisplay();
-      ... some code dealing with shared resources 
-      ... ie the window surface
-    } finally {
-      NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock();
-    }
-    

- - The underlying toolkit's locking mechanism may relate to {@link NativeWindow}'s - {@link NativeWindow#lockSurface lockSurface()}. Hence it is important - that both implementation harmonize well, ie {@link NativeWindow#lockSurface lockSurface()} - shall issue a ToolkitLock lock befor it aquires it's surface lock. This is true - in the AWT implementation for example. Otherwise the surface lock would steal - the ToolkitLock's lock and a deadlock would be unavoidable.

- - However the necessity of needing a global state synchronization will of course - impact your performance very much, especially in case of a multithreaded/multiwindow case. - */ -public interface ToolkitLock { - /** Locks the toolkit. */ - public void lock(); - - /** Unlocks the toolkit. */ - public void unlock(); -} diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java index f0ea11011..192abf775 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java @@ -33,6 +33,8 @@ package javax.media.nativewindow.x11; import javax.media.nativewindow.*; +import com.jogamp.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.x11.X11Util; /** Encapsulates a graphics device on X11 platforms. */ @@ -49,5 +51,14 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl public Object clone() { return super.clone(); } + + public void lock() { + X11Util.XLockDisplay(handle); + } + + public void unlock() { + X11Util.XUnlockDisplay(handle); + } + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java index a18ee91c2..97bdc37cf 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java @@ -56,53 +56,23 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl /** Creates a new X11GraphicsScreen using a thread local display connection */ public static AbstractGraphicsScreen createDefault() { - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - try { - long display = X11Util.createThreadLocalDefaultDisplay(); - X11Util.XLockDisplay(display); - try{ - int scrnIdx = X11Lib.DefaultScreen(display); - return createScreenDevice(display, scrnIdx); - }finally{ - X11Util.XUnlockDisplay(display); - } - } finally { - NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); - } + long display = X11Util.createThreadLocalDisplay(null); + int scrnIdx = X11Lib.DefaultScreen(display); + return createScreenDevice(display, scrnIdx); } public long getDefaultVisualID() { // It still could be an AWT hold handle .. - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - try { - long display = getDevice().getHandle(); - X11Util.XLockDisplay(display); - try{ - int scrnIdx = X11Lib.DefaultScreen(display); - return X11Lib.DefaultVisualID(display, scrnIdx); - }finally{ - X11Util.XUnlockDisplay(display); - } - } finally { - NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); - } + long display = getDevice().getHandle(); + int scrnIdx = X11Lib.DefaultScreen(display); + return X11Lib.DefaultVisualID(display, scrnIdx); } private static int fetchScreen(X11GraphicsDevice device, int screen) { // It still could be an AWT hold handle .. - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - try { - long display = device.getHandle(); - X11Util.XLockDisplay(display); - try{ - if(X11Lib.XineramaEnabled(display)) { - screen = 0; // Xinerama -> 1 screen - } - }finally{ - X11Util.XUnlockDisplay(display); - } - } finally { - NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + long display = device.getHandle(); + if(X11Lib.XineramaEnabled(display)) { + screen = 0; // Xinerama -> 1 screen } return screen; } -- cgit v1.2.3