diff options
author | Sven Gothel <[email protected]> | 2013-12-21 14:40:36 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-12-21 14:40:36 +0100 |
commit | 972feb4be95d1c16c71b84694729952e91dda668 (patch) | |
tree | 6c73b547fc8e9dbd9e0855520cee221e05d7da95 /src/jogl/classes | |
parent | bbb7f94c015fbfefdff672eb2d261fbd230c4e81 (diff) |
Bug 925 - Accept an ES3 Context, if reported via GL-Version-String w/o EGL_OPENGL_ES3_BIT_KHR
Add Quirk 'GLES3ViaEGLES2Config': ES3 Context is used via EGL_OPENGL_ES2_BIT and 'version 2' for create context attributes.
- GLContextImpl.setGLFunctionAvailability(..)'s ES version validation
only fails if requested major version == 1 and doesn't match.
Hence requesting major==2 and having version 3 is tolerated.
- GLContextImpl.setGLFunctionAvailability(..)'s Quirks:
requested-major < has-major -> Adding GLES3ViaEGLES2Config
- EGLDrawableFactory.mapAvailableEGLESConfig(..):
Reflects has-major version, i.e. GLES3ViaEGLES2Config situation where
an ES2 request leads to an ES3 version.
Note: All workarounds can be found via lookup of GLES3ViaEGLES2Config (as usual when using quirks).
Diffstat (limited to 'src/jogl/classes')
6 files changed, 128 insertions, 34 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java index 95f87be29..daa0d94dd 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java +++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java @@ -31,6 +31,9 @@ import java.util.IdentityHashMap; import javax.media.nativewindow.AbstractGraphicsDevice; +import jogamp.opengl.egl.EGL; +import jogamp.opengl.egl.EGLExt; + /** * GLRendererQuirks contains information of known bugs of various GL renderer. * This information allows us to workaround them. @@ -235,15 +238,33 @@ public class GLRendererQuirks { */ public static final int GLSharedContextBuggy = 14; + /** + * Bug 925 - Accept an ES3 Context, if reported via GL-Version-String w/o {@link EGLExt#EGL_OPENGL_ES3_BIT_KHR}. + * <p> + * The ES3 Context can be used via {@link EGL#EGL_OPENGL_ES2_BIT}. + * </p> + * <p> + * The ES3 Context {@link EGL#eglCreateContext(long, long, long, java.nio.IntBuffer) must be created} with version attributes: + * <pre> + * EGL.EGL_CONTEXT_CLIENT_VERSION, 2, .. + * </pre> + * </p> + * <ul> + * <li>Mesa/AMD >= 9.2.1</li> + * <li>Some Android ES3 drivers ..</li> + * </ul> + */ + public static final int GLES3ViaEGLES2Config = 15; + /** Number of quirks known. */ - public static final int COUNT = 15; + public static final int COUNT = 16; private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval", "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard", "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display", "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext", "NoFullFBOSupport", "GLSLNonCompliant", "GL4NeedsGL3Request", - "GLSharedContextBuggy" + "GLSharedContextBuggy", "GLES3ViaEGLES2Config" }; private static final IdentityHashMap<String, GLRendererQuirks> stickyDeviceQuirks = new IdentityHashMap<String, GLRendererQuirks>(); @@ -278,6 +299,16 @@ public class GLRendererQuirks { sq.addQuirks(quirks, offset, len); } /** + * {@link #addQuirks(GLRendererQuirks) Adding given quirks} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}. + * <p> + * Not thread safe. + * </p> + */ + public static void addStickyDeviceQuirks(AbstractGraphicsDevice device, GLRendererQuirks quirks) throws IllegalArgumentException { + final GLRendererQuirks sq = getStickyDeviceQuirks(device); + sq.addQuirks(quirks); + } + /** * {@link #exist(int) Query} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}. * <p> * Not thread safe. However, use after changing the sticky quirks is safe. diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 083a88c51..d081c4adf 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -74,6 +74,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDebugListener; import javax.media.opengl.GLDebugMessage; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLPipelineFactory; import javax.media.opengl.GLProfile; @@ -1452,12 +1453,12 @@ public abstract class GLContextImpl extends GLContext { // Strict Match (GLVersionMapping): // Relaxed match for versions ( !isES && major < 3 ) requests, last resort! // Otherwise: - // - fail if hasVersion < reqVersion - // - fail if ES major-version mismatch + // - fail if hasVersion < reqVersion (desktop and ES) + // - fail if ES 1.0 major-version mismatch // if( strictMatch && ( ( ( isES || major >= 3 ) && hasGLVersionByInt.compareTo(reqGLVersion) < 0 ) || - ( isES && major != hasGLVersionByInt.getMajor() ) + ( isES && 1 == major && major != hasGLVersionByInt.getMajor() ) ) ) { if(DEBUG) { System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (Int): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByInt); @@ -1487,12 +1488,12 @@ public abstract class GLContextImpl extends GLContext { // Strict Match (GLVersionMapping): // Relaxed match for versions ( !isES && major < 3 ) requests, last resort! // Otherwise: - // - fail if hasVersion < reqVersion - // - fail if ES major-version mismatch + // - fail if hasVersion < reqVersion (desktop and ES) + // - fail if ES 1.0 major-version mismatch // if( strictMatch && ( ( ( isES || major >= 3 ) && hasGLVersionByString.compareTo(reqGLVersion) < 0 ) || - ( isES && major != hasGLVersionByString.getMajor() ) + ( isES && 1 == major && major != hasGLVersionByString.getMajor() ) ) ) { if(DEBUG) { System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (String): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByString); @@ -1661,6 +1662,7 @@ public abstract class GLContextImpl extends GLContext { final String MesaRendererIntelsp = "Intel(R)"; final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT ); final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT ); + final boolean esCtx = 0 != ( ctp & GLContext.CTX_PROFILE_ES ); final boolean isX11 = NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true); final boolean isWindows = Platform.getOSType() == Platform.OSType.WINDOWS; final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium "); @@ -1668,6 +1670,34 @@ public abstract class GLContextImpl extends GLContext { final boolean isDriverNVIDIAGeForce = !isDriverMesa && ( glVendor.contains("NVIDIA Corporation") || glRenderer.contains("NVIDIA ") ); // + // General Quirks + // + if( esCtx ) { + final int quirk = GLRendererQuirks.GLES3ViaEGLES2Config; + if( GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) { + // Merge default sticky quirk! + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Default EGL Device"); + } + quirks[i++] = quirk; + } else if( 2 == reqMajor && 2 < major ) { + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES req "+reqMajor+" and 2 < "+major); + } + quirks[i++] = quirk; + if( withinGLVersionsMapping ) { + // Thread safe due to single threaded initialization! + GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1); + } else { + // FIXME: Remove when moving EGL/ES to ARB ctx creation + synchronized(GLContextImpl.class) { + GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1); + } + } + } + } + + // // OS related quirks // if( Platform.getOSType() == Platform.OSType.MACOS ) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index b2f06dce6..967b88358 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -44,6 +44,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -187,7 +188,11 @@ public class EGLContext extends GLContextImpl { { if ( glProfile.usesNativeGLES3() ) { contextVersionReq = 3; - contextVersionAttr = 3; + if( GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) { + contextVersionAttr = 2; + } else { + contextVersionAttr = 3; + } } else if ( glProfile.usesNativeGLES2() ) { contextVersionReq = 2; contextVersionAttr = 2; diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index f7799f1ec..3c8531730 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -362,10 +362,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return new ArrayList<GLCapabilitiesImmutable>(0); } - private boolean mapAvailableEGLESConfig(AbstractGraphicsDevice adevice, int esProfile, + private boolean mapAvailableEGLESConfig(AbstractGraphicsDevice adevice, int[] esProfile, boolean[] hasPBuffer, GLRendererQuirks[] rendererQuirks, int[] ctp) { final String profileString; - switch( esProfile ) { + switch( esProfile[0] ) { case 3: profileString = GLProfile.GLES3; break; case 2: @@ -413,7 +413,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if(null == defaultSharedResource) { return false; } - switch(esProfile) { + switch(esProfile[0]) { case 3: if( !defaultSharedResource.wasES3ContextCreated ) { return false; @@ -436,7 +436,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { ctp[0] = defaultSharedResource.ctpES1; break; } - EGLContext.mapStaticGLVersion(adevice, esProfile, 0, ctp[0]); + if( null != rendererQuirks[0] ) { + GLRendererQuirks.addStickyDeviceQuirks(adevice, rendererQuirks[0]); + } + EGLContext.mapStaticGLVersion(adevice, esProfile[0], 0, ctp[0]); return true; } @@ -491,6 +494,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } rendererQuirks[0] = context.getRendererQuirks(); ctp[0] = context.getContextOptions(); + esProfile[0] = context.getGLVersionNumber().getMajor(); success = true; } else { // Oops .. something is wrong @@ -499,10 +503,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } } - } catch (GLException gle) { + } catch (Throwable t) { if (DEBUG) { System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed"); - gle.printStackTrace(); + t.printStackTrace(); } } finally { context.destroy(); @@ -594,8 +598,6 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { private SharedResource createEGLSharedResourceImpl(AbstractGraphicsDevice adevice) { final boolean madeCurrentES1; - final boolean madeCurrentES2; - final boolean madeCurrentES3; boolean[] hasPBufferES1 = new boolean[] { false }; boolean[] hasPBufferES3ES2 = new boolean[] { false }; // EGLContext[] eglCtxES1 = new EGLContext[] { null }; @@ -611,18 +613,27 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } if( null != eglES1DynamicLookupHelper ) { - madeCurrentES1 = mapAvailableEGLESConfig(adevice, 1, hasPBufferES1, rendererQuirksES1, ctpES1); + final int[] esProfile = { 1 }; + madeCurrentES1 = mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES1, rendererQuirksES1, ctpES1) && 1 == esProfile[0]; } else { madeCurrentES1 = false; } + boolean madeCurrentES2 = false; + boolean madeCurrentES3 = false; if( null != eglES2DynamicLookupHelper ) { - madeCurrentES3 = mapAvailableEGLESConfig(adevice, 3, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2); - madeCurrentES2 = mapAvailableEGLESConfig(adevice, 2, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2); - } else { - madeCurrentES2 = false; - madeCurrentES3 = false; + // ES3 Query + final int[] esProfile = { 3 }; + madeCurrentES3 = mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2) && 3 == esProfile[0]; + // ES2 Query, may result in ES3 + esProfile[0] = 2; + if( mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2) ) { + switch( esProfile[0] ) { + case 2: madeCurrentES2 = true; break; + case 3: madeCurrentES3 = true; break; + default: throw new InternalError("XXXX Got "+esProfile[0]); + } + } } - if( !EGLContext.getAvailableGLVersionsSet(adevice) ) { // Even though we override the non EGL native mapping intentionally, // avoid exception due to double 'set' - carefull exception of the rule. @@ -640,9 +651,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } if (DEBUG) { System.err.println("EGLDrawableFactory.createShared: devices: queried nativeTK "+QUERY_EGL_ES_NATIVE_TK+", adevice " + adevice + ", defaultDevice " + defaultDevice); - System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", hasPBuffer "+hasPBufferES1[0]); - System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", hasPBuffer "+hasPBufferES3ES2[0]); - System.err.println("EGLDrawableFactory.createShared: context ES3: " + madeCurrentES3 + ", hasPBuffer "+hasPBufferES3ES2[0]); + System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", hasPBuffer "+hasPBufferES1[0]+", quirks "+rendererQuirksES1[0]); + System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", hasPBuffer "+hasPBufferES3ES2[0]+", quirks "+rendererQuirksES3ES2[0]); + System.err.println("EGLDrawableFactory.createShared: context ES3: " + madeCurrentES3 + ", hasPBuffer "+hasPBufferES3ES2[0]+", quirks "+rendererQuirksES3ES2[0]); dumpMap(); } return sr; diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 0e5551b8e..88ed0be92 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -46,6 +46,7 @@ import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -55,6 +56,7 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { @@ -94,8 +96,9 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple } final long cfg = EGLConfigId2EGLConfig(dpy, eglConfigID); if(0 < cfg) { + final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() ); final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsRequested); - final EGLGLCapabilities caps = EGLConfig2Capabilities((EGLGraphicsDevice)absDevice, capsRequested.getGLProfile(), cfg, winattrmask, false); + final EGLGLCapabilities caps = EGLConfig2Capabilities(defaultQuirks, (EGLGraphicsDevice)absDevice, capsRequested.getGLProfile(), cfg, winattrmask, false); return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser()); } return null; @@ -179,6 +182,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple } /** + * @param defaultQuirks GLRendererQuirks of the EGLDrawableFactory's defaultDevice * @param device * @param glp desired GLProfile, may be null * @param config @@ -186,8 +190,8 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple * @param forceTransparentFlag * @return */ - public static EGLGLCapabilities EGLConfig2Capabilities(EGLGraphicsDevice device, GLProfile glp, long config, - int winattrmask, boolean forceTransparentFlag) { + public static EGLGLCapabilities EGLConfig2Capabilities(GLRendererQuirks defaultQuirks, EGLGraphicsDevice device, GLProfile glp, + long config, int winattrmask, boolean forceTransparentFlag) { final long display = device.getHandle(); final int cfgID; final int rType; @@ -232,7 +236,14 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple } return null; } - rType = values.get(1); + { + final int rTypeOrig = values.get(1); + if( defaultQuirks.exist(GLRendererQuirks.GLES3ViaEGLES2Config) && 0 != ( EGL.EGL_OPENGL_ES2_BIT & rTypeOrig ) ) { + rType = rTypeOrig | EGLExt.EGL_OPENGL_ES3_BIT_KHR; + } else { + rType = rTypeOrig; + } + } if( EGL.EGL_NATIVE_VISUAL_ID == attributes.get(2) ) { visualID = values.get(2); @@ -251,7 +262,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple if(!EGLGLCapabilities.isCompatible(glp, rType)) { if(DEBUG) { System.err.println("config "+toHexString(config)+": Requested GLProfile "+glp+ - " not compatible with EGL-RenderableType["+EGLGLCapabilities.renderableTypeToString(null, rType)+"]"); + " with quirks "+defaultQuirks+" not compatible with EGL-RenderableType["+EGLGLCapabilities.renderableTypeToString(null, rType)+"]"); } return null; } @@ -453,7 +464,11 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple } else if(caps.getGLProfile().usesNativeGLES2()) { attrs.put(idx++, EGL.EGL_OPENGL_ES2_BIT); } else if(caps.getGLProfile().usesNativeGLES3()) { - attrs.put(idx++, EGLExt.EGL_OPENGL_ES3_BIT_KHR); + if( GLRendererQuirks.existStickyDeviceQuirk(GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) { + attrs.put(idx++, EGL.EGL_OPENGL_ES2_BIT); + } else { + attrs.put(idx++, EGLExt.EGL_OPENGL_ES3_BIT_KHR); + } } else { attrs.put(idx++, EGL.EGL_OPENGL_BIT); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index 568fede45..8802c3c7d 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -53,6 +53,7 @@ import javax.media.opengl.GLDrawableFactory; import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; import jogamp.opengl.GLGraphicsConfigurationFactory; import jogamp.opengl.GLGraphicsConfigurationUtil; @@ -476,9 +477,10 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact } static List<GLCapabilitiesImmutable> eglConfigs2GLCaps(EGLGraphicsDevice device, GLProfile glp, PointerBuffer configs, int num, int winattrmask, boolean forceTransparentFlag, boolean onlyFirstValid) { + final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() ); List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(num); for(int i=0; i<num; i++) { - final GLCapabilitiesImmutable caps = EGLGraphicsConfiguration.EGLConfig2Capabilities(device, glp, configs.get(i), winattrmask, forceTransparentFlag); + final GLCapabilitiesImmutable caps = EGLGraphicsConfiguration.EGLConfig2Capabilities(defaultQuirks, device, glp, configs.get(i), winattrmask, forceTransparentFlag); if(null != caps) { bucket.add(caps); if(onlyFirstValid) { |