diff options
author | Sven Gothel <[email protected]> | 2009-06-18 06:50:13 +0000 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2009-06-18 06:50:13 +0000 |
commit | 3c6a7838b1a647b42cc8b37d1a433ed9a1431860 (patch) | |
tree | 2ed11714feef306f04e1c34beb71591f34563e21 /src | |
parent | 5607c14460e9e8abd2833517016f1dd3ec9c685c (diff) |
- Fix: X11 locking
The current thread default display or
the given display is being used,
hence it is no more required to use a ToolkitLock
for X11 without AWT.
Removed X11 ToolkitLock in case of X11 without AWT,
which is being detected with the absence of the classes
java.awt.Component _AND_ javax.media.nativewindow.awt.AWTGraphicsDevice
or with the system property
java.awt.headless=true
Only in the Java2D/Swing case, one 'leaking' Display
is created within canCreateGLPbuffer().
- Workaround for Hotsport bugs #4395095, #6852404
4395095 JNI access to java.nio DirectBuffer constructor/accessor
6852404 Race condition in JNI Direct Buffer access and creation routines
- Added build.xml
-Dbuild.noarchives=true property to skip the time consuming
creation of zip archives.
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1988 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src')
16 files changed, 331 insertions, 218 deletions
diff --git a/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java b/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java index b3d25b52c..8f21fef42 100644 --- a/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java +++ b/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java @@ -39,63 +39,18 @@ import javax.media.nativewindow.NativeWindowFactory; import com.sun.nativewindow.impl.x11.*; public class GLXUtil { - private static final boolean DEBUG = Debug.debug("GLXUtil"); - - private GLXUtil() {} - - // ATI's proprietary drivers apparently send GLX tokens even for - // direct contexts, so we need to disable the context optimizations - // in this case - private static boolean isVendorATI; - - // Display connection for use by visual selection algorithm and by all offscreen surfaces - private static boolean multisampleAvailable=false; - - private static volatile boolean isInit=false; - - private static synchronized void init() { - if (!isInit) { - synchronized (GLXUtil.class) { - if (!isInit) { - long locDisplay = X11Util.getThreadLocalDefaultDisplay(); - if(locDisplay!=0) { - if (DEBUG) { - int screen = X11Lib.DefaultScreen(locDisplay); - System.err.println("!!! GLX server vendor : " + - GLX.glXQueryServerString(locDisplay, screen, GLX.GLX_VENDOR)); - System.err.println("!!! GLX server version: " + - GLX.glXQueryServerString(locDisplay, screen, GLX.GLX_VERSION)); - System.err.println("!!! GLX client vendor : " + - GLX.glXGetClientString(locDisplay, GLX.GLX_VENDOR)); - System.err.println("!!! GLX client version: " + - GLX.glXGetClientString(locDisplay, GLX.GLX_VERSION)); - } - String vendor = GLX.glXGetClientString(locDisplay, GLX.GLX_VENDOR); - if (vendor != null && vendor.startsWith("ATI")) { - isVendorATI = true; - } - String exts = GLX.glXGetClientString(locDisplay, GLX.GLX_EXTENSIONS); - if (exts != null) { - multisampleAvailable = (exts.indexOf("GLX_ARB_multisample") >= 0); - } - isInit=true; - } else { - throw new GLException("Unable to open default display, needed for visual selection and offscreen surface handling"); - } - } - } + public static boolean isMultisampleAvailable(long display) { + String exts = GLX.glXGetClientString(display, GLX.GLX_EXTENSIONS); + if (exts != null) { + return (exts.indexOf("GLX_ARB_multisample") >= 0); } - } - - public static boolean isMultisampleAvailable() { - init(); - return multisampleAvailable; + return false; } /** Workaround for apparent issue with ATI's proprietary drivers where direct contexts still send GLX tokens for GL calls */ - public static boolean isVendorATI() { - init(); - return isVendorATI; + public static boolean isVendorATI(long display) { + String vendor = GLX.glXGetClientString(display, GLX.GLX_VENDOR); + return vendor != null && vendor.startsWith("ATI") ; } } diff --git a/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXContext.java b/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXContext.java index 921d305a8..7029b81b0 100644 --- a/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXContext.java @@ -134,6 +134,7 @@ public abstract class X11GLXContext extends GLContextImpl { } GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); long display = config.getScreen().getDevice().getHandle(); + isVendorATI = GLXUtil.isVendorATI(display); if(config.getFBConfigID()<0) { // not able to use FBConfig @@ -424,8 +425,7 @@ public abstract class X11GLXContext extends GLContextImpl { } public boolean isOptimizable() { - return (super.isOptimizable() && - !GLXUtil.isVendorATI()); + return (super.isOptimizable() && !isVendorATI); } //---------------------------------------------------------------------- @@ -436,4 +436,6 @@ public abstract class X11GLXContext extends GLContextImpl { return context; } + private boolean isVendorATI = false; + } diff --git a/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java index 404881329..83f671cb4 100644 --- a/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java @@ -288,7 +288,10 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem // FBConfig - public static GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg) { + // sgothel: The synchronized was added, due to bugs within the GLX implementation on my platform + // in regards to multithreading (FIXME). + + public synchronized static GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg, boolean isMultisampleEnabled) { int[] tmp = new int[1]; int val; val = glXGetFBConfig(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0); @@ -309,7 +312,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); - if (GLXUtil.isMultisampleAvailable()) { + if (isMultisampleEnabled) { res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); } @@ -333,7 +336,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return res; } - private static String glXGetFBConfigErrorCode(int err) { + private synchronized static String glXGetFBConfigErrorCode(int err) { switch (err) { case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION"; case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE"; @@ -341,7 +344,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } } - public static int glXGetFBConfig(long display, long cfg, int attrib, int[] tmp, int tmp_offset) { + public synchronized static int glXGetFBConfig(long display, long cfg, int attrib, int[] tmp, int tmp_offset) { if (display == 0) { throw new GLException("No display connection"); } @@ -376,7 +379,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return res; } - public static GLCapabilities XVisualInfo2GLCapabilities(GLProfile glp, long display, XVisualInfo info) { + public static GLCapabilities XVisualInfo2GLCapabilities(GLProfile glp, long display, XVisualInfo info, boolean isMultisampleEnabled) { int[] tmp = new int[1]; int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0); if (val == 0) { @@ -404,7 +407,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); - if (GLXUtil.isMultisampleAvailable()) { + if (isMultisampleEnabled) { res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0)); } diff --git a/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 1e2f2f185..9acf580c4 100644 --- a/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/sun/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -74,26 +74,27 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac long fbcfg = 0; int fbid = -1; - long display = x11Screen.getDevice().getHandle(); - int screen = x11Screen.getIndex(); - // Utilizing FBConfig // GLCapabilities capsFB = null; NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { + long display = x11Screen.getDevice().getHandle(); + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + long visID = X11Lib.DefaultVisualID(display, x11Screen.getIndex()); xvis = X11GLXGraphicsConfiguration.XVisualID2XVisualInfo(display, visID); - caps = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, xvis); + caps = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, xvis, isMultisampleAvailable); - int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(caps, true, GLXUtil.isMultisampleAvailable(), usePBuffer, 0, 0); + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(caps, true, isMultisampleAvailable, usePBuffer, 0, 0); int[] count = { -1 }; java.nio.LongBuffer fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); if (fbcfgsL == null || fbcfgsL.limit()<1) { throw new Exception("Could not fetch FBConfig for "+caps); } fbcfg = fbcfgsL.get(0); - capsFB = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfg); + capsFB = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfg, isMultisampleAvailable); int[] tmpID = new int[1]; fbid = X11GLXGraphicsConfiguration.glXGetFBConfig(display, fbcfg, GLX.GLX_FBCONFIG_ID, tmpID, 0); @@ -102,10 +103,10 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac if (xvis==null) { throw new GLException("Error: Choosen FBConfig has no visual"); } - } catch (Throwable t) { - } finally { + } catch (Throwable t) { + } finally { NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); - } + } return new X11GLXGraphicsConfiguration(x11Screen, (null!=capsFB)?capsFB:caps, caps, null, xvis, fbcfg, fbid); } @@ -163,12 +164,6 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac GLCapabilitiesChooser chooser, X11GraphicsScreen x11Screen, boolean usePBuffer) { - int screen = x11Screen.getIndex(); - AbstractGraphicsDevice absDevice = x11Screen.getDevice(); - long display = absDevice.getHandle(); - - int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, true, GLXUtil.isMultisampleAvailable(), usePBuffer, 0, 0); - int[] count = { -1 }; int recommendedIndex = -1; GLCapabilities[] caps = null; java.nio.LongBuffer fbcfgsL = null; @@ -181,6 +176,13 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac // NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { + int screen = x11Screen.getIndex(); + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, true, isMultisampleAvailable, usePBuffer, 0, 0); + int[] count = { -1 }; + fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); if (fbcfgsL == null || fbcfgsL.limit()<1) { if(DEBUG) { @@ -191,7 +193,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac recommendedIndex = 0; // 1st match is always recommended .. caps = new GLCapabilities[fbcfgsL.limit()]; for (int i = 0; i < fbcfgsL.limit(); i++) { - caps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i)); + caps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i), isMultisampleAvailable); } if(null==chooser) { @@ -228,22 +230,15 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilities capabilities, GLCapabilitiesChooser chooser, X11GraphicsScreen x11Screen) { - if (chooser == null) { chooser = new DefaultGLCapabilitiesChooser(); } - int screen = x11Screen.getIndex(); - AbstractGraphicsDevice absDevice = x11Screen.getDevice(); - long display = absDevice.getHandle(); - // Until we have a rock-solid visual selection algorithm written // in pure Java, we're going to provide the underlying window // system's selection to the chooser as a hint GLProfile glProfile = capabilities.getGLProfile(); - int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, false, GLXUtil.isMultisampleAvailable(), false, 0, 0); - XVisualInfo[] infos = null; GLCapabilities[] caps = null; int recommendedIndex = -1; XVisualInfo retXVisualInfo = null; @@ -251,6 +246,13 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); try { + int screen = x11Screen.getIndex(); + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, false, isMultisampleAvailable, false, 0, 0); + XVisualInfo[] infos = null; + XVisualInfo recommendedVis = GLX.glXChooseVisualCopied(display, screen, attribs, 0); if (DEBUG) { System.err.print("!!! glXChooseVisual recommended "); @@ -269,7 +271,7 @@ public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFac } caps = new GLCapabilities[infos.length]; for (int i = 0; i < infos.length; i++) { - caps[i] = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, infos[i]); + caps[i] = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, infos[i], isMultisampleAvailable); // Attempt to find the visual chosen by glXChooseVisual if (recommendedVis != null && recommendedVis.visualid() == infos[i].visualid()) { recommendedIndex = i; diff --git a/src/jogl/classes/com/sun/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/sun/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java index 78ff306aa..604bde46b 100644 --- a/src/jogl/classes/com/sun/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/sun/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java @@ -94,8 +94,10 @@ public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfiguration if(DEBUG) { System.err.println("X11AWTGLXGraphicsConfigurationFactory: using a thread local X11 display"); } - } else if(DEBUG) { - System.err.println("X11AWTGLXGraphicsConfigurationFactory: using AWT X11 display 0x"+Long.toHexString(displayHandle)); + } else { + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: using AWT X11 display 0x"+Long.toHexString(displayHandle)); + } } ((AWTGraphicsDevice)awtScreen.getDevice()).setHandle(displayHandle); x11Device = new X11GraphicsDevice(displayHandle); diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index 385006b75..ead5f6396 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.security.*; import com.sun.opengl.impl.*; import com.sun.nativewindow.impl.NWReflection; +import com.sun.nativewindow.impl.jvm.JVMUtil; /** * Specifies the the OpenGL profile. @@ -613,6 +614,8 @@ public class GLProfile implements Cloneable { * Throws an GLException if no profile could be found at all. */ static { + JVMUtil.initSingleton(); + boolean hasDesktopGL = false; boolean hasDesktopGLES12 = false; boolean hasNativeOSFactory = false; diff --git a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11NativeWindowFactory.java b/src/nativewindow/classes/com/sun/nativewindow/impl/LockingNativeWindowFactory.java index 1c67d6184..880fd8c7d 100644 --- a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11NativeWindowFactory.java +++ b/src/nativewindow/classes/com/sun/nativewindow/impl/LockingNativeWindowFactory.java @@ -30,14 +30,12 @@ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ -package com.sun.nativewindow.impl.x11; +package com.sun.nativewindow.impl; import javax.media.nativewindow.*; -import com.sun.nativewindow.impl.*; -public class X11NativeWindowFactory extends NativeWindowFactoryImpl { - // On X11 platforms we need to do some locking; this basic - // implementation should suffice for some simple window toolkits +public class LockingNativeWindowFactory extends NativeWindowFactoryImpl { + // Provides a generic basic and recursive locking mechanism for your discretion. private ToolkitLock toolkitLock = new ToolkitLock() { private Thread owner; private int recursionCount; diff --git a/src/nativewindow/classes/com/sun/nativewindow/impl/jvm/JVMUtil.java b/src/nativewindow/classes/com/sun/nativewindow/impl/jvm/JVMUtil.java new file mode 100644 index 000000000..a4bffb100 --- /dev/null +++ b/src/nativewindow/classes/com/sun/nativewindow/impl/jvm/JVMUtil.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.sun.nativewindow.impl.jvm; + +import java.nio.ByteBuffer; +import com.sun.nativewindow.impl.*; + +/** + * Currently this tool works around the Hotspot race condition bugs: + <PRE> + 4395095 JNI access to java.nio DirectBuffer constructor/accessor + 6852404 Race condition in JNI Direct Buffer access and creation routines + </PRE> + * + * Make sure to initialize this class as soon as possible, + * before doing any multithreading work. + * + */ +public class JVMUtil { + private static final boolean DEBUG = Debug.debug("JVMUtil"); + + static { + initSingleton(); + } + + private static volatile boolean isInit = false; + + public static synchronized void initSingleton() { + if(isInit) return; + isInit=true; + + NativeLibLoaderBase.loadNativeWindow("jvm"); + + ByteBuffer buffer = InternalBufferUtil.newByteBuffer(64); + if( ! initialize(buffer) ) { + throw new RuntimeException("Failed to initialize the JVMUtil "+Thread.currentThread().getName()); + } + if(DEBUG) { + Exception e = new Exception("JVMUtil.initSingleton() .. initialized "+Thread.currentThread().getName()); + e.printStackTrace(); + } + } + + private JVMUtil() {} + + private static native boolean initialize(java.nio.ByteBuffer buffer); +} + diff --git a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java index acd55a823..11343f3e1 100644 --- a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java @@ -33,6 +33,7 @@ package com.sun.nativewindow.impl.x11; import java.util.HashMap; +import java.util.Map; import javax.media.nativewindow.*; @@ -54,35 +55,112 @@ public class X11Util { private X11Util() {} - private static ThreadLocal currentDisplayAssociation = new ThreadLocal(); + private static ThreadLocal currentDisplayMap = new ThreadLocal(); - /** Returns the global static default display connection, read the toolkit lock/unlock - * requirements {@link X11Util above} for synchronization. */ - public static boolean isXineramaEnabledOnThreadLocalDefaultDisplay() { - long dpy = getThreadLocalDefaultDisplay(); - return X11Lib.XineramaEnabled(dpy); + public static class NamedDisplay implements Cloneable { + private String name; + private long handle; + + protected NamedDisplay(String name, long handle) { + this.name=name; + this.handle=handle; + } + + public String getName() { return name; } + public long getHandle() { return handle; } + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } + + /** 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. */ + /** Returns this thread current default display. If it doesn not exist, it is being created */ public static long getThreadLocalDefaultDisplay() { - Long dpyL = (Long) currentDisplayAssociation.get(); - if(null==dpyL) { - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - try { - long dpy = X11Lib.XOpenDisplay(null); - if(0==dpy) { - throw new NativeWindowException("Unable to create a default display connection on Thread "+Thread.currentThread().getName()); - } - dpyL = new Long(dpy); - currentDisplayAssociation.set( dpyL ); - if(DEBUG) { - Exception e = new Exception("Created new TLS display connection 0x"+Long.toHexString(dpy)+" for thread "+Thread.currentThread().getName()); - e.printStackTrace(); - } - } finally { - NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + return getThreadLocalDisplay(null); + } + + /** Returns this thread named display. If it doesn not exist, it is being created */ + public static long getThreadLocalDisplay(String name) { + NamedDisplay namedDpy = getCurrentDisplay(name); + if(null==namedDpy) { + long dpy = X11Lib.XOpenDisplay(name); + if(0==dpy) { + throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection in Thread "+Thread.currentThread().getName()); + } + namedDpy = new NamedDisplay(name, dpy); + setCurrentDisplay( namedDpy ); + if(DEBUG) { + Exception e = new Exception("X11Util.Display: Created new TLS display("+name+") connection 0x"+Long.toHexString(dpy)+" in thread "+Thread.currentThread().getName()); + e.printStackTrace(); } } - return dpyL.longValue(); + return namedDpy.getHandle(); } + + /** Closes this thread named display. It returns the handle of the closed display or 0, if it does not exist. */ + public static long closeThreadLocalDisplay(String name) { + NamedDisplay namedDpy = removeCurrentDisplay(name); + if(null==namedDpy) { + if(DEBUG) { + Exception e = new Exception("X11Util.Display: Display("+name+") with given handle is not mapped to TLS in thread "+Thread.currentThread().getName()); + e.printStackTrace(); + } + return 0; + } + long dpy = namedDpy.getHandle(); + X11Lib.XCloseDisplay(dpy); + if(DEBUG) { + Exception e = new Exception("X11Util.Display: Closed TLS Display("+name+") with handle 0x"+Long.toHexString(dpy)+" in thread "+Thread.currentThread().getName()); + e.printStackTrace(); + } + return dpy; + } + + private static Map getCurrentDisplayMapImpl() { + Map displayMap = (Map) currentDisplayMap.get(); + if(null==displayMap) { + displayMap = new HashMap(); + currentDisplayMap.set( displayMap ); + } + return displayMap; + } + + /** maps the given display to the thread local display map + * and notifies all threads synchronized to this display map. */ + private static NamedDisplay setCurrentDisplay(NamedDisplay newDisplay) { + Map displayMap = getCurrentDisplayMapImpl(); + NamedDisplay oldDisplay = null; + synchronized(displayMap) { + String name = (null==newDisplay.getName())?"nil":newDisplay.getName(); + oldDisplay = (NamedDisplay) displayMap.put(name, newDisplay); + displayMap.notifyAll(); + } + return oldDisplay; + } + + /** removes the mapping of the given name from the thread local display map + * and notifies all threads synchronized to this display map. */ + private static NamedDisplay removeCurrentDisplay(String name) { + Map displayMap = getCurrentDisplayMapImpl(); + NamedDisplay oldDisplay = null; + synchronized(displayMap) { + if(null==name) name="nil"; + oldDisplay = (NamedDisplay) displayMap.remove(name); + displayMap.notifyAll(); + } + return oldDisplay; + } + + /** Returns the thread local display mapped to the given name */ + private static NamedDisplay getCurrentDisplay(String name) { + if(null==name) name="nil"; + Map displayMap = getCurrentDisplayMapImpl(); + return (NamedDisplay) displayMap.get(name); + } + } diff --git a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java b/src/nativewindow/classes/com/sun/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java index 53b82ce08..dff733735 100644 --- a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java +++ b/src/nativewindow/classes/com/sun/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java @@ -42,7 +42,7 @@ import com.sun.nativewindow.impl.jawt.*; import com.sun.nativewindow.impl.jawt.x11.*; import com.sun.nativewindow.impl.x11.*; -public class X11AWTNativeWindowFactory extends X11NativeWindowFactory { +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 diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index 39ec18bc4..d12c43230 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -37,6 +37,7 @@ import java.security.*; import java.util.*; import com.sun.nativewindow.impl.*; +import com.sun.nativewindow.impl.jvm.JVMUtil; /** Provides a pluggable mechanism for arbitrary window toolkits to adapt their components to the {@link NativeWindow} interface, @@ -94,6 +95,8 @@ public abstract class NativeWindowFactory { } static { + JVMUtil.initSingleton(); + // Gather the windowing OS first nativeOSNamePure = System.getProperty("os.name"); nativeOSNameCustom = System.getProperty("nativewindow.ws.name"); @@ -124,15 +127,11 @@ public abstract class NativeWindowFactory { } catch (Exception e) { } } - boolean toolkitLockDisabled = Boolean.getBoolean("nativewindow.toolkitlock.disabled"); // test .. + boolean toolkitLockDisabled = Boolean.getBoolean("java.awt.headless"); - if(TYPE_X11.equals(nativeWindowingTypeCustom) && !toolkitLockDisabled) { + if( !toolkitLockDisabled && TYPE_X11.equals(nativeWindowingTypeCustom) ) { NativeWindowFactory _factory = null; - // FIXME: there are regressions in functionality in the - // JOGL 2 rewrite compared to JOGL 1.1.1 which are - // described in the writeup below. - // // There are certain operations that may be done by // user-level native code which must share the display // connection with the underlying window toolkit. In JOGL, @@ -145,33 +144,11 @@ public abstract class NativeWindowFactory { // makes X calls from multiple threads: for example, the // AWT Toolkit thread and one or more Event Dispatch // Threads. - // CHECK: OK - // - // In the JOGL API, there are other operations that use an - // X display connection which do not involve locking an - // on-screen window created by the toolkit: visual - // selection, pbuffers, external contexts and external - // drawables. // - // The JOGL GLPbuffer implementation uses its own display - // connection via "XOpenDisplay(null)". This was true even - // in JOGL 1.1.1. It is believed, but not 100% clear, - // whether X implementations are robust enough to handle - // the opening of a new display connection in a - // multithreaded fashion with no synchronization. - // (Semantically this should be allowed, but practically, - // it is unclear.) Currently the JOGL implementation locks - // the ToolkitLock around pbuffer-related operations. - // CHECK: OK - Using X11GraphicsScreen.createDefault() now, - // utilizing one display per thread. - // However, locking code is still intact. - // FIXME: Shall it really have one new display per - // Pbuffer ? - // - // Even if the pbuffer case is over-synchronized, there - // are definitely cases where synchronization with the - // toolkit is required. From recollection, visual - // selection is performed outside of the cover of the + // There are cases where synchronization with the + // toolkit is required in case of a shared resource pattern, + // e.g. with AWT. From recollection, visual selection is + // performed outside of the cover of the // toolkit's lock, and the toolkit's display connection is // used for this operation, so for correctness the toolkit // must be locked during glXChooseFBConfig / @@ -208,26 +185,6 @@ public abstract class NativeWindowFactory { } catch (Exception e) { } } - // If it turns out that the AWT is not available, for - // example on embedded profiles (CDC / FP), then - // synchronization is still needed, for example among - // multiple threads that might create pbuffers - // or for threads using the static default display to query information. - // The X11NativeWindowFactory provides a simple reentrant lock - // for this purpose. It is expected that third-party - // toolkits will either replace this factory, and thereby - // the implementation of this lock, if stronger - // interoperability is desired, for example full support - // for external GLDrawables. - if (null ==_factory) { - // Try the non-AWT X11 native window factory - try { - Constructor factoryConstructor = - NWReflection.getConstructor("com.sun.nativewindow.impl.x11.X11NativeWindowFactory", new Class[] {}); - _factory = (NativeWindowFactory) factoryConstructor.newInstance(null); - } catch (Exception e) { } - } - if (null !=_factory) { factory = _factory; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java index 03121dfaa..34bc48f99 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java @@ -46,7 +46,7 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl /** Constructs a new X11GraphicsScreen corresponding to the given native screen index. */ public X11GraphicsScreen(X11GraphicsDevice device, int screen) { - super(device, fetchScreen(screen)); + super(device, fetchScreen(device, screen)); } public static AbstractGraphicsScreen createScreenDevice(long display, int screenIdx) { @@ -73,8 +73,8 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl } } - private static int fetchScreen(int screen) { - if(!com.sun.nativewindow.impl.x11.X11Util.isXineramaEnabledOnThreadLocalDefaultDisplay()) { + private static int fetchScreen(X11GraphicsDevice device, int screen) { + if(!X11Lib.XineramaEnabled(device.getHandle())) { return screen; } return 0; diff --git a/src/nativewindow/native/JVM_Tool.c b/src/nativewindow/native/JVM_Tool.c new file mode 100644 index 000000000..e04032aa2 --- /dev/null +++ b/src/nativewindow/native/JVM_Tool.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2003 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 + * MIDROSYSTEMS, 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. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +#include <jni.h> + +JNIEXPORT jboolean JNICALL +Java_com_sun_nativewindow_impl_jvm_JVMUtil_initialize(JNIEnv *env, jclass _unused, jobject nioBuffer) { + int res; + void * ptr = NULL; + if (nioBuffer != NULL) { + ptr = (void *) (*env)->GetDirectBufferAddress(env, nioBuffer); + } + return ( NULL==ptr ) ? JNI_FALSE : JNI_TRUE ; +} + diff --git a/src/newt/classes/com/sun/javafx/newt/NewtFactory.java b/src/newt/classes/com/sun/javafx/newt/NewtFactory.java index c9b230355..5eae559aa 100755 --- a/src/newt/classes/com/sun/javafx/newt/NewtFactory.java +++ b/src/newt/classes/com/sun/javafx/newt/NewtFactory.java @@ -36,11 +36,13 @@ package com.sun.javafx.newt; import javax.media.nativewindow.*; import java.util.ArrayList; import java.util.Iterator; +import com.sun.nativewindow.impl.jvm.JVMUtil; public abstract class NewtFactory { // Work-around for initialization order problems on Mac OS X // between native Newt and (apparently) Fmod static { + JVMUtil.initSingleton(); Window.init(NativeWindowFactory.getNativeWindowType(true)); } diff --git a/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java b/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java index 99c0f599c..050b9b24d 100755 --- a/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java +++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java @@ -33,10 +33,11 @@ package com.sun.javafx.newt.x11; -import com.sun.javafx.newt.*; -import com.sun.javafx.newt.impl.*; import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import com.sun.nativewindow.impl.x11.X11Util; public class X11Display extends Display { static { @@ -65,15 +66,23 @@ public class X11Display extends Display { } protected void createNative() { - long handle= CreateDisplay(name); + long handle= X11Util.getThreadLocalDisplay(name); if (handle == 0 ) { throw new RuntimeException("Error creating display: "+name); } + try { + CompleteDisplay(handle); + } catch(RuntimeException e) { + X11Util.closeThreadLocalDisplay(name); + throw e; + } aDevice = new X11GraphicsDevice(handle); } protected void closeNative() { - DestroyDisplay(getHandle()); + if(0==X11Util.closeThreadLocalDisplay(name)) { + throw new NativeWindowException(this+" was not mapped"); + } } protected void dispatchMessages() { @@ -88,12 +97,11 @@ public class X11Display extends Display { // private static native boolean initIDs(); - private native long CreateDisplay(String name); - private native void DestroyDisplay(long handle); + private native void CompleteDisplay(long handle); private native void DispatchMessages(long display, long javaObjectAtom, long windowDeleteAtom); - private void displayCreated(long javaObjectAtom, long windowDeleteAtom) { + private void displayCompleted(long javaObjectAtom, long windowDeleteAtom) { this.javaObjectAtom=javaObjectAtom; this.windowDeleteAtom=windowDeleteAtom; } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index c239dd780..8651a8cea 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -156,7 +156,7 @@ static jmethodID windowCreatedID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; -static jmethodID displayCreatedID = NULL; +static jmethodID displayCompletedID = NULL; static void _throwNewRuntimeException(JNIEnv *env, const char* msg, ...) { @@ -184,8 +184,8 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Display_initIDs { jclass c; - displayCreatedID = (*env)->GetMethodID(env, clazz, "displayCreated", "(JJ)V"); - if (displayCreatedID == NULL) { + displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V"); + if (displayCompletedID == NULL) { return JNI_FALSE; } @@ -223,60 +223,34 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Display_initIDs /* * Class: com_sun_javafx_newt_x11_X11Display - * Method: CreateDisplay - * Signature: (Ljava/lang/String;)J + * Method: CompleteDisplay + * Signature: (J)V */ -JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Display_CreateDisplay - (JNIEnv *env, jobject obj, jstring displayName) +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_CompleteDisplay + (JNIEnv *env, jobject obj, jlong display) { - Display * dpy = NULL; - const char * _displayName = NULL; + Display * dpy = (Display *)(intptr_t)display; jlong javaObjectAtom; jlong windowDeleteAtom; - if(displayName!=0) { - _displayName = (*env)->GetStringUTFChars(env, displayName, 0); - } - DBG_PRINT1("open display connection for %s ..\n", ((NULL==_displayName)?"NULL":_displayName)); - dpy = XOpenDisplay(_displayName); if(dpy==NULL) { - _throwNewRuntimeException(env, "couldn't open display connection for %s\n", ((NULL==_displayName)?"NULL":_displayName)); - } - if(_displayName!=0) { - (*env)->ReleaseStringChars(env, displayName, (const jchar *)_displayName); + _throwNewRuntimeException(env, "given display connection is NULL\n"); } javaObjectAtom = (jlong) XInternAtom(dpy, "JOGL_JAVA_OBJECT", False); if(None==javaObjectAtom) { - XCloseDisplay(dpy); _throwNewRuntimeException(env, "could not create Atom JOGL_JAVA_OBJECT, bail out!\n"); - return 0; + return; } windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False); if(None==windowDeleteAtom) { - XCloseDisplay(dpy); _throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!\n"); - return 0; + return; } - DBG_PRINT1("X11Display_CreateDisplay dpy %p\n", dpy); - - (*env)->CallVoidMethod(env, obj, displayCreatedID, javaObjectAtom, windowDeleteAtom); + DBG_PRINT1("X11Display_completeDisplay dpy %p\n", dpy); - return (jlong) (intptr_t) dpy; -} - -/* - * Class: com_sun_javafx_newt_x11_X11Display - * Method: DestroyDisplay - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_DestroyDisplay - (JNIEnv *env, jobject obj, jlong display) -{ - Display * dpy = (Display *)(intptr_t)display; - DBG_PRINT1("X11Display_DestroyDisplay dpy %p\n", dpy); - XCloseDisplay(dpy); + (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom); } static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { |