diff options
Diffstat (limited to 'src/nativewindow/classes')
22 files changed, 1137 insertions, 280 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/GraphicsConfigurationFactoryImpl.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/GraphicsConfigurationFactoryImpl.java index 22f2d544f..96f6ab2ba 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/GraphicsConfigurationFactoryImpl.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/GraphicsConfigurationFactoryImpl.java @@ -35,9 +35,8 @@ package com.jogamp.nativewindow.impl; import javax.media.nativewindow.*; public class GraphicsConfigurationFactoryImpl extends GraphicsConfigurationFactory { - public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, - CapabilitiesChooser chooser, - AbstractGraphicsScreen screen) { + protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( + Capabilities capabilities, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) { return new DefaultGraphicsConfiguration(screen, capabilities, capabilities); } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java index 8f82bed2b..34f5d6267 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NativeWindowFactoryImpl.java @@ -41,6 +41,12 @@ import javax.media.nativewindow.*; public class NativeWindowFactoryImpl extends NativeWindowFactory { protected static final boolean DEBUG = Debug.debug("NativeWindow"); + private static final ToolkitLock nullToolkitLock = new NullToolkitLock(); + + public static ToolkitLock getNullToolkitLock() { + return nullToolkitLock; + } + // This subclass of NativeWindowFactory handles the case of // NativeWindows being passed in protected NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException { @@ -56,7 +62,7 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory { throw new IllegalArgumentException("AbstractGraphicsConfiguration is null with a non NativeWindow object"); } - if (ReflectionUtil.instanceOf(winObj, AWTComponentClassName)) { + if (NativeWindowFactory.isAWTAvailable() && ReflectionUtil.instanceOf(winObj, AWTComponentClassName)) { return getAWTNativeWindow(winObj, config); } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/NullToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NullToolkitLock.java new file mode 100644 index 000000000..5a03cba7f --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/NullToolkitLock.java @@ -0,0 +1,50 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.nativewindow.impl; + +import javax.media.nativewindow.ToolkitLock; + +/** + * Implementing a singleton global recursive {@link javax.media.nativewindow.ToolkitLock} + * without any locking. Since there is no locking it all, + * it is intrinsically recursive. + */ +public class NullToolkitLock implements ToolkitLock { + + /** Singleton via {@link NativeWindowFactoryImpl#getNullToolkitLock()} */ + protected NullToolkitLock() { } + + public final void lock() { + if(TRACE_LOCK) { System.err.println("NullToolkitLock.lock()"); } + } + + public final void unlock() { + if(TRACE_LOCK) { System.err.println("NullToolkitLock.unlock()"); } + } +} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/ProxySurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/ProxySurface.java index 9d9f360cd..eebcdb0ab 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/ProxySurface.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/ProxySurface.java @@ -43,10 +43,10 @@ import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.SurfaceChangeable; -import com.jogamp.common.util.RecursiveToolkitLock; +import com.jogamp.common.util.locks.RecursiveLock; public class ProxySurface implements NativeSurface, SurfaceChangeable { - private RecursiveToolkitLock recurLock = new RecursiveToolkitLock(); + private RecursiveLock recurLock = new RecursiveLock(); protected int width, height, scrnIndex; protected long surfaceHandle, displayHandle; protected AbstractGraphicsConfiguration config; @@ -78,31 +78,36 @@ public class ProxySurface implements NativeSurface, SurfaceChangeable { surfaceHandle=0; } - public synchronized int lockSurface() throws NativeWindowException { + public final int lockSurface() throws NativeWindowException { recurLock.lock(); + + if(recurLock.getRecursionCount() == 0) { + config.getScreen().getDevice().lock(); + } return LOCK_SUCCESS; } - public synchronized void unlockSurface() { + public final void unlockSurface() { + recurLock.validateLocked(); + + if(recurLock.getRecursionCount()==0) { + config.getScreen().getDevice().unlock(); + } recurLock.unlock(); } - public synchronized boolean isSurfaceLockedByOtherThread() { + public final boolean isSurfaceLockedByOtherThread() { return recurLock.isLockedByOtherThread(); } - public synchronized boolean isSurfaceLocked() { + public final boolean isSurfaceLocked() { return recurLock.isLocked(); } - public Thread getSurfaceLockOwner() { + public final Thread getSurfaceLockOwner() { return recurLock.getOwner(); } - public Exception getSurfaceLockStack() { - return recurLock.getLockedStack(); - } - public boolean surfaceSwap() { return false; } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTToolkitLock.java new file mode 100644 index 000000000..017d74874 --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTToolkitLock.java @@ -0,0 +1,54 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.nativewindow.impl.jawt; + +import javax.media.nativewindow.ToolkitLock; + +/** + * Implementing a singleton global recursive {@link javax.media.nativewindow.ToolkitLock} + * utilizing JAWT's AWT lock via {@link JAWTUtil#lockToolkit()}. + * <br> + * This strategy should only be used if AWT is using the underlying native windowing toolkit + * in a not intrinsic thread safe manner, e.g. under X11 where no XInitThreads() call + * is issued before any other X11 usage. This is the current situation for e.g. Webstart or Applets. + */ +public class JAWTToolkitLock implements ToolkitLock { + + /** Singleton via {@link JAWTUtil#getJAWTToolkitLock()} */ + protected JAWTToolkitLock() {} + + public final void lock() { + if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.lock()"); } + JAWTUtil.lockToolkit(); + } + + public final void unlock() { + if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.unlock()"); } + JAWTUtil.unlockToolkit(); + } +} 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 7127bacf9..ff62c9521 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTUtil.java @@ -40,27 +40,28 @@ import com.jogamp.nativewindow.impl.*; import javax.media.nativewindow.*; -import com.jogamp.common.util.RecursiveToolkitLock; +import com.jogamp.common.util.locks.RecursiveLock; import java.awt.GraphicsEnvironment; import java.lang.reflect.*; import java.security.*; public class JAWTUtil { + protected static final boolean DEBUG = Debug.debug("JAWT"); // See whether we're running in headless mode private static final boolean headlessMode; // Java2D magic .. - private static final Class j2dClazz; private static final Method isQueueFlusherThread; private static final boolean j2dExist; private static Class sunToolkitClass; private static Method sunToolkitAWTLockMethod; private static Method sunToolkitAWTUnlockMethod; - private static final boolean hasSunToolkitAWTLock; - private static final boolean useSunToolkitAWTLock; + private static boolean hasSunToolkitAWTLock; + + private static final JAWTToolkitLock jawtToolkitLock; static { JAWTJNILibLoader.loadAWTImpl(); @@ -68,45 +69,53 @@ public class JAWTUtil { headlessMode = GraphicsEnvironment.isHeadless(); - boolean ok=false; - Class jC=null; - Method m=null; - if(!headlessMode) { + boolean ok = false; + Class jC = null; + Method m = null; + if (!headlessMode) { try { jC = Class.forName("com.jogamp.opengl.impl.awt.Java2D"); m = jC.getMethod("isQueueFlusherThread", null); ok = true; - } catch (Exception e) {} + } catch (Exception e) { + } } - j2dClazz = jC; isQueueFlusherThread = m; j2dExist = ok; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - try { - sunToolkitClass = Class.forName("sun.awt.SunToolkit"); - sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[] {}); - sunToolkitAWTLockMethod.setAccessible(true); - sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[] {}); - sunToolkitAWTUnlockMethod.setAccessible(true); - } catch (Exception e) { - // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5 - } - return null; + try { + sunToolkitClass = Class.forName("sun.awt.SunToolkit"); + sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{}); + sunToolkitAWTLockMethod.setAccessible(true); + sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{}); + sunToolkitAWTUnlockMethod.setAccessible(true); + } catch (Exception e) { + // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5 + } + return null; + } + }); + boolean _hasSunToolkitAWTLock = false; + if (null != sunToolkitAWTLockMethod && null != sunToolkitAWTUnlockMethod) { + try { + sunToolkitAWTLockMethod.invoke(null, null); + sunToolkitAWTUnlockMethod.invoke(null, null); + _hasSunToolkitAWTLock = true; + } catch (Exception e) { } - }); - boolean _hasSunToolkitAWTLock = false; - if ( null!=sunToolkitAWTLockMethod && null!=sunToolkitAWTUnlockMethod ) { - try { - sunToolkitAWTLockMethod.invoke(null, null); - sunToolkitAWTUnlockMethod.invoke(null, null); - _hasSunToolkitAWTLock = true; - } catch (Exception e) {} - } - hasSunToolkitAWTLock = _hasSunToolkitAWTLock; - // useSunToolkitAWTLock = hasSunToolkitAWTLock; - useSunToolkitAWTLock = false; + } + hasSunToolkitAWTLock = _hasSunToolkitAWTLock; + // hasSunToolkitAWTLock = false; + + jawtToolkitLock = new JAWTToolkitLock(); + + if (DEBUG) { + System.err.println("JAWTUtil: Has sun.awt.SunToolkit.awtLock/awtUnlock " + hasSunToolkitAWTLock); + System.err.println("JAWTUtil: Has Java2D " + j2dExist); + System.err.println("JAWTUtil: Is headless " + headlessMode); + } } public static void initSingleton() { @@ -132,8 +141,14 @@ public class JAWTUtil { return headlessMode; } - private static void awtLock() { - if(useSunToolkitAWTLock) { + /** + * Locks the AWT's global ReentrantLock.<br> + * + * JAWT's native Lock() function calls SunToolkit.awtLock(), + * which just uses AWT's global ReentrantLock.<br> + */ + public static void awtLock() { + if(hasSunToolkitAWTLock) { try { sunToolkitAWTLockMethod.invoke(null, null); } catch (Exception e) { @@ -144,8 +159,14 @@ public class JAWTUtil { } } - private static void awtUnlock() { - if(useSunToolkitAWTLock) { + /** + * Unlocks the AWT's global ReentrantLock.<br> + * + * JAWT's native Unlock() function calls SunToolkit.awtUnlock(), + * which just uses AWT's global ReentrantLock.<br> + */ + public static void awtUnlock() { + if(hasSunToolkitAWTLock) { try { sunToolkitAWTUnlockMethod.invoke(null, null); } catch (Exception e) { @@ -156,36 +177,20 @@ public class JAWTUtil { } } - private static RecursiveToolkitLock recurLock = new RecursiveToolkitLock(); - - public static synchronized void lockToolkit() throws NativeWindowException { - recurLock.lock(); - - if(recurLock.getRecursionCount()==0 && - !isJava2DQueueFlusherThread() && - !headlessMode) { + public static void lockToolkit() throws NativeWindowException { + if(!isJava2DQueueFlusherThread() && !headlessMode) { awtLock(); } } - public static synchronized void unlockToolkit() { - recurLock.validateLocked(); - - if(recurLock.getRecursionCount()==0 && - !isJava2DQueueFlusherThread() && - !headlessMode) { + public static void unlockToolkit() { + if(!isJava2DQueueFlusherThread() && !headlessMode) { awtUnlock(); } - - recurLock.unlock(); - } - - public static boolean isToolkitLocked() { - return recurLock.isLocked(); } - public static Exception getLockedStack() { - return recurLock.getLockedStack(); + public static JAWTToolkitLock getJAWTToolkitLock() { + return jawtToolkitLock; } } 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 ad0b6104b..00d64b4e4 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/JAWTWindow.java @@ -38,7 +38,7 @@ package com.jogamp.nativewindow.impl.jawt; import com.jogamp.nativewindow.impl.*; -import com.jogamp.common.util.RecursiveToolkitLock; +import com.jogamp.common.util.locks.RecursiveLock; import java.awt.Component; import java.awt.Window; @@ -48,14 +48,7 @@ import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.Rectangle; public abstract class JAWTWindow implements NativeWindow { - protected static final boolean DEBUG = Debug.debug("JAWT"); - - // See whether we're running in headless mode - private static boolean headlessMode; - - static { - headlessMode = GraphicsEnvironment.isHeadless(); - } + protected static final boolean DEBUG = JAWTUtil.DEBUG; // lifetime: forever protected Component component; @@ -113,47 +106,60 @@ public abstract class JAWTWindow implements NativeWindow { // NativeSurface // - private RecursiveToolkitLock recurLock = new RecursiveToolkitLock(); + private RecursiveLock recurLock = new RecursiveLock(); protected abstract int lockSurfaceImpl() throws NativeWindowException; - public final synchronized int lockSurface() throws NativeWindowException { + public final int lockSurface() throws NativeWindowException { + int res = LOCK_SURFACE_NOT_READY; + recurLock.lock(); if(recurLock.getRecursionCount() == 0) { - return lockSurfaceImpl(); + config.getScreen().getDevice().lock(); + try { + res = lockSurfaceImpl(); + } finally { + // Unlock in case surface couldn't be locked + if(LOCK_SURFACE_NOT_READY >= res ) { + config.getScreen().getDevice().unlock(); + recurLock.unlock(); + } + } + } else { + res = LOCK_SUCCESS; } - return LOCK_SUCCESS; + return res; } protected abstract void unlockSurfaceImpl() throws NativeWindowException; - public synchronized void unlockSurface() { + public final void unlockSurface() { recurLock.validateLocked(); if(recurLock.getRecursionCount()==0) { - unlockSurfaceImpl(); + try { + unlockSurfaceImpl(); + } finally { + config.getScreen().getDevice().unlock(); + } } recurLock.unlock(); } - public synchronized boolean isSurfaceLockedByOtherThread() { + public final boolean isSurfaceLockedByOtherThread() { return recurLock.isLockedByOtherThread(); } - public synchronized boolean isSurfaceLocked() { + public final boolean isSurfaceLocked() { return recurLock.isLocked(); } - public Thread getSurfaceLockOwner() { + public final Thread getSurfaceLockOwner() { return recurLock.getOwner(); } - public Exception getSurfaceLockStack() { - return recurLock.getLockedStack(); - } - public boolean surfaceSwap() { return false; } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTToolkitLock.java new file mode 100644 index 000000000..7eaac2ca6 --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11JAWTToolkitLock.java @@ -0,0 +1,60 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.nativewindow.impl.jawt.x11; + +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.x11.X11Util; +import javax.media.nativewindow.ToolkitLock; + +/** + * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock} + * utilizing JAWT's AWT lock via {@link JAWTUtil#lockToolkit()} and {@link X11Util#XLockDisplay(long)}. + * <br> + * This strategy should only be used if AWT is using the underlying native windowing toolkit + * in a not intrinsic thread safe manner, e.g. under X11 where no XInitThreads() call + * is issued before any other X11 usage. This is the current situation for e.g. Webstart or Applets. + */ +public class X11JAWTToolkitLock implements ToolkitLock { + long displayHandle; + + public X11JAWTToolkitLock(long displayHandle) { + this.displayHandle = displayHandle; + } + + public final void lock() { + if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.lock()"); } + JAWTUtil.lockToolkit(); + X11Util.XLockDisplay(displayHandle); + } + + public final void unlock() { + if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.unlock()"); } + X11Util.XUnlockDisplay(displayHandle); + JAWTUtil.unlockToolkit(); + } +} 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 c74a62b7e..4a2c9ada3 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 @@ -60,79 +60,65 @@ public class X11JAWTWindow extends JAWTWindow { if(0==displayHandle) { displayHandle = X11Util.createThreadLocalDisplay(null); } - awtDevice.setHandle(displayHandle); + awtDevice.setSubType(NativeWindowFactory.TYPE_X11, displayHandle); } } protected int lockSurfaceImpl() throws NativeWindowException { - // 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(); + 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; } protected void unlockSurfaceImpl() throws NativeWindowException { - // 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); + if(null!=ds) { + if (null!=dsi) { + ds.FreeDrawingSurfaceInfo(dsi); + } + if (dsLocked) { + ds.Unlock(); } - ds = null; - dsi = null; - x11dsi = null; - } finally { - // config.getNativeGraphicsConfiguration().getScreen().getDevice().unlock(); - // JAWTUtil.unlockToolkit(); + JAWT.getJAWT().FreeDrawingSurface(ds); } + ds = null; + dsi = null; + x11dsi = null; } // Variables for lockSurface/unlockSurface diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11SunJDKReflection.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11SunJDKReflection.java index 7cca6f9f3..081975afb 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11SunJDKReflection.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/jawt/x11/X11SunJDKReflection.java @@ -89,7 +89,7 @@ public class X11SunJDKReflection { } try { - return ((Integer) x11GraphicsDeviceGetScreenMethod.invoke(device, new Object[] {})).intValue(); + return ((Integer) x11GraphicsDeviceGetScreenMethod.invoke(device, null)).intValue(); } catch (Exception e) { return 0; } @@ -101,7 +101,7 @@ public class X11SunJDKReflection { } try { - return ((Long) x11GraphicsDeviceGetDisplayMethod.invoke(device, new Object[] {})).longValue(); + return ((Long) x11GraphicsDeviceGetDisplayMethod.invoke(device, null)).longValue(); } catch (Exception e) { return 0; } @@ -124,7 +124,7 @@ public class X11SunJDKReflection { } try { - return ((Integer) x11GraphicsConfigGetVisualMethod.invoke(config, new Object[] {})).intValue(); + return ((Integer) x11GraphicsConfigGetVisualMethod.invoke(config, null)).intValue(); } catch (Exception e) { return 0; } 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 fbf4524a4..87324a57c 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java @@ -38,13 +38,11 @@ import com.jogamp.nativewindow.impl.x11.XVisualInfo; import com.jogamp.nativewindow.impl.x11.X11Lib; public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory { - public AbstractGraphicsConfiguration - chooseGraphicsConfiguration(Capabilities capabilities, - CapabilitiesChooser chooser, - AbstractGraphicsScreen screen) + protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( + Capabilities capabilities, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) throws IllegalArgumentException, NativeWindowException { - if(null==screen || !(screen instanceof X11GraphicsScreen)) { + if(!(screen instanceof X11GraphicsScreen)) { throw new NativeWindowException("Only valid X11GraphicsScreen are allowed"); } return new X11GraphicsConfiguration((X11GraphicsScreen)screen, capabilities, capabilities, getXVisualInfo(screen, capabilities)); @@ -58,7 +56,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor int num[] = { -1 }; long display = screen.getDevice().getHandle(); - XVisualInfo[] xvis = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0); + XVisualInfo[] xvis = X11Util.XGetVisualInfo(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0); if(xvis==null || num[0]<1) { return null; @@ -84,7 +82,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor vinfo_template.setC_class(c_class); long display = screen.getDevice().getHandle(); - XVisualInfo[] vinfos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, vinfo_template, num, 0); + XVisualInfo[] vinfos = X11Util.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++) { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11ToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11ToolkitLock.java new file mode 100644 index 000000000..2e0e911b9 --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11ToolkitLock.java @@ -0,0 +1,55 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.nativewindow.impl.x11; + +import javax.media.nativewindow.ToolkitLock; + +/** + * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock} + * utilizing {@link X11Util#XLockDisplay(long)}. + * <br> + * This strategy should not be used in case XInitThreads() is being used, + * or a higher level toolkit lock is required, ie AWT lock. + */ +public class X11ToolkitLock implements ToolkitLock { + long displayHandle; + + public X11ToolkitLock(long displayHandle) { + this.displayHandle = displayHandle; + } + + public final void lock() { + if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock()"); } + X11Util.XLockDisplay(displayHandle); + } + + public final void unlock() { + if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock()"); } + X11Util.XUnlockDisplay(displayHandle); + } +} 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 6871cd5f2..3e991e52e 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java @@ -38,11 +38,15 @@ import java.util.Collection; import java.util.ArrayList; import java.util.Iterator; import com.jogamp.common.util.LongObjectHashMap; -import com.jogamp.common.util.RecursiveToolkitLock; +import com.jogamp.common.util.locks.RecursiveLock; import javax.media.nativewindow.*; import com.jogamp.nativewindow.impl.*; +import java.nio.Buffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; +import java.security.AccessController; /** * Contains a thread safe X11 utility to retrieve thread local display connection,<br> @@ -52,25 +56,58 @@ import com.jogamp.nativewindow.impl.*; * where an application heavily utilizing this class on temporary new threads.<br> */ public class X11Util { - private static final boolean DEBUG = Debug.debug("X11Util"); + private static final boolean DEBUG = Debug.debug("X11Util"); - public static final String nullDisplayName; + private static String nullDisplayName = null; + private static boolean isFirstX11ActionOnProcess = false; + private static boolean isInit = false; - static { - NWJNILibLoader.loadNativeWindow("x11"); + public static synchronized void initSingleton(boolean firstX11ActionOnProcess) { + if(!isInit) { + NWJNILibLoader.loadNativeWindow("x11"); - initialize( true ); + /** + * Always issue XInitThreads() since we have independent + * off-thread created Display connections able to utilize multithreading, ie NEWT */ + initialize( true ); + // initialize( firstX11ActionOnProcess ); + isFirstX11ActionOnProcess = firstX11ActionOnProcess; - long dpy = X11Lib.XOpenDisplay(null); - nullDisplayName = X11Lib.XDisplayString(dpy); - X11Lib.XCloseDisplay(dpy); - if(DEBUG) { - System.out.println("X11 Display(NULL) <"+nullDisplayName+">"); + if(DEBUG) { + System.out.println("X11Util.isFirstX11ActionOnProcess: "+isFirstX11ActionOnProcess); + } + isInit = true; } } - public static void initSingleton() { - // just exist to ensure static init has been run + public static boolean isFirstX11ActionOnProcess() { + return isFirstX11ActionOnProcess; + } + + public static String getNullDisplayName() { + if(null==nullDisplayName) { + synchronized(X11Util.class) { + if(null==nullDisplayName) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + long dpy = X11Lib.XOpenDisplay(null); + X11Util.XLockDisplay(dpy); + try { + nullDisplayName = X11Lib.XDisplayString(dpy); + } finally { + X11Util.XUnlockDisplay(dpy); + } + X11Lib.XCloseDisplay(dpy); + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + if(DEBUG) { + System.out.println("X11 Display(NULL) <"+nullDisplayName+">"); + } + } + } + } + return nullDisplayName; } private X11Util() {} @@ -82,7 +119,7 @@ public class X11Util { private static ThreadLocal currentDisplayMap = new ThreadLocal(); - public static class NamedDisplay extends RecursiveToolkitLock implements Cloneable { + public static class NamedDisplay extends RecursiveLock implements Cloneable { String name; long handle; int refCount; @@ -147,7 +184,7 @@ public class X11Util { name = validateDisplayName(name); NamedDisplay namedDpy = getCurrentDisplay(name); if(null==namedDpy) { - long dpy = X11Lib.XOpenDisplay(name); + long dpy = XOpenDisplay(name); if(0==dpy) { throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection in Thread "+Thread.currentThread().getName()); } @@ -199,7 +236,7 @@ public class X11Util { if(null==globalNamedDisplayMap.remove(dpy)) { throw new RuntimeException("Internal: "+namedDpy); } } if(!namedDpy.isUncloseable()) { - X11Lib.XCloseDisplay(dpy); + XCloseDisplay(dpy); } } else if(DEBUG) { Exception e = new Exception("X11Util.Display: Keep TLS "+namedDpy+" in thread "+Thread.currentThread().getName()); @@ -281,7 +318,7 @@ public class X11Util { /** Returns this created named display. */ public static long createDisplay(String name) { name = validateDisplayName(name); - long dpy = X11Lib.XOpenDisplay(name); + long dpy = XOpenDisplay(name); if(0==dpy) { throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection. Thread "+Thread.currentThread().getName()); } @@ -292,7 +329,7 @@ public class X11Util { globalNamedDisplayMap.put(dpy, namedDpy); } if(DEBUG) { - Exception e = new Exception("X11Util.Display: Created new global "+namedDpy+". Thread "+Thread.currentThread().getName()); + Exception e = new Exception("X11Util.Display: Created new "+namedDpy+". Thread "+Thread.currentThread().getName()); e.printStackTrace(); } return namedDpy.getHandle(); @@ -312,7 +349,7 @@ public class X11Util { } if(!namedDpy.isUncloseable()) { - X11Lib.XCloseDisplay(namedDpy.getHandle()); + XCloseDisplay(namedDpy.getHandle()); } } @@ -320,42 +357,331 @@ public class X11Util { * @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 ; + return ( null == name ) ? getNullDisplayName() : name ; } public static String validateDisplayName(String name, long handle) { if(null==name && 0!=handle) { - name = getNameOfDisplay(handle); + name = XDisplayString(handle); } return validateDisplayName(name); } - public static boolean setSynchronizeDisplay(long handle, boolean onoff) { - boolean res = X11Lib.XSynchronize(handle, onoff); - return res; + /******************************* + ** + ** Locked X11Lib wrapped functions + ** + *******************************/ + public static long XOpenDisplay(String arg0) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + return X11Lib.XOpenDisplay(arg0); + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + public static int XSync(long display, boolean discard) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XSync(display, discard); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static boolean XSynchronize(long display, boolean onoff) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XSynchronize(display, onoff); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static boolean XineramaEnabled(long display) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XineramaEnabled(display); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static int DefaultScreen(long display) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.DefaultScreen(display); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static long RootWindow(long display, int screen_number) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.RootWindow(display, screen_number); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static long XCreatePixmap(long display, long arg1, int arg2, int arg3, int arg4) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XCreatePixmap(display, arg1, arg2, arg3, arg4); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static String XDisplayString(long display) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XDisplayString(display); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static int XFlush(long display) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XFlush(display); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static int XFree(Buffer arg0) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + return X11Lib.XFree(arg0); + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static int XFreePixmap(long display, long arg1) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XFreePixmap(display, arg1); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static long DefaultVisualID(long display, int screen) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.DefaultVisualID(display, screen); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static long CreateDummyWindow(long display, int screen_index, long visualID) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.CreateDummyWindow(display, screen_index, visualID); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static void DestroyDummyWindow(long display, long window) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + X11Lib.DestroyDummyWindow(display, window); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static int XCloseDisplay(long display) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XCloseDisplay(display); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static XVisualInfo[] XGetVisualInfo(long display, long arg1, XVisualInfo arg2, int[] arg3, int arg3_offset) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XGetVisualInfo(display, arg1, arg2, arg3, arg3_offset); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static boolean XF86VidModeGetGammaRamp(long display, int screen, int size, ShortBuffer red_array, ShortBuffer green_array, ShortBuffer blue_array) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XF86VidModeGetGammaRamp(display, screen, size, red_array, green_array, blue_array); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static boolean XF86VidModeGetGammaRamp(long display, int screen, int size, short[] red_array, int red_array_offset, short[] green_array, int green_array_offset, short[] blue_array, int blue_array_offset) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XF86VidModeGetGammaRamp(display, screen, size, red_array, red_array_offset, green_array, green_array_offset, blue_array, blue_array_offset); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static boolean XF86VidModeGetGammaRampSize(long display, int screen, IntBuffer size) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XF86VidModeGetGammaRampSize(display, screen, size); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static boolean XF86VidModeGetGammaRampSize(long display, int screen, int[] size, int size_offset) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XF86VidModeGetGammaRampSize(display, screen, size, size_offset); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } + } + + public static boolean XF86VidModeSetGammaRamp(long display, int screen, int size, ShortBuffer red_array, ShortBuffer green_array, ShortBuffer blue_array) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XF86VidModeSetGammaRamp(display, screen, size, red_array, green_array, blue_array); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } } - public static String getNameOfDisplay(long handle) { - String name = X11Lib.XDisplayString(handle); - return name; + public static boolean XF86VidModeSetGammaRamp(long display, int screen, int size, short[] red_array, int red_array_offset, short[] green_array, int green_array_offset, short[] blue_array, int blue_array_offset) { + NativeWindowFactory.getDefaultToolkitLock().lock(); + try { + X11Util.XLockDisplay(display); + try { + return X11Lib.XF86VidModeSetGammaRamp(display, screen, size, red_array, red_array_offset, green_array, green_array_offset, blue_array, blue_array_offset); + } finally { + X11Util.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); + } } public static void XLockDisplay(long handle) { - if(DEBUG) { - System.out.println("... X11 Display Lock try 0x"+Long.toHexString(handle)); + if(ToolkitLock.TRACE_LOCK) { + System.out.println("+++ X11 Display Lock get 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) { + if(ToolkitLock.TRACE_LOCK) { System.out.println("--- X11 Display Lock rel 0x"+Long.toHexString(handle)); } X11Lib.XUnlockDisplay(handle); } - private static native void initialize(boolean initConcurrentThreadSupport); + private static native void initialize(boolean firstUIActionOnProcess); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index c133df5b4..b003db8f5 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -56,7 +57,15 @@ public interface AbstractGraphicsDevice extends Cloneable { */ public long getHandle(); + /** + * Optionally locking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}. + * The lock implementation must be recursive. + */ public void lock(); + /** + * Optionally unlocking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}. + * The lock implementation must be recursive. + */ public void unlock(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index e18b7b2dc..ca0f106f5 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -32,18 +32,46 @@ package javax.media.nativewindow; +import com.jogamp.nativewindow.impl.NativeWindowFactoryImpl; + public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice { private String type; protected long handle; + protected ToolkitLock toolkitLock; + /** + * Create an instance with the system default {@link ToolkitLock}, + * gathered via {@link NativeWindowFactory#createDefaultToolkitLock()}. + * @param type + */ public DefaultGraphicsDevice(String type) { this.type = type; this.handle = 0; + setToolkitLock( NativeWindowFactory.getDefaultToolkitLock(type) ); } + /** + * Create an instance with the system default {@link ToolkitLock}. + * gathered via {@link NativeWindowFactory#createDefaultToolkitLock()}. + * @param type + * @param handle + */ public DefaultGraphicsDevice(String type, long handle) { this.type = type; this.handle = handle; + setToolkitLock( NativeWindowFactory.createDefaultToolkitLock(type, handle) ); + } + + /** + * Create an instance with the given {@link ToolkitLock} instance. + * @param type + * @param handle + * @param locker + */ + public DefaultGraphicsDevice(String type, long handle, ToolkitLock locker) { + this.type = type; + this.handle = handle; + setToolkitLock( locker ); } public Object clone() { @@ -62,10 +90,46 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice return handle; } - public void lock() { + /** + * Set the internal ToolkitLock, which is used within the + * {@link #lock()} and {@link #unlock()} implementation. + * + * @param locker the ToolkitLock, if null, {@link com.jogamp.nativewindow.impl.NullToolkitLock} is being used + */ + protected void setToolkitLock(ToolkitLock locker) { + this.toolkitLock = ( null == locker ) ? NativeWindowFactoryImpl.getNullToolkitLock() : locker ; + } + + /** + * @return the used ToolkitLock + * + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) + */ + public final ToolkitLock getToolkitLock() { + return toolkitLock; + } + + /** + * No lock is performed on the graphics device per default, + * instead the aggregated recursive {@link ToolkitLock#lock()} is invoked. + * + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) + */ + public final void lock() { + toolkitLock.lock(); } - public void unlock() { + /** + * No lock is performed on the graphics device per default, + * instead the aggregated recursive {@link ToolkitLock#unlock()} is invoked. + * + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) + * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) + */ + public final void unlock() { + toolkitLock.unlock(); } public String toString() { diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java index 0a1a91876..75c8aea22 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java @@ -78,7 +78,7 @@ public abstract class GraphicsConfigurationFactory { if (NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { try { GraphicsConfigurationFactory factory = (GraphicsConfigurationFactory) - ReflectionUtil.createInstance("com.jogamp.nativewindow.impl.x11.X11GraphicsConfigurationFactory", new Object[] {}, + ReflectionUtil.createInstance("com.jogamp.nativewindow.impl.x11.X11GraphicsConfigurationFactory", null, GraphicsConfigurationFactory.class.getClassLoader()); registerFactory(javax.media.nativewindow.x11.X11GraphicsDevice.class, factory); } catch (Exception e) { @@ -198,9 +198,29 @@ public abstract class GraphicsConfigurationFactory { * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) * @see javax.media.nativewindow.DefaultGraphicsConfiguration#setChosenCapabilities(Capabilities caps) */ - public abstract AbstractGraphicsConfiguration + public final AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) + throws IllegalArgumentException, NativeWindowException { + if(null==screen) { + throw new NativeWindowException("Screen is null"); + } + AbstractGraphicsDevice device = screen.getDevice(); + if(null==device) { + throw new NativeWindowException("Screen's Device is null"); + } + device.lock(); + try { + return chooseGraphicsConfigurationImpl(capabilities, chooser, screen); + } finally { + device.unlock(); + } + } + + protected abstract AbstractGraphicsConfiguration + chooseGraphicsConfigurationImpl(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen screen) throws IllegalArgumentException, NativeWindowException; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java index ef45a79d3..a5b71fbf8 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java @@ -1,6 +1,5 @@ /** * Copyright 2010 JogAmp Community. All rights reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -63,14 +62,17 @@ public interface NativeSurface extends SurfaceUpdatedListener { * This call allows recursion from the same thread.<P> * * The implementation may want to aquire the - * application level {@link com.jogamp.common.util.RecursiveToolkitLock} + * application level {@link com.jogamp.common.util.locks.RecursiveLock} * first before proceeding with a native surface lock. <P> * + * The implementation shall also invoke {@link AbstractGraphicsDevice#lock()} + * for the initial lock (recursive count zero).<P> + * * @return {@link #LOCK_SUCCESS}, {@link #LOCK_SURFACE_CHANGED} or {@link #LOCK_SURFACE_NOT_READY}. * * @throws RuntimeException after timeout when waiting for the surface lock * - * @see com.jogamp.common.util.RecursiveToolkitLock + * @see com.jogamp.common.util.locks.RecursiveLock */ public int lockSurface(); @@ -79,10 +81,13 @@ public interface NativeSurface extends SurfaceUpdatedListener { * * Shall not modify the surface handle, see {@link #lockSurface()} <P> * + * The implementation shall also invoke {@link AbstractGraphicsDevice#unlock()} + * for the final unlock (recursive count zero).<P> + * * @throws RuntimeException if surface is not locked * * @see #lockSurface - * @see com.jogamp.common.util.RecursiveToolkitLock + * @see com.jogamp.common.util.locks.RecursiveLock */ public void unlockSurface() throws NativeWindowException ; @@ -102,14 +107,6 @@ public interface NativeSurface extends SurfaceUpdatedListener { public Thread getSurfaceLockOwner(); /** - * Return the lock-exception, or null if not locked. - * - * The lock-exception is created at {@link #lockSurface()} - * and hence holds the locker's call stack. - */ - public Exception getSurfaceLockStack(); - - /** * Provide a mechanism to utilize custom (pre-) swap surface * code. This method is called before the render toolkit (e.g. JOGL) * swaps the buffer/surface. The implementation may itself apply the swapping, diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index f716e8ac9..7897460a0 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,13 +33,14 @@ package javax.media.nativewindow; -import java.lang.reflect.*; import java.security.*; import java.util.*; import com.jogamp.common.util.*; import com.jogamp.common.jvm.JVMUtil; import com.jogamp.nativewindow.impl.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; /** Provides a pluggable mechanism for arbitrary window toolkits to adapt their components to the {@link NativeWindow} interface, @@ -74,9 +76,20 @@ public abstract class NativeWindowFactory { private static String nativeOSNamePure; private static String nativeWindowingTypeCustom; private static String nativeOSNameCustom; - private static final boolean isAWTAvailable; + private static boolean isAWTAvailable; public static final String AWTComponentClassName = "java.awt.Component" ; + public static final String JAWTUtilClassName = "com.jogamp.nativewindow.impl.jawt.JAWTUtil" ; public static final String X11UtilClassName = "com.jogamp.nativewindow.impl.x11.X11Util"; + public static final String X11JAWTToolkitLockClassName = "com.jogamp.nativewindow.impl.jawt.x11.X11JAWTToolkitLock" ; + public static final String X11ToolkitLockClassName = "com.jogamp.nativewindow.impl.x11.X11ToolkitLock" ; + private static Class jawtUtilClass; + private static Method jawtUtilGetJAWTToolkitMethod; + private static Method jawtUtilInitMethod; + private static Class x11JAWTToolkitLockClass; + private static Constructor x11JAWTToolkitLockConstructor; + private static Class x11ToolkitLockClass; + private static Constructor x11ToolkitLockConstructor; + private static boolean isFirstUIActionOnProcess; /** Creates a new NativeWindowFactory instance. End users do not need to call this method. */ @@ -100,54 +113,117 @@ public abstract class NativeWindowFactory { static { JVMUtil.initSingleton(); + } - // Gather the windowing OS first - AccessControlContext acc = AccessController.getContext(); - nativeOSNamePure = Debug.getProperty("os.name", false, acc); - nativeWindowingTypePure = _getNativeWindowingType(nativeOSNamePure.toLowerCase()); - nativeOSNameCustom = Debug.getProperty("nativewindow.ws.name", true, acc); - if(null==nativeOSNameCustom||nativeOSNameCustom.length()==0) { - nativeOSNameCustom = nativeOSNamePure; - nativeWindowingTypeCustom = nativeWindowingTypePure; - } else { - nativeWindowingTypeCustom = nativeOSNameCustom; - } - - ClassLoader cl = NativeWindowFactory.class.getClassLoader(); + static boolean initialized = false; + + /** + * Static one time initialization of this factory.<br> + * This initialization method <b>must be called</b> once by the program or utilizing modules!<br> + * @param firstUIActionOnProcess Should be <code>true</code> if called before the first UI action of the running program, + * otherwise <code>false</code>. + */ + public static synchronized void initSingleton(final boolean firstUIActionOnProcess) { + if(!initialized) { + initialized = true; + + if(DEBUG) { + Throwable td = new Throwable("Info: NativeWindowFactory.initSingleton("+firstUIActionOnProcess+")"); + td.printStackTrace(); + } - if( TYPE_X11.equals(nativeWindowingTypePure) ) { - ReflectionUtil.callStaticMethod( X11UtilClassName, "initSingleton", new Class[] { }, new Object[] { }, cl ); - } + // Gather the windowing OS first + AccessControlContext acc = AccessController.getContext(); + nativeOSNamePure = Debug.getProperty("os.name", false, acc); + nativeWindowingTypePure = _getNativeWindowingType(nativeOSNamePure.toLowerCase()); + nativeOSNameCustom = Debug.getProperty("nativewindow.ws.name", true, acc); + if(null==nativeOSNameCustom||nativeOSNameCustom.length()==0) { + nativeOSNameCustom = nativeOSNamePure; + nativeWindowingTypeCustom = nativeWindowingTypePure; + } else { + nativeWindowingTypeCustom = nativeOSNameCustom; + } - registeredFactories = Collections.synchronizedMap(new HashMap()); + ClassLoader cl = NativeWindowFactory.class.getClassLoader(); - String factoryClassName = null; + if( TYPE_X11.equals(nativeWindowingTypePure) ) { + // explicit initialization of X11Util + ReflectionUtil.callStaticMethod(X11UtilClassName, "initSingleton", + new Class[] { boolean.class }, + new Object[] { new Boolean(firstUIActionOnProcess) }, cl ); + } + isFirstUIActionOnProcess = firstUIActionOnProcess; + + if( !Debug.getBooleanProperty("java.awt.headless", true, acc) && + ReflectionUtil.isClassAvailable(AWTComponentClassName, cl) && + ReflectionUtil.isClassAvailable("javax.media.nativewindow.awt.AWTGraphicsDevice", cl) ) { + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + jawtUtilClass = Class.forName(JAWTUtilClassName, false, NativeWindowFactory.class.getClassLoader()); + jawtUtilInitMethod = jawtUtilClass.getDeclaredMethod("initSingleton", null); + jawtUtilInitMethod.setAccessible(true); + jawtUtilGetJAWTToolkitMethod = jawtUtilClass.getDeclaredMethod("getJAWTToolkitLock", new Class[]{}); + jawtUtilGetJAWTToolkitMethod.setAccessible(true); + } catch (Exception e) { + // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5 + } + return null; + } + }); + if(null != jawtUtilClass && null != jawtUtilGetJAWTToolkitMethod && null != jawtUtilInitMethod) { + ReflectionUtil.callMethod(null, jawtUtilInitMethod, null); + + Object resO = ReflectionUtil.callStaticMethod(JAWTUtilClassName, "isHeadlessMode", null, null, cl ); + if(resO instanceof Boolean) { + // AWT is only available in case all above classes are available + // and AWT is not int headless mode + isAWTAvailable = ((Boolean)resO).equals(Boolean.FALSE); + } else { + isAWTAvailable = false; + } + } else { + isAWTAvailable = false; + } + } else { + isAWTAvailable = false; + } - // register our default factory -> NativeWindow - NativeWindowFactory factory = new NativeWindowFactoryImpl(); - nativeWindowClass = javax.media.nativewindow.NativeWindow.class; - registerFactory(nativeWindowClass, factory); - defaultFactory = factory; - - // 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, cl) && - ReflectionUtil.isClassAvailable("javax.media.nativewindow.awt.AWTGraphicsDevice", cl) ; - - if ( isAWTAvailable ) { - // register either our default factory or (if exist) the X11/AWT one -> AWT Component - registerFactory(ReflectionUtil.getClass(AWTComponentClassName, false, cl), factory); - } + registeredFactories = Collections.synchronizedMap(new HashMap()); + + // register our default factory -> NativeWindow + NativeWindowFactory factory = new NativeWindowFactoryImpl(); + nativeWindowClass = javax.media.nativewindow.NativeWindow.class; + registerFactory(nativeWindowClass, factory); + defaultFactory = factory; + + if ( isAWTAvailable ) { + // register either our default factory or (if exist) the X11/AWT one -> AWT Component + registerFactory(ReflectionUtil.getClass(AWTComponentClassName, false, cl), factory); + } - if(DEBUG) { - System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+ - ", defaultFactory "+factory); + if( TYPE_X11 == nativeWindowingTypePure ) { + // passing through RuntimeException if not exists intended + x11ToolkitLockClass = ReflectionUtil.getClass(X11ToolkitLockClassName, false, cl); + x11ToolkitLockConstructor = ReflectionUtil.getConstructor(x11ToolkitLockClass, new Class[] { long.class } ); + if( isAWTAvailable() ) { + x11JAWTToolkitLockClass = ReflectionUtil.getClass(X11JAWTToolkitLockClassName, false, cl); + x11JAWTToolkitLockConstructor = ReflectionUtil.getConstructor(x11JAWTToolkitLockClass, new Class[] { long.class } ); + } + } + + if(DEBUG) { + System.err.println("NativeWindowFactory firstUIActionOnProcess "+firstUIActionOnProcess); + System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+", defaultFactory "+factory); + } } } - public static void initSingleton() { - // just exist to ensure static init has been run + /** @return true if initialized with <b>{@link #initSingleton(boolean) initSingleton(firstUIActionOnProcess==true)}</b>, + otherwise false. */ + public static boolean isFirstUIActionOnProcess() { + return isFirstUIActionOnProcess; } /** @return true if not headless, AWT Component and NativeWindow's AWT part available */ @@ -171,6 +247,91 @@ public abstract class NativeWindowFactory { return defaultFactory; } + /** + * Provides the system default {@link ToolkitLock}, a singleton instance. + * <br> + * This is a {@link com.jogamp.nativewindow.impl.jawt.JAWTToolkitLock} + * in case of a <b>X11 system</b> <em>and</em> <b>AWT availability</b> and if + * this factory has been initialized with <b>{@link #initSingleton(boolean) initSingleton(firstUIActionOnProcess==true)}</b>, <br> + * otherwise {@link com.jogamp.nativewindow.impl.NullToolkitLock} is returned. + */ + public static ToolkitLock getDefaultToolkitLock() { + return getDefaultToolkitLock(getNativeWindowType(false)); + } + + /** + * Provides the default {@link ToolkitLock} for <code>type</code>, a singleton instance. + * <br> + * This is a {@link com.jogamp.nativewindow.impl.jawt.JAWTToolkitLock} + * in case of a <b>X11 type</b> or <b>AWT type / X11 system</b> <em>and</em> <b>AWT availability</b> and if + * this factory has been initialized with <b>{@link #initSingleton(boolean) initSingleton(firstUIActionOnProcess==true)}</b>, <br> + * otherwise {@link com.jogamp.nativewindow.impl.NullToolkitLock} is returned. + */ + public static ToolkitLock getDefaultToolkitLock(String type) { + if( isAWTAvailable() && !isFirstUIActionOnProcess() && + ( TYPE_X11 == type || TYPE_AWT == type && TYPE_X11 == getNativeWindowType(false) ) ) { + return getAWTToolkitLock(); + } + return NativeWindowFactoryImpl.getNullToolkitLock(); + } + + protected static ToolkitLock getAWTToolkitLock() { + Object resO = ReflectionUtil.callMethod(null, jawtUtilGetJAWTToolkitMethod, null); + + if(resO instanceof ToolkitLock) { + return (ToolkitLock) resO; + } else { + throw new RuntimeException("JAWTUtil.getJAWTToolkitLock() didn't return a ToolkitLock"); + } + } + + public static ToolkitLock getNullToolkitLock() { + return NativeWindowFactoryImpl.getNullToolkitLock(); + } + /** + * Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>. + * <br> + * This is a {@link com.jogamp.nativewindow.impl.jawt.x11.X11JAWTToolkitLock} + * in case of a <b>X11 type</b> <em>and</em> <b>AWT availability</b> and if + * this factory has been initialized with <b>{@link #initSingleton(boolean) initSingleton(firstUIActionOnProcess==true)}</b>, <br> + * or a {@link com.jogamp.nativewindow.impl.x11.X11ToolkitLock} + * in case of a <b>X11 type</b> <em>and</em> <b>no AWT availability</b> and if + * this factory has been initialized with <b>{@link #initSingleton(boolean) initSingleton(firstUIActionOnProcess==true)}</b>, <br> + * otherwise {@link com.jogamp.nativewindow.impl.NullToolkitLock} is returned. + */ + public static ToolkitLock createDefaultToolkitLock(String type, long deviceHandle) { + if( TYPE_X11 == type ) { + if( 0== deviceHandle ) { + throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11"); + } + if( !isFirstUIActionOnProcess() ) { + if( isAWTAvailable() ) { + return createX11AWTToolkitLock(deviceHandle); + } else { + return createX11ToolkitLock(deviceHandle); + } + } + } + return NativeWindowFactoryImpl.getNullToolkitLock(); + } + + protected static ToolkitLock createX11AWTToolkitLock(long deviceHandle) { + try { + return (ToolkitLock) x11JAWTToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)}); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + protected static ToolkitLock createX11ToolkitLock(long deviceHandle) { + try { + return (ToolkitLock) x11ToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)}); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + /** Returns the appropriate NativeWindowFactory to handle window objects of the given type. The windowClass might be {@link NativeWindow NativeWindow}, in which case the client has diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java new file mode 100644 index 000000000..09c89ebe3 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java @@ -0,0 +1,45 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.nativewindow; + +import com.jogamp.nativewindow.impl.Debug; +import java.security.AccessController; + +/** + * Marker for a singleton global recursive blocking lock implementation, + * optionally locking a native windowing toolkit as well. + * <br> + * One use case is the AWT locking on X11, see {@link com.jogamp.nativewindow.impl.jawt.JAWTToolkitLock}. + */ +public interface ToolkitLock { + public static final boolean TRACE_LOCK = Debug.isPropertyDefined("nativewindow.TraceLock", true, AccessController.getContext()); + + public void lock(); + public void unlock(); +} diff --git a/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsDevice.java index d326b9159..e91261211 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/awt/AWTGraphicsDevice.java @@ -43,17 +43,18 @@ import javax.media.nativewindow.*; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import javax.media.nativewindow.AbstractGraphicsDevice; -import com.jogamp.nativewindow.impl.*; /** A wrapper for an AWT GraphicsDevice allowing it to be handled in a toolkit-independent manner. */ public class AWTGraphicsDevice extends DefaultGraphicsDevice implements Cloneable { private GraphicsDevice device; + private String subType; protected AWTGraphicsDevice(GraphicsDevice device) { super(NativeWindowFactory.TYPE_AWT); this.device = device; + this.subType = null; } public static AbstractGraphicsDevice createDevice(GraphicsDevice awtDevice) { @@ -73,14 +74,23 @@ public class AWTGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl /** * In case the native handle was specified, e.g. using X11, - * we shall be able to mark it. + * we shall be able to mark it.<br> + * This will also set the subType, queried with {@link #getSubType()} + * and reset the ToolkitLock type with {@link NativeWindowFactory#createDefaultToolkitLock(java.lang.String, long)} + * and {@link #setToolkitLock(javax.media.nativewindow.ToolkitLock)}. */ - public void setHandle(long handle) { + public void setSubType(String subType, long handle) { this.handle = handle; + this.subType = subType; + setToolkitLock( NativeWindowFactory.createDefaultToolkitLock(subType, handle) ); + } + + public String getSubType() { + return subType; } public String toString() { - return getClass().toString()+"[type "+getType()+", awtDevice "+device+", handle 0x"+Long.toHexString(getHandle())+"]"; + return getClass().toString()+"[type "+getType()+"[subType "+getSubType()+"], awtDevice "+device+", handle 0x"+Long.toHexString(getHandle())+"]"; } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java index 192abf775..31744702d 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsDevice.java @@ -33,14 +33,14 @@ 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. */ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable { - /** Constructs a new X11GraphicsDevice corresponding to the given native display handle. */ + /** Constructs a new X11GraphicsDevice corresponding to the given native display handle and default + * {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#createDefaultToolkitLock(java.lang.String, long)}. + */ public X11GraphicsDevice(long display) { super(NativeWindowFactory.TYPE_X11, display); if(0==display) { @@ -48,17 +48,19 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl } } - public Object clone() { - return super.clone(); - } - - public void lock() { - X11Util.XLockDisplay(handle); + /** + * @param display the Display connection + * @param locker custom {@link javax.media.nativewindow.ToolkitLock}, eg to force null locking in NEWT + */ + public X11GraphicsDevice(long display, ToolkitLock locker) { + super(NativeWindowFactory.TYPE_X11, display, locker); + if(0==display) { + throw new NativeWindowException("null display"); + } } - public void unlock() { - X11Util.XUnlockDisplay(handle); + public Object clone() { + return super.clone(); } - } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java index 97bdc37cf..73af5f852 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java @@ -34,7 +34,6 @@ package javax.media.nativewindow.x11; import javax.media.nativewindow.*; import com.jogamp.nativewindow.impl.x11.X11Util; -import com.jogamp.nativewindow.impl.x11.X11Lib; /** Encapsulates a screen index on X11 platforms. Objects of this type are passed to {@link @@ -57,21 +56,21 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl /** Creates a new X11GraphicsScreen using a thread local display connection */ public static AbstractGraphicsScreen createDefault() { long display = X11Util.createThreadLocalDisplay(null); - int scrnIdx = X11Lib.DefaultScreen(display); + int scrnIdx = X11Util.DefaultScreen(display); return createScreenDevice(display, scrnIdx); } public long getDefaultVisualID() { // It still could be an AWT hold handle .. long display = getDevice().getHandle(); - int scrnIdx = X11Lib.DefaultScreen(display); - return X11Lib.DefaultVisualID(display, scrnIdx); + int scrnIdx = X11Util.DefaultScreen(display); + return X11Util.DefaultVisualID(display, scrnIdx); } private static int fetchScreen(X11GraphicsDevice device, int screen) { // It still could be an AWT hold handle .. long display = device.getHandle(); - if(X11Lib.XineramaEnabled(display)) { + if(X11Util.XineramaEnabled(display)) { screen = 0; // Xinerama -> 1 screen } return screen; |