aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2009-06-18 06:50:13 +0000
committerSven Gothel <[email protected]>2009-06-18 06:50:13 +0000
commit3c6a7838b1a647b42cc8b37d1a433ed9a1431860 (patch)
tree2ed11714feef306f04e1c34beb71591f34563e21 /src/nativewindow/classes
parent5607c14460e9e8abd2833517016f1dd3ec9c685c (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/nativewindow/classes')
-rw-r--r--src/nativewindow/classes/com/sun/nativewindow/impl/LockingNativeWindowFactory.java (renamed from src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11NativeWindowFactory.java)8
-rw-r--r--src/nativewindow/classes/com/sun/nativewindow/impl/jvm/JVMUtil.java78
-rw-r--r--src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java126
-rw-r--r--src/nativewindow/classes/com/sun/nativewindow/impl/x11/awt/X11AWTNativeWindowFactory.java2
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java61
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java6
6 files changed, 196 insertions, 85 deletions
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;