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 ------------- 11 files changed, 205 insertions(+), 510 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 (limited to 'src/nativewindow/classes/com') 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; - } -} -- cgit v1.2.3