/*
* 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
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
* ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
* DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
package javax.media.opengl;
import jogamp.opengl.Debug;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.jvm.JNILibLoaderBase;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.JarUtil;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.cache.TempJarCache;
import com.jogamp.nativewindow.NativeWindowVersion;
import com.jogamp.opengl.JoglVersion;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.fixedfunc.GLPointerFunc;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
/**
* 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()},
* or more specialized versions using the other static GetProfile methods.
*/
public class GLProfile {
public static final boolean DEBUG = Debug.debug("GLProfile");
/**
* Static one time initialization of JOGL.
*
* The parameter firstUIActionOnProcess
has an impact on concurrent locking,
* see {@link javax.media.nativewindow.NativeWindowFactory#initSingleton(boolean) NativeWindowFactory.initSingleton(firstUIActionOnProcess)}.
*
*
* Applications shall call this methods ASAP , before any other UI invocation.
* You may issue the call in your main class
static block, which is the earliest point in your application/applet lifecycle,
* or within the main function
.
* In case applications are able to initialize JOGL before any other UI action,
* they shall invoke this method with firstUIActionOnProcess=true
and benefit from fast native multithreading support on all platforms if possible.
*
* RCP Application (Applet's, Webstart, Netbeans, ..) using JOGL may not be able to initialize JOGL
* before the first UI action.
* In such case you shall invoke this method with firstUIActionOnProcess=false
.
* On some platforms, notably X11 with AWT usage, JOGL will utilize special locking mechanisms which may slow down your
* application.
*
* Remark: NEWT is currently not affected by this behavior, ie always uses native multithreading.
*
* However, in case this method is not invoked, hence GLProfile is not initialized explicitly by the user,
* the first call to {@link #getDefault()}, {@link #get(java.lang.String)}, etc, will initialize with firstUIActionOnProcess=false
,
* hence without the possibility to enable native multithreading.
* This is not the recommended way, since it may has a performance impact, but it allows you to run code without explicit initialization.
*
*
* @param firstUIActionOnProcess Should be true
if called before the first UI action of the running program,
* otherwise false
.
*/
public static synchronized void initSingleton(final boolean firstUIActionOnProcess) {
if(!initialized) {
initialized = true;
// run the whole static initialization privileged to speed up,
// since this skips checking further access
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
if(TempJarCache.isInitialized()) {
final Class> c = GLProfile.class;
final ClassLoader cl = c.getClassLoader();
try {
final String jarName = JarUtil.getJarName(c.getName(), cl);
if(DEBUG) {
System.err.println("GLProfile classURL: "+IOUtil.getClassURL(c.getName(), cl));
System.err.println("GLProfile jarName: "+jarName);
}
if(jarName!=null) {
if( jarName.startsWith("jogl.all") ) {
// all-in-one variant
JNILibLoaderBase.addNativeJarLibs(c, "jogl-all");
} else {
// atomic variant
JNILibLoaderBase.addNativeJarLibs(c, "nativewindow");
JNILibLoaderBase.addNativeJarLibs(c, "jogl");
if( ReflectionUtil.isClassAvailable("com.jogamp.newt.NewtFactory", cl) ) {
JNILibLoaderBase.addNativeJarLibs(c, "newt");
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
initProfilesForDefaultDevices(firstUIActionOnProcess);
return null;
}
});
}
}
/**
* 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);
}
/**
* Manual shutdown method, may be called after your last JOGL use
* within the running JVM.
* It releases all temporary created resources, ie issues {@link javax.media.opengl.GLDrawableFactory#shutdown()}.
* The shutdown implementation is called via the JVM shutdown hook, if not manually invoked here.
* Invoke shutdown()
manually is recommended, due to the unreliable JVM state within the shutdown hook.
*/
public static synchronized void shutdown() {
if(initialized) {
initialized = false;
GLDrawableFactory.shutdown();
GLContext.shutdown();
}
}
//
// Query platform available OpenGL implementation
//
/**
* Returns the availability of a profile on a device.
*
* @param device a valid AbstractGraphicsDevice, or null for the default device.
* @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or [ null, GL ]
for the default profile.
* @return true if the profile is available for the device, otherwise false.
*/
public static boolean isAvailable(AbstractGraphicsDevice device, String profile) {
try {
return null != getProfileMap(device).get(profile);
} catch (GLException gle) { /* profiles for device n/a */ }
return false;
}
/**
* Returns the availability of a profile on the default device.
*
* @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or [ null, GL ]
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) {
boolean avail;
StringBuffer sb = new StringBuffer();
validateInitialization();
if(null==device) {
device = defaultDevice;
}
sb.append("GLAvailability[Native[GL4bc ");
avail=isAvailable(device, GL4bc);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_COMPAT);
}
sb.append(", GL4 ");
avail=isAvailable(device, GL4);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_CORE);
}
sb.append(", GL3bc ");
avail=isAvailable(device, GL3bc);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_COMPAT);
}
sb.append(", GL3 ");
avail=isAvailable(device, GL3);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_CORE);
}
sb.append(", GL2 ");
avail=isAvailable(device, GL2);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_COMPAT);
}
sb.append(", GL2ES1 ");
sb.append(isAvailable(device, GL2ES1));
sb.append(", GLES1 ");
avail=isAvailable(device, GLES1);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 1, GLContext.CTX_PROFILE_ES);
}
sb.append(", GL2ES2 ");
sb.append(isAvailable(device, GL2ES2));
sb.append(", GLES2 ");
avail=isAvailable(device, GLES2);
sb.append(avail);
if(avail) {
glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_ES);
}
sb.append("], Profiles[");
HashMap profileMap = null;
try {
profileMap = getProfileMap(device);
} catch (GLException gle) { /* profiles for device n/a */ }
if(null != profileMap) {
for(Iterator i=profileMap.values().iterator(); i.hasNext(); ) {
sb.append(i.next().toString());
sb.append(", ");
}
sb.append(", default ");
try {
sb.append(getDefault(device));
} catch (GLException gle) {
sb.append("n/a");
}
}
sb.append("]]");
return sb.toString();
}
/** Uses the default device */
public static String glAvailabilityToString() {
return glAvailabilityToString(null);
}
//
// Public (user-visible) profiles
//
/** The desktop OpenGL compatibility profile 4.x, with x >= 0, ie GL2 plus GL4.
bc
stands for backward compatibility. */
public static final String GL4bc = "GL4bc";
/** The desktop OpenGL core profile 4.x, with x >= 0 */
public static final String GL4 = "GL4";
/** The desktop OpenGL compatibility profile 3.x, with x >= 1, ie GL2 plus GL3.
bc
stands for backward compatibility. */
public static final String GL3bc = "GL3bc";
/** The desktop OpenGL core profile 3.x, with x >= 1 */
public static final String GL3 = "GL3";
/** The desktop OpenGL profile 1.x up to 3.0 */
public static final String GL2 = "GL2";
/** The embedded OpenGL profile ES 1.x, with x >= 0 */
public static final String GLES1 = "GLES1";
/** The embedded OpenGL profile ES 2.x, with x >= 0 */
public static final String GLES2 = "GLES2";
/** The intersection of the desktop GL2 and embedded ES1 profile */
public static final String GL2ES1 = "GL2ES1";
/** The intersection of the desktop GL3, GL2 and embedded ES2 profile */
public static final String GL2ES2 = "GL2ES2";
/** 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
* from highest to lowest version.
* This includes the generic subset profiles GL2GL3, GL2ES2 and GL2ES1.
*
*
* 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, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 };
/**
* Order of maximum profiles.
*
*
* GL4bc
* GL4
* GL3bc
* GL3
* GL2
* GLES2
* GLES1
*
*
*/
public static final String[] GL_PROFILE_LIST_MAX = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2, GLES1 };
/**
* Order of minimum profiles.
*
*
* GLES1
* GLES2
* GL2
* GL3
* GL3bc
* GL4
* GL4bc
*
*
*/
public static final String[] GL_PROFILE_LIST_MIN = new String[] { GLES1, GLES2, GL2, GL3, GL3bc, GL4, GL4bc };
/**
* Order of minimum original desktop profiles.
*
*
* GL2
* GL3bc
* GL4bc
* GL3
* GL4
*
*
*/
public static final String[] GL_PROFILE_LIST_MIN_DESKTOP = new String[] { GL2, GL3bc, GL4bc, GL3, GL4 };
/**
* Order of maximum fixed function profiles
*
*
* GL4bc
* GL3bc
* GL2
* GLES1
*
*
*/
public static final String[] GL_PROFILE_LIST_MAX_FIXEDFUNC = new String[] { GL4bc, GL3bc, GL2, GLES1 };
/**
* Order of maximum programmable shader profiles
*
*
* GL4bc
* GL4
* GL3bc
* GL3
* GL2
* GLES2
*
*
*/
public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2 };
/**
* All GL2ES2 Profiles in the order of default detection.
*
* @see #GL_PROFILE_LIST_MAX_PROGSHADER
*/
public static final String[] GL_PROFILE_LIST_GL2ES2 = GL_PROFILE_LIST_MAX_PROGSHADER;
/**
* All GL2ES1 Profiles in the order of default detection.
*
* @see #GL_PROFILE_LIST_MAX_FIXEDFUNC
*/
public static final String[] GL_PROFILE_LIST_GL2ES1 = GL_PROFILE_LIST_MAX_FIXEDFUNC;
/**
* All GLES Profiles in the order of default detection.
*
*
*
*/
public static final String[] GL_PROFILE_LIST_GLES = new String[] { GLES2, GLES1 };
/** 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}
* @throws GLException if no profile is available for the device.
* @see #GL_PROFILE_LIST_ALL
*/
public static GLProfile getDefault(AbstractGraphicsDevice device) {
GLProfile glp = get(device, GL_DEFAULT);
return glp;
}
/** Uses the default device
* @throws GLException if no profile is available for the default device.
*/
public static GLProfile getDefault() {
return getDefault(defaultDevice);
}
/**
* Returns the highest profile.
* It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX}
*
* @throws GLException if no profile is available for the device.
* @see #GL_PROFILE_LIST_MAX
*/
public static GLProfile getMaximum(AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL_PROFILE_LIST_MAX);
}
/** Uses the default device
* @throws GLException if no profile is available for the default device.
* @see #GL_PROFILE_LIST_MAX
*/
public static GLProfile getMaximum()
throws GLException
{
return get(GL_PROFILE_LIST_MAX);
}
/**
* Returns the lowest profile.
* It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MIN}
*
* @throws GLException if no desktop profile is available for the device.
* @see #GL_PROFILE_LIST_MIN
*/
public static GLProfile getMinimum(AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL_PROFILE_LIST_MIN);
}
/** Uses the default device
* @throws GLException if no desktop profile is available for the default device.
* @see #GL_PROFILE_LIST_MIN
*/
public static GLProfile getMinimum()
throws GLException
{
return get(GL_PROFILE_LIST_MIN);
}
/**
* Returns the highest profile, implementing the fixed function pipeline.
* It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_FIXEDFUNC}
*
* @throws GLException if no fixed function profile is available for the device.
* @see #GL_PROFILE_LIST_MAX_FIXEDFUNC
*/
public static GLProfile getMaxFixedFunc(AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL_PROFILE_LIST_MAX_FIXEDFUNC);
}
/** Uses the default device
* @throws GLException if no fixed function profile is available for the default device.
* @see #GL_PROFILE_LIST_MAX_FIXEDFUNC
*/
public static GLProfile getMaxFixedFunc()
throws GLException
{
return get(GL_PROFILE_LIST_MAX_FIXEDFUNC);
}
/**
* Returns the highest profile, implementing the programmable shader pipeline.
* It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_PROGSHADER}
*
* @throws GLException if no programmable profile is available for the device.
* @see #GL_PROFILE_LIST_MAX_PROGSHADER
*/
public static GLProfile getMaxProgrammable(AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL_PROFILE_LIST_MAX_PROGSHADER);
}
/** Uses the default device
* @throws GLException if no programmable profile is available for the default device.
* @see #GL_PROFILE_LIST_MAX_PROGSHADER
*/
public static GLProfile getMaxProgrammable()
throws GLException
{
return get(GL_PROFILE_LIST_MAX_PROGSHADER);
}
/**
* Returns an available GL2ES1 compatible profile.
* It returns the first available of the set: {@link GLProfile#GL_PROFILE_LIST_GL2ES1}.
*
* @throws GLException if no GL2ES1 compatible profile is available for the device.
* @see #GL_PROFILE_LIST_GL2ES1
*/
public static GLProfile getGL2ES1(AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL_PROFILE_LIST_GL2ES1);
}
/**
* Returns an available GL2ES1 compatible profile.
* It returns the first available of the set: {@link GLProfile#GL_PROFILE_LIST_GL2ES1}.
*
* @throws GLException if no GL2ES1 compatible profile is available for the default device.
* @see #GL_PROFILE_LIST_GL2ES1
*/
public static GLProfile getGL2ES1()
throws GLException
{
return get(GL_PROFILE_LIST_GL2ES1);
}
/**
* Returns an available GL2ES2 compatible profile.
* It returns the first available of the set: {@link GLProfile#GL_PROFILE_LIST_GL2ES2}.
*
* @throws GLException if no GL2ES2 compatible profile is available for the device.
* @see #GL_PROFILE_LIST_GL2ES2
*/
public static GLProfile getGL2ES2(AbstractGraphicsDevice device)
throws GLException
{
return get(device, GL_PROFILE_LIST_GL2ES2);
}
/**
* Returns an available GL2ES2 compatible profile
* It returns the first available of the set: {@link GLProfile#GL_PROFILE_LIST_GL2ES2}.
*
* @throws GLException if no GL2ES2 compatible profile is available for the default device.
* @see #GL_PROFILE_LIST_GL2ES2
*/
public static GLProfile getGL2ES2()
throws GLException
{
return get(GL_PROFILE_LIST_GL2ES2);
}
/** Returns a GLProfile object.
* verifies the given profile and chooses an appropriate implementation.
* A generic value of null
or GL
will result in
* the default profile.
*
* @param device a valid AbstractGraphicsDevice, or null for the default device.
* @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or [ null, GL ]
for the default profile.
* @throws GLException if the requested profile is not available for the device.
*/
public static GLProfile get(AbstractGraphicsDevice device, String profile)
throws GLException
{
if(null==profile || profile.equals("GL")) {
profile = GL_DEFAULT;
}
final HashMap glpMap = getProfileMap(device);
final GLProfile glp = glpMap.get(profile);
if(null == glp) {
throw new GLException("Profile "+profile+" is not available on "+device+", but: "+glpMap.values());
}
return glp;
}
/** Uses the default device
* @param profile a valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..),
* or [ null, GL ]
for the default profile.
* @throws GLException if the requested profile is not available for the default device.
*/
public static GLProfile get(String profile)
throws GLException
{
return get(defaultDevice, profile);
}
/**
* Returns the first profile from the given list,
* where an implementation is available.
*
* @param device a valid AbstractGraphicsDevice, or null for the default device.
* @param profiles array of valid GLProfile name ({@link #GL4bc}, {@link #GL4}, {@link #GL2}, ..)
* @throws GLException if the non of the requested profiles is available for the device.
*/
public static GLProfile get(AbstractGraphicsDevice device, String[] profiles)
throws GLException
{
HashMap map = getProfileMap(device);
for(int i=0; i()); // empty
if(DEBUG) {
System.err.println("GLProfile: device could not be initialized: "+device);
System.err.println("GLProfile: compatible w/ desktop: "+deviceIsDesktopCompatible+
", egl "+deviceIsEGLCompatible);
System.err.println("GLProfile: desktoplFactory "+desktopFactory);
System.err.println("GLProfile: eglFactory "+eglFactory);
System.err.println("GLProfile: hasGLES1Impl "+hasGLES1Impl);
System.err.println("GLProfile: hasGLES2Impl "+hasGLES2Impl);
}
}
if(!GLContext.getAvailableGLVersionsSet(device)) {
GLContext.setAvailableGLVersionsSet(device);
}
if (DEBUG) {
System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": added profile(s): desktop "+addedDesktopProfile+", egl "+addedEGLProfile);
System.err.println("GLProfile.initProfilesForDevice: "+device.getConnection()+": "+glAvailabilityToString(device));
if(addedDesktopProfile) {
dumpGLInfo(desktopFactory, device);
List availCaps = desktopFactory.getAvailableCapabilities(device);
for(int i=0; i availCaps = eglFactory.getAvailableCapabilities(device);
for(int i=0; i 0)
msg.append(", ");
msg.append(list[i]);
}
msg.append("]");
return msg.toString();
}
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");
}
sb.append("[");
sb.append(str);
sb.append("]");
}
private static boolean computeProfileMap(AbstractGraphicsDevice device, boolean desktopCtxUndef, boolean esCtxUndef) {
if (DEBUG) {
System.err.println("GLProfile.init map "+device.getConnection()+", desktopCtxUndef "+desktopCtxUndef+", esCtxUndef "+esCtxUndef);
}
GLProfile defaultGLProfile = null;
HashMap _mappedProfiles = new HashMap(GL_PROFILE_LIST_ALL.length + 1 /* default */);
for(int i=0; i 0;
}
/**
* Returns the profile implementation
*/
private static String computeProfileImpl(AbstractGraphicsDevice device, String profile, boolean desktopCtxUndef, boolean esCtxUndef) {
if (GL2ES1.equals(profile)) {
if(hasGL234Impl) {
if(GLContext.isGL4bcAvailable(device)) {
return GL4bc;
} else if(GLContext.isGL3bcAvailable(device)) {
return GL3bc;
} else if(desktopCtxUndef || GLContext.isGL2Available(device)) {
return GL2;
}
}
if(hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device))) {
return GLES1;
}
} else if (GL2ES2.equals(profile)) {
if(hasGL234Impl) {
if(GLContext.isGL4bcAvailable(device)) {
return GL4bc;
} else if(GLContext.isGL4Available(device)) {
return GL4;
} else if(GLContext.isGL3bcAvailable(device)) {
return GL3bc;
} else if(GLContext.isGL3Available(device)) {
return GL3;
} else if(desktopCtxUndef || GLContext.isGL2Available(device)) {
return GL2;
}
}
if(hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device))) {
return GLES2;
}
} else if(GL2GL3.equals(profile)) {
if(hasGL234Impl) {
if(GLContext.isGL4bcAvailable(device)) {
return GL4bc;
} else if(GLContext.isGL4Available(device)) {
return GL4;
} else if(GLContext.isGL3bcAvailable(device)) {
return GL3bc;
} else if(GLContext.isGL3Available(device)) {
return GL3;
} else if(desktopCtxUndef || GLContext.isGL2Available(device)) {
return GL2;
}
}
} else if(GL4bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device))) {
return GL4bc;
} else if(GL4.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device))) {
return GL4;
} else if(GL3bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device))) {
return GL3bc;
} else if(GL3.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device))) {
return GL3;
} else if(GL2.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device))) {
return GL2;
} else if(GLES2.equals(profile) && hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device))) {
return GLES2;
} else if(GLES1.equals(profile) && hasGLES1Impl && ( esCtxUndef || 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 "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> deviceConn2ProfileMap =
new HashMap>();
/**
* This implementation support lazy initialization, while avoiding recursion/deadlocks.
* If no mapping 'device -> GLProfiles-Map' exists yet, it triggers
* - create empty mapping device -> GLProfiles-Map
* - initialization GLProfiles-Map'
* @return the GLProfile HashMap if exists, otherwise null
* @throws GLException if no profile for the given device is available.
*/
private static HashMap getProfileMap(AbstractGraphicsDevice device) throws GLException {
validateInitialization();
if(null==device) {
device = defaultDevice;
}
String deviceKey = device.getUniqueID();
HashMap map = deviceConn2ProfileMap.get(deviceKey);
if( null == map ) {
if( !initProfilesForDevice(device) ) {
throw new GLException("No Profile available for "+device);
}
if( null == deviceConn2ProfileMap.get(deviceKey) ) {
throw new InternalError("initProfilesForDevice(..) didn't issue setProfileMap(..) on "+device);
}
}
return map;
}
private static void setProfileMap(AbstractGraphicsDevice device, HashMap mappedProfiles) {
validateInitialization();
synchronized ( deviceConn2ProfileMap ) {
deviceConn2ProfileMap.put(device.getUniqueID(), mappedProfiles);
}
}
private GLProfile(String profile, String profileImpl) {
this.profile = profile;
this.profileImpl = profileImpl;
}
private String profileImpl = null;
private String profile = null;
}