diff options
Diffstat (limited to 'src/jogl/classes/javax/media/opengl/GLProfile.java')
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLProfile.java | 1102 |
1 files changed, 677 insertions, 425 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index f85c6ba23..80f46955d 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * 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 @@ -29,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. @@ -37,6 +37,7 @@ package javax.media.opengl; +import jogamp.nativewindow.NWJNILibLoader; import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.DesktopGLDynamicLookupHelper; @@ -49,6 +50,7 @@ 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.gluegen.runtime.FunctionAddressResolver; import com.jogamp.nativewindow.NativeWindowVersion; import com.jogamp.opengl.JoglVersion; @@ -56,158 +58,138 @@ import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.fixedfunc.GLPointerFunc; +import java.lang.reflect.Constructor; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashMap; -import java.util.Iterator; import java.util.List; +import java.util.Map; /** * Specifies the the OpenGL profile. - * + * * This class static singleton initialization queries the availability of all OpenGL Profiles * and instantiates singleton GLProfile objects for each available profile. * - * The platform default profile may be used, using {@link GLProfile#GetProfileDefault()}, + * The platform default profile may be used, using {@link GLProfile#GetProfileDefault()}, * or more specialized versions using the other static GetProfile methods. */ public class GLProfile { - + public static final boolean DEBUG = Debug.debug("GLProfile"); - - /** - * We have to disable support for ANGLE, the D3D ES2 emulation on Windows provided w/ Firefox and Chrome. - * When run in the mentioned browsers, the eglInitialize(..) implementation crashes. - * <p> - * This can be overridden by explicitly enabling ANGLE on Windows by setting the property - * <code>jogl.enable.ANGLE</code>. - * </p> - */ - private static final boolean enableANGLE = Debug.isPropertyDefined("jogl.enable.ANGLE", true); static { // Also initializes TempJarCache if shall be used. Platform.initSingleton(); } - + /** * 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)}. + * This method shall not need to be called for other reasons than having a defined initialization sequence. * </p> - * <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 are not be able to initialize JOGL - * before the first UI action. - * In such case you shall pass <code>firstUIActionOnProcess=false</code>.</P> + * * <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>. + * the first call to {@link #getDefault()}, {@link #get(java.lang.String)}. * <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. + * <p> + * To initialize JOGL at startup ASAP, this method may be invoked in the <i>main class</i>'s + * static initializer block, in the <i>static main() method</i> or in the <i>Applet init() method</i>. + * </p> + * + * <p> + * Since JOGL's initialization is complex and involves multi threading, it is <b>not</b> recommended + * to be have it invoked on the AWT EDT thread. In case all JOGL usage is performed + * on the AWT EDT, invoke this method outside the AWT EDT - see above. + * </p> + * */ - public static void initSingleton(final boolean firstUIActionOnProcess) { + public static void initSingleton() { + final boolean justInitialized; initLock.lock(); try { - if(!initialized) { // volatile: ok + if(!initialized) { initialized = true; + justInitialized = true; if(DEBUG) { - System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName()); + System.err.println("GLProfile.initSingleton() - thread "+Thread.currentThread().getName()); Thread.dumpStack(); } - + + if(ReflectionUtil.DEBUG_STATS_FORNAME) { + ReflectionUtil.resetForNameCount(); + } + // run the whole static initialization privileged to speed up, // since this skips checking further access AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { Platform.initSingleton(); - + if(TempJarCache.isInitialized()) { - String[] atomicNativeJarBaseNames = new String[] { "nativewindow", "jogl", null }; - if( ReflectionUtil.isClassAvailable("com.jogamp.newt.NewtFactory", GLProfile.class.getClassLoader()) ) { - atomicNativeJarBaseNames[2] = "newt"; + final ClassLoader cl = GLProfile.class.getClassLoader(); + final String newtFactoryClassName = "com.jogamp.newt.NewtFactory"; + final Class<?>[] classesFromJavaJars = new Class<?>[] { NWJNILibLoader.class, GLProfile.class, null }; + if( ReflectionUtil.isClassAvailable(newtFactoryClassName, cl) ) { + classesFromJavaJars[2] = ReflectionUtil.getClass(newtFactoryClassName, false, cl); } - JNILibLoaderBase.addNativeJarLibs(GLProfile.class, "jogl-all", atomicNativeJarBaseNames); + JNILibLoaderBase.addNativeJarLibsJoglCfg(classesFromJavaJars); } - initProfilesForDefaultDevices(firstUIActionOnProcess); + initProfilesForDefaultDevices(); return null; } }); + if( ReflectionUtil.DEBUG_STATS_FORNAME ) { + if( justInitialized ) { + System.err.println(ReflectionUtil.getForNameStats(null).toString()); + } + } + } else { + justInitialized = false; } } 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); + if(DEBUG) { + if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES3Impl ) ) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true)); + } + } } /** * Trigger eager initialization of GLProfiles for the given device, * in case it isn't done yet. - * + * * @throws GLException if no profile for the given device is available. */ public static void initProfiles(AbstractGraphicsDevice device) throws GLException { getProfileMap(device, true); } - /** - * Shutdown type for {@link GLProfile#shutdown(ShutdownType)}. - * <p> - * {@link #SHARED_ONLY} For thread based resources only, suitable for eg. {@link java.applet.Applet Applet} restart.<br> - * {@link #COMPLETE} Everything.<br> - * </p> - */ - public enum ShutdownType { - /* Shared thread based resources only, eg. for Applets */ - SHARED_ONLY, - /* Everything */ - COMPLETE; - } - /** * 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.<br> * <p> - * This method shall not need to be called for other reasons than issuing a proper shutdown of resources. + * This method shall not need to be called for other reasons than issuing a proper shutdown of resources at a defined time. * </p> - * @param type the shutdown type, see {@link ShutdownType}. */ - public static void shutdown(ShutdownType type) { + public static void shutdown() { initLock.lock(); try { - if(initialized) { // volatile: ok + if(initialized) { initialized = false; if(DEBUG) { - System.err.println("GLProfile.shutdown(type: "+type+") - thread "+Thread.currentThread().getName()); + System.err.println("GLProfile.shutdown() - thread "+Thread.currentThread().getName()); Thread.dumpStack(); - } - GLDrawableFactory.shutdown(type); - if(ShutdownType.COMPLETE == type) { - GLContext.shutdown(); } - NativeWindowFactory.shutdown(); + GLDrawableFactory.shutdown(); } } finally { initLock.unlock(); @@ -218,11 +200,11 @@ public class GLProfile { // Query platform available OpenGL implementation // - /** + /** * Returns the availability of a profile on a device. - * + * * @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device. - * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), + * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), * or <code>[ null, GL ]</code> for the default profile. * @return true if the profile is available for the device, otherwise false. */ @@ -233,31 +215,31 @@ public class GLProfile { 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. - * - * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), + * + * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), * or <code>[ null, GL ]</code> for the default profile. * @return true if the profile is available for the default device, otherwise false. */ public static boolean isAvailable(String profile) { return isAvailable(null, profile); } - - /** + + /** * Returns the availability of any profile on the default device. - * + * * @return true if any profile is available for the default device, otherwise false. */ public static boolean isAnyAvailable() { return isAvailable(null, null); } - + public static String glAvailabilityToString(AbstractGraphicsDevice device) { return glAvailabilityToString(device, null).toString(); } - + public static StringBuilder glAvailabilityToString(AbstractGraphicsDevice device, StringBuilder sb) { return glAvailabilityToString(device, sb, null, 0); } @@ -276,121 +258,183 @@ public class GLProfile { final boolean useIndent = null != indent; initSingleton(); - + + int allCount = 0; + int nativeCount = 0; + if(null==device) { device = defaultDevice; } final HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, false); - + if(useIndent) { - doIndent(sb, indent, indentCount).append("Native"); + doIndent(sb, indent, indentCount).append("Natives"); indentCount++; - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL4bc").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4bc+" ").append(indent); } else { - sb.append("Native[GL4bc "); - } + sb.append("Natives["+GL4bc+" "); + } avail=isAvailableImpl(map, GL4bc); sb.append(avail); if(avail) { + nativeCount++; glAvailabilityToString(device, sb.append(" "), 4, GLContext.CTX_PROFILE_COMPAT); } + allCount++; if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL4").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4+" ").append(indent); } else { - sb.append(", GL4 "); + sb.append(", "+GL4+" "); } avail=isAvailableImpl(map, GL4); sb.append(avail); if(avail) { + nativeCount++; glAvailabilityToString(device, sb.append(" "), 4, GLContext.CTX_PROFILE_CORE); } + allCount++; + + if(useIndent) { + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES3+" ").append(indent); + } else { + sb.append(", "+GLES3+" "); + } + avail=isAvailableImpl(map, GLES3); + sb.append(avail); + if(avail) { + nativeCount++; + glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_ES); + } + allCount++; if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL3bc").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL3bc+" ").append(indent); } else { - sb.append(", GL3bc "); + sb.append(", "+GL3bc+" "); } avail=isAvailableImpl(map, GL3bc); sb.append(avail); if(avail) { + nativeCount++; glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_COMPAT); } + allCount++; if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL3").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL3+" ").append(indent); } else { - sb.append(", GL3 "); + sb.append(", "+GL3+" "); } avail=isAvailableImpl(map, GL3); sb.append(avail); if(avail) { + nativeCount++; glAvailabilityToString(device, sb.append(" "), 3, GLContext.CTX_PROFILE_CORE); } + allCount++; if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2+" ").append(indent); } else { - sb.append(", GL2 "); + sb.append(", "+GL2+" "); } avail=isAvailableImpl(map, GL2); sb.append(avail); if(avail) { + nativeCount++; glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_COMPAT); } + allCount++; if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2ES1").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES2+" ").append(indent); } else { - sb.append(", GL2ES1 "); + sb.append(", "+GLES2+" "); } - sb.append(isAvailableImpl(map, GL2ES1)); + avail=isAvailableImpl(map, GLES2); + sb.append(avail); + if(avail) { + nativeCount++; + glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_ES); + } + allCount++; if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES1").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GLES1+" ").append(indent); } else { - sb.append(", GLES1 "); + sb.append(", "+GLES1+" "); } avail=isAvailableImpl(map, GLES1); sb.append(avail); if(avail) { + nativeCount++; glAvailabilityToString(device, sb.append(" "), 1, GLContext.CTX_PROFILE_ES); } + allCount++; if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GL2ES2").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Count\t"+nativeCount+" / "+allCount); + indentCount--; + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Common"); + indentCount++; } else { - sb.append(", GL2ES2 "); + sb.append(", count "+nativeCount+" / "+allCount+"], Common["); } - sb.append(isAvailableImpl(map, GL2ES2)); if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("GLES2").append(indent); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL4ES3+" ").append(indent); } else { - sb.append(", GLES2 "); + sb.append(", "+GL4ES3+" "); } - avail=isAvailableImpl(map, GLES2); - sb.append(avail); - if(avail) { - glAvailabilityToString(device, sb.append(" "), 2, GLContext.CTX_PROFILE_ES); + sb.append(isAvailableImpl(map, GL4ES3)); + allCount++; + + if(useIndent) { + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2GL3+" ").append(indent); + } else { + sb.append(", "+GL2GL3+" "); } + sb.append(isAvailableImpl(map, GL2GL3)); + allCount++; + + if(useIndent) { + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2ES2+" ").append(indent); + } else { + sb.append(", "+GL2ES2+" "); + } + sb.append(isAvailableImpl(map, GL2ES2)); + allCount++; + + if(useIndent) { + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append(GL2ES1+" ").append(indent); + } else { + sb.append(", "+GL2ES1+" "); + } + sb.append(isAvailableImpl(map, GL2ES1)); + allCount++; if(useIndent) { indentCount--; - doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Profiles"); + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Mappings"); indentCount++; } else { - sb.append("], Profiles["); + sb.append("], Mappings["); } - + + int profileCount = 0; + if(null != map) { - for(Iterator<GLProfile> i=map.values().iterator(); i.hasNext(); ) { - if(useIndent) { - doIndent(sb.append(Platform.getNewline()), indent, indentCount); - } - sb.append(i.next().toString()); - if(!useIndent) { - sb.append(", "); + for (Map.Entry<String,GLProfile> entry : map.entrySet()) { + if( !GL_DEFAULT.equals(entry.getKey()) ) { + if(useIndent) { + doIndent(sb.append(Platform.getNewline()), indent, indentCount); + } + sb.append(entry.getKey()+(useIndent?" \t":" ")+entry.getValue()); + if(!useIndent) { + sb.append(", "); + } + profileCount++; } } if(useIndent) { @@ -405,14 +449,15 @@ public class GLProfile { } } if(useIndent) { + doIndent(sb.append(Platform.getNewline()), indent, indentCount).append("Count\t"+profileCount+" / "+allCount); sb.append(Platform.getNewline()); } else { - sb.append("]"); + sb.append(", count "+profileCount+" / "+allCount+"]"); } return sb; } - + /** Uses the default device */ public static String glAvailabilityToString() { return glAvailabilityToString(null); @@ -445,6 +490,9 @@ public class GLProfile { /** The embedded OpenGL profile ES 2.x, with x >= 0 */ public static final String GLES2 = "GLES2"; + /** The embedded OpenGL profile ES 3.x, with x >= 0 */ + public static final String GLES3 = "GLES3"; + /** The intersection of the desktop GL2 and embedded ES1 profile */ public static final String GL2ES1 = "GL2ES1"; @@ -454,85 +502,92 @@ public class GLProfile { /** The intersection of the desktop GL3 and GL2 profile */ public static final String GL2GL3 = "GL2GL3"; + /** The intersection of the desktop GL4 and ES3 profile, available only if either ES3 or GL4 w/ <code>GL_ARB_ES3_compatibility</code> is available. */ + public static final String GL4ES3 = "GL4ES3"; + /** 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 * from highest to lowest version. * <p> This includes the generic subset profiles GL2GL3, GL2ES2 and GL2ES1.</p> * * <ul> - * <li> GL4bc - * <li> GL3bc - * <li> GL2 - * <li> GL4 - * <li> GL3 - * <li> GL2GL3 - * <li> GLES2 - * <li> GL2ES2 - * <li> GLES1 - * <li> GL2ES1 + * <li> GL4bc </li> + * <li> GL3bc </li> + * <li> GL2 </li> + * <li> GL4 </li> + * <li> GL3 </li> + * <li> GLES3 </li> + * <li> GL4ES3 </li> + * <li> GL2GL3 </li> + * <li> GLES2 </li> + * <li> GL2ES2 </li> + * <li> GLES1 </li> + * <li> GL2ES1 </li> * </ul> * */ - public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 }; + public static final String[] GL_PROFILE_LIST_ALL = new String[] { GL4bc, GL3bc, GL2, GL4, GL3, GLES3, GL4ES3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 }; /** * Order of maximum profiles. * * <ul> - * <li> GL4bc - * <li> GL4 - * <li> GL3bc - * <li> GL3 - * <li> GL2 - * <li> GLES2 - * <li> GLES1 + * <li> GL4bc </li> + * <li> GL4 </li> + * <li> GL3bc </li> + * <li> GL3 </li> + * <li> GLES3 </li> + * <li> GL2 </li> + * <li> GLES2 </li> + * <li> GLES1 </li> * </ul> * */ - public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2, GLES1 }; + public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2, GLES1 }; /** * Order of minimum profiles. * * <ul> - * <li> GLES1 - * <li> GLES2 - * <li> GL2 - * <li> GL3 - * <li> GL3bc - * <li> GL4 - * <li> GL4bc + * <li> GLES1 </li> + * <li> GLES2 </li> + * <li> GL2 </li> + * <li> GLES3 </li> + * <li> GL3 </li> + * <li> GL3bc </li> + * <li> GL4 </li> + * <li> GL4bc </li> * </ul> * */ - public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GL3, GL3bc, GL4, GL4bc }; - + public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GLES3, GL3, GL3bc, GL4, GL4bc }; + /** * Order of minimum original desktop profiles. * * <ul> - * <li> GL2 - * <li> GL3bc - * <li> GL4bc - * <li> GL3 - * <li> GL4 + * <li> GL2 </li> + * <li> GL3bc </li> + * <li> GL4bc </li> + * <li> GL3 </li> + * <li> GL4 </li> * </ul> * */ public static final String[] GL_PROFILE_LIST_MIN_DESKTOP = new String[] { GL2, GL3bc, GL4bc, GL3, GL4 }; - + /** * Order of maximum fixed function profiles * * <ul> - * <li> GL4bc - * <li> GL3bc - * <li> GL2 - * <li> GLES1 + * <li> GL4bc </li> + * <li> GL3bc </li> + * <li> GL2 </li> + * <li> GLES1 </li> * </ul> * */ @@ -542,16 +597,30 @@ public class GLProfile { * Order of maximum programmable shader profiles * * <ul> - * <li> GL4bc - * <li> GL4 - * <li> GL3bc - * <li> GL3 - * <li> GL2 - * <li> GLES2 + * <li> GL4bc </li> + * <li> GL4 </li> + * <li> GL3bc </li> + * <li> GL3 </li> + * <li> GLES3 </li> + * <li> GL2 </li> + * <li> GLES2 </li> * </ul> * */ - public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2 }; + public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GLES2 }; + + /** + * Order of maximum programmable shader <i>core only</i> profiles + * + * <ul> + * <li> GL4 </li> + * <li> GL3 </li> + * <li> GLES3 </li> + * <li> GLES2 </li> + * </ul> + * + */ + public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER_CORE = new String[] { GL4, GL3, GLES3, GLES2 }; /** Returns a default GLProfile object, reflecting the best for the running platform. * It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL} @@ -567,7 +636,7 @@ public class GLProfile { /** Returns a default GLProfile object, reflecting the best for the running platform. * It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL} * and favors hardware acceleration. - * <p>Uses the default device.</p> + * <p>Uses the default device.</p> * @throws GLException if no profile is available for the default device. */ public static GLProfile getDefault() { @@ -587,7 +656,7 @@ public class GLProfile { return get(device, GL_PROFILE_LIST_MAX, favorHardwareRasterizer); } - /** Uses the default device + /** Uses the default device * @throws GLException if no profile is available for the default device. * @see #GL_PROFILE_LIST_MAX */ @@ -610,7 +679,7 @@ public class GLProfile { return get(device, GL_PROFILE_LIST_MIN, favorHardwareRasterizer); } - /** Uses the default device + /** Uses the default device * @throws GLException if no desktop profile is available for the default device. * @see #GL_PROFILE_LIST_MIN */ @@ -634,7 +703,7 @@ public class GLProfile { return get(device, GL_PROFILE_LIST_MAX_FIXEDFUNC, favorHardwareRasterizer); } - /** Uses the default device + /** Uses the default device * @throws GLException if no fixed function profile is available for the default device. * @see #GL_PROFILE_LIST_MAX_FIXEDFUNC */ @@ -657,7 +726,7 @@ public class GLProfile { return get(device, GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer); } - /** Uses the default device + /** Uses the default device * @throws GLException if no programmable profile is available for the default device. * @see #GL_PROFILE_LIST_MAX_PROGSHADER */ @@ -667,7 +736,30 @@ public class GLProfile { return get(GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer); } - /** + /** + * Returns the highest profile, implementing the programmable shader <i>core</i> pipeline <i>only</i>. + * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_PROGSHADER_CORE} + * + * @throws GLException if no programmable core profile is available for the device. + * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE + */ + public static GLProfile getMaxProgrammableCore(AbstractGraphicsDevice device, boolean favorHardwareRasterizer) + throws GLException + { + return get(device, GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer); + } + + /** Uses the default device + * @throws GLException if no programmable core profile is available for the default device. + * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE + */ + public static GLProfile getMaxProgrammableCore(boolean favorHardwareRasterizer) + throws GLException + { + return get(GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer); + } + + /** * Returns the GL2ES1 profile implementation, hence compatible w/ GL2ES1.<br/> * It returns: * <pre> @@ -686,8 +778,8 @@ public class GLProfile { return get(device, GL2ES1).getImpl(); } - /** - * Calls {@link #getGL2ES1(AbstractGraphicsDevice)} using the default device. + /** + * Calls {@link #getGL2ES1(AbstractGraphicsDevice)} using the default device. * <p>Selection favors hardware rasterizer.</p> * @see #getGL2ES1(AbstractGraphicsDevice) */ @@ -697,7 +789,7 @@ public class GLProfile { return get(defaultDevice, GL2ES1).getImpl(); } - /** + /** * Returns the GL2ES2 profile implementation, hence compatible w/ GL2ES2.<br/> * It returns: * <pre> @@ -716,8 +808,8 @@ public class GLProfile { return get(device, GL2ES2).getImpl(); } - /** - * Calls {@link #getGL2ES2(AbstractGraphicsDevice)} using the default device. + /** + * Calls {@link #getGL2ES2(AbstractGraphicsDevice)} using the default device. * <p>Selection favors hardware rasterizer.</p> * @see #getGL2ES2(AbstractGraphicsDevice) */ @@ -727,7 +819,37 @@ public class GLProfile { return get(defaultDevice, GL2ES2).getImpl(); } - /** + /** + * Returns the GL4ES3 profile implementation, hence compatible w/ GL4ES3.<br/> + * It returns: + * <pre> + * GLProfile.get(device, GLProfile.GL4ES3).getImpl()); + * </pre> + * <p>Selection favors hardware rasterizer.</p> + * + * @throws GLException if no GL4ES3 compatible profile is available for the default device. + * @see #isGL4ES3() + * @see #get(AbstractGraphicsDevice, String) + * @see #getImpl() + */ + public static GLProfile getGL4ES3(AbstractGraphicsDevice device) + throws GLException + { + return get(device, GL4ES3).getImpl(); + } + + /** + * Calls {@link #getGL4ES3(AbstractGraphicsDevice)} using the default device. + * <p>Selection favors hardware rasterizer.</p> + * @see #getGL4ES3(AbstractGraphicsDevice) + */ + public static GLProfile getGL4ES3() + throws GLException + { + return get(defaultDevice, GL4ES3).getImpl(); + } + + /** * Returns the GL2GL3 profile implementation, hence compatible w/ GL2GL3.<br/> * It returns: * <pre> @@ -746,8 +868,8 @@ public class GLProfile { return get(device, GL2GL3).getImpl(); } - /** - * Calls {@link #getGL2GL3(AbstractGraphicsDevice)} using the default device. + /** + * Calls {@link #getGL2GL3(AbstractGraphicsDevice)} using the default device. * <p>Selection favors hardware rasterizer.</p> * @see #getGL2GL3(AbstractGraphicsDevice) */ @@ -763,7 +885,7 @@ public class GLProfile { * the default profile. * * @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device. - * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), + * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), * or <code>[ null, GL ]</code> for the default profile. * @throws GLException if the requested profile is not available for the device. */ @@ -781,8 +903,8 @@ public class GLProfile { return glp; } - /** Uses the default device - * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), + /** Uses the default device + * @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..), * or <code>[ null, GL ]</code> for the default profile. * @throws GLException if the requested profile is not available for the default device. */ @@ -798,14 +920,14 @@ public class GLProfile { * * @param device a valid AbstractGraphicsDevice, or <code>null</null> for the default device. * @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..) - * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false. + * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false. * @throws GLException if the non of the requested profiles is available for the device. */ public static GLProfile get(AbstractGraphicsDevice device, String[] profiles, boolean favorHardwareRasterizer) throws GLException { GLProfile glProfileAny = null; - + HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, true); for(int i=0; i<profiles.length; i++) { final GLProfile glProfile = map.get(profiles[i]); @@ -818,18 +940,18 @@ public class GLProfile { } if(null==glProfileAny) { glProfileAny = glProfile; - } + } } } if(null!=glProfileAny) { return glProfileAny; - } + } throw new GLException("Profiles "+array2String(profiles)+" not available on device "+device); } - /** Uses the default device - * @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..) - * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false. + /** Uses the default device + * @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..) + * @param favorHardwareRasterizer set to true, if hardware rasterizer shall be favored, otherwise false. * @throws GLException if the non of the requested profiles is available for the default device. */ public static GLProfile get(String[] profiles, boolean favorHardwareRasterizer) @@ -837,19 +959,26 @@ public class GLProfile { { return get(defaultDevice, profiles, favorHardwareRasterizer); } - - /** Indicates whether the native OpenGL ES1 profile is in use. + + /** Indicates whether the native OpenGL ES1 profile is in use. * This requires an EGL interface. */ public static boolean usesNativeGLES1(String profileImpl) { return GLES1.equals(profileImpl); } - /** Indicates whether the native OpenGL ES2 profile is in use. - * This requires an EGL or ES2 compatible interface. + /** Indicates whether the native OpenGL ES3 or ES2 profile is in use. + * This requires an EGL, ES3 or ES2 compatible interface. */ public static boolean usesNativeGLES2(String profileImpl) { - return GLES2.equals(profileImpl); + return GLES3.equals(profileImpl) || GLES2.equals(profileImpl); + } + + /** Indicates whether the native OpenGL ES2 profile is in use. + * This requires an EGL, ES3 compatible interface. + */ + public static boolean usesNativeGLES3(String profileImpl) { + return GLES3.equals(profileImpl); } /** Indicates whether either of the native OpenGL ES profiles are in use. */ @@ -908,28 +1037,64 @@ public class GLProfile { public final String getGLImplBaseClassName() { return getGLImplBaseClassName(getImplName()); } + private static final String getGLImplBaseClassName(String profileImpl) { + if( GLES2 == profileImpl || GLES3 == profileImpl ) { + return "jogamp.opengl.es3.GLES3"; + } else if( GLES1 == profileImpl ) { + return "jogamp.opengl.es1.GLES1"; + } else if ( GL4bc == profileImpl || + GL4 == profileImpl || + GL3bc == profileImpl || + GL3 == profileImpl || + GL2 == profileImpl ) { + return "jogamp.opengl.gl4.GL4bc"; + } else { + throw new GLException("unsupported profile \"" + profileImpl + "\""); + } + } + + public final Constructor<?> getGLCtor(boolean glObject) { + return getGLCtor(getImplName(), glObject); + } + private static final Constructor<?> getGLCtor(String profileImpl, boolean glObject) { + if( GLES2 == profileImpl || GLES3 == profileImpl ) { + return glObject ? ctorGLES3Impl : ctorGLES3ProcAddr; + } else if( GLES1 == profileImpl ) { + return glObject ? ctorGLES1Impl : ctorGLES1ProcAddr; + } else if ( GL4bc == profileImpl || + GL4 == profileImpl || + GL3bc == profileImpl || + GL3 == profileImpl || + GL2 == profileImpl ) { + return glObject ? ctorGL234Impl : ctorGL234ProcAddr; + } else { + throw new GLException("unsupported profile \"" + profileImpl + "\""); + } + } /** * @param o GLProfile object to compare with * @return true if given Object is a GLProfile and * if both, profile and profileImpl is equal with this. */ + @Override public final boolean equals(Object o) { if(this==o) { return true; } if(o instanceof GLProfile) { - GLProfile glp = (GLProfile)o; - return getName().equals(glp.getName()) && getImplName().equals(glp.getImplName()) ; + final GLProfile glp = (GLProfile)o; + return getName() == glp.getName() && getImplName() == glp.getImplName() ; } return false; } + @Override public int hashCode() { int hash = 5; hash = 97 * hash + getImplName().hashCode(); hash = 97 * hash + getName().hashCode(); return hash; } - + /** * @param glp GLProfile to compare with * @throws GLException if given GLProfile and this aren't equal @@ -949,14 +1114,14 @@ public class GLProfile { public final GLProfile getImpl() { return null != profileImpl ? profileImpl : this; } - + /** return true if impl. is a hardware rasterizer, otherwise false. */ public final boolean isHardwareRasterizer() { return isHardwareRasterizer; } - - /** - * return this profiles implementation name, eg. GL2ES2 -> GL2, or GL3 -> GL3 + + /** + * return this profiles implementation name, eg. GL2ES2 -> GL2, or GL3 -> GL3 */ public final String getImplName() { return null != profileImpl ? profileImpl.getName() : getName(); @@ -982,7 +1147,7 @@ public class GLProfile { return isGL4() || isGL3bc() || GL3 == profile; } - /** Indicates whether this context is a GL2 context <p>Includes [ GL4bc, GL3bc, GL2 ].</p> */ + /** Indicates whether this profile is capable of GL2 . <p>Includes [ GL4bc, GL3bc, GL2 ].</p> */ public final boolean isGL2() { return isGL3bc() || GL2 == profile; } @@ -992,9 +1157,19 @@ public class GLProfile { return GLES1 == profile; } - /** Indicates whether this profile is capable of GLES2. <p>Includes [ GLES2 ].</p> */ + /** Indicates whether this profile is capable of GLES2. <p>Includes [ GLES2, GLES3 ].</p> */ public final boolean isGLES2() { - return GLES2 == profile; + return isGLES3() || GLES2 == profile; + } + + /** Indicates whether this profile is capable of GLES3. <p>Includes [ GLES3 ].</p> */ + public final boolean isGLES3() { + return GLES3 == profile; + } + + /** Indicates whether this profile is capable of GLES. <p>Includes [ GLES1, GLES2, GLES3 ].</p> */ + public final boolean isGLES() { + return GLES3 == profile || GLES2 == profile || GLES1 == profile; } /** Indicates whether this profile is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p> */ @@ -1002,17 +1177,36 @@ public class GLProfile { return GL2ES1 == profile || isGLES1() || isGL2(); } - /** Indicates whether this profile is capable os GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p> */ + /** Indicates whether this profile is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p> */ public final boolean isGL2GL3() { return GL2GL3 == profile || isGL3() || isGL2(); } - /** Indicates whether this profile is capable os GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3, GL2ES2, GLES2 ].</p> */ + /** Indicates whether this profile is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p> */ public final boolean isGL2ES2() { return GL2ES2 == profile || isGLES2() || isGL2GL3(); } - /** Indicates whether this profile supports GLSL, ie. {@link #isGL2ES2()}. */ + /** + * Indicates whether this profile is capable of GL2ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].</p> + * @see #isGL3ES3() + * @see #isGL2GL3() + */ + public final boolean isGL2ES3() { + return isGL3ES3() || isGL2GL3(); + } + + /** Indicates whether this profile is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p> */ + public final boolean isGL3ES3() { + return isGL4ES3() || isGL3(); + } + + /** Indicates whether this profile is capable of GL4ES3. <p>Includes [ GL4bc, GL4, GLES3 ].</p> */ + public final boolean isGL4ES3() { + return GL4ES3 == profile || isGLES3() || isGL4(); + } + + /** Indicates whether this profile supports GLSL, i.e. {@link #isGL2ES2()}. */ public final boolean hasGLSL() { return isGL2ES2() ; } @@ -1027,12 +1221,17 @@ public class GLProfile { return GLES2 == getImplName(); } + /** Indicates whether this profile uses the native OpenGL ES3 implementations. */ + public final boolean usesNativeGLES3() { + return GLES3 == getImplName(); + } + /** Indicates whether this profile uses either of the native OpenGL ES implementations. */ public final boolean usesNativeGLES() { - return usesNativeGLES2() || usesNativeGLES1(); + return usesNativeGLES3() || usesNativeGLES2() || usesNativeGLES1(); } - /** + /** * General validation if type is a valid GL data type * for the current profile */ @@ -1060,17 +1259,17 @@ public class GLProfile { if( isGL2() ) { return true; } - } + } if(throwException) { throw new GLException("Illegal data type on profile "+this+": "+type); } return false; } - - public boolean isValidArrayDataType(int index, int comps, int type, + + public boolean isValidArrayDataType(int index, int comps, int type, boolean isVertexAttribPointer, boolean throwException) { - String arrayName = getGLArrayName(index); - if(isGLES1()) { + final String arrayName = getGLArrayName(index); + if( isGLES1() ) { if(isVertexAttribPointer) { if(throwException) { throw new GLException("Illegal array type for "+arrayName+" on profile GLES1: VertexAttribPointer"); @@ -1086,7 +1285,7 @@ public class GLProfile { case GL.GL_FIXED: case GL.GL_FLOAT: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type); } @@ -1098,7 +1297,7 @@ public class GLProfile { case 3: case 4: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); } @@ -1112,7 +1311,7 @@ public class GLProfile { case GL.GL_FIXED: case GL.GL_FLOAT: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type); } @@ -1122,7 +1321,7 @@ public class GLProfile { case 0: case 3: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); } @@ -1135,7 +1334,7 @@ public class GLProfile { case GL.GL_FIXED: case GL.GL_FLOAT: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GLES1: "+type); } @@ -1145,7 +1344,7 @@ public class GLProfile { case 0: case 4: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); } @@ -1153,7 +1352,7 @@ public class GLProfile { } break; } - } else if(isGLES2()) { + } else if( isGLES2() ) { // simply ignore !isVertexAttribPointer case, since it is simulated anyway .. switch(type) { case GL.GL_UNSIGNED_BYTE: @@ -1163,7 +1362,7 @@ public class GLProfile { case GL.GL_FLOAT: case GL.GL_FIXED: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GLES2: "+type); } @@ -1177,7 +1376,7 @@ public class GLProfile { case 3: case 4: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GLES2: "+comps); } @@ -1195,7 +1394,7 @@ public class GLProfile { case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: case javax.media.opengl.GL2.GL_DOUBLE: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); } @@ -1208,7 +1407,7 @@ public class GLProfile { case 3: case 4: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); } @@ -1223,7 +1422,7 @@ public class GLProfile { case javax.media.opengl.GL2ES2.GL_INT: case javax.media.opengl.GL2.GL_DOUBLE: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); } @@ -1235,7 +1434,7 @@ public class GLProfile { case 3: case 4: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); } @@ -1250,7 +1449,7 @@ public class GLProfile { case javax.media.opengl.GL2ES2.GL_INT: case javax.media.opengl.GL2.GL_DOUBLE: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); } @@ -1260,7 +1459,7 @@ public class GLProfile { case 0: case 3: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GLES1: "+comps); } @@ -1278,7 +1477,7 @@ public class GLProfile { case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: case javax.media.opengl.GL2.GL_DOUBLE: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); } @@ -1289,7 +1488,7 @@ public class GLProfile { case 3: case 4: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); } @@ -1303,7 +1502,7 @@ public class GLProfile { case javax.media.opengl.GL2ES2.GL_INT: case javax.media.opengl.GL2.GL_DOUBLE: break; - default: + default: if(throwException) { throw new GLException("Illegal data type for "+arrayName+" on profile GL2: "+type); } @@ -1316,7 +1515,7 @@ public class GLProfile { case 3: case 4: break; - default: + default: if(throwException) { throw new GLException("Illegal component number for "+arrayName+" on profile GL2: "+comps); } @@ -1329,52 +1528,120 @@ public class GLProfile { return true; } + @Override public String toString() { return "GLProfile[" + getName() + "/" + getImplName() + "."+(this.isHardwareRasterizer?"hw":"sw")+"]"; } private static /*final*/ boolean isAWTAvailable; - private static /*final*/ boolean hasDesktopGLFactory; + private static /*final*/ boolean hasDesktopGLFactory; private static /*final*/ boolean hasGL234Impl; private static /*final*/ boolean hasEGLFactory; - private static /*final*/ boolean hasGLES2Impl; + private static /*final*/ boolean hasGLES3Impl; private static /*final*/ boolean hasGLES1Impl; + private static /*final*/ Constructor<?> ctorGL234Impl; + private static /*final*/ Constructor<?> ctorGLES3Impl; + private static /*final*/ Constructor<?> ctorGLES1Impl; + private static /*final*/ Constructor<?> ctorGL234ProcAddr; + private static /*final*/ Constructor<?> ctorGLES3ProcAddr; + private static /*final*/ Constructor<?> ctorGLES1ProcAddr; private static /*final*/ GLDrawableFactoryImpl eglFactory = null; private static /*final*/ GLDrawableFactoryImpl desktopFactory = null; private static /*final*/ AbstractGraphicsDevice defaultDevice = null; - private static volatile boolean initialized = false; - private static RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock(); + private static boolean initialized = false; + private static final RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock(); + + private static final Class<?>[] ctorGLArgs = new Class<?>[] { GLProfile.class, jogamp.opengl.GLContextImpl.class }; + private static final Class<?>[] ctorProcArgs = new Class<?>[] { FunctionAddressResolver.class }; + private static final String GL4bcImplClassName = "jogamp.opengl.gl4.GL4bcImpl"; + private static final String GL4bcProcClassName = "jogamp.opengl.gl4.GL4bcProcAddressTable"; + private static final String GLES1ImplClassName = "jogamp.opengl.es1.GLES1Impl"; + private static final String GLES1ProcClassName = "jogamp.opengl.es1.GLES1ProcAddressTable"; + private static final String GLES3ImplClassName = "jogamp.opengl.es3.GLES3Impl"; + private static final String GLES3ProcClassName = "jogamp.opengl.es3.GLES3ProcAddressTable"; + + private static final Constructor<?> getCtor(final String clazzName, final boolean glObject, final ClassLoader cl) { + try { + return ReflectionUtil.getConstructor(clazzName, glObject ? ctorGLArgs : ctorProcArgs, cl); + } catch (Throwable t) { + if( DEBUG ) { + System.err.println("Catched: "+t.getMessage()); + t.printStackTrace(); + } + return null; + } + } + + private static final void initGLCtorImpl() { + final ClassLoader classloader = GLProfile.class.getClassLoader(); + + // depends on hasDesktopGLFactory + { + final Constructor<?> ctorGL = getCtor(GL4bcImplClassName, true, classloader); + final Constructor<?> ctorProc = null != ctorGL ? getCtor(GL4bcProcClassName, false, classloader) : null; + if( null != ctorProc ) { + hasGL234Impl = true; + ctorGL234Impl = ctorGL; + ctorGL234ProcAddr = ctorProc; + } else { + hasGL234Impl = false; + ctorGL234Impl = null; + ctorGL234ProcAddr = null; + } + } + + // depends on hasEGLFactory + { + final Constructor<?> ctorGL = getCtor(GLES1ImplClassName, true, classloader); + final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES1ProcClassName, false, classloader) : null; + if( null != ctorProc ) { + hasGLES1Impl = true; + ctorGLES1Impl = ctorGL; + ctorGLES1ProcAddr = ctorProc; + } else { + hasGLES1Impl = false; + ctorGLES1Impl = null; + ctorGLES1ProcAddr = null; + } + } + { + final Constructor<?> ctorGL = getCtor(GLES3ImplClassName, true, classloader); + final Constructor<?> ctorProc = null != ctorGL ? getCtor(GLES3ProcClassName, false, classloader) : null; + if( null != ctorProc ) { + hasGLES3Impl = true; + ctorGLES3Impl = ctorGL; + ctorGLES3ProcAddr = ctorProc; + } else { + hasGLES3Impl = false; + ctorGLES3Impl = null; + ctorGLES3ProcAddr = null; + } + } + } /** * Tries the profiles implementation and native libraries. */ - private static void initProfilesForDefaultDevices(boolean firstUIActionOnProcess) { - NativeWindowFactory.initSingleton(firstUIActionOnProcess); - + private static void initProfilesForDefaultDevices() { + NativeWindowFactory.initSingleton(); if(DEBUG) { - System.err.println("GLProfile.init firstUIActionOnProcess: "+ firstUIActionOnProcess - + ", thread: " + Thread.currentThread().getName()); + System.err.println("GLProfile.init - thread: " + Thread.currentThread().getName()); System.err.println(VersionUtil.getPlatformInfo()); System.err.println(GlueGenVersion.getInstance()); System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); } - ClassLoader classloader = GLProfile.class.getClassLoader(); + final ClassLoader classloader = GLProfile.class.getClassLoader(); isAWTAvailable = NativeWindowFactory.isAWTAvailable() && ReflectionUtil.isClassAvailable("javax.media.opengl.awt.GLCanvas", classloader) ; // JOGL - // depends on hasDesktopGLFactory - hasGL234Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.gl4.GL4bcImpl", classloader); - - // depends on hasEGLFactory - hasGLES1Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es1.GLES1Impl", classloader); - hasGLES2Impl = ReflectionUtil.isClassAvailable("jogamp.opengl.es2.GLES2Impl", classloader); - + initGLCtorImpl(); + // // Iteration of desktop GL availability detection // utilizing the detected GL version in the shared context. @@ -1383,7 +1650,7 @@ public class GLProfile { // which will register at GLContext .. // GLDrawableFactory.initSingleton(); - + Throwable t=null; // if successfull it has a shared dummy drawable and context created try { @@ -1417,10 +1684,6 @@ public class GLProfile { } } else { defaultDesktopDevice = desktopFactory.getDefaultDevice(); - defaultDevice = defaultDesktopDevice; - if(DEBUG) { - System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice); - } } if ( ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) { @@ -1428,23 +1691,10 @@ public class GLProfile { try { eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2); if(null != eglFactory) { - final boolean isANGLE = ((jogamp.opengl.egl.EGLDrawableFactory)eglFactory).isANGLE(); - if(isANGLE && !enableANGLE) { - if(DEBUG) { - System.err.println("Info: GLProfile.init - EGL/ES2 ANGLE disabled"); - } - eglFactory.destroy(ShutdownType.COMPLETE); - eglFactory = null; - hasEGLFactory = false; - } else { - if(DEBUG && isANGLE) { - System.err.println("Info: GLProfile.init - EGL/ES2 ANGLE enabled"); - } - hasEGLFactory = true; - // update hasGLES1Impl, hasGLES2Impl based on EGL - hasGLES2Impl = null!=eglFactory.getGLDynamicLookupHelper(2) && hasGLES2Impl; - hasGLES1Impl = null!=eglFactory.getGLDynamicLookupHelper(1) && hasGLES1Impl; - } + hasEGLFactory = true; + // update hasGLES1Impl, hasGLES3Impl based on EGL + hasGLES3Impl = null!=eglFactory.getGLDynamicLookupHelper(2) && hasGLES3Impl; + hasGLES1Impl = null!=eglFactory.getGLDynamicLookupHelper(1) && hasGLES1Impl; } } catch (LinkageError le) { t=le; @@ -1462,9 +1712,9 @@ public class GLProfile { } } - final AbstractGraphicsDevice defaultEGLDevice; + final AbstractGraphicsDevice defaultEGLDevice; if(null == eglFactory) { - hasGLES2Impl = false; + hasGLES3Impl = false; hasGLES1Impl = false; defaultEGLDevice = null; if(DEBUG) { @@ -1472,33 +1722,42 @@ public class GLProfile { } } else { defaultEGLDevice = eglFactory.getDefaultDevice(); - if(null == defaultDevice) { - defaultDevice = defaultEGLDevice; - if(DEBUG) { - System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice); - } + } + + if( null != defaultDesktopDevice ) { + defaultDevice = defaultDesktopDevice; + if(DEBUG) { + System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice); + } + } else if ( null != defaultEGLDevice ) { + defaultDevice = defaultEGLDevice; + if(DEBUG) { + System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice); } + } else { + if(DEBUG) { + System.err.println("Info: GLProfile.init - Default device not available"); + } + defaultDevice = null; } - /** Should not be required .. but keep it here if simple probe on defaultDevice ain't enough. - final boolean addedDesktopProfile = initProfilesForDevice(defaultDesktopDevice); - final boolean addedEGLProfile = initProfilesForDevice(defaultEGLDevice); - final boolean addedAnyProfile = addedDesktopProfile || addedEGLProfile ; - */ - final boolean addedAnyProfile = initProfilesForDevice(defaultDevice); + // we require to initialize the EGL device 1st, if available + final boolean addedEGLProfile = null != defaultEGLDevice ? initProfilesForDevice(defaultEGLDevice) : false; + final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false; + final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ; if(DEBUG) { - // System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")"); - System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile); - System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); - System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory); - System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); - System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory); - System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); - System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl); - System.err.println("GLProfile.init defaultDevice "+defaultDevice); - System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL)); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null)); + System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")"); + System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); + System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory); + System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); + System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory); + System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); + System.err.println("GLProfile.init hasGLES3Impl "+hasGLES3Impl); + System.err.println("GLProfile.init defaultDevice "+defaultDevice); + System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice); + System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice); + System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL)); } } @@ -1527,7 +1786,7 @@ public class GLProfile { boolean isSet = GLContext.getAvailableGLVersionsSet(device); if(DEBUG) { - System.err.println("Info: GLProfile.initProfilesForDevice: "+device+", isSet "+isSet); + System.err.println("Info: GLProfile.initProfilesForDevice: "+device+" ("+device.getClass().getName()+"), isSet "+isSet+", hasDesktopGLFactory "+hasDesktopGLFactory+", hasEGLFactory "+hasEGLFactory); } if(isSet) { // Avoid recursion and check whether impl. is sane! @@ -1541,9 +1800,9 @@ public class GLProfile { boolean addedDesktopProfile = false; boolean addedEGLProfile = false; - + final boolean deviceIsDesktopCompatible = hasDesktopGLFactory && desktopFactory.getIsDeviceCompatible(device); - + if( deviceIsDesktopCompatible ) { // 1st pretend we have all Desktop and EGL profiles .. computeProfileMap(device, true /* desktopCtxUndef*/, true /* esCtxUndef */); @@ -1568,11 +1827,11 @@ public class GLProfile { } addedDesktopProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); } - + final boolean deviceIsEGLCompatible = hasEGLFactory && eglFactory.getIsDeviceCompatible(device); - - // also test GLES1 and GLES2 on desktop, since we have implementations / emulations available. - if( deviceIsEGLCompatible && ( hasGLES2Impl || hasGLES1Impl ) ) { + + // also test GLES1, GLES2 and GLES3 on desktop, since we have implementations / emulations available. + if( deviceIsEGLCompatible && ( hasGLES3Impl || hasGLES1Impl ) ) { // 1st pretend we have all EGL profiles .. computeProfileMap(device, false /* desktopCtxUndef*/, true /* esCtxUndef */); @@ -1588,36 +1847,18 @@ public class GLProfile { } 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) + // but it seems even EGL.eglInitialize(eglDisplay, null, null) // fails in some scenarios (eg VirtualBox 4.1.6) w/ EGL error 0x3001 (EGL_NOT_INITIALIZED). hasEGLFactory = false; - hasGLES2Impl = false; + hasGLES3Impl = false; hasGLES1Impl = false; } if (DEBUG) { System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail); } - if( hasGLES2Impl ) { - // The native ES2 impl. overwrites a previous mapping using 'ES2 compatibility' by a desktop profile - GLContext.mapAvailableGLVersion(device, - 2, GLContext.CTX_PROFILE_ES, - 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_IMPL_ES2_COMPAT); - if (DEBUG) { - System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES2 -> ES 2.0"); - } - } - if( hasGLES1Impl ) { - // Always favor the native ES1 impl. - GLContext.mapAvailableGLVersion(device, - 1, GLContext.CTX_PROFILE_ES, - 1, 0, GLContext.CTX_PROFILE_ES); - if (DEBUG) { - System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES1 -> ES 1.0"); - } - } addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); - } - + } + if( !addedDesktopProfile && !addedEGLProfile ) { setProfileMap(device, new HashMap<String /*GLProfile_name*/, GLProfile>()); // empty if(DEBUG) { @@ -1627,7 +1868,7 @@ public class GLProfile { System.err.println("GLProfile: desktoplFactory "+desktopFactory); System.err.println("GLProfile: eglFactory "+eglFactory); System.err.println("GLProfile: hasGLES1Impl "+hasGLES1Impl); - System.err.println("GLProfile: hasGLES2Impl "+hasGLES2Impl); + System.err.println("GLProfile: hasGLES3Impl "+hasGLES3Impl); } } @@ -1705,31 +1946,31 @@ public class GLProfile { final boolean isHardwareRasterizer[] = new boolean[1]; GLProfile defaultGLProfileAny = null; GLProfile defaultGLProfileHW = null; - HashMap<String, GLProfile> _mappedProfiles = new HashMap<String, GLProfile>(GL_PROFILE_LIST_ALL.length + 1 /* default */); + final HashMap<String, GLProfile> _mappedProfiles = new HashMap<String, GLProfile>(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(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer); - if(null!=profileImpl) { + final String profile = GL_PROFILE_LIST_ALL[i]; + final String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer); + if( null != profileImpl ) { final GLProfile glProfile; - if(profile.equals(profileImpl)) { + if( profile.equals( profileImpl ) ) { glProfile = new GLProfile(profile, null, isHardwareRasterizer[0]); } else { - final GLProfile _mglp = _mappedProfiles.get(profileImpl); - if(null == _mglp) { - throw new InternalError("XXX0"); + final GLProfile _mglp = _mappedProfiles.get( profileImpl ); + if( null == _mglp ) { + throw new InternalError("XXX0 profile["+i+"]: "+profile+" -> profileImpl "+profileImpl+" !!! not mapped "); } glProfile = new GLProfile(profile, _mglp, isHardwareRasterizer[0]); } _mappedProfiles.put(profile, glProfile); if (DEBUG) { - System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection()); + System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection()); } - if(null==defaultGLProfileHW && isHardwareRasterizer[0]) { + if( null == defaultGLProfileHW && isHardwareRasterizer[0] ) { defaultGLProfileHW=glProfile; if (DEBUG) { System.err.println("GLProfile.init map defaultHW "+glProfile+" on device "+device.getConnection()); } - } else if(null==defaultGLProfileAny) { + } else if( null == defaultGLProfileAny ) { defaultGLProfileAny=glProfile; if (DEBUG) { System.err.println("GLProfile.init map defaultAny "+glProfile+" on device "+device.getConnection()); @@ -1741,9 +1982,9 @@ public class GLProfile { } } } - if(null!=defaultGLProfileHW) { + if( null != defaultGLProfileHW ) { _mappedProfiles.put(GL_DEFAULT, defaultGLProfileHW); - } else if(null!=defaultGLProfileAny) { + } else if( null != defaultGLProfileAny ) { _mappedProfiles.put(GL_DEFAULT, defaultGLProfileAny); } setProfileMap(device, _mappedProfiles); @@ -1754,10 +1995,6 @@ public class GLProfile { * Returns the profile implementation */ private static String computeProfileImpl(AbstractGraphicsDevice device, String profile, boolean desktopCtxUndef, boolean esCtxUndef, boolean isHardwareRasterizer[]) { - // OSX GL3.. doesn't support GLSL<150, - // hence GL2ES2 and GL2GL3 need to be mapped on GL2 on OSX for GLSL compatibility. - final boolean isOSX = Platform.OS_TYPE == Platform.OSType.MACOS; - if (GL2ES1.equals(profile)) { final boolean es1HardwareRasterizer[] = new boolean[1]; final boolean gles1Available = hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, es1HardwareRasterizer) ); @@ -1785,104 +2022,114 @@ public class GLProfile { } } else if (GL2ES2.equals(profile)) { final boolean es2HardwareRasterizer[] = new boolean[1]; - final boolean gles2Available = hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, es2HardwareRasterizer) ); + final boolean gles2Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES2Available(device, es2HardwareRasterizer) ); final boolean gles2HWAvailable = gles2Available && es2HardwareRasterizer[0] ; + final boolean es3HardwareRasterizer[] = new boolean[1]; + final boolean gles3Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, es3HardwareRasterizer) ); + final boolean gles3HWAvailable = gles3Available && es3HardwareRasterizer[0] ; if(hasGL234Impl) { - if(!isOSX) { - if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { - if(!gles2HWAvailable || isHardwareRasterizer[0]) { - return GL4bc; - } + if(GLContext.isGL4Available(device, isHardwareRasterizer)) { + if( (!gles3HWAvailable && !gles2HWAvailable ) || isHardwareRasterizer[0] ) { + return GL4; } - if(GLContext.isGL4Available(device, isHardwareRasterizer)) { - if(!gles2HWAvailable || isHardwareRasterizer[0]) { - return GL4; - } + } + if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { + if( (!gles3HWAvailable && !gles2HWAvailable ) || isHardwareRasterizer[0] ) { + return GL4bc; } - if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { - if(!gles2HWAvailable || isHardwareRasterizer[0]) { - return GL3bc; - } + } + if(GLContext.isGL3Available(device, isHardwareRasterizer)) { + if( (!gles3HWAvailable && !gles2HWAvailable ) || isHardwareRasterizer[0] ) { + return GL3; } - if(GLContext.isGL3Available(device, isHardwareRasterizer)) { - if(!gles2HWAvailable || isHardwareRasterizer[0]) { - return GL3; - } + } + if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { + if( (!gles3HWAvailable && !gles2HWAvailable ) || isHardwareRasterizer[0] ) { + return GL3bc; } } if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) { - if(!gles2HWAvailable || isHardwareRasterizer[0]) { + if( (!gles3HWAvailable && !gles2HWAvailable ) || isHardwareRasterizer[0] ) { return GL2; } } } + if(gles3Available && ( !gles2HWAvailable || gles3HWAvailable ) ) { + isHardwareRasterizer[0] = es3HardwareRasterizer[0]; + return GLES3; + } if(gles2Available) { isHardwareRasterizer[0] = es2HardwareRasterizer[0]; return GLES2; } + } else if (GL4ES3.equals(profile)) { + final boolean gles3CompatAvail = GLContext.isGLES3CompatibleAvailable(device); + if( desktopCtxUndef || esCtxUndef || gles3CompatAvail ) { + final boolean es3HardwareRasterizer[] = new boolean[1]; + final boolean gles3Available = hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, es3HardwareRasterizer) ); + final boolean gles3HWAvailable = gles3Available && es3HardwareRasterizer[0] ; + if(hasGL234Impl) { + if(GLContext.isGL4Available(device, isHardwareRasterizer)) { + if(!gles3HWAvailable || isHardwareRasterizer[0]) { + return GL4; + } + } + if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { + if(!gles3HWAvailable || isHardwareRasterizer[0]) { + return GL4bc; + } + } + if(GLContext.isGL3Available(device, isHardwareRasterizer)) { + if(!gles3HWAvailable || isHardwareRasterizer[0]) { + return GL3; + } + } + if( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { + if(!gles3HWAvailable || isHardwareRasterizer[0]) { + return GL3bc; + } + } + } + if(gles3Available) { + isHardwareRasterizer[0] = es3HardwareRasterizer[0]; + return GLES3; + } + } } else if(GL2GL3.equals(profile)) { if(hasGL234Impl) { - if(!isOSX && GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { + if( GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { return GL4bc; - } else if(!isOSX && GLContext.isGL4Available(device, isHardwareRasterizer)) { + } else if( GLContext.isGL4Available(device, isHardwareRasterizer)) { return GL4; - } else if(!isOSX && GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { + } else if( GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { return GL3bc; - } else if(!isOSX && GLContext.isGL3Available(device, isHardwareRasterizer)) { + } else if( GLContext.isGL3Available(device, isHardwareRasterizer)) { return GL3; } else if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) { return GL2; } } } else if(GL4bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device, isHardwareRasterizer))) { - return GL4bc; + return desktopCtxUndef ? GL4bc : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_COMPAT); } else if(GL4.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device, isHardwareRasterizer))) { - return GL4; + return desktopCtxUndef ? GL4 : GLContext.getAvailableGLProfileName(device, 4, GLContext.CTX_PROFILE_CORE); } else if(GL3bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer))) { - return GL3bc; + return desktopCtxUndef ? GL3bc : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_COMPAT); } else if(GL3.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device, isHardwareRasterizer))) { - return GL3; + return desktopCtxUndef ? GL3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_CORE); } else if(GL2.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) { - return GL2; - } else if(GLES2.equals(profile) && hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) { - return GLES2; - /** - * TODO: GLES2_TRUE_DESKTOP (see: GLContextImpl, GLProfile) - * Hack to enable GLES2 for desktop profiles w/ ES2 compatibility, - * however .. a consequent implementation would need to have all GL2ES2 - * implementing profile to also implement GLES2! - * Let's rely on GL2ES2 and let the user/impl. query isGLES2Compatible() - } else if(GLES2.equals(profile)) { - if(hasGL234Impl || hasGLES2Impl) { - if(esCtxUndef) { - return GLES2; - } - return GLContext.getAvailableGLProfile(device, 2, GLContext.CTX_PROFILE_ES); - } - */ + return desktopCtxUndef ? GL2 : GLContext.getAvailableGLProfileName(device, 2, GLContext.CTX_PROFILE_COMPAT); + } else if(GLES3.equals(profile) && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES3Available(device, isHardwareRasterizer))) { + return esCtxUndef ? GLES3 : GLContext.getAvailableGLProfileName(device, 3, GLContext.CTX_PROFILE_ES); + } else if(GLES2.equals(profile) && hasGLES3Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) { + return esCtxUndef ? GLES2 : GLContext.getAvailableGLProfileName(device, 2, GLContext.CTX_PROFILE_ES); } else if(GLES1.equals(profile) && hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, isHardwareRasterizer))) { - return GLES1; + return esCtxUndef ? GLES1 : GLContext.getAvailableGLProfileName(device, 1, GLContext.CTX_PROFILE_ES); } 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 "jogamp.opengl.gl4.GL4bc"; - } else if(GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl)) { - return "jogamp.opengl.es1.GLES1"; - } else if(GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl)) { - return "jogamp.opengl.es2.GLES2"; - } else { - throw new GLException("unsupported profile \"" + profileImpl + "\""); - } - } - - private static /*final*/ HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>> deviceConn2ProfileMap = + private static /*final*/ HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>> deviceConn2ProfileMap = new HashMap<String /*device_connection*/, HashMap<String /*GLProfile_name*/, GLProfile>>(); /** @@ -1893,17 +2140,22 @@ public class GLProfile { * * @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 + * @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, boolean throwExceptionOnZeroProfile) - throws GLException + private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device, boolean throwExceptionOnZeroProfile) + throws GLException { initSingleton(); + if(null==defaultDevice) { // avoid NPE and notify of incomplete initialization + throw new GLException("No default device available"); + } + if(null==device) { device = defaultDevice; } + final String deviceKey = device.getUniqueID(); HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey); if( null != map ) { |