diff options
author | Sven Gothel <[email protected]> | 2010-11-14 09:04:45 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-11-14 09:04:45 +0100 |
commit | 83d3a3f2ea8dc328e621b3abbe671f46379c7e65 (patch) | |
tree | b7fafe2ef1610a6be0723316ae5bf5938b9f222d /src/jogl/classes/javax | |
parent | c3bfb82614e9fa0f8ea7169cd412a6f0c71973e0 (diff) |
JOGL: Complete eager and lazy mapping of GLProfiles in respect to multiple device.
AbstractGraphicsDevice's 'connection' and 'type' attribute is used as a unique key
to map GLProfiles and GLContext's major/profile -> major/minor/profile mapping.
Eager initialiaztion as well as lazy is supported to maintain a simple API.
This is currently tested on X11, where one app display NEWT/GL window and content
on the local and remote device.
See TestRemoteWindow01NEWT.java and TestRemoteGLWindows01NEWT.java
Diffstat (limited to 'src/jogl/classes/javax')
6 files changed, 740 insertions, 321 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java index 4368add3f..d48b95c79 100644 --- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java +++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java @@ -81,7 +81,7 @@ public class GLCapabilities extends Capabilities implements Cloneable { * @param glp GLProfile, or null for the default GLProfile */ public GLCapabilities(GLProfile glp) { - glProfile = (null!=glp)?glp:GLProfile.getDefault(); + glProfile = (null!=glp)?glp:GLProfile.getDefault(GLProfile.getDefaultDevice()); } public Object clone() { diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index 2f63d5c8e..34ac8e93b 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -40,9 +40,10 @@ package javax.media.opengl; +import com.jogamp.opengl.impl.Debug; import java.util.HashMap; -import com.jogamp.common.util.IntIntHashMap; -import com.jogamp.common.util.IntObjectHashMap; +import java.util.HashSet; +import javax.media.nativewindow.AbstractGraphicsDevice; /** Abstraction for an OpenGL rendering context. In order to perform OpenGL rendering, a context must be "made current" on the current @@ -56,8 +57,9 @@ import com.jogamp.common.util.IntObjectHashMap; process is handled by the implementation, and the GLContext abstraction provides a stable object which clients can use to refer to a given context. */ - public abstract class GLContext { + protected static final boolean DEBUG0 = Debug.debug("GLContext"); + /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}. */ public static final int CONTEXT_NOT_CURRENT = 0; /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}. */ @@ -65,6 +67,21 @@ public abstract class GLContext { /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}. */ public static final int CONTEXT_CURRENT_NEW = 2; + /** <code>ARB_create_context</code> related: created via ARB_create_context */ + protected static final int CTX_IS_ARB_CREATED = 1 << 0; + /** <code>ARB_create_context</code> related: compatibility profile */ + protected static final int CTX_PROFILE_COMPAT = 1 << 1; + /** <code>ARB_create_context</code> related: core profile */ + protected static final int CTX_PROFILE_CORE = 1 << 2; + /** <code>ARB_create_context</code> related: ES profile */ + protected static final int CTX_PROFILE_ES = 1 << 3; + /** <code>ARB_create_context</code> related: flag forward compatible */ + protected static final int CTX_OPTION_FORWARD = 1 << 4; + /** <code>ARB_create_context</code> related: not flag forward compatible */ + protected static final int CTX_OPTION_ANY = 1 << 5; + /** <code>ARB_create_context</code> related: flag debug */ + protected static final int CTX_OPTION_DEBUG = 1 << 6; + private static ThreadLocal currentContext = new ThreadLocal(); private HashMap/*<int, Object>*/ attachedObjects = new HashMap(); @@ -72,6 +89,26 @@ public abstract class GLContext { /** The underlying native OpenGL context */ protected long contextHandle; + protected GLContext() { + resetStates(); + } + + protected int ctxMajorVersion; + protected int ctxMinorVersion; + protected int ctxOptions; + protected String ctxVersionString; + + protected void resetStates() { + ctxMajorVersion=-1; + ctxMinorVersion=-1; + ctxOptions=0; + ctxVersionString=null; + if(null!=attachedObjects) { + attachedObjects.clear(); + } + contextHandle=0; + } + /** * Returns the GLDrawable to which this context may be used to * draw. @@ -225,6 +262,8 @@ public abstract class GLContext { /** * Returns the GL pipeline object for this GLContext. + * + * @return the aggregated GL instance, or null if this context was not yet made current. */ public abstract GL getGL(); @@ -371,41 +410,26 @@ public abstract class GLContext { return ctxVersionString; } - protected int ctxMajorVersion=-1; - protected int ctxMinorVersion=-1; - protected int ctxOptions=0; - protected String ctxVersionString=null; - - /** <code>ARB_create_context</code> related: created via ARB_create_context */ - protected static final int CTX_IS_ARB_CREATED = 1 << 0; - /** <code>ARB_create_context</code> related: compatibility profile */ - protected static final int CTX_PROFILE_COMPAT = 1 << 1; - /** <code>ARB_create_context</code> related: core profile */ - protected static final int CTX_PROFILE_CORE = 1 << 2; - /** <code>ARB_create_context</code> related: ES profile */ - protected static final int CTX_PROFILE_ES = 1 << 3; - /** <code>ARB_create_context</code> related: flag forward compatible */ - protected static final int CTX_OPTION_FORWARD = 1 << 4; - /** <code>ARB_create_context</code> related: not flag forward compatible */ - protected static final int CTX_OPTION_ANY = 1 << 5; - /** <code>ARB_create_context</code> related: flag debug */ - protected static final int CTX_OPTION_DEBUG = 1 << 6; - - public final boolean isGL4bc() { - return ctxMajorVersion>=4 && 0!=(ctxOptions & CTX_PROFILE_COMPAT); + return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) + && 0 != (ctxOptions & CTX_PROFILE_COMPAT); } public final boolean isGL4() { - return ctxMajorVersion>=4 && 0!=(ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)); + return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) + && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)); } public final boolean isGL3bc() { - return ctxMajorVersion>=3 && 0!=(ctxOptions & CTX_PROFILE_COMPAT); + return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + && 0 != (ctxOptions & CTX_IS_ARB_CREATED) + && 0 != (ctxOptions & CTX_PROFILE_COMPAT); } public final boolean isGL3() { - return ctxMajorVersion>=3 && 0!=(ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)); + return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + && 0 != (ctxOptions & CTX_IS_ARB_CREATED) + && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)); } public final boolean isGL2() { @@ -483,18 +507,122 @@ public abstract class GLContext { return true; } + protected static int compose8bit(int one, int two, int three, int four) { + return ( ( one & 0x000000FF ) << 24 ) | + ( ( two & 0x000000FF ) << 16 ) | + ( ( three & 0x000000FF ) << 8 ) | + ( ( four & 0x000000FF ) ) ; + } + + protected static int getComposed8bit(int bits32, int which ) { + switch (which) { + case 1: return ( bits32 & 0xFF000000 ) >> 24 ; + case 2: return ( bits32 & 0x00FF0000 ) >> 16 ; + case 3: return ( bits32 & 0x0000FF00 ) >> 8 ; + case 4: return ( bits32 & 0xFF0000FF ) ; + } + throw new GLException("argument which out of range: "+which); + } + + protected static String composed8BitToString(int bits32, boolean hex1, boolean hex2, boolean hex3, boolean hex4) { + int a = getComposed8bit(bits32, 1); + int b = getComposed8bit(bits32, 2); + int c = getComposed8bit(bits32, 3); + int d = getComposed8bit(bits32, 4); + return "["+toString(a, hex1)+", "+toString(b, hex2)+", "+toString(c, hex3)+", "+toString(d, hex4)+"]"; + } + + private static void validateProfileBits(int bits, String argName) { + int num = 0; + if( 0 != ( CTX_PROFILE_COMPAT & bits ) ) { num++; } + if( 0 != ( CTX_PROFILE_CORE & bits ) ) { num++; } + if( 0 != ( CTX_PROFILE_ES & bits ) ) { num++; } + if(1!=num) { + throw new GLException("Internal Error: "+argName+": 1 != num-profiles: "+num); + } + } + + // + // version mapping + // + /** - * @param major Key Value either 1, 2, 3 or 4 + * @see #getDeviceVersionAvailableKey(javax.media.nativewindow.AbstractGraphicsDevice, int, int) + */ + protected static /*final*/ HashMap/*<DeviceVersionAvailableKey, Integer>*/ deviceVersionAvailable = new HashMap(); + + /** + * @see #getUniqueDeviceString(javax.media.nativewindow.AbstractGraphicsDevice) + */ + private static /*final*/ HashSet/*<UniqueDeviceString>*/ deviceVersionsAvailableSet = new HashSet(); + + protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctp) { + return getUniqueDeviceString(device) + "-" + toHexString(compose8bit(major, minor, ctp, 0)); + } + + protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) { + return getUniqueDeviceString(device) + "-" + toHexString(compose8bit(major, profile, 0, 0)); + } + + protected static String getUniqueDeviceString(AbstractGraphicsDevice device) { + return device.getType() + "_" + device.getConnection() ; + } + + protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { + synchronized ( deviceVersionsAvailableSet ) { + return deviceVersionsAvailableSet.contains(getUniqueDeviceString(device)); + } + } + + protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) { + synchronized ( deviceVersionsAvailableSet ) { + String devKey = getUniqueDeviceString(device); + if ( deviceVersionsAvailableSet.contains(devKey) ) { + throw new InternalError("Already set: "+devKey); + } + deviceVersionsAvailableSet.add(devKey); + if (DEBUG0) { + String msg = getThreadName() + ": !!! createContextARB: SET mappedVersionsAvailableSet "+devKey; + Throwable t = new Throwable(msg); + t.printStackTrace(); + // System.err.println(msg); + } + } + } + + /** + * Called by {@link com.jogamp.opengl.impl.GLContextImpl#createContextARBMapVersionsAvailable} not intended to be used by + * implementations. However, if {@link #createContextARB} is not being used within + * {@link javax.media.opengl.GLDrawableFactory#getOrCreateSharedContext(javax.media.nativewindow.AbstractGraphicsDevice)}, + * GLProfile has to map the available versions. + * + * @param reqMajor Key Value either 1, 2, 3 or 4 * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} + * @return the old mapped value + * + * @see #createContextARBMapVersionsAvailable */ - public static final String getGLVersionAvailable(int major, int profile) { - int _major[] = { 0 }; - int _minor[] = { 0 }; - int _ctp[] = { 0 }; - if(getGLVersionAvailable(major, profile, _major, _minor, _ctp)) { - return getGLVersion(_major[0], _minor[0], _ctp[0], null); + protected static Integer mapAvailableGLVersion(AbstractGraphicsDevice device, + int reqMajor, int profile, int resMajor, int resMinor, int resCtp) + { + validateProfileBits(profile, "profile"); + validateProfileBits(resCtp, "resCtp"); + + String key = getDeviceVersionAvailableKey(device, reqMajor, profile); + Integer val = new Integer(compose8bit(resMajor, resMinor, resCtp, 0)); + synchronized(deviceVersionAvailable) { + val = (Integer) deviceVersionAvailable.put( key, val ); } - return null; + return val; + } + + protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int profile) { + String key = getDeviceVersionAvailableKey(device, reqMajor, profile); + Integer val; + synchronized(deviceVersionAvailable) { + val = (Integer) deviceVersionAvailable.get( key ); + } + return val; } /** @@ -504,15 +632,16 @@ public abstract class GLContext { * @param minor if not null, returns the used minor version * @param ctp if not null, returns the used context profile */ - public static final boolean getGLVersionAvailable(int reqMajor, int reqProfile, int[] major, int minor[], int ctp[]) { - int key = compose8bit(reqMajor, reqProfile, 0, 0); - int val; - synchronized(mappedVersionsAvailableLock) { - val = mappedVersionsAvailable.get( key ); - } - if(val<=0) { + protected static boolean getAvailableGLVersion(AbstractGraphicsDevice device, + int reqMajor, int reqProfile, int[] major, int minor[], int ctp[]) { + + Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile); + if(null==valI) { return false; } + + int val = valI.intValue(); + if(null!=major) { major[0] = getComposed8bit(val, 1); } @@ -529,14 +658,51 @@ public abstract class GLContext { * @param major Key Value either 1, 2, 3 or 4 * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} */ - public static final boolean isGLVersionAvailable(int major, int profile) { - return getGLVersionAvailable(major, profile, null, null, null); + public static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int major, int profile) { + return null != getAvailableGLVersion(device, major, profile); + } + + public static boolean isGLES1Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES); + } + + public static boolean isGLES2Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES); + } + + public static boolean isGL4bcAvailable(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT); + } + + public static boolean isGL4Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE); + } + + public static boolean isGL3bcAvailable(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT); + } + + public static boolean isGL3Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE); + } + + public static boolean isGL2Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT); + } + + /** + * @param major Key Value either 1, 2, 3 or 4 + * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} + */ + public static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) { + int _major[] = { 0 }; + int _minor[] = { 0 }; + int _ctp[] = { 0 }; + if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) { + return getGLVersion(_major[0], _minor[0], _ctp[0], null); + } + return null; } - public static final boolean isGL4bcAvailable() { return isGLVersionAvailable(4, CTX_PROFILE_COMPAT); } - public static final boolean isGL4Available() { return isGLVersionAvailable(4, CTX_PROFILE_CORE); } - public static final boolean isGL3bcAvailable() { return isGLVersionAvailable(3, CTX_PROFILE_COMPAT); } - public static final boolean isGL3Available() { return isGLVersionAvailable(3, CTX_PROFILE_CORE); } - public static final boolean isGL2Available() { return isGLVersionAvailable(2, CTX_PROFILE_COMPAT); } public static String getGLVersion(int major, int minor, int ctp, String gl_version) { boolean needColon = false; @@ -560,83 +726,6 @@ public abstract class GLContext { return sb.toString(); } - protected static final Object mappedVersionsAvailableLock; - protected static final IntIntHashMap mappedVersionsAvailable; - protected static volatile boolean mappedVersionsAvailableSet; - - protected static final Object mappedProcAddressLock; - protected static final IntObjectHashMap mappedGLProcAddress; - protected static final IntObjectHashMap mappedGLXProcAddress; - - static { - mappedVersionsAvailableLock = new Object(); - mappedVersionsAvailableSet = false; - mappedVersionsAvailable = new IntIntHashMap(); - mappedVersionsAvailable.setKeyNotFoundValue(-1); - mappedProcAddressLock = new Object(); - mappedGLProcAddress = new IntObjectHashMap(); - mappedGLProcAddress.setKeyNotFoundValue(null); - mappedGLXProcAddress = new IntObjectHashMap(); - mappedGLXProcAddress.setKeyNotFoundValue(null); - } - - private static void validateProfileBits(int bits, String argName) { - int num = 0; - if( 0 != ( CTX_PROFILE_COMPAT & bits ) ) { num++; } - if( 0 != ( CTX_PROFILE_CORE & bits ) ) { num++; } - if( 0 != ( CTX_PROFILE_ES & bits ) ) { num++; } - if(1!=num) { - throw new GLException("Internal Error: "+argName+": 1 != num-profiles: "+num); - } - } - - /** - * Called by {@link GLContextImpl#createContextARBMapVersionsAvailable} not intendet to be used by - * implementations. However, if {@link #createContextARB} is not being used within the - * {@link GLDrawableImpl} constructor, GLProfile has to map the available versions. - * - * @param reqMajor Key Value either 1, 2, 3 or 4 - * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} - - * @see #createContextARBMapVersionsAvailable - */ - protected static void mapVersionAvailable(int reqMajor, int profile, int resMajor, int resMinor, int resCtp) - { - validateProfileBits(profile, "profile"); - validateProfileBits(resCtp, "resCtp"); - - int key = compose8bit(reqMajor, profile, 0, 0); - int val = compose8bit(resMajor, resMinor, resCtp, 0); - synchronized(mappedVersionsAvailableLock) { - mappedVersionsAvailable.put( key, val ); - } - } - - protected static int compose8bit(int one, int two, int three, int four) { - return ( ( one & 0x000000FF ) << 24 ) | - ( ( two & 0x000000FF ) << 16 ) | - ( ( three & 0x000000FF ) << 8 ) | - ( ( four & 0x000000FF ) ) ; - } - - protected static int getComposed8bit(int bits32, int which ) { - switch (which) { - case 1: return ( bits32 & 0xFF000000 ) >> 24 ; - case 2: return ( bits32 & 0x00FF0000 ) >> 16 ; - case 3: return ( bits32 & 0x0000FF00 ) >> 8 ; - case 4: return ( bits32 & 0xFF0000FF ) ; - } - throw new GLException("argument which out of range: "+which); - } - - protected static String composed8BitToString(int bits32, boolean hex1, boolean hex2, boolean hex3, boolean hex4) { - int a = getComposed8bit(bits32, 1); - int b = getComposed8bit(bits32, 2); - int c = getComposed8bit(bits32, 3); - int d = getComposed8bit(bits32, 4); - return "["+toString(a, hex1)+", "+toString(b, hex2)+", "+toString(c, hex3)+", "+toString(d, hex4)+"]"; - } - protected static String toString(int val, boolean hex) { if(hex) { return "0x" + Integer.toHexString(val); @@ -662,6 +751,10 @@ public abstract class GLContext { } return needColon; } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } } diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index d1bdcdda1..f6dce1c9c 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -47,6 +47,7 @@ import com.jogamp.common.util.ReflectionUtil; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.HashSet; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; @@ -150,6 +151,8 @@ public abstract class GLDrawableFactory { eglFactory = tmp; } + private AbstractGraphicsDevice defaultSharedDevice = null; + protected GLDrawableFactory() { synchronized(glDrawableFactories) { glDrawableFactories.add(this); @@ -168,6 +171,55 @@ public abstract class GLDrawableFactory { protected abstract void shutdownInstance(); + /** + * Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection()}. for this factory<br> + * The implementation must return a non <code>null</code> default device, which must not be opened, ie. it's native handle may be <code>null</code>. + * @return the default shared device for this factory, eg. :0.0 on X11 desktop. + */ + public abstract AbstractGraphicsDevice getDefaultDevice(); + + /** + * @return true if the device is compatible with this factory, ie. if it can be used for creation. Otherwise false. + */ + public abstract boolean getIsDeviceCompatible(AbstractGraphicsDevice device); + + /** + * Returns true if a shared context is already mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}, + * or if a new shared context could be created and mapped. Otherwise return false.<br> + * Creation of the shared context is tried only once. + * + * @param device if <code>null</code>, the platform default device is being used + */ + public final boolean getIsSharedContextAvailable(AbstractGraphicsDevice device) { + return null != getOrCreateSharedContext(device); + } + + /** + * Returns the shared context mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}, + * either a preexisting or newly created, or <code>null</code> if creation failed or not supported.<br> + * Creation of the shared context is tried only once. + * + * @param device if <code>null</code>, the platform default device is being used + */ + protected final GLContext getOrCreateSharedContext(AbstractGraphicsDevice device) { + if(null==device) { + device = getDefaultDevice(); + if(null==device) { + throw new InternalError("no default device"); + } + if (GLProfile.DEBUG) { + System.err.println("Info: GLDrawableFactory.getOrCreateSharedContext: using default device : "+device); + } + } else if( !getIsDeviceCompatible(device) ) { + if (GLProfile.DEBUG) { + System.err.println("Info: GLDrawableFactory.getOrCreateSharedContext: device not compatible : "+device); + } + return null; + } + return getOrCreateSharedContextImpl(device); + } + protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device); + /** * Returns the sole GLDrawableFactory instance. * diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index c5f5a8511..4111eb5a2 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -40,7 +40,6 @@ package javax.media.opengl; import com.jogamp.common.GlueGenVersion; import com.jogamp.common.jvm.JVMUtil; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.common.util.VersionUtil; import com.jogamp.nativewindow.NativeWindowVersion; import com.jogamp.opengl.impl.Debug; import com.jogamp.opengl.impl.GLDrawableFactoryImpl; @@ -50,6 +49,7 @@ import com.jogamp.opengl.JoglVersion; import java.util.HashMap; import java.util.Iterator; import java.security.*; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.fixedfunc.GLPointerFunc; import javax.media.nativewindow.NativeWindowFactory; @@ -104,18 +104,22 @@ public class GLProfile { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { registerFactoryShutdownHook(); - initProfiles(firstUIActionOnProcess); + initProfilesForDefaultDevices(firstUIActionOnProcess); return null; } }); - - if(null==defaultGLProfile) { - throw new GLException("No profile available: "+array2String(GL_PROFILE_LIST_ALL)+", "+glAvailabilityToString()); - } } } /** + * Trigger eager initialization of GLProfiles for the given device, + * in case it isn't done yet. + */ + public static void initProfiles(AbstractGraphicsDevice device) { + getProfileMap(device); + } + + /** * Manual shutdown method, may be called after your last JOGL use * within the running JVM.<br> * This method is called via the JVM shutdown hook.<br> @@ -132,87 +136,169 @@ public class GLProfile { // Query platform available OpenGL implementation // - public static final boolean isGL4bcAvailable() { return null != mappedProfiles.get(GL4bc); } - public static final boolean isGL4Available() { return null != mappedProfiles.get(GL4); } - public static final boolean isGL3bcAvailable() { return null != mappedProfiles.get(GL3bc); } - public static final boolean isGL3Available() { return null != mappedProfiles.get(GL3); } - public static final boolean isGL2Available() { return null != mappedProfiles.get(GL2); } - public static final boolean isGLES2Available() { return null != mappedProfiles.get(GLES2); } - public static final boolean isGLES1Available() { return null != mappedProfiles.get(GLES1); } - public static final boolean isGL2ES1Available() { return null != mappedProfiles.get(GL2ES1); } - public static final boolean isGL2ES2Available() { return null != mappedProfiles.get(GL2ES2); } - - public static final String glAvailabilityToString() { + public static boolean isGL4bcAvailable(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GL4bc); + } + + public static boolean isGL4Available(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GL4); + } + + public static boolean isGL3bcAvailable(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GL3bc); + } + + public static boolean isGL3Available(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GL3); + } + + public static boolean isGL2Available(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GL2); + } + + public static boolean isGLES2Available(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GLES2); + } + + public static boolean isGLES1Available(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GLES1); + } + + public static boolean isGL2ES1Available(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GL2ES1); + } + + public static boolean isGL2ES2Available(AbstractGraphicsDevice device) { + return null != getProfileMap(device).get(GL2ES2); + } + + /** Uses the default device */ + public static boolean isGL4bcAvailable() { + return isGL4bcAvailable(null); + } + + /** Uses the default device */ + public static boolean isGL4Available() { + return isGL4Available(null); + } + + /** Uses the default device */ + public static boolean isGL3bcAvailable() { + return isGL3bcAvailable(null); + } + + /** Uses the default device */ + public static boolean isGL3Available() { + return isGL3Available(null); + } + + /** Uses the default device */ + public static boolean isGL2Available() { + return isGL2Available(null); + } + + /** Uses the default device */ + public static boolean isGLES2Available() { + return isGLES2Available(null); + } + + /** Uses the default device */ + public static boolean isGLES1Available() { + return isGLES1Available(null); + } + + /** Uses the default device */ + public static boolean isGL2ES1Available() { + return isGL2ES1Available(null); + } + + /** Uses the default device */ + public static boolean isGL2ES2Available() { + return isGL2ES2Available(null); + } + + public static String glAvailabilityToString(AbstractGraphicsDevice device) { boolean avail; StringBuffer sb = new StringBuffer(); + validateInitialization(); + + if(null==device) { + device = defaultDevice; + } + sb.append("GLAvailability[Native[GL4bc "); - avail=isGL4bcAvailable(); + avail=isGL4bcAvailable(device); sb.append(avail); if(avail) { - glAvailabilityToString(sb, 4, GLContext.CTX_PROFILE_COMPAT); + glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_COMPAT); } sb.append(", GL4 "); - avail=isGL4Available(); + avail=isGL4Available(device); sb.append(avail); if(avail) { - glAvailabilityToString(sb, 4, GLContext.CTX_PROFILE_CORE); + glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_CORE); } sb.append(", GL3bc "); - avail=isGL3bcAvailable(); + avail=isGL3bcAvailable(device); sb.append(avail); if(avail) { - glAvailabilityToString(sb, 3, GLContext.CTX_PROFILE_COMPAT); + glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_COMPAT); } sb.append(", GL3 "); - avail=isGL3Available(); + avail=isGL3Available(device); sb.append(avail); if(avail) { - glAvailabilityToString(sb, 3, GLContext.CTX_PROFILE_CORE); + glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_CORE); } sb.append(", GL2 "); - avail=isGL2Available(); + avail=isGL2Available(device); sb.append(avail); if(avail) { - glAvailabilityToString(sb, 2, GLContext.CTX_PROFILE_COMPAT); + glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_COMPAT); } sb.append(", GL2ES1 "); - sb.append(isGL2ES1Available()); + sb.append(isGL2ES1Available(device)); sb.append(", GLES1 "); - avail=isGLES1Available(); + avail=isGLES1Available(device); sb.append(avail); if(avail) { - glAvailabilityToString(sb, 1, GLContext.CTX_PROFILE_ES); + glAvailabilityToString(device, sb, 1, GLContext.CTX_PROFILE_ES); } sb.append(", GL2ES2 "); - sb.append(isGL2ES2Available()); + sb.append(isGL2ES2Available(device)); sb.append(", GLES2 "); - avail=isGLES2Available(); + avail=isGLES2Available(device); sb.append(avail); if(avail) { - glAvailabilityToString(sb, 2, GLContext.CTX_PROFILE_ES); + glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_ES); } sb.append("], Profiles["); - for(Iterator i=mappedProfiles.values().iterator(); i.hasNext(); ) { + for(Iterator i=getProfileMap(device).values().iterator(); i.hasNext(); ) { sb.append(((GLProfile)i.next()).toString()); sb.append(", "); } sb.append(", default "); - sb.append(defaultGLProfile); + sb.append(getDefault(device)); sb.append("]]"); return sb.toString(); } + /** Uses the default device */ + public static String glAvailabilityToString() { + return glAvailabilityToString(null); + } + // // Public (user-visible) profiles // @@ -249,6 +335,9 @@ public class GLProfile { /** The intersection of the desktop GL3 and GL2 profile */ public static final String GL2GL3 = "GL2GL3"; + /** The default profile, used for the device default profile map */ + private static final String GL_DEFAULT = "GL_DEFAULT"; + /** * All GL Profiles in the order of default detection. * Desktop compatibility profiles (the one with fixed function pipeline) comes first. @@ -337,12 +426,14 @@ public class GLProfile { * It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL} * @see #GL_PROFILE_LIST_ALL */ - public static final GLProfile getDefault() { - validateInitialization(); - if(null==defaultGLProfile) { - throw new GLException("No default profile available"); // should never be reached - } - return defaultGLProfile; + public static GLProfile getDefault(AbstractGraphicsDevice device) { + GLProfile glp = get(device, GL_DEFAULT); + return glp; + } + + /** Uses the default device */ + public static GLProfile getDefault() { + return getDefault(defaultDevice); } /** @@ -352,7 +443,14 @@ public class GLProfile { * @throws GLException if no implementation for the given profile is found. * @see #GL_PROFILE_LIST_MAX_FIXEDFUNC */ - public static final GLProfile getMaxFixedFunc() + public static GLProfile getMaxFixedFunc(AbstractGraphicsDevice device) + throws GLException + { + return get(device, GL_PROFILE_LIST_MAX_FIXEDFUNC); + } + + /** Uses the default device */ + public static GLProfile getMaxFixedFunc() throws GLException { return get(GL_PROFILE_LIST_MAX_FIXEDFUNC); @@ -365,7 +463,14 @@ public class GLProfile { * @throws GLException if no implementation for the given profile is found. * @see #GL_PROFILE_LIST_MAX_PROGSHADER */ - public static final GLProfile getMaxProgrammable() + public static GLProfile getMaxProgrammable(AbstractGraphicsDevice device) + throws GLException + { + return get(device, GL_PROFILE_LIST_MAX_PROGSHADER); + } + + /** Uses the default device */ + public static GLProfile getMaxProgrammable() throws GLException { return get(GL_PROFILE_LIST_MAX_PROGSHADER); @@ -378,7 +483,14 @@ public class GLProfile { * @throws GLException if no implementation for the given profile is found. * @see #GL_PROFILE_LIST_GL2ES1 */ - public static final GLProfile getGL2ES1() + public static GLProfile getGL2ES1(AbstractGraphicsDevice device) + throws GLException + { + return get(device, GL_PROFILE_LIST_GL2ES1); + } + + /** Uses the default device */ + public static GLProfile getGL2ES1() throws GLException { return get(GL_PROFILE_LIST_GL2ES1); @@ -391,29 +503,40 @@ public class GLProfile { * @throws GLException if no implementation for the given profile is found. * @see #GL_PROFILE_LIST_GL2ES2 */ - public static final GLProfile getGL2ES2() + public static GLProfile getGL2ES2(AbstractGraphicsDevice device) + throws GLException + { + return get(device, GL_PROFILE_LIST_GL2ES2); + } + + /** Uses the default device */ + public static GLProfile getGL2ES2() throws GLException { return get(GL_PROFILE_LIST_GL2ES2); } /** Returns a GLProfile object. - * Verfifies the given profile and chooses an apropriate implementation. + * verifies the given profile and chooses an appropriate implementation. * A generic value of <code>null</code> or <code>GL</code> will result in * the default profile. * * @throws GLException if no implementation for the given profile is found. */ - public static final GLProfile get(String profile) + public static GLProfile get(AbstractGraphicsDevice device, String profile) throws GLException { - validateInitialization(); - if(null==profile || profile.equals("GL")) return getDefault(); - GLProfile glProfile = (GLProfile) mappedProfiles.get(profile); - if(null==glProfile) { - throw new GLException("No implementation for profile "+profile+" available"); + if(null==profile || profile.equals("GL")) { + profile = GL_DEFAULT; } - return glProfile; + return (GLProfile) getProfileMap(device).get(profile); + } + + /** Uses the default device */ + public static GLProfile get(String profile) + throws GLException + { + return get(defaultDevice, profile); } /** @@ -422,36 +545,43 @@ public class GLProfile { * * @throws GLException if no implementation for the given profile is found. */ - public static final GLProfile get(String[] profiles) + public static GLProfile get(AbstractGraphicsDevice device, String[] profiles) throws GLException { - validateInitialization(); + HashMap map = getProfileMap(device); for(int i=0; i<profiles.length; i++) { String profile = profiles[i]; - GLProfile glProfile = (GLProfile) mappedProfiles.get(profile); + GLProfile glProfile = (GLProfile) map.get(profile); if(null!=glProfile) { return glProfile; } } - throw new GLException("Profiles "+array2String(profiles)+" not available"); + throw new GLException("Profiles "+array2String(profiles)+" not available on device "+device); + } + + /** Uses the default device */ + public static GLProfile get(String[] profiles) + throws GLException + { + return get(defaultDevice, profiles); } /** Indicates whether the native OpenGL ES1 profile is in use. * This requires an EGL interface. */ - public static final boolean usesNativeGLES1(String profileImpl) { + public static boolean usesNativeGLES1(String profileImpl) { return GLES1.equals(profileImpl); } /** Indicates whether the native OpenGL ES2 profile is in use. - * This requires an EGL interface. + * This requires an EGL or ES2 compatible interface. */ - public static final boolean usesNativeGLES2(String profileImpl) { + public static boolean usesNativeGLES2(String profileImpl) { return GLES2.equals(profileImpl); } /** Indicates whether either of the native OpenGL ES profiles are in use. */ - public static final boolean usesNativeGLES(String profileImpl) { + public static boolean usesNativeGLES(String profileImpl) { return usesNativeGLES2(profileImpl) || usesNativeGLES1(profileImpl); } @@ -922,20 +1052,16 @@ public class GLProfile { private static /*final*/ boolean isAWTAvailable; + private static /*final*/ boolean hasDesktopGL; private static /*final*/ boolean hasGL234Impl; - private static /*final*/ boolean hasGL4bcImpl; - private static /*final*/ boolean hasGL4Impl; - private static /*final*/ boolean hasGL3bcImpl; - private static /*final*/ boolean hasGL3Impl; - private static /*final*/ boolean hasGL2Impl; private static /*final*/ boolean hasGLES2Impl; private static /*final*/ boolean hasGLES1Impl; - /** The JVM/process wide default GL profile **/ - private static /*final*/ GLProfile defaultGLProfile; - - /** All GLProfiles */ - private static /*final*/ HashMap/*<String, GLProfile>*/ mappedProfiles; + private static /*final*/ GLDrawableFactoryImpl eglFactory; + private static /*final*/ GLDrawableFactoryImpl desktopFactory; + private static /*final*/ AbstractGraphicsDevice defaultDevice; + private static /*final*/ AbstractGraphicsDevice defaultDesktopDevice; + private static /*final*/ AbstractGraphicsDevice defaultEGLDevice; static boolean initialized = false; @@ -947,7 +1073,11 @@ public class GLProfile { * Tries the profiles implementation and native libraries. * Throws an GLException if no profile could be found at all. */ - private static void initProfiles(boolean firstUIActionOnProcess) { + private static void initProfilesForDefaultDevices(boolean firstUIActionOnProcess) { + + if(DEBUG) { + System.err.println("GLProfile.init firstUIActionOnProcess "+firstUIActionOnProcess); + } NativeWindowFactory.initSingleton(firstUIActionOnProcess); @@ -957,17 +1087,7 @@ public class GLProfile { ReflectionUtil.isClassAvailable("javax.media.opengl.awt.GLCanvas", classloader) ; // JOGL hasGL234Impl = ReflectionUtil.isClassAvailable("com.jogamp.opengl.impl.gl4.GL4bcImpl", classloader); - hasGL4bcImpl = hasGL234Impl; - hasGL4Impl = hasGL234Impl; - hasGL3bcImpl = hasGL234Impl; - hasGL3Impl = hasGL234Impl; - hasGL2Impl = hasGL234Impl; - mappedProfiles = computeProfileMap(); - - boolean hasDesktopGL = false; - boolean hasNativeOSFactory = false; - Throwable t; - + // // Iteration of desktop GL availability detection // utilizing the detected GL version in the shared context. @@ -975,14 +1095,12 @@ public class GLProfile { // - Instantiate GLDrawableFactory incl its shared dummy drawable/context, // which will register at GLContext .. // - - t=null; + Throwable t=null; // if successfull it has a shared dummy drawable and context created try { - GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GL2); - hasNativeOSFactory = null != factory; - if(hasNativeOSFactory) { - DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) factory.getGLDynamicLookupHelper(0); + desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GL2); + if(null != desktopFactory) { + DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) desktopFactory.getGLDynamicLookupHelper(0); if(null!=glLookupHelper) { hasDesktopGL = glLookupHelper.hasGLBinding(); } @@ -998,43 +1116,29 @@ public class GLProfile { if(null!=t) { t.printStackTrace(); } - if(!hasNativeOSFactory) { - System.err.println("Info: GLProfile.init - Native platform GLDrawable factory not available"); + if(null == desktopFactory) { + System.err.println("Info: GLProfile.init - Desktop GLDrawable factory not available"); } } - if(hasDesktopGL && !GLContext.mappedVersionsAvailableSet) { - // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, - // so we have to add the usual suspect - GLContext.mapVersionAvailable(2, GLContext.CTX_PROFILE_COMPAT, 1, 5, GLContext.CTX_PROFILE_COMPAT|GLContext.CTX_OPTION_ANY); - } - - if(!hasNativeOSFactory) { + if(null == desktopFactory) { hasDesktopGL = false; hasGL234Impl = false; - hasGL4bcImpl = false; - hasGL4Impl = false; - hasGL3bcImpl = false; - hasGL3Impl = false; - hasGL2Impl = false; } else { - hasGL4bcImpl = hasGL4bcImpl && GLContext.isGL4bcAvailable(); - hasGL4Impl = hasGL4Impl && GLContext.isGL4Available(); - hasGL3bcImpl = hasGL3bcImpl && GLContext.isGL3bcAvailable(); - hasGL3Impl = hasGL3Impl && GLContext.isGL3Available(); - hasGL2Impl = hasGL2Impl && GLContext.isGL2Available(); + defaultDesktopDevice = desktopFactory.getDefaultDevice(); + defaultDevice = defaultDesktopDevice; } if ( ReflectionUtil.isClassAvailable("com.jogamp.opengl.impl.egl.EGLDrawableFactory", classloader) ) { t=null; try { - GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2); - if(null != factory) { - GLDynamicLookupHelper eglLookupHelper = factory.getGLDynamicLookupHelper(2); + eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2); + if(null != eglFactory) { + GLDynamicLookupHelper eglLookupHelper = eglFactory.getGLDynamicLookupHelper(2); if(null!=eglLookupHelper) { hasGLES2Impl = eglLookupHelper.isLibComplete(); } - eglLookupHelper = factory.getGLDynamicLookupHelper(1); + eglLookupHelper = eglFactory.getGLDynamicLookupHelper(1); if(null!=eglLookupHelper) { hasGLES1Impl = eglLookupHelper.isLibComplete(); } @@ -1048,30 +1152,151 @@ public class GLProfile { } catch (RuntimeException re) { t=re; } - if(DEBUG && null!=t) { - t.printStackTrace(); + if(DEBUG) { + if(null!=t) { + t.printStackTrace(); + } + if(null == eglFactory) { + System.err.println("Info: GLProfile.init - EGL GLDrawable factory not available"); + } } } - if(hasGLES2Impl) { - GLContext.mapVersionAvailable(2, GLContext.CTX_PROFILE_ES, 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_OPTION_ANY); + + if(null == eglFactory) { + hasGLES2Impl = false; + hasGLES1Impl = false; + } else { + defaultEGLDevice = eglFactory.getDefaultDevice(); + if (null==defaultDevice) { + defaultDevice = defaultEGLDevice; + } + } + + boolean addedAnyProfile = initProfilesForDevice(defaultDesktopDevice); + addedAnyProfile = addedAnyProfile || initProfilesForDevice(defaultEGLDevice); + + if(DEBUG) { + System.err.println(GlueGenVersion.getInstance()); + System.err.println(NativeWindowVersion.getInstance()); + System.err.print(JoglVersion.getInstance()); + + System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); + System.err.println("GLProfile.init has desktopFactory "+(null!=desktopFactory)); + System.err.println("GLProfile.init hasDesktopGL "+hasDesktopGL); + System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); + System.err.println("GLProfile.init has eglFactory "+(null!=eglFactory)); + System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); + System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl); + System.err.println("GLProfile.init defaultDesktopDevice "+defaultDevice); + System.err.println("GLProfile.init defaultEGLDevice "+defaultDevice); + System.err.println("GLProfile.init defaultDevice "+defaultDevice); + } + + if(!addedAnyProfile) { + throw new GLException("No profile available: "+array2String(GL_PROFILE_LIST_ALL)+", "+ glAvailabilityToString()); } - if(hasGLES1Impl) { - GLContext.mapVersionAvailable(1, GLContext.CTX_PROFILE_ES, 1, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_OPTION_ANY); + } + + /** + * @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) { + boolean isSet = GLContext.getAvailableGLVersionsSet(device); + + if(DEBUG) { + String msg = "Info: GLProfile.initProfilesForDevice: "+device.getConnection()+", isSet "+isSet; + Throwable t = new Throwable(msg); + t.printStackTrace(); + // System.err.println(msg); + } + if(isSet) { + return null != GLProfile.getDefault(device); + } + + boolean addedAnyProfile = false; + + if( hasDesktopGL && desktopFactory.getIsDeviceCompatible(device)) { + // 1st pretend we have all Desktop and EGL profiles .. + computeProfileMap(device, true /* desktopCtxUndef*/, true /* eglCtxUndef */); + + // Triggers eager initialization of share context in GLDrawableFactory for the device, + // hence querying all available GLProfiles + boolean desktopSharedCtxAvail = desktopFactory.getIsSharedContextAvailable(device); + if (DEBUG) { + System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": desktop Shared Ctx "+desktopSharedCtxAvail); + } + if( null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_COMPAT) ) { + // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, + // so we have to add the usual suspect + GLContext.mapAvailableGLVersion(device, + 2, GLContext.CTX_PROFILE_COMPAT, + 1, 5, GLContext.CTX_PROFILE_COMPAT|GLContext.CTX_OPTION_ANY); + } + computeProfileMap(device, false /* desktopCtxUndef*/, false /* eglCtxUndef */); + addedAnyProfile = null != GLProfile.getDefault(device); + } else { + if(DEBUG) { + System.err.println("GLProfile: DesktopFactory - Device is not available: "+device.getConnection()); + } } - mappedProfiles = computeProfileMap(); + if( null!=eglFactory && ( hasGLES2Impl || hasGLES1Impl ) && eglFactory.getIsDeviceCompatible(device)) { + // 1st pretend we have all EGL profiles .. + computeProfileMap(device, false /* desktopCtxUndef*/, true /* eglCtxUndef */); + + // Triggers eager initialization of share context in GLDrawableFactory for the device, + // hence querying all available GLProfiles + boolean eglSharedCtxAvail = eglFactory.getIsSharedContextAvailable(device); + if (DEBUG) { + System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": egl Shared Ctx "+eglSharedCtxAvail); + } + if(hasGLES2Impl && null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_ES) ) { + // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, + // so we have to add the usual suspect + GLContext.mapAvailableGLVersion(device, + 2, GLContext.CTX_PROFILE_ES, + 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_OPTION_ANY); + } + if(hasGLES1Impl && null == GLContext.getAvailableGLVersion(device, 1, GLContext.CTX_PROFILE_ES)) { + // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, + // so we have to add the usual suspect + GLContext.mapAvailableGLVersion(device, + 1, GLContext.CTX_PROFILE_ES, + 1, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_OPTION_ANY); + } + computeProfileMap(device, false /* desktopCtxUndef*/, false /* eglCtxUndef */); + addedAnyProfile = addedAnyProfile || null != GLProfile.getDefault(device); + } else { + if(DEBUG) { + System.err.println("GLProfile: EGLFactory - Device is not available: "+device.getConnection()); + } + } + if(!GLContext.getAvailableGLVersionsSet(device)) { + GLContext.setAvailableGLVersionsSet(device); + } if (DEBUG) { - System.err.println(GlueGenVersion.getInstance().getInfo(null)); - System.err.println(NativeWindowVersion.getInstance().getInfo(null)); - System.err.print(JoglVersion.getInstance().getInfo(null)); - System.err.println("GLProfile.init firstUIActionOnProcess "+firstUIActionOnProcess); - System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); - System.err.println("GLProfile.init hasNativeOSFactory "+hasNativeOSFactory); - System.err.println("GLProfile.init hasDesktopGL "+hasDesktopGL); - System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); - System.err.println("GLProfile.init "+glAvailabilityToString()); + System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": added profile(s): "+addedAnyProfile); + System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": "+glAvailabilityToString(device)); } + + return addedAnyProfile; + } + + public static AbstractGraphicsDevice getDefaultDevice() { + validateInitialization(); + return defaultDevice; + } + + public static AbstractGraphicsDevice getDefaultDesktopDevice() { + validateInitialization(); + return defaultDesktopDevice; + } + + public static AbstractGraphicsDevice getDefaultEGLDevice() { + validateInitialization(); + return defaultEGLDevice; } private static synchronized void registerFactoryShutdownHook() { @@ -1102,7 +1327,7 @@ public class GLProfile { } } - private static final String array2String(String[] list) { + private static String array2String(String[] list) { StringBuffer msg = new StringBuffer(); msg.append("["); for (int i = 0; i < list.length; i++) { @@ -1114,8 +1339,8 @@ public class GLProfile { return msg.toString(); } - private static final void glAvailabilityToString(StringBuffer sb, int major, int profile) { - String str = GLContext.getGLVersionAvailable(major, profile); + private static void glAvailabilityToString(AbstractGraphicsDevice device, StringBuffer sb, int major, int profile) { + String str = GLContext.getAvailableGLVersionAsString(device, major, profile); if(null==str) { throw new GLException("Internal Error"); } @@ -1124,103 +1349,152 @@ public class GLProfile { sb.append("]"); } - private static HashMap computeProfileMap() { - defaultGLProfile=null; - HashMap/*<String, GLProfile>*/ _mappedProfiles = new HashMap(GL_PROFILE_LIST_ALL.length); + private static void computeProfileMap(AbstractGraphicsDevice device, boolean desktopCtxUndef, boolean eglCtxUndef) { + if (DEBUG) { + System.err.println("GLProfile.init map "+device.getConnection()+", desktopCtxUndef "+desktopCtxUndef+", eglCtxUndef "+eglCtxUndef); + } + GLProfile defaultGLProfile = null; + HashMap/*<String, GLProfile>*/ _mappedProfiles = new HashMap(GL_PROFILE_LIST_ALL.length + 1 /* default */); for(int i=0; i<GL_PROFILE_LIST_ALL.length; i++) { String profile = GL_PROFILE_LIST_ALL[i]; - String profileImpl = computeProfileImpl(profile); + String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, eglCtxUndef); if(null!=profileImpl) { GLProfile glProfile = new GLProfile(profile, profileImpl); _mappedProfiles.put(profile, glProfile); if (DEBUG) { - System.err.println("GLProfile.init map "+glProfile); + System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection()); } if(null==defaultGLProfile) { defaultGLProfile=glProfile; if (DEBUG) { - System.err.println("GLProfile.init default "+glProfile); + System.err.println("GLProfile.init map default "+glProfile+" on device "+device.getConnection()); } } } else { if (DEBUG) { - System.err.println("GLProfile.init map *** no mapping for "+profile); + System.err.println("GLProfile.init map *** no mapping for "+profile+" on device "+device.getConnection()); } } } - return _mappedProfiles; - } - - private static final String getGLImplBaseClassName(String profileImpl) { - if ( GL4bc.equals(profileImpl) || - GL4.equals(profileImpl) || - GL3bc.equals(profileImpl) || - GL3.equals(profileImpl) || - GL2.equals(profileImpl) ) { - return "com.jogamp.opengl.impl.gl4.GL4bc"; - } else if(GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl)) { - return "com.jogamp.opengl.impl.es1.GLES1"; - } else if(GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl)) { - return "com.jogamp.opengl.impl.es2.GLES2"; - } else { - throw new GLException("unsupported profile \"" + profileImpl + "\""); + if(null!=defaultGLProfile) { + _mappedProfiles.put(GL_DEFAULT, defaultGLProfile); } + setProfileMap(device, _mappedProfiles); } /** * Returns the profile implementation */ - private static String computeProfileImpl(String profile) { + private static String computeProfileImpl(AbstractGraphicsDevice device, String profile, boolean desktopCtxUndef, boolean eglCtxUndef) { if (GL2ES1.equals(profile)) { - if(hasGL2Impl) { - return GL2; - } else if(hasGL3bcImpl) { - return GL3bc; - } else if(hasGL4bcImpl) { - return GL4bc; - } else if(hasGLES1Impl) { + if(hasGL234Impl) { + if(desktopCtxUndef || GLContext.isGL2Available(device)) { + return GL2; + } else if(GLContext.isGL3bcAvailable(device)) { + return GL3bc; + } else if(GLContext.isGL4bcAvailable(device)) { + return GL4bc; + } + } + if(hasGLES1Impl && ( eglCtxUndef || GLContext.isGLES1Available(device))) { return GLES1; } } else if (GL2ES2.equals(profile)) { - if(hasGL2Impl) { - return GL2; - } else if(hasGL3Impl) { - return GL3; - } else if(hasGL4Impl) { - return GL4; - } else if(hasGLES2Impl) { + if(hasGL234Impl) { + if(desktopCtxUndef || GLContext.isGL2Available(device)) { + return GL2; + } else if(GLContext.isGL3Available(device)) { + return GL3; + } else if(GLContext.isGL4Available(device)) { + return GL4; + } + } + if(hasGLES2Impl && ( eglCtxUndef || GLContext.isGLES2Available(device))) { return GLES2; } } else if(GL2GL3.equals(profile)) { - if(hasGL2Impl) { - return GL2; - } else if(hasGL3bcImpl) { - return GL3bc; - } else if(hasGL4bcImpl) { - return GL4bc; - } else if(hasGL3Impl) { - return GL3; - } else if(hasGL4Impl) { - return GL4; + if(hasGL234Impl) { + if(desktopCtxUndef || GLContext.isGL2Available(device)) { + return GL2; + } else if(GLContext.isGL3bcAvailable(device)) { + return GL3bc; + } else if(GLContext.isGL4bcAvailable(device)) { + return GL4bc; + } else if(GLContext.isGL3Available(device)) { + return GL3; + } else if(GLContext.isGL4Available(device)) { + return GL4; + } } - } else if(GL4bc.equals(profile) && hasGL4bcImpl) { + } else if(GL4bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device))) { return GL4bc; - } else if(GL4.equals(profile) && hasGL4Impl) { + } else if(GL4.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device))) { return GL4; - } else if(GL3bc.equals(profile) && hasGL3bcImpl) { + } else if(GL3bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device))) { return GL3bc; - } else if(GL3.equals(profile) && hasGL3Impl) { + } else if(GL3.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device))) { return GL3; - } else if(GL2.equals(profile) && hasGL2Impl) { + } else if(GL2.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device))) { return GL2; - } else if(GLES2.equals(profile) && hasGLES2Impl) { + } else if(GLES2.equals(profile) && hasGLES2Impl && ( eglCtxUndef || GLContext.isGLES2Available(device))) { return GLES2; - } else if(GLES1.equals(profile) && hasGLES1Impl) { + } else if(GLES1.equals(profile) && hasGLES1Impl && ( eglCtxUndef || GLContext.isGLES1Available(device))) { return GLES1; } return null; } + private static String getGLImplBaseClassName(String profileImpl) { + if ( GL4bc.equals(profileImpl) || + GL4.equals(profileImpl) || + GL3bc.equals(profileImpl) || + GL3.equals(profileImpl) || + GL2.equals(profileImpl) ) { + return "com.jogamp.opengl.impl.gl4.GL4bc"; + } else if(GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl)) { + return "com.jogamp.opengl.impl.es1.GLES1"; + } else if(GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl)) { + return "com.jogamp.opengl.impl.es2.GLES2"; + } else { + throw new GLException("unsupported profile \"" + profileImpl + "\""); + } + } + + private static /*final*/ HashMap/*<device_connection, HashMap<GL-String, GLProfile>*/ deviceConn2ProfileMap = new HashMap(); + + /** + * This implementation support lazy initialization, while avoiding recursion/deadlocks.<br> + * If no mapping 'device -> GLProfiles-Map' exists yet, it triggers<br> + * - create empty mapping device -> GLProfiles-Map <br> + * - initialization<br< + * + * @param device the key 'device -> GLProfiles-Map' + * @return the GLProfile HashMap + */ + private static HashMap getProfileMap(AbstractGraphicsDevice device) { + validateInitialization(); + if(null==device) { + device = defaultDevice; + } + String deviceKey = GLContext.getUniqueDeviceString(device); + HashMap map = (HashMap) deviceConn2ProfileMap.get(deviceKey); + if(null==map) { + map = new HashMap(); + synchronized ( deviceConn2ProfileMap ) { + deviceConn2ProfileMap.put(deviceKey, map); + } + initProfilesForDevice(device); + } + return map; + } + + private static void setProfileMap(AbstractGraphicsDevice device, HashMap/*<GL-String, GLProfile>*/mappedProfiles) { + validateInitialization(); + synchronized ( deviceConn2ProfileMap ) { + deviceConn2ProfileMap.put(GLContext.getUniqueDeviceString(device), mappedProfiles); + } + } + private GLProfile(String profile, String profileImpl) { this.profile = profile; this.profileImpl = profileImpl; diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 9db718bfb..c0f2736fb 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -83,7 +83,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { static { DEBUG = Debug.debug("GLCanvas"); - defaultGLProfile = GLProfile.getDefault(); + defaultGLProfile = GLProfile.getDefault(GLProfile.getDefaultDesktopDevice()); } private GLProfile glProfile; @@ -795,11 +795,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { * A most simple JOGL AWT test entry */ public static void main(String args[]) { - System.err.println(GlueGenVersion.getInstance().getInfo(null)); - System.err.println(NativeWindowVersion.getInstance().getInfo(null)); - System.err.print(JoglVersion.getInstance().getInfo(null)); + System.err.println(GlueGenVersion.getInstance()); + System.err.println(NativeWindowVersion.getInstance()); + System.err.print(JoglVersion.getInstance()); - GLCapabilities caps = new GLCapabilities( GLProfile.getDefault() ); + GLCapabilities caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDesktopDevice()) ); Frame frame = new Frame("JOGL AWT Test"); GLCanvas glCanvas = new GLCanvas(caps); @@ -809,7 +809,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable { glCanvas.addGLEventListener(new GLEventListener() { public void init(GLAutoDrawable drawable) { GL gl = drawable.getGL(); - System.err.println(JoglVersion.getInstance().getGLInfo(gl, null)); + System.err.println(JoglVersion.getInstance().toString(gl)); } public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index b9bbf71c2..955e51e69 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -1275,7 +1275,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable { public GLProfile getGLProfile() { // FIXME: should do better than this; is it possible to using only platform-independent code? - return GLProfile.getDefault(); + return GLProfile.getDefault(GLProfile.getDefaultDesktopDevice()); } public void handleReshape() { |