aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax/media/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/javax/media/opengl')
-rw-r--r--src/jogl/classes/javax/media/opengl/GLDrawableFactory.java25
-rw-r--r--src/jogl/classes/javax/media/opengl/GLProfile.java256
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java1
3 files changed, 162 insertions, 120 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 5fff1ce02..ff8d00ebe 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -89,7 +89,6 @@ import javax.media.opengl.GLProfile.ShutdownType;
property <code>opengl.factory.class.name</code> to the
fully-qualified name of the desired class. </P>
*/
-
public abstract class GLDrawableFactory {
private static final String nativeOSType;
@@ -274,18 +273,31 @@ public abstract class GLDrawableFactory {
}
/**
- * Returns true if a shared context could be created while initialization
- * of shared resources for <code>device</code> {@link AbstractGraphicsDevice#getConnection()}.<br>
- * This does not imply a shared context is mapped, but was available<br>.
+ * Validate and start the shared resource runner thread if necessary and
+ * if the implementation uses it.
+ *
+ * @return the shared resource runner thread, if implementation uses it.
+ */
+ protected abstract Thread getSharedResourceThread();
+
+ /**
+ * Create the shared resource used internally as a reference for capabilities etc.
+ * <p>
+ * Returns true if a shared resource could be created
+ * for the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}.<br>
+ * This does not imply a shared resource is mapped (ie. made persistent), but is available in general<br>.
+ * </p>
*
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+ * @return true if a shared resource could been created, otherwise false.
*/
- public abstract boolean getWasSharedContextCreated(AbstractGraphicsDevice device);
-
+ protected abstract boolean createSharedResource(AbstractGraphicsDevice device);
+
/**
* Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null
*/
public static GLDrawableFactory getDesktopFactory() {
+ initSingleton();
return nativeOSFactory;
}
@@ -293,6 +305,7 @@ public abstract class GLDrawableFactory {
* Returns the sole GLDrawableFactory instance for EGL if exist or null
*/
public static GLDrawableFactory getEGLFactory() {
+ initSingleton();
return eglFactory;
}
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index 7f0c9b3d3..d52fbcd16 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -48,6 +48,8 @@ import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.cache.TempJarCache;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveThreadGroupLock;
import com.jogamp.nativewindow.NativeWindowVersion;
import com.jogamp.opengl.JoglVersion;
@@ -80,65 +82,73 @@ public class GLProfile {
}
/**
- * Static one time initialization of JOGL.
+ * Static initialization of JOGL.
* <p>
* The parameter <code>firstUIActionOnProcess</code> has an impact on concurrent locking,<br>
* see {@link javax.media.nativewindow.NativeWindowFactory#initSingleton(boolean) NativeWindowFactory.initSingleton(firstUIActionOnProcess)}.
* </p>
* <p>
- * Applications shall call this methods <b>ASAP</b>, before any other UI invocation.<br>
- * You may issue the call in your <code>main class</code> static block, which is the earliest point in your application/applet lifecycle,
- * or within the <code>main function</code>.<br>
- * In case applications are able to initialize JOGL before any other UI action,<br>
- * they shall invoke this method with <code>firstUIActionOnProcess=true</code> and benefit from fast native multithreading support on all platforms if possible.</P>
+ * Applications using this method may place it's call before any other UI invocation
+ * in the <code>main class</code>'s static block or within the <code>main function</code>.
+ * In such case, applications may pass <code>firstUIActionOnProcess=true</code> to use native toolkit locking.</P>
* <P>
- * RCP Application (Applet's, Webstart, Netbeans, ..) using JOGL may not be able to initialize JOGL
- * before the first UI action.<br>
- * In such case you shall invoke this method with <code>firstUIActionOnProcess=false</code>.<br>
- * On some platforms, notably X11 with AWT usage, JOGL will utilize special locking mechanisms which may slow down your
- * application.</P>
+ * RCP Application (Applet's, Webstart, Netbeans, ..) using JOGL are not be able to initialize JOGL
+ * before the first UI action.
+ * In such case you shall pass <code>firstUIActionOnProcess=false</code>.</P>
* <P>
- * Remark: NEWT is currently not affected by this behavior, ie always uses native multithreading.</P>
- * <P>
- * However, in case this method is not invoked, hence GLProfile is not initialized explicitly by the user,<br>
- * the first call to {@link #getDefault()}, {@link #get(java.lang.String)}, etc, will initialize with <code>firstUIActionOnProcess=false</code>,<br>
- * hence without the possibility to enable native multithreading.<br>
- * This is not the recommended way, since it may has a performance impact, but it allows you to run code without explicit initialization.</P>
+ * In case this method is not invoked, GLProfile is initialized implicit by
+ * the first call to {@link #getDefault()}, {@link #get(java.lang.String)} passing <code>firstUIActionOnProcess=false</code>.
* <P>
*
* @param firstUIActionOnProcess Should be <code>true</code> if called before the first UI action of the running program,
* otherwise <code>false</code>.
+ *
+ * @deprecated This method shall not need to be called for other reasons than having a defined initialization sequence.
+ * To ensure homogeneous behavior with application not calling this method, you shall pass <code>firstUIActionOnProcess=false</code>.
+ * This method is subject to be removed in future versions of JOGL.
*/
public static void initSingleton(final boolean firstUIActionOnProcess) {
- if(!initialized) { // volatile: ok
- synchronized(GLProfile.class) {
- if(!initialized) {
- initialized = true;
- if(DEBUG) {
- System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName());
- Thread.dumpStack();
- }
- Platform.initSingleton();
-
- // run the whole static initialization privileged to speed up,
- // since this skips checking further access
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- if(TempJarCache.isInitialized()) {
- String[] atomicNativeJarBaseNames = new String[] { "nativewindow", "jogl", null };
- if( ReflectionUtil.isClassAvailable("com.jogamp.newt.NewtFactory", GLProfile.class.getClassLoader()) ) {
- atomicNativeJarBaseNames[2] = "newt";
- }
- JNILibLoaderBase.addNativeJarLibs(GLProfile.class, "jogl-all", atomicNativeJarBaseNames);
- }
- initProfilesForDefaultDevices(firstUIActionOnProcess);
- return null;
- }
- });
+ initLock.lock();
+ try {
+ if(!initialized) { // volatile: ok
+ initialized = true;
+ if(DEBUG) {
+ System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName());
+ Thread.dumpStack();
}
+ Platform.initSingleton();
+
+ // run the whole static initialization privileged to speed up,
+ // since this skips checking further access
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ if(TempJarCache.isInitialized()) {
+ String[] atomicNativeJarBaseNames = new String[] { "nativewindow", "jogl", null };
+ if( ReflectionUtil.isClassAvailable("com.jogamp.newt.NewtFactory", GLProfile.class.getClassLoader()) ) {
+ atomicNativeJarBaseNames[2] = "newt";
+ }
+ JNILibLoaderBase.addNativeJarLibs(GLProfile.class, "jogl-all", atomicNativeJarBaseNames);
+ }
+ initProfilesForDefaultDevices(firstUIActionOnProcess);
+ return null;
+ }
+ });
}
+ } finally {
+ initLock.unlock();
}
}
+
+ /**
+ * Static initialization of JOGL.
+ *
+ * <p>
+ * This method shall not need to be called for other reasons than having a defined initialization sequence.
+ * </p>
+ */
+ public static void initSingleton() {
+ GLProfile.initSingleton(false);
+ }
/**
* Trigger eager initialization of GLProfiles for the given device,
@@ -147,7 +157,7 @@ public class GLProfile {
* @throws GLException if no profile for the given device is available.
*/
public static void initProfiles(AbstractGraphicsDevice device) throws GLException {
- getProfileMap(device);
+ getProfileMap(device, true);
}
/**
@@ -168,26 +178,29 @@ public class GLProfile {
* Manual shutdown method, may be called after your last JOGL use
* within the running JVM.<br>
* It releases all temporary created resources, ie issues {@link javax.media.opengl.GLDrawableFactory#shutdown()}.<br>
- * The shutdown implementation is called via the JVM shutdown hook, if not manually invoked here.<br>
- * Invoke <code>shutdown(type)</code> manually is recommended, due to the unreliable JVM state within the shutdown hook.<br>
+ * The shutdown implementation is called via the JVM shutdown hook, if not manually invoked.<br>
+ * <p>
+ * This method shall not need to be called for other reasons than issuing a proper shutdown of resources.
+ * </p>
* @param type the shutdown type, see {@link ShutdownType}.
*/
public static void shutdown(ShutdownType type) {
- if(initialized) { // volatile: ok
- synchronized(GLProfile.class) {
- if(initialized) {
- initialized = false;
- if(DEBUG) {
- System.err.println("GLProfile.shutdown(type: "+type+") - thread "+Thread.currentThread().getName());
- Thread.dumpStack();
- }
- GLDrawableFactory.shutdown(type);
- if(ShutdownType.COMPLETE == type) {
- GLContext.shutdown();
- }
- NativeWindowFactory.shutdown();
+ initLock.lock();
+ try {
+ if(initialized) { // volatile: ok
+ initialized = false;
+ if(DEBUG) {
+ System.err.println("GLProfile.shutdown(type: "+type+") - thread "+Thread.currentThread().getName());
+ Thread.dumpStack();
+ }
+ GLDrawableFactory.shutdown(type);
+ if(ShutdownType.COMPLETE == type) {
+ GLContext.shutdown();
}
+ NativeWindowFactory.shutdown();
}
+ } finally {
+ initLock.unlock();
}
}
@@ -204,12 +217,13 @@ public class GLProfile {
* @return true if the profile is available for the device, otherwise false.
*/
public static boolean isAvailable(AbstractGraphicsDevice device, String profile) {
- try {
- return null != getProfileMap(device).get(profile);
- } catch (GLException gle) { /* profiles for device n/a */ }
- return false;
+ initSingleton();
+ return isAvailableImpl(getProfileMap(device, false), profile);
}
-
+ private static boolean isAvailableImpl(HashMap<String /*GLProfile_name*/, GLProfile> map, String profile) {
+ return null != map && null != map.get(profile);
+ }
+
/**
* Returns the availability of a profile on the default device.
*
@@ -234,74 +248,71 @@ public class GLProfile {
boolean avail;
StringBuffer sb = new StringBuffer();
- validateInitialization();
-
+ initSingleton();
+
if(null==device) {
device = defaultDevice;
}
-
+ final HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, false);
+
sb.append("GLAvailability[Native[GL4bc ");
- avail=isAvailable(device, GL4bc);
+ avail=isAvailableImpl(map, GL4bc);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_COMPAT);
}
sb.append(", GL4 ");
- avail=isAvailable(device, GL4);
+ avail=isAvailableImpl(map, GL4);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_CORE);
}
sb.append(", GL3bc ");
- avail=isAvailable(device, GL3bc);
+ avail=isAvailableImpl(map, GL3bc);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_COMPAT);
}
sb.append(", GL3 ");
- avail=isAvailable(device, GL3);
+ avail=isAvailableImpl(map, GL3);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_CORE);
}
sb.append(", GL2 ");
- avail=isAvailable(device, GL2);
+ avail=isAvailableImpl(map, GL2);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_COMPAT);
}
sb.append(", GL2ES1 ");
- sb.append(isAvailable(device, GL2ES1));
+ sb.append(isAvailableImpl(map, GL2ES1));
sb.append(", GLES1 ");
- avail=isAvailable(device, GLES1);
+ avail=isAvailableImpl(map, GLES1);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 1, GLContext.CTX_PROFILE_ES);
}
sb.append(", GL2ES2 ");
- sb.append(isAvailable(device, GL2ES2));
+ sb.append(isAvailableImpl(map, GL2ES2));
sb.append(", GLES2 ");
- avail=isAvailable(device, GLES2);
+ avail=isAvailableImpl(map, GLES2);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_ES);
}
sb.append("], Profiles[");
- HashMap<String /*GLProfile_name*/, GLProfile> profileMap = null;
- try {
- profileMap = getProfileMap(device);
- } catch (GLException gle) { /* profiles for device n/a */ }
- if(null != profileMap) {
- for(Iterator<GLProfile> i=profileMap.values().iterator(); i.hasNext(); ) {
+ if(null != map) {
+ for(Iterator<GLProfile> i=map.values().iterator(); i.hasNext(); ) {
sb.append(i.next().toString());
sb.append(", ");
}
@@ -316,7 +327,7 @@ public class GLProfile {
return sb.toString();
}
-
+
/** Uses the default device */
public static String glAvailabilityToString() {
return glAvailabilityToString(null);
@@ -637,7 +648,7 @@ public class GLProfile {
if(null==profile || profile.equals("GL")) {
profile = GL_DEFAULT;
}
- final HashMap<String /*GLProfile_name*/, GLProfile> glpMap = getProfileMap(device);
+ final HashMap<String /*GLProfile_name*/, GLProfile> glpMap = getProfileMap(device, true);
final GLProfile glp = glpMap.get(profile);
if(null == glp) {
throw new GLException("Profile "+profile+" is not available on "+device+", but: "+glpMap.values());
@@ -667,7 +678,7 @@ public class GLProfile {
public static GLProfile get(AbstractGraphicsDevice device, String[] profiles)
throws GLException
{
- HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device);
+ HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, true);
for(int i=0; i<profiles.length; i++) {
String profile = profiles[i];
GLProfile glProfile = map.get(profile);
@@ -1193,6 +1204,7 @@ public class GLProfile {
private static /*final*/ AbstractGraphicsDevice defaultEGLDevice;
private static volatile boolean initialized = false;
+ private static RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
/**
* Tries the profiles implementation and native libraries.
@@ -1332,19 +1344,24 @@ public class GLProfile {
* @param device the device for which profiles shall be initialized
* @return true if any profile for the device exists, otherwise false
*/
- private static synchronized boolean initProfilesForDevice(AbstractGraphicsDevice device) {
+ private static boolean initProfilesForDevice(AbstractGraphicsDevice device) {
if(null == device) {
return false;
}
- GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device);
- factory.enterThreadCriticalZone();
+ initLock.lock();
try {
- return initProfilesForDeviceCritical(device);
+ GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device);
+ factory.enterThreadCriticalZone();
+ try {
+ return initProfilesForDeviceCritical(device);
+ } finally {
+ factory.leaveThreadCriticalZone();
+ }
} finally {
- factory.leaveThreadCriticalZone();
+ initLock.unlock();
}
}
- private static synchronized boolean initProfilesForDeviceCritical(AbstractGraphicsDevice device) {
+ private static boolean initProfilesForDeviceCritical(AbstractGraphicsDevice device) {
boolean isSet = GLContext.getAvailableGLVersionsSet(device);
if(DEBUG) {
@@ -1368,7 +1385,14 @@ public class GLProfile {
// Triggers eager initialization of share context in GLDrawableFactory for the device,
// hence querying all available GLProfiles
- boolean desktopSharedCtxAvail = desktopFactory.getWasSharedContextCreated(device);
+ final Thread sharedResourceThread = desktopFactory.getSharedResourceThread();
+ if(null != sharedResourceThread) {
+ initLock.addOwner(sharedResourceThread);
+ }
+ boolean desktopSharedCtxAvail = desktopFactory.createSharedResource(device);
+ if(null != sharedResourceThread) {
+ initLock.removeOwner(sharedResourceThread);
+ }
if(!desktopSharedCtxAvail) {
hasDesktopGLFactory = false;
}
@@ -1390,7 +1414,14 @@ public class GLProfile {
// Triggers eager initialization of share context in GLDrawableFactory for the device,
// hence querying all available GLProfiles
- boolean eglSharedCtxAvail = eglFactory.getWasSharedContextCreated(device);
+ final Thread sharedResourceThread = eglFactory.getSharedResourceThread();
+ if(null != sharedResourceThread) {
+ initLock.addOwner(sharedResourceThread);
+ }
+ boolean eglSharedCtxAvail = eglFactory.createSharedResource(device);
+ if(null != sharedResourceThread) {
+ initLock.removeOwner(sharedResourceThread);
+ }
if(!eglSharedCtxAvail) {
// Remark: On Windows there is a libEGL.dll delivered w/ Chrome 15.0.874.121m and Firefox 8.0.1
// but it seems even EGL.eglInitialize(eglDisplay, null, null)
@@ -1471,30 +1502,20 @@ public class GLProfile {
}
public static AbstractGraphicsDevice getDefaultDevice() {
- validateInitialization();
+ initSingleton();
return defaultDevice;
}
public static AbstractGraphicsDevice getDefaultDesktopDevice() {
- validateInitialization();
+ initSingleton();
return defaultDesktopDevice;
}
public static AbstractGraphicsDevice getDefaultEGLDevice() {
- validateInitialization();
+ initSingleton();
return defaultEGLDevice;
}
- private static void validateInitialization() {
- if(!initialized) { // volatile: ok
- synchronized(GLProfile.class) {
- if(!initialized) {
- initSingleton(false);
- }
- }
- }
- }
-
private static String array2String(String[] list) {
StringBuffer msg = new StringBuffer();
msg.append("[");
@@ -1656,29 +1677,38 @@ public class GLProfile {
* - initialization<br<
*
* @param device the key 'device -> GLProfiles-Map'
+ * @param throwExceptionOnZeroProfile true if <code>GLException</code> shall be thrown in case of no mapped profile, otherwise false.
* @return the GLProfile HashMap if exists, otherwise null
* @throws GLException if no profile for the given device is available.
*/
- private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device) throws GLException {
- validateInitialization();
+ private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device, boolean throwExceptionOnZeroProfile)
+ throws GLException
+ {
+ initSingleton();
+
if(null==device) {
device = defaultDevice;
}
String deviceKey = device.getUniqueID();
HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey);
- if( null == map ) {
- if( !initProfilesForDevice(device) ) {
+ if( null != map ) {
+ return map;
+ }
+ if( !initProfilesForDevice(device) ) {
+ if( throwExceptionOnZeroProfile ) {
throw new GLException("No Profile available for "+device);
+ } else {
+ return null;
}
- if( null == deviceConn2ProfileMap.get(deviceKey) ) {
- throw new InternalError("initProfilesForDevice(..) didn't issue setProfileMap(..) on "+device);
- }
+ }
+ map = deviceConn2ProfileMap.get(deviceKey);
+ if( null == map && throwExceptionOnZeroProfile ) {
+ throw new InternalError("initProfilesForDevice(..) didn't setProfileMap(..) for "+device);
}
return map;
}
private static void setProfileMap(AbstractGraphicsDevice device, HashMap<String /*GLProfile_name*/, GLProfile> mappedProfiles) {
- validateInitialization();
synchronized ( deviceConn2ProfileMap ) {
deviceConn2ProfileMap.put(device.getUniqueID(), mappedProfiles);
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 329bb125e..ab4276dee 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -1047,7 +1047,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- GLProfile.initSingleton(false);
GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory();
List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(null);
for(int i=0; i<availCaps.size(); i++) {