diff options
author | Sven Gothel <[email protected]> | 2012-02-20 18:03:36 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-02-20 18:03:36 +0100 |
commit | a4c7bf0420e369e71561d2847f2fc444ce5abafa (patch) | |
tree | eaf13946a0ef653fc9de163a911484be10f33379 /src/jogl | |
parent | 505525c857bc4d62815a69463e263d0c2c847ac1 (diff) |
API Change [GLProfile/GLContext]: Add notion of hardware acceleration in GLProfile.get<Profile>() methods.
We need to distinguish between software and hardware accelerated OpenGL profiles
to allow choosing the proper profiles [default, GL2ES1, GL2ES2, ..]
on platforms where both, software and hardware implementations exist (GL, GLES2, ..).
Where no preference is being requested, hardware acceleration is favored:
GLProfile.getDefault()
GLProfile.getGL2ES1()
GLProfile.getGL2ES2()
Some method signatures needed to change
GLProfile:
getMaxProgrammable(AbstractGraphicsDevice device) ->
getMaxProgrammable(AbstractGraphicsDevice device, boolean favorHardwareRasterizer)
GLProfile adds: isHardwareRasterizer()
Determination whether a hardware acceleration is being used or not
is extended in GLContextImpl by querying the current context's
GL_RENDERER string. If the latter contains 'software' (case insensitive)
it is not hardware accelerated. At least this works w/ newer Mesa3D impl,
where GLX_SLOW_CONFIG is not set!
Diffstat (limited to 'src/jogl')
7 files changed, 268 insertions, 112 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index 9e861bf52..894f44b9f 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -861,8 +861,14 @@ public abstract class GLContext { return val; } - protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int profile) { - String key = getDeviceVersionAvailableKey(device, reqMajor, profile); + /** + * @param device the device to request whether the profile is available for + * @param reqMajor Key Value either 1, 2, 3 or 4 + * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} + * @return the available GL version as encoded with {@link #composeBits(int, int, int), otherwise <code>null</code> + */ + protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile) { + String key = getDeviceVersionAvailableKey(device, reqMajor, reqProfile); Integer val; synchronized(deviceVersionAvailable) { val = deviceVersionAvailable.get( key ); @@ -877,8 +883,8 @@ public abstract class GLContext { * @param minor if not null, returns the used minor version * @param ctp if not null, returns the used context profile */ - protected static boolean getAvailableGLVersion(AbstractGraphicsDevice device, - int reqMajor, int reqProfile, int[] major, int minor[], int ctp[]) { + protected static boolean getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile, + int[] major, int minor[], int ctp[]) { Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile); if(null==valI) { @@ -898,7 +904,7 @@ public abstract class GLContext { } return true; } - + /** * returns the highest GLProfile string regarding the implementation version and context profile bits. * @throws GLException if version and context profile bits could not be mapped to a GLProfile @@ -937,39 +943,47 @@ public abstract class GLContext { } /** - * @param major Key Value either 1, 2, 3 or 4 - * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} + * @param device the device to request whether the profile is available for + * @param reqMajor Key Value either 1, 2, 3 or 4 + * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} + * @param isHardware return value of one boolean, whether the profile is a hardware rasterizer or not + * @return true if the requested GL version is available regardless of a software or hardware rasterizer, otherwise false. */ - public static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int major, int profile) { - return null != getAvailableGLVersion(device, major, profile); + public static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) { + Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile); + if(null==valI) { + return false; + } + isHardware[0] = 0 == ( valI.intValue() & GLContext.CTX_IMPL_ACCEL_SOFT ) ; + return true; } - public static boolean isGLES1Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES); + public static boolean isGLES1Available(AbstractGraphicsDevice device, boolean isHardware[]) { + return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES, isHardware); } - public static boolean isGLES2Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES); + public static boolean isGLES2Available(AbstractGraphicsDevice device, boolean isHardware[]) { + return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware); } - public static boolean isGL4bcAvailable(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT); + public static boolean isGL4bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware); } - public static boolean isGL4Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE); + public static boolean isGL4Available(AbstractGraphicsDevice device, boolean isHardware[]) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE, isHardware); } - public static boolean isGL3bcAvailable(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT); + public static boolean isGL3bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT, isHardware); } - public static boolean isGL3Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE); + public static boolean isGL3Available(AbstractGraphicsDevice device, boolean isHardware[]) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE, isHardware); } - public static boolean isGL2Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT); + public static boolean isGL2Available(AbstractGraphicsDevice device, boolean isHardware[]) { + return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware); } /** diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index 9f0093230..b32cd2962 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -545,6 +545,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. * @throws GLException if no profile is available for the device. * @see #GL_PROFILE_LIST_ALL */ @@ -553,7 +554,10 @@ public class GLProfile { return glp; } - /** Uses the default device + /** 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> * @throws GLException if no profile is available for the default device. */ public static GLProfile getDefault() { @@ -567,20 +571,20 @@ public class GLProfile { * @throws GLException if no profile is available for the device. * @see #GL_PROFILE_LIST_MAX */ - public static GLProfile getMaximum(AbstractGraphicsDevice device) + public static GLProfile getMaximum(AbstractGraphicsDevice device, boolean favorHardwareRasterizer) throws GLException { - return get(device, GL_PROFILE_LIST_MAX); + return get(device, GL_PROFILE_LIST_MAX, favorHardwareRasterizer); } /** Uses the default device * @throws GLException if no profile is available for the default device. * @see #GL_PROFILE_LIST_MAX */ - public static GLProfile getMaximum() + public static GLProfile getMaximum(boolean favorHardwareRasterizer) throws GLException { - return get(GL_PROFILE_LIST_MAX); + return get(GL_PROFILE_LIST_MAX, favorHardwareRasterizer); } /** @@ -590,20 +594,20 @@ public class GLProfile { * @throws GLException if no desktop profile is available for the device. * @see #GL_PROFILE_LIST_MIN */ - public static GLProfile getMinimum(AbstractGraphicsDevice device) + public static GLProfile getMinimum(AbstractGraphicsDevice device, boolean favorHardwareRasterizer) throws GLException { - return get(device, GL_PROFILE_LIST_MIN); + return get(device, GL_PROFILE_LIST_MIN, favorHardwareRasterizer); } /** 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() + public static GLProfile getMinimum(boolean favorHardwareRasterizer) throws GLException { - return get(GL_PROFILE_LIST_MIN); + return get(GL_PROFILE_LIST_MIN, favorHardwareRasterizer); } @@ -614,20 +618,20 @@ public class GLProfile { * @throws GLException if no fixed function profile is available for the device. * @see #GL_PROFILE_LIST_MAX_FIXEDFUNC */ - public static GLProfile getMaxFixedFunc(AbstractGraphicsDevice device) + public static GLProfile getMaxFixedFunc(AbstractGraphicsDevice device, boolean favorHardwareRasterizer) throws GLException { - return get(device, GL_PROFILE_LIST_MAX_FIXEDFUNC); + return get(device, GL_PROFILE_LIST_MAX_FIXEDFUNC, favorHardwareRasterizer); } /** 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() + public static GLProfile getMaxFixedFunc(boolean favorHardwareRasterizer) throws GLException { - return get(GL_PROFILE_LIST_MAX_FIXEDFUNC); + return get(GL_PROFILE_LIST_MAX_FIXEDFUNC, favorHardwareRasterizer); } /** @@ -637,20 +641,20 @@ public class GLProfile { * @throws GLException if no programmable profile is available for the device. * @see #GL_PROFILE_LIST_MAX_PROGSHADER */ - public static GLProfile getMaxProgrammable(AbstractGraphicsDevice device) + public static GLProfile getMaxProgrammable(AbstractGraphicsDevice device, boolean favorHardwareRasterizer) throws GLException { - return get(device, GL_PROFILE_LIST_MAX_PROGSHADER); + return get(device, GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer); } /** 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() + public static GLProfile getMaxProgrammable(boolean favorHardwareRasterizer) throws GLException { - return get(GL_PROFILE_LIST_MAX_PROGSHADER); + return get(GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer); } /** @@ -659,6 +663,7 @@ public class GLProfile { * <pre> * GLProfile.get(device, GLProfile.GL2ES1).getImpl()); * </pre> + * <p>Selection favors hardware rasterizer.</p> * * @throws GLException if no GL2ES1 compatible profile is available for the default device. * @see #get(AbstractGraphicsDevice, String) @@ -672,6 +677,7 @@ public class GLProfile { /** * Calls {@link #getGL2ES1(AbstractGraphicsDevice)} using the default device. + * <p>Selection favors hardware rasterizer.</p> * @see #getGL2ES1(AbstractGraphicsDevice) */ public static GLProfile getGL2ES1() @@ -686,6 +692,7 @@ public class GLProfile { * <pre> * GLProfile.get(device, GLProfile.GL2ES2).getImpl()); * </pre> + * <p>Selection favors hardware rasterizer.</p> * * @throws GLException if no GL2ES2 compatible profile is available for the default device. * @see #get(AbstractGraphicsDevice, String) @@ -699,6 +706,7 @@ public class GLProfile { /** * Calls {@link #getGL2ES2(AbstractGraphicsDevice)} using the default device. + * <p>Selection favors hardware rasterizer.</p> * @see #getGL2ES2(AbstractGraphicsDevice) */ public static GLProfile getGL2ES2() @@ -747,31 +755,45 @@ public class GLProfile { * where an implementation is available. * * @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 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 device. */ - public static GLProfile get(AbstractGraphicsDevice device, String[] profiles) + 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++) { - String profile = profiles[i]; - GLProfile glProfile = map.get(profile); + final GLProfile glProfile = map.get(profiles[i]); if(null!=glProfile) { - return glProfile; + if(!favorHardwareRasterizer) { + return glProfile; + } + if(glProfile.isHardwareRasterizer()) { + return 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. * @throws GLException if the non of the requested profiles is available for the default device. */ - public static GLProfile get(String[] profiles) + public static GLProfile get(String[] profiles, boolean favorHardwareRasterizer) throws GLException { - return get(defaultDevice, profiles); + return get(defaultDevice, profiles, favorHardwareRasterizer); } /** Indicates whether the native OpenGL ES1 profile is in use. @@ -886,6 +908,11 @@ public class GLProfile { 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 */ @@ -1261,7 +1288,7 @@ public class GLProfile { } public String toString() { - return "GLProfile[" + getName() + "/" + getImplName() + "]"; + return "GLProfile[" + getName() + "/" + getImplName() + "."+(this.isHardwareRasterizer?"hw":"sw")+"]"; } private static /*final*/ boolean isAWTAvailable; @@ -1459,12 +1486,8 @@ public class GLProfile { if (DEBUG) { System.err.println("GLProfile.initProfilesForDevice: "+device+": desktop Shared Ctx "+desktopSharedCtxAvail); } - if( hasDesktopGLFactory && null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_COMPAT) ) { - // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, - // so we have to add the usual suspect - GLContext.mapAvailableGLVersion(device, - 2, GLContext.CTX_PROFILE_COMPAT, - 1, 5, GLContext.CTX_PROFILE_COMPAT); + if( hasDesktopGLFactory && !GLContext.getAvailableGLVersionsSet(device) ) { + throw new InternalError("Available GLVersions not set"); } addedDesktopProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); } @@ -1502,12 +1525,18 @@ public class GLProfile { 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 */); } @@ -1596,30 +1625,37 @@ public class GLProfile { if (DEBUG) { System.err.println("GLProfile.init map "+device.getConnection()+", desktopCtxUndef "+desktopCtxUndef+", esCtxUndef "+esCtxUndef); } - GLProfile defaultGLProfile = null; + 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 */); 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); + String profileImpl = computeProfileImpl(device, profile, desktopCtxUndef, esCtxUndef, isHardwareRasterizer); if(null!=profileImpl) { final GLProfile glProfile; if(profile.equals(profileImpl)) { - glProfile = new GLProfile(profile, null); + glProfile = new GLProfile(profile, null, isHardwareRasterizer[0]); } else { final GLProfile _mglp = _mappedProfiles.get(profileImpl); if(null == _mglp) { throw new InternalError("XXX0"); } - glProfile = new GLProfile(profile, _mglp); + glProfile = new GLProfile(profile, _mglp, isHardwareRasterizer[0]); } _mappedProfiles.put(profile, glProfile); if (DEBUG) { System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection()); } - if(null==defaultGLProfile) { - defaultGLProfile=glProfile; + 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) { + defaultGLProfileAny=glProfile; if (DEBUG) { - System.err.println("GLProfile.init map default "+glProfile+" on device "+device.getConnection()); + System.err.println("GLProfile.init map defaultAny "+glProfile+" on device "+device.getConnection()); } } } else { @@ -1628,8 +1664,10 @@ public class GLProfile { } } } - if(null!=defaultGLProfile) { - _mappedProfiles.put(GL_DEFAULT, defaultGLProfile); + if(null!=defaultGLProfileHW) { + _mappedProfiles.put(GL_DEFAULT, defaultGLProfileHW); + } else if(null!=defaultGLProfileAny) { + _mappedProfiles.put(GL_DEFAULT, defaultGLProfileAny); } setProfileMap(device, _mappedProfiles); return _mappedProfiles.size() > 0; @@ -1638,66 +1676,98 @@ public class GLProfile { /** * Returns the profile implementation */ - private static String computeProfileImpl(AbstractGraphicsDevice device, String profile, boolean desktopCtxUndef, boolean esCtxUndef) { + 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) ); + final boolean gles1HWAvailable = gles1Available && es1HardwareRasterizer[0] ; if(hasGL234Impl) { - if(GLContext.isGL4bcAvailable(device)) { - return GL4bc; - } else if(GLContext.isGL3bcAvailable(device)) { - return GL3bc; - } else if(desktopCtxUndef || GLContext.isGL2Available(device)) { - return GL2; + if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { + if(!gles1HWAvailable || isHardwareRasterizer[0]) { + return GL4bc; + } + } + if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { + if(!gles1HWAvailable || isHardwareRasterizer[0]) { + return GL3bc; + } + } + if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) { + if(!gles1HWAvailable || isHardwareRasterizer[0]) { + return GL2; + } } } - if(hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device))) { + if(gles1Available) { + isHardwareRasterizer[0] = es1HardwareRasterizer[0]; return GLES1; } } else if (GL2ES2.equals(profile)) { + final boolean es2HardwareRasterizer[] = new boolean[1]; + final boolean gles2Available = hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, es2HardwareRasterizer) ); + final boolean gles2HWAvailable = gles2Available && es2HardwareRasterizer[0] ; if(hasGL234Impl) { - if(!isOSX && GLContext.isGL4bcAvailable(device)) { - return GL4bc; - } else if(!isOSX && GLContext.isGL4Available(device)) { - return GL4; - } else if(!isOSX && GLContext.isGL3bcAvailable(device)) { - return GL3bc; - } else if(!isOSX && GLContext.isGL3Available(device)) { - return GL3; - } else if(desktopCtxUndef || GLContext.isGL2Available(device)) { - return GL2; + if(!isOSX) { + if(GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { + if(!gles2HWAvailable || isHardwareRasterizer[0]) { + return GL4bc; + } + } + if(GLContext.isGL4Available(device, isHardwareRasterizer)) { + if(!gles2HWAvailable || isHardwareRasterizer[0]) { + return GL4; + } + } + if(GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { + if(!gles2HWAvailable || isHardwareRasterizer[0]) { + return GL3bc; + } + } + if(GLContext.isGL3Available(device, isHardwareRasterizer)) { + if(!gles2HWAvailable || isHardwareRasterizer[0]) { + return GL3; + } + } + } + if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) { + if(!gles2HWAvailable || isHardwareRasterizer[0]) { + return GL2; + } } } - if(hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device))) { + if(gles2Available) { + isHardwareRasterizer[0] = es2HardwareRasterizer[0]; return GLES2; } } else if(GL2GL3.equals(profile)) { if(hasGL234Impl) { - if(!isOSX && GLContext.isGL4bcAvailable(device)) { + if(!isOSX && GLContext.isGL4bcAvailable(device, isHardwareRasterizer)) { return GL4bc; - } else if(!isOSX && GLContext.isGL4Available(device)) { + } else if(!isOSX && GLContext.isGL4Available(device, isHardwareRasterizer)) { return GL4; - } else if(!isOSX && GLContext.isGL3bcAvailable(device)) { + } else if(!isOSX && GLContext.isGL3bcAvailable(device, isHardwareRasterizer)) { return GL3bc; - } else if(!isOSX && GLContext.isGL3Available(device)) { + } else if(!isOSX && GLContext.isGL3Available(device, isHardwareRasterizer)) { return GL3; - } else if(desktopCtxUndef || GLContext.isGL2Available(device)) { + } else if(desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer)) { return GL2; } } - } else if(GL4bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device))) { + } else if(GL4bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4bcAvailable(device, isHardwareRasterizer))) { return GL4bc; - } else if(GL4.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device))) { + } else if(GL4.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL4Available(device, isHardwareRasterizer))) { return GL4; - } else if(GL3bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device))) { + } else if(GL3bc.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3bcAvailable(device, isHardwareRasterizer))) { return GL3bc; - } else if(GL3.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device))) { + } else if(GL3.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL3Available(device, isHardwareRasterizer))) { return GL3; - } else if(GL2.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device))) { + } else if(GL2.equals(profile) && hasGL234Impl && ( desktopCtxUndef || GLContext.isGL2Available(device, isHardwareRasterizer))) { return GL2; - } else if(GLES2.equals(profile) && hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device))) { + } else if(GLES2.equals(profile) && hasGLES2Impl && ( esCtxUndef || GLContext.isGLES2Available(device, isHardwareRasterizer))) { return GLES2; /** * TODO: GLES2_TRUE_DESKTOP (see: GLContextImpl, GLProfile) @@ -1713,7 +1783,7 @@ public class GLProfile { return GLContext.getAvailableGLProfile(device, 2, GLContext.CTX_PROFILE_ES); } */ - } else if(GLES1.equals(profile) && hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device))) { + } else if(GLES1.equals(profile) && hasGLES1Impl && ( esCtxUndef || GLContext.isGLES1Available(device, isHardwareRasterizer))) { return GLES1; } return null; @@ -1782,11 +1852,13 @@ public class GLProfile { } } - private GLProfile(String profile, GLProfile profileImpl) { + private GLProfile(String profile, GLProfile profileImpl, boolean isHardwareRasterizer) { this.profile = profile; this.profileImpl = profileImpl; + this.isHardwareRasterizer = isHardwareRasterizer; } - private GLProfile profileImpl = null; - private String profile = null; + private GLProfile profileImpl; + private String profile; + private boolean isHardwareRasterizer; } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 1924ba409..08a9baeb9 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -514,14 +514,43 @@ public abstract class GLContextImpl extends GLContext { } if (DEBUG) { if(created) { - System.err.println(getThreadName() + ": !!! Create GL context OK: " + toHexString(contextHandle) + " for " + getClass().getName()); + System.err.println(getThreadName() + ": !!! Create GL context OK: " + toHexString(contextHandle) + " for " + getClass().getName()+" - "+getGLVersion()); } else { System.err.println(getThreadName() + ": !!! Create GL context FAILED for " + getClass().getName()); } - } + } if(!created) { return CONTEXT_NOT_CURRENT; } + + // finalize mapping the available GLVersions, in case it's not done yet + { + final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); + final AbstractGraphicsDevice device = config.getScreen().getDevice(); + + if( !GLContext.getAvailableGLVersionsSet(device) ) { + final int reqMajor; + final int reqProfile; + if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { + // ES1 or ES2 + reqMajor = ctxMajorVersion; + reqProfile = GLContext.CTX_PROFILE_ES; + } else { + // Only GL2 actually + if(ctxMajorVersion>2 || 0 != ( ctxOptions & GLContext.CTX_PROFILE_CORE)) { + throw new InternalError("XXX: "+getGLVersion()); + } + reqMajor = 2; + reqProfile = GLContext.CTX_PROFILE_COMPAT; + } + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, + ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.setAvailableGLVersionsSet(device); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! createContextOLD-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion()); + } + } + } GLContextShareSet.contextCreated(this); return CONTEXT_CURRENT_NEW; } @@ -714,7 +743,7 @@ public abstract class GLContextImpl extends GLContext { } } if(0!=_context) { - AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by // createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..) GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxMajorVersion, ctxMinorVersion, ctxOptions); @@ -729,10 +758,10 @@ public abstract class GLContextImpl extends GLContext { }*/ destroyContextARBImpl(_context); if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable HAVE: " + getGLVersion()); + System.err.println(getThreadName() + ": !!! createContextARB-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion()); } } else if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); + System.err.println(getThreadName() + ": !!! createContextARB-MapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); } resetStates(); } @@ -951,11 +980,12 @@ public abstract class GLContextImpl extends GLContext { } updateGLXProcAddressTable(); - AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); - AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); - if(!drawable.getChosenGLCapabilities().getHardwareAccelerated()) { + if(!isCurrentContextHardwareRasterizer()) { ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT; - } + } + final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); + final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits); if (DEBUG) { System.err.println(getThreadName() + ": !!! Context FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); @@ -1024,11 +1054,12 @@ public abstract class GLContextImpl extends GLContext { } protected final void removeCachedVersion(int major, int minor, int ctxProfileBits) { - AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); - AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); - if(!drawable.getChosenGLCapabilities().getHardwareAccelerated()) { + if(!isCurrentContextHardwareRasterizer()) { ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT; } + final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); + final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits); if (DEBUG) { System.err.println(getThreadName() + ": !!! RM Context FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); @@ -1049,6 +1080,21 @@ public abstract class GLContextImpl extends GLContext { } } + private final boolean isCurrentContextHardwareRasterizer() { + boolean isHardwareRasterizer = true; + + if(!drawable.getChosenGLCapabilities().getHardwareAccelerated()) { + isHardwareRasterizer = false; + } else { + // On some platforms (eg. X11), a software GL impl. does not properly declare itself properly. + final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper(); + final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString"); + final String glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString).toLowerCase(); + isHardwareRasterizer = !glRenderer.contains("software"); + } + return isHardwareRasterizer; + } + /** * Updates the platform's 'GLX' function cache */ @@ -1259,4 +1305,7 @@ public abstract class GLContextImpl extends GLContext { gl.getGL2GL3().glDebugMessageInsertAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, id, len, buf); } } + + /** Internal bootstraping glGetString(GL_RENDERER) */ + protected static native String glGetStringInt(int name, long procAddress); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index c412bbe1d..91d05f945 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -205,7 +205,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { boolean hasRECTTextures = false; boolean hasAppleFloatPixels = false; { - GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP); + GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); if (null == glp) { throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index f40a5f0bf..5eafebc11 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -292,7 +292,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { sharedDevice.lock(); try { AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); - GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP); + GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); if (null == glp) { throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index 4e8a35fa5..70e22476b 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -229,7 +229,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); - GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP); + GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); if (null == glp) { throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); } diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c index 16f60e4e7..c1d6ad181 100644 --- a/src/jogl/native/JoglCommon.c +++ b/src/jogl/native/JoglCommon.c @@ -1,6 +1,10 @@ +#include "jogamp_opengl_GLContextImpl.h" #include "JoglCommon.h" +#include <assert.h> +#include <KHR/khrplatform.h> + static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; @@ -53,3 +57,20 @@ jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) return strChars; } +/* + * Class: jogamp_opengl_GLContextImpl + * Method: glGetStringInt + * Signature: (IJ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_jogamp_opengl_GLContextImpl_glGetStringInt(JNIEnv *env, jclass _unused, jint name, jlong procAddress) { + typedef const khronos_uint8_t * (KHRONOS_APIENTRY*_local_PFNGLGETSTRINGPROC)(unsigned int name); + _local_PFNGLGETSTRINGPROC ptr_glGetString; + const khronos_uint8_t * _res; + ptr_glGetString = (_local_PFNGLGETSTRINGPROC) (intptr_t) procAddress; + assert(ptr_glGetString != NULL); + _res = (* ptr_glGetString) ((unsigned int) name); + if (NULL == _res) return NULL; + return (*env)->NewStringUTF(env, _res); +} + |