diff options
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLContextImpl.java | 826 |
1 files changed, 571 insertions, 255 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 8f4105f98..6866374bc 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -45,7 +45,10 @@ import java.nio.IntBuffer; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; import java.util.Map; +import java.util.Set; import com.jogamp.common.ExceptionUtils; import com.jogamp.common.os.DynamicLookupHelper; @@ -59,12 +62,12 @@ import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.GLRendererQuirks; - import com.jogamp.nativewindow.AbstractGraphicsConfiguration; import com.jogamp.nativewindow.AbstractGraphicsDevice; import com.jogamp.nativewindow.NativeSurface; import com.jogamp.nativewindow.NativeWindowFactory; import com.jogamp.nativewindow.ProxySurface; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GL2ES3; @@ -126,11 +129,13 @@ public abstract class GLContextImpl extends GLContext { * If GL >= 3.0 (ES or desktop) and not having {@link GLRendererQuirks#NoSurfacelessCtx}, * being evaluated if not surface-handle is null and not yet set at makeCurrent(..). */ - private boolean surfacelessOK = false; + private boolean isSurfaceless = false; private boolean pixelDataEvaluated; private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType; + private int currentSwapInterval; + protected GL gl; protected static final Object mappedContextTypeObjectLock; @@ -207,8 +212,9 @@ public abstract class GLContextImpl extends GLContext { boundFBOTarget[1] = 0; // read } - surfacelessOK = false; + isSurfaceless = false; pixelDataEvaluated = false; + currentSwapInterval = 0; super.resetStates(isInit); } @@ -536,7 +542,7 @@ public abstract class GLContextImpl extends GLContext { //---------------------------------------------------------------------- // - protected final boolean isSurfacelessOK() { return surfacelessOK; } + protected final boolean isSurfaceless() { return isSurfaceless; } /** * {@inheritDoc} @@ -607,7 +613,7 @@ public abstract class GLContextImpl extends GLContext { if ( drawable.isRealized() ) { lock.lock(); try { - if ( 0 == drawable.getHandle() && !surfacelessOK ) { + if ( 0 == drawable.getHandle() && !isSurfaceless ) { if( DEBUG ) { System.err.println(getThreadName() +": GLContext.makeCurrent: Surfaceless evaluate"); } @@ -671,7 +677,7 @@ public abstract class GLContextImpl extends GLContext { } if ( CONTEXT_NOT_CURRENT != res ) { // still locked! - if( 0 == drawable.getHandle() && !surfacelessOK ) { + if( 0 == drawable.getHandle() && !isSurfaceless ) { if( hasRendererQuirk(GLRendererQuirks.NoSurfacelessCtx) ) { throw new GLException(String.format("Surfaceless not supported due to quirk %s: %s", GLRendererQuirks.toString(GLRendererQuirks.NoSurfacelessCtx), toString())); @@ -679,15 +685,15 @@ public abstract class GLContextImpl extends GLContext { if( DEBUG ) { System.err.println(getThreadName() +": GLContext.makeCurrent: Surfaceless OK - validated"); } - surfacelessOK = true; + isSurfaceless = true; } setCurrent(this); if( CONTEXT_CURRENT_NEW == res ) { // check if the drawable's and the GL's GLProfile are equal // throws an GLException if not - drawable.getGLProfile().verifyEquality(gl.getGLProfile()); + // FIXME: drawable.getGLProfile().verifyEquality(gl.getGLProfile()); - glDebugHandler.init( isGL2GL3() && isGLDebugEnabled() ); + glDebugHandler.init( isGLDebugEnabled() ); if(DEBUG_GL) { setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ); @@ -802,28 +808,28 @@ public abstract class GLContextImpl extends GLContext { reqProfile = GLContext.CTX_PROFILE_COMPAT; isCompat = true; } - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + final MappedGLVersion me = mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); // Perform all required profile mappings if( isCompat ) { // COMPAT via non ARB - GLContext.mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); if( reqMajor >= 4 ) { - GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - GLContext.mapAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 3, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); + mapAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); } if( reqMajor >= 3 ) { - GLContext.mapAvailableGLVersion(device, 2, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 2, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); } } else { // CORE via non ARB, unlikely, however .. if( reqMajor >= 4 ) { - GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 3, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); } } GLContext.setAvailableGLVersionsSet(device, true); if (DEBUG) { - System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion()); + System.err.println(getThreadName() + ": createContextOLD-MapGLVersions HAVE: " + me); } } } @@ -947,13 +953,13 @@ public abstract class GLContextImpl extends GLContext { { final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice device = config.getScreen().getDevice(); - if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB: mappedVersionsAvailableSet("+device.getConnection()+"): "+ - GLContext.getAvailableGLVersionsSet(device)); - } final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final GLProfile glp = glCaps.getGLProfile(); + if (DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions is SET ("+device.getConnection()+"): "+ + GLContext.getAvailableGLVersionsSet(device)); + } if ( !GLContext.getAvailableGLVersionsSet(device) ) { if( !mapGLVersions(device) ) { // none of the ARB context creation calls was successful, bail out @@ -965,7 +971,7 @@ public abstract class GLContextImpl extends GLContext { GLContext.getRequestMajorAndCompat(glp, reqMajorCTP); if(DEBUG) { - System.err.println(getThreadName() + ": createContextARB: Requested "+glp+" -> "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[1], null)); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions Requested "+glp+" -> "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[1], null)); } final int _major[] = { 0 }; final int _minor[] = { 0 }; @@ -975,7 +981,7 @@ public abstract class GLContextImpl extends GLContext { _major, _minor, _ctp)) { _ctp[0] |= additionalCtxCreationFlags; if(DEBUG) { - System.err.println(getThreadName() + ": createContextARB: Mapped "+GLContext.getGLVersion(_major[0], _minor[0], _ctp[0], null)); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions Mapped "+GLContext.getGLVersion(_major[0], _minor[0], _ctp[0], null)); } _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { @@ -987,8 +993,156 @@ public abstract class GLContextImpl extends GLContext { return _ctx; } + //---------------------------------------------------------------------- + // + + public static class MappedGLVersion { + public final AbstractGraphicsDevice device; + public final int reqMajorVersion; + public final int reqProfile; + public final VersionNumber ctxVersion; + public final int ctxOptions; + public final GLRendererQuirks quirks; + public final VersionNumber preCtxVersion; + public final int preCtxOptions; + public MappedGLVersion(final AbstractGraphicsDevice device, final int reqMajorVersion, final int reqProfile, + final VersionNumber ctxVersion, final int ctxOptions, final GLRendererQuirks quirks, + final VersionNumber preCtxVersion, final int preCtxOptions) { + this.device = device; + this.reqMajorVersion = reqMajorVersion; + this.reqProfile = reqProfile; + this.ctxVersion = ctxVersion; + this.ctxOptions = ctxOptions; + this.quirks = quirks; + this.preCtxVersion = preCtxVersion; + this.preCtxOptions = preCtxOptions; + } + public final String toString() { + return toString(new StringBuilder(), -1, -1, -1, -1).toString(); + } + public final StringBuilder toString(final StringBuilder sb, final int minMajor, final int minMinor, final int maxMajor, final int maxMinor) { + sb.append(device.toString()).append(" ").append(reqMajorVersion).append(" ("); + GLContext.getGLProfile(sb, reqProfile).append(")"); + if( minMajor >=0 && minMinor >=0 && maxMajor >= 0 && maxMinor >= 0) { + sb.append("[").append(minMajor).append(".").append(minMinor).append(" .. ").append(maxMajor).append(".").append(maxMinor).append("]"); + } + sb.append(": ["); + if( null != preCtxVersion ) { + GLContext.getGLVersion(sb, preCtxVersion, preCtxOptions, null); + } else { + sb.append("None"); + } + sb.append("] -> ["); + GLContext.getGLVersion(sb, ctxVersion, ctxOptions, null).append("]"); + return sb; + } + } + public static interface MappedGLVersionListener { + void glVersionMapped(final MappedGLVersion e); + } + private static MappedGLVersionListener mapGLVersionListener = null; + protected static synchronized void setMappedGLVersionListener(final MappedGLVersionListener mvl) { + mapGLVersionListener = mvl; + } + + /** + * Called by {@link jogamp.opengl.GLContextImpl#createContextARBMapVersionsAvailable(int,int)} not intended to be used by + * implementations. However, if {@link jogamp.opengl.GLContextImpl#createContextARB(long, boolean)} is not being used within + * {@link com.jogamp.opengl.GLDrawableFactory#getOrCreateSharedContext(com.jogamp.nativewindow.AbstractGraphicsDevice)}, + * GLProfile has to map the available versions. + * + * @param reqMajor Key Value either 1, 2, 3 or 4 + * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES} + * @param resVersion the resulting version number + * @param resCtp the resulting context options + * @return the old mapped value + * + * @see #createContextARBMapVersionsAvailable + */ + protected static MappedGLVersion mapAvailableGLVersion(final AbstractGraphicsDevice device, + final int reqMajor, final int profile, + final VersionNumber resVersion, final int resCtp, + final GLRendererQuirks resQuirks) + { + final Integer preVal = mapAvailableGLVersion(device, reqMajor, profile, resVersion, resCtp); + final int[] preCtp = { 0 }; + final VersionNumber preVersion = null != preVal ? decomposeBits(preVal.intValue(), preCtp) : null; + final MappedGLVersion res = new MappedGLVersion(device, reqMajor, profile, resVersion, resCtp, resQuirks, preVersion, preCtp[0]); + if( null != mapGLVersionListener ) { + mapGLVersionListener.glVersionMapped(res); + } + return res; + } + private static Integer mapAvailableGLVersion(final AbstractGraphicsDevice device, + final int reqMajor, final int profile, final VersionNumber resVersion, int resCtp) + { + validateProfileBits(profile, "profile"); + validateProfileBits(resCtp, "resCtp"); + + if(FORCE_NO_FBO_SUPPORT) { + resCtp &= ~CTX_IMPL_FBO ; + } + if(DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions MAP "+device+": "+reqMajor+" ("+GLContext.getGLProfile(new StringBuilder(), profile).toString()+ ") -> "+ + getGLVersion(resVersion.getMajor(), resVersion.getMinor(), resCtp, null)); + } + final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile); + final Integer val = Integer.valueOf(composeBits(resVersion.getMajor(), resVersion.getMinor(), resCtp)); + synchronized(deviceVersionAvailable) { + return deviceVersionAvailable.put( objectKey, val ); + } + } + + + protected static void remapAvailableGLVersions(final AbstractGraphicsDevice fromDevice, final AbstractGraphicsDevice toDevice) { + if( fromDevice == toDevice || fromDevice.getUniqueID() == toDevice.getUniqueID() ) { + return; // NOP + } + synchronized(deviceVersionAvailable) { + if(DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions REMAP "+fromDevice+" -> "+toDevice); + } + final IdentityHashMap<String, Integer> newDeviceVersionAvailable = new IdentityHashMap<String, Integer>(); + final Set<String> keys = deviceVersionAvailable.keySet(); + for(final Iterator<String> keyI = keys.iterator(); keyI.hasNext(); ) { + final String origKey = keyI.next(); + final Integer valI = deviceVersionAvailable.get(origKey); + if( null != valI ) { + if(DEBUG) { + final int[] ctp = { 0 }; + final VersionNumber version = decomposeBits(valI.intValue(), ctp); + System.err.println(" MapGLVersions REMAP OLD "+origKey+" -> "+GLContext.getGLVersion(new StringBuilder(), version, ctp[0], null).toString()); + } + newDeviceVersionAvailable.put(origKey, valI); + final int devSepIdx = origKey.lastIndexOf('-'); + if( 0 >= devSepIdx ) { + throw new InternalError("device-separator '-' at "+devSepIdx+" of "+origKey); + } + final String devUniqueID = origKey.substring(0, devSepIdx); + if( fromDevice.getUniqueID().equals(devUniqueID) ) { + final String profileReq = origKey.substring(devSepIdx); + final String newKey = (toDevice.getUniqueID()+profileReq).intern(); + if(DEBUG) { + System.err.println(" MapGLVersions REMAP NEW "+newKey+" -> (ditto)"); + } + newDeviceVersionAvailable.put(newKey, valI); + } + } + } + deviceVersionAvailable.clear(); + deviceVersionAvailable.putAll(newDeviceVersionAvailable); + GLContext.setAvailableGLVersionsSet(toDevice, true); + } + } + private final boolean mapGLVersions(final AbstractGraphicsDevice device) { synchronized (GLContext.deviceVersionAvailable) { + final boolean hasOpenGLESSupport = drawable.getFactory().hasOpenGLESSupport(); + final boolean hasOpenGLDesktopSupport = drawable.getFactory().hasOpenGLDesktopSupport(); + final boolean hasMinorVersionSupport = drawable.getFactoryImpl().hasMajorMinorCreateContextARB(); + if (DEBUG) { + System.err.println(getThreadName() + ": createContextARB-MapGLVersions START (GLDesktop "+hasOpenGLDesktopSupport+", GLES "+hasOpenGLESSupport+", minorVersion "+hasMinorVersionSupport+") on "+device); + } final long t0 = ( DEBUG ) ? System.nanoTime() : 0; boolean success = false; // Following GLProfile.GL_PROFILE_LIST_ALL order of profile detection { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 } @@ -997,6 +1151,43 @@ public abstract class GLContextImpl extends GLContext { boolean hasGL2 = false; boolean hasGL4 = false; boolean hasGL3 = false; + boolean hasES3 = false; + boolean hasES2 = false; + boolean hasES1 = false; + + if( hasOpenGLESSupport && !GLProfile.disableOpenGLES ) { + if( !hasES3) { + hasES3 = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_ES, hasMinorVersionSupport); // ES3 + success |= hasES3; + if( hasES3 ) { + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel ES3 to all lower core profiles: ES2 + mapAvailableGLVersion(device, 2, CTX_PROFILE_ES, ctxVersion, ctxOptions, glRendererQuirks); + if( PROFILE_ALIASING ) { + hasES2 = true; + } + } + resetStates(false); // clean context states, since creation was temporary + } + } + if( !hasES2) { + hasES2 = createContextARBMapVersionsAvailable(device, 2, CTX_PROFILE_ES, hasMinorVersionSupport); // ES2 + success |= hasES2; + if( hasES2 ) { + if( ctxVersion.getMajor() >= 3 && hasRendererQuirk(GLRendererQuirks.GLES3ViaEGLES2Config)) { + mapAvailableGLVersion(device, 3, CTX_PROFILE_ES, ctxVersion, ctxOptions, glRendererQuirks); + } + resetStates(false); // clean context states, since creation was temporary + } + } + if( !hasES1) { + hasES1 = createContextARBMapVersionsAvailable(device, 1, CTX_PROFILE_ES, hasMinorVersionSupport); // ES1 + success |= hasES1; + if( hasES1 ) { + resetStates(false); // clean context states, since creation was temporary + } + } + } // Even w/ PROFILE_ALIASING, try to use true core GL profiles // ensuring proper user behavior across platforms due to different feature sets! @@ -1006,31 +1197,31 @@ public abstract class GLContextImpl extends GLContext { /** * OSX 10.9 GLRendererQuirks.GL4NeedsGL3Request, quirk is added as usual @ setRendererQuirks(..) */ - if( !GLProfile.disableOpenGLCore && !hasGL4 && !hasGL3 ) { - hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 + if( hasOpenGLDesktopSupport && !GLProfile.disableOpenGLDesktop && !GLProfile.disableOpenGLCore && !hasGL4 && !hasGL3 ) { + hasGL3 = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_CORE, hasMinorVersionSupport); // GL3 success |= hasGL3; if( hasGL3 ) { final boolean isHWAccel = 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ); if( isHWAccel && ctxVersion.getMajor() >= 4 ) { // Gotcha: Creating a '3.2' ctx delivers a >= 4 ctx. - GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); hasGL4 = true; if(DEBUG) { - System.err.println("Quirk Triggerd: "+GLRendererQuirks.toString(GLRendererQuirks.GL4NeedsGL3Request)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions: Quirk Triggerd: "+GLRendererQuirks.toString(GLRendererQuirks.GL4NeedsGL3Request)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()); } } resetStates(false); // clean the context states, since creation was temporary } } } - if( !GLProfile.disableOpenGLCore ) { + if( hasOpenGLDesktopSupport && !GLProfile.disableOpenGLDesktop && !GLProfile.disableOpenGLCore ) { if( !hasGL4 ) { - hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4 + hasGL4 = createContextARBMapVersionsAvailable(device, 4, CTX_PROFILE_CORE, hasMinorVersionSupport); // GL4 success |= hasGL4; if( hasGL4 ) { if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { // Map hw-accel GL4 to all lower core profiles: GL3 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); if( PROFILE_ALIASING ) { hasGL3 = true; } @@ -1039,72 +1230,74 @@ public abstract class GLContextImpl extends GLContext { } } if( !hasGL3 ) { - hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 + hasGL3 = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_CORE, hasMinorVersionSupport); // GL3 success |= hasGL3; if( hasGL3 ) { resetStates(false); // clean this context states, since creation was temporary } } } - if( !hasGL4bc ) { - hasGL4bc = createContextARBMapVersionsAvailable(4, CTX_PROFILE_COMPAT); // GL4bc - success |= hasGL4bc; - if( hasGL4bc ) { - if( !hasGL4 ) { // last chance .. ignore hw-accel - GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - hasGL4 = true; - } - if( !hasGL3 ) { // last chance .. ignore hw-accel - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - hasGL3 = true; - } - if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { - // Map hw-accel GL4bc to all lower compatible profiles: GL3bc, GL2 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - if(PROFILE_ALIASING) { - hasGL3bc = true; - hasGL2 = true; + if( hasOpenGLDesktopSupport && !GLProfile.disableOpenGLDesktop ) { + if( !hasGL4bc ) { + hasGL4bc = createContextARBMapVersionsAvailable(device, 4, CTX_PROFILE_COMPAT, hasMinorVersionSupport); // GL4bc + success |= hasGL4bc; + if( hasGL4bc ) { + if( !hasGL4 ) { // last chance .. ignore hw-accel + mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); + hasGL4 = true; + } + if( !hasGL3 ) { // last chance .. ignore hw-accel + mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); + hasGL3 = true; + } + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel GL4bc to all lower compatible profiles: GL3bc, GL2 + mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion, ctxOptions, glRendererQuirks); + mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion, ctxOptions, glRendererQuirks); + if(PROFILE_ALIASING) { + hasGL3bc = true; + hasGL2 = true; + } } + resetStates(false); // clean this context states, since creation was temporary } - resetStates(false); // clean this context states, since creation was temporary } - } - if( !hasGL3bc ) { - hasGL3bc = createContextARBMapVersionsAvailable(3, CTX_PROFILE_COMPAT); // GL3bc - success |= hasGL3bc; - if( hasGL3bc ) { - if(!hasGL3) { // last chance .. ignore hw-accel - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - hasGL3 = true; - } - if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { - // Map hw-accel GL3bc to all lower compatible profiles: GL2 - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - if(PROFILE_ALIASING) { - hasGL2 = true; + if( !hasGL3bc ) { + hasGL3bc = createContextARBMapVersionsAvailable(device, 3, CTX_PROFILE_COMPAT, hasMinorVersionSupport); // GL3bc + success |= hasGL3bc; + if( hasGL3bc ) { + if(!hasGL3) { // last chance .. ignore hw-accel + mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion, ctxOptions, glRendererQuirks); + hasGL3 = true; } + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel GL3bc to all lower compatible profiles: GL2 + mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion, ctxOptions, glRendererQuirks); + if(PROFILE_ALIASING) { + hasGL2 = true; + } + } + resetStates(false); // clean this context states, since creation was temporary } - resetStates(false); // clean this context states, since creation was temporary } - } - if( !hasGL2 ) { - hasGL2 = createContextARBMapVersionsAvailable(2, CTX_PROFILE_COMPAT); // GL2 - success |= hasGL2; - if( hasGL2 ) { - resetStates(false); // clean this context states, since creation was temporary + if( !hasGL2 ) { + hasGL2 = createContextARBMapVersionsAvailable(device, 2, CTX_PROFILE_COMPAT, hasMinorVersionSupport); // GL2 + success |= hasGL2; + if( hasGL2 ) { + resetStates(false); // clean this context states, since creation was temporary + } } } if(success) { // only claim GL versions set [and hence detected] if ARB context creation was successful GLContext.setAvailableGLVersionsSet(device, true); - if(DEBUG) { - final long t1 = System.nanoTime(); - System.err.println("GLContextImpl.mapGLVersions: "+device+", profileAliasing: "+PROFILE_ALIASING+", total "+(t1-t0)/1e6 +"ms"); + } + if(DEBUG) { + final long t1 = System.nanoTime(); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions END (success "+success+") on "+device+", profileAliasing: "+PROFILE_ALIASING+", total "+(t1-t0)/1e6 +"ms"); + if( success ) { System.err.println(GLContext.dumpAvailableGLVersions(null).toString()); } - } else if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB-MapVersions NONE for :"+device); } return success; } @@ -1114,38 +1307,61 @@ public abstract class GLContextImpl extends GLContext { * Note: Since context creation is temporary, caller need to issue {@link #resetStates(boolean)}, if creation was successful, i.e. returns true. * This method does not reset the states, allowing the caller to utilize the state variables. **/ - private final boolean createContextARBMapVersionsAvailable(final int reqMajor, final int reqProfile) { + private final boolean createContextARBMapVersionsAvailable(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, + final boolean hasMinorVersionSupport) { long _context; int ctp = CTX_IS_ARB_CREATED | reqProfile; // To ensure GL profile compatibility within the JOGL application // we always try to map against the highest GL version, // so the user can always cast to the highest available one. - int majorMax, minorMax; - int majorMin, minorMin; + int maxMajor, maxMinor; + int minMajor, minMinor; final int major[] = new int[1]; final int minor[] = new int[1]; - if( CTX_PROFILE_ES == reqProfile ) { - majorMax=reqMajor; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=reqMajor; minorMin=0; + if( hasMinorVersionSupport ) { + if( CTX_PROFILE_ES == reqProfile ) { + // ES3, ES2 or ES1 + maxMajor=reqMajor; maxMinor=GLContext.getMaxMinor(ctp, maxMajor); + minMajor=reqMajor; minMinor=0; + } else { + if( 4 == reqMajor ) { + maxMajor=4; maxMinor=GLContext.getMaxMinor(ctp, maxMajor); + minMajor=4; minMinor=0; + } else if( 3 == reqMajor ) { + maxMajor=3; maxMinor=GLContext.getMaxMinor(ctp, maxMajor); + minMajor=3; minMinor=1; + } else /* if( glp.isGL2() ) */ { + // our minimum desktop OpenGL runtime requirements are 1.1, + // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts + maxMajor=3; maxMinor=0; + minMajor=2; minMinor=0; + } + } } else { - if( 4 == reqMajor ) { - majorMax=4; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=4; minorMin=0; - } else if( 3 == reqMajor ) { - majorMax=3; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=3; minorMin=1; - } else /* if( glp.isGL2() ) */ { - // our minimum desktop OpenGL runtime requirements are 1.1, - // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts - majorMax=3; minorMax=0; - majorMin=2; minorMin=0; + if( CTX_PROFILE_ES == reqProfile ) { + // ES3, ES2 or ES1 + maxMajor=reqMajor; maxMinor=0; + minMajor=reqMajor; minMinor=0; + } else { + if( 4 == reqMajor ) { + maxMajor=4; maxMinor=0; + minMajor=4; minMinor=0; + } else if( 3 == reqMajor ) { + maxMajor=3; maxMinor=1; + minMajor=3; minMinor=1; + } else /* if( glp.isGL2() ) */ { + // our minimum desktop OpenGL runtime requirements are 1.1, + // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts + maxMajor=2; maxMinor=0; + minMajor=2; minMinor=0; + } } } _context = createContextARBVersions(0, true, ctp, - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, + /* max */ maxMajor, maxMinor, + /* min */ minMajor, minMinor, /* res */ major, minor); if( 0 == _context && CTX_PROFILE_CORE == reqProfile && !PROFILE_ALIASING ) { @@ -1153,8 +1369,8 @@ public abstract class GLContextImpl extends GLContext { ctp &= ~CTX_PROFILE_CORE ; ctp |= CTX_OPTION_FORWARD ; _context = createContextARBVersions(0, true, ctp, - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, + /* max */ maxMajor, maxMinor, + /* min */ minMajor, minMinor, /* res */ major, minor); if( 0 == _context ) { // Try a compatible one .. even though not requested .. last resort @@ -1162,25 +1378,24 @@ public abstract class GLContextImpl extends GLContext { ctp &= ~CTX_OPTION_FORWARD ; ctp |= CTX_PROFILE_COMPAT ; _context = createContextARBVersions(0, true, ctp, - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, + /* max */ maxMajor, maxMinor, + /* min */ minMajor, minMinor, /* res */ major, minor); } } final boolean res; if( 0 != _context ) { - final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by // createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..) - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + final MappedGLVersion me = mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion, ctxOptions, glRendererQuirks); destroyContextARBImpl(_context); if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion()); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions HAVE "+me.toString(new StringBuilder(), minMajor, minMinor, maxMajor, maxMinor).toString()); } res = true; } else { if (DEBUG) { - System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); + System.err.println(getThreadName() + ": createContextARB-MapGLVersions NOPE "+device+", "+reqMajor+" ("+GLContext.getGLProfile(new StringBuilder(), reqProfile).toString()+ ") ["+maxMajor+"."+maxMinor+" .. "+minMajor+"."+minMinor+"]"); } res = false; } @@ -1188,11 +1403,11 @@ public abstract class GLContextImpl extends GLContext { } private final long createContextARBVersions(final long share, final boolean direct, final int ctxOptionFlags, - final int majorMax, final int minorMax, - final int majorMin, final int minorMin, + final int maxMajor, final int maxMinor, + final int minMajor, final int minMinor, final int major[], final int minor[]) { - major[0]=majorMax; - minor[0]=minorMax; + major[0]=maxMajor; + minor[0]=maxMinor; long _context=0; int i=0; @@ -1200,7 +1415,7 @@ public abstract class GLContextImpl extends GLContext { if (DEBUG) { i++; System.err.println(getThreadName() + ": createContextARBVersions."+i+": share "+share+", direct "+direct+ - ", version "+major[0]+"."+minor[0]+", major["+majorMin+".."+majorMax+"], minor["+minorMin+".."+minorMax+"]"); + ", version "+major[0]+"."+minor[0]+" ["+maxMajor+"."+maxMinor+" .. "+minMajor+"."+minMinor+"]"); } _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); @@ -1213,12 +1428,12 @@ public abstract class GLContextImpl extends GLContext { } } - } while ( ( major[0]>majorMin || major[0]==majorMin && minor[0] >minorMin ) && // #1 check whether version is above lower limit + } while ( ( major[0]>minMajor || major[0]==minMajor && minor[0] >minMinor ) && // #1 check whether version is above lower limit GLContext.decrementGLVersion(ctxOptionFlags, major, minor) // #2 decrement version ); if (DEBUG) { System.err.println(getThreadName() + ": createContextARBVersions.X: ctx "+toHexString(_context)+", share "+share+", direct "+direct+ - ", version "+major[0]+"."+minor[0]+", major["+majorMin+".."+majorMax+"], minor["+minorMin+".."+minorMax+"]"); + ", version "+major[0]+"."+minor[0]+" ["+maxMajor+"."+maxMinor+" .. "+minMajor+"."+minMinor+"]"); } return _context; } @@ -1261,11 +1476,19 @@ public abstract class GLContextImpl extends GLContext { // Helpers for various context implementations // - private final Object createInstance(final GLProfile glp, final boolean glObject, final Object[] cstrArgs) { + private final boolean verifyInstance(final GLProfile glp, final String suffix, final Object instance) { + return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix); + } + private final Object createInstance(final AbstractGraphicsDevice adevice, final int majorVersion, final int minorVersion, final int contextOption, + final boolean glObject, final Object[] cstrArgs) { + final String profileString = GLContext.getGLProfile(majorVersion, minorVersion, contextOption); + final GLProfile glp = GLProfile.get(adevice, profileString) ; return ReflectionUtil.createInstance(glp.getGLCtor(glObject), cstrArgs); } - - private final boolean verifyInstance(final GLProfile glp, final String suffix, final Object instance) { + private final boolean verifyInstance(final AbstractGraphicsDevice adevice, final int majorVersion, final int minorVersion, final int contextOption, + final String suffix, final Object instance) { + final String profileString = GLContext.getGLProfile(majorVersion, minorVersion, contextOption); + final GLProfile glp = GLProfile.get(adevice, profileString) ; return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix); } @@ -1273,8 +1496,11 @@ public abstract class GLContextImpl extends GLContext { * Create the GL instance for this context, * requires valid {@link #getGLProcAddressTable()} result! */ - private final GL createGL(final GLProfile glp) { - final GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } ); + private final GL createGL(final AbstractGraphicsDevice adevice, final int majorVersion, final int minorVersion, final int contextOption) { + final String profileString = GLContext.getGLProfile(majorVersion, minorVersion, contextOption); + final GLProfile glp = GLProfile.get(adevice, profileString); + final GL gl = (GL) ReflectionUtil.createInstance(glp.getGLCtor(true), new Object[] { glp, this }); + //nal GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } ); /* FIXME: refactor dependence on Java 2D / JOGL bridge if (tracker != null) { @@ -1348,34 +1574,53 @@ public abstract class GLContextImpl extends GLContext { } protected abstract Map<String, String> getExtensionNameMap() ; + /** + * Returns the DynamicLookupHelper + */ + public final GLDynamicLookupHelper getGLDynamicLookupHelper() { + return drawable.getFactoryImpl().getGLDynamicLookupHelper( ctxVersion.getMajor(), ctxOptions ); + } + public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions) { + return drawable.getFactoryImpl().getGLDynamicLookupHelper( majorVersion, contextOptions ); + } + /** Helper routine which resets a ProcAddressTable generated by the - GLEmitter by looking up anew all of its function pointers. */ - protected final void resetProcAddressTable(final ProcAddressTable table) { + GLEmitter by looking up anew all of its function pointers + using the given {@link GLDynamicLookupHelper}. */ + protected final void resetProcAddressTable(final ProcAddressTable table, final GLDynamicLookupHelper dlh) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { - table.reset(getDrawableImpl().getGLDynamicLookupHelper() ); + table.reset( dlh ); return null; } } ); } - private final PrivilegedAction<Object> privInitGLGetPtrAction = new PrivilegedAction<Object>() { - @Override - public Object run() { - final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper(); - glDynLookupHelper.claimAllLinkPermission(); - try { - glGetStringPtr = glDynLookupHelper.dynamicLookupFunction("glGetString"); - glGetIntegervPtr = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv"); - } finally { - glDynLookupHelper.releaseAllLinkPermission(); - } - return null; - } }; - private final boolean initGLRendererAndGLVersionStrings() { + /** + * Updates the platform's 'GLX' function cache + * @param contextFQN provides a fully qualified key of the context including device and GL profile + * @param dlh {@link GLDynamicLookupHelper} used to {@link #resetProcAddressTable(ProcAddressTable, GLDynamicLookupHelper)} instance. + */ + protected abstract void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh); + + private final boolean initGLRendererAndGLVersionStrings(final int majorVersion, final int contextOptions) { if( !glGetPtrInit ) { - AccessController.doPrivileged(privInitGLGetPtrAction); + AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override + public Object run() { + final GLDynamicLookupHelper glDynLookupHelper = getGLDynamicLookupHelper(majorVersion, contextOptions); + if( null != glDynLookupHelper ) { + glDynLookupHelper.claimAllLinkPermission(); + try { + glGetStringPtr = glDynLookupHelper.dynamicLookupFunction("glGetString"); + glGetIntegervPtr = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv"); + } finally { + glDynLookupHelper.releaseAllLinkPermission(); + } + } + return null; + } } ); glGetPtrInit = true; } if( 0 == glGetStringPtr || 0 == glGetIntegervPtr ) { @@ -1521,7 +1766,7 @@ public abstract class GLContextImpl extends GLContext { final VersionNumber reqGLVersion = new VersionNumber(major, minor, 0); final VersionNumber hasGLVersionByString; { - final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings(); + final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings(major, ctxProfileBits); if( !initGLRendererAndGLVersionStringsOK ) { final String errMsg = "Intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null); if( strictMatch ) { @@ -1557,50 +1802,51 @@ public abstract class GLContextImpl extends GLContext { { // Validate the requested version w/ the GL-version from an integer query, // as supported by GL [ES] >= 3.0 implementation. - final VersionNumber hasGLVersionByInt; - { - final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 }; - getGLIntVersion(glIntMajor, glIntMinor); - hasGLVersionByInt = new VersionNumber(glIntMajor[0], glIntMinor[0], 0); - } - if (DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Version verification (Int): String "+glVersion+", Number(Int) "+hasGLVersionByInt); - } - + // // Only validate integer based version if: // - ctx >= 3.0 is requested _or_ string-version >= 3.0 // - _and_ a valid int version was fetched, // otherwise cont. w/ version-string method -> 3.0 > Version || Version > MAX! // - if ( ( major >= 3 || hasGLVersionByString.compareTo(Version3_0) >= 0 ) && - GLContext.isValidGLVersion(ctxProfileBits, hasGLVersionByInt.getMajor(), hasGLVersionByInt.getMinor()) ) { - // Strict Match (GLVersionMapping): - // Relaxed match for versions ( !isES && major < 3 ) requests, last resort! - // Otherwise: - // - fail if hasVersion < reqVersion (desktop and ES) - // - fail if ES major-version mismatch: - // - request 1, >= 3 must be equal - // - request 2 must be [2..3] - // - final int hasMajor = hasGLVersionByInt.getMajor(); - if( strictMatch && - ( ( ( isES || major >= 3 ) && hasGLVersionByInt.compareTo(reqGLVersion) < 0 ) || - ( isES && - ( - ( 2 == major && ( 2 > hasMajor || hasMajor > 3 ) ) || // 2 -> [2..3] - ( ( 1 == major || 3 <= major ) && major != hasMajor ) // 1,3,.. -> equal - ) - ) - ) ) { - if(DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (Int): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByInt); + final VersionNumber hasGLVersionByInt; + if ( major >= 3 || hasGLVersionByString.compareTo(Version3_0) >= 0 ) { + final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 }; + getGLIntVersion(glIntMajor, glIntMinor); + hasGLVersionByInt = new VersionNumber(glIntMajor[0], glIntMinor[0], 0); + if (DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Version verification (Int): String "+glVersion+", Number(Int) "+hasGLVersionByInt); + } + if ( GLContext.isValidGLVersion(ctxProfileBits, hasGLVersionByInt.getMajor(), hasGLVersionByInt.getMinor()) ) { + // Strict Match (GLVersionMapping): + // Relaxed match for versions ( !isES && major < 3 ) requests, last resort! + // Otherwise: + // - fail if hasVersion < reqVersion (desktop and ES) + // - fail if ES major-version mismatch: + // - request 1, >= 3 must be equal + // - request 2 must be [2..3] + // + final int hasMajor = hasGLVersionByInt.getMajor(); + if( strictMatch && + ( ( ( isES || major >= 3 ) && hasGLVersionByInt.compareTo(reqGLVersion) < 0 ) || + ( isES && + ( + ( 2 == major && ( 2 > hasMajor || hasMajor > 3 ) ) || // 2 -> [2..3] + ( ( 1 == major || 3 <= major ) && major != hasMajor ) // 1,3,.. -> equal + ) + ) + ) ) { + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (Int): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+hasGLVersionByInt); + } + return false; } - return false; + // Use returned GL version! + major = hasGLVersionByInt.getMajor(); + minor = hasGLVersionByInt.getMinor(); + versionGL3IntOK = true; + } else { + versionGL3IntOK = false; } - // Use returned GL version! - major = hasGLVersionByInt.getMajor(); - minor = hasGLVersionByInt.getMinor(); - versionGL3IntOK = true; } else { versionGL3IntOK = false; } @@ -1668,7 +1914,8 @@ public abstract class GLContextImpl extends GLContext { } if( major < 2 ) { // there is no ES2/3-compat for a profile w/ major < 2 - ctxProfileBits &= ~ ( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_ES3_COMPAT | GLContext.CTX_IMPL_ES31_COMPAT ) ; + ctxProfileBits &= ~ ( GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_ES3_COMPAT | + GLContext.CTX_IMPL_ES31_COMPAT | GLContext.CTX_IMPL_ES32_COMPAT ) ; } if(!isCurrentContextHardwareRasterizer()) { @@ -1692,43 +1939,72 @@ public abstract class GLContextImpl extends GLContext { if (DEBUG) { System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)); } - - updateGLXProcAddressTable(); + final GLDynamicLookupHelper dynamicLookup = getGLDynamicLookupHelper(major, ctxProfileBits); + if( null == dynamicLookup ) { + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, No GLDynamicLookupHelper for request: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + } + return false; + } + updateGLXProcAddressTable(contextFQN, dynamicLookup); // // UpdateGLProcAddressTable functionality // _and_ setup GL instance, which ctor requires valid getGLProcAddressTable() result! // { - final GLProfile glp = drawable.getGLProfile(); + final GLProfile glp = drawable.getGLProfile(); // !withinGLVersionsMapping ProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { table = mappedGLProcAddress.get( contextFQN ); - if(null != table && !verifyInstance(glp, "ProcAddressTable", table)) { - throw new GLException("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ - ") -> "+ table.getClass().getName()+" not matching "+glp.getGLImplBaseClassName()); + if(null != table) { + if( !verifyInstance(adevice, major, minor, ctxProfileBits, "ProcAddressTable", table) ) { + throw new GLException("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +" not matching "+table.getClass().getName()); + } + if( !withinGLVersionsMapping && !verifyInstance(glp, "ProcAddressTable", table) ) { + throw new GLException("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +": "+table.getClass().getName()+" not matching "+glp.getGLImplBaseClassName()+"/"+glp); + } } } if(null != table) { glProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+toHexString(table.hashCode())); + if( withinGLVersionsMapping ) { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +": "+table.getClass().getName()); + } else { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ toHexString(table.hashCode()) +": "+table.getClass().getName()+" -> "+glp.getGLImplBaseClassName()); + } } } else { - glProcAddressTable = (ProcAddressTable) createInstance(glp, false, + glProcAddressTable = (ProcAddressTable) createInstance(adevice, major, minor, ctxProfileBits, false, new Object[] { new GLProcAddressResolver() } ); - resetProcAddressTable( glProcAddressTable ); + resetProcAddressTable(glProcAddressTable, dynamicLookup); + synchronized(mappedContextTypeObjectLock) { mappedGLProcAddress.put(contextFQN, glProcAddressTable); if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(glProcAddressTable.hashCode())); + if( withinGLVersionsMapping ) { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+toHexString(glProcAddressTable.hashCode()) +": "+glProcAddressTable.getClass().getName()); + } else { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+toHexString(glProcAddressTable.hashCode()) +": "+glProcAddressTable.getClass().getName()+" -> "+glp.getGLImplBaseClassName()); + } } } } - if( null == this.gl || !verifyInstance(glp, "Impl", this.gl) ) { - setGL( createGL( glp ) ); + if( null == this.gl || !verifyInstance(adevice, major, minor, ctxProfileBits, "Impl", this.gl) ) { + setGL( createGL( adevice, major, minor, ctxProfileBits ) ); + } + if( !withinGLVersionsMapping && !verifyInstance(glp, "Impl", this.gl) ) { + throw new GLException("GLContext GL Object mismatch: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+": "+this.gl.getClass().getName()+" not matching "+glp.getGLImplBaseClassName()+"/"+glp); } } @@ -1762,7 +2038,9 @@ public abstract class GLContextImpl extends GLContext { if( major >= 3 ) { ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ; ctxProfileBits |= CTX_IMPL_FBO; - if( minor >= 1 ) { + if( minor >= 2 ) { + ctxProfileBits |= CTX_IMPL_ES32_COMPAT | CTX_IMPL_ES31_COMPAT; + } else if( minor >= 1 ) { ctxProfileBits |= CTX_IMPL_ES31_COMPAT; } } else if( major >= 2 ) { @@ -1770,10 +2048,15 @@ public abstract class GLContextImpl extends GLContext { ctxProfileBits |= CTX_IMPL_FBO; } } else if( ( major > 4 || major == 4 && minor >= 5 ) || - ( ( major > 3 || major == 3 && minor >= 1 ) && isExtensionAvailable( GLExtensions.ARB_ES3_1_compatibility ) ) ) { - // See GLContext.isGLES31CompatibleAvailable(..)/isGLES31Compatible() - // Includes [ GL ≥ 4.5, GL ≥ 3.1 w/ GL_ARB_ES3_1_compatibility and GLES ≥ 3.1 ] - ctxProfileBits |= CTX_IMPL_ES31_COMPAT | CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ; + ( major > 3 || major == 3 && minor >= 1 ) ) { + // See GLContext.isGLES31CompatibleAvailable(..)/isGLES3[12]Compatible() + // Includes [ GL ≥ 4.5, GL ≥ 3.1 w/ GL_ARB_ES3_[12]_compatibility and GLES ≥ 3.[12] ] + if( isExtensionAvailable( GLExtensions.ARB_ES3_2_compatibility ) ) { + ctxProfileBits |= CTX_IMPL_ES32_COMPAT | CTX_IMPL_ES31_COMPAT; + } else if( isExtensionAvailable( GLExtensions.ARB_ES3_1_compatibility ) ) { + ctxProfileBits |= CTX_IMPL_ES31_COMPAT; + } + ctxProfileBits |= CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT; ctxProfileBits |= CTX_IMPL_FBO; } else if( ( major > 4 || major == 4 && minor >= 3 ) || ( ( major > 3 || major == 3 && minor >= 1 ) && isExtensionAvailable( GLExtensions.ARB_ES3_compatibility ) ) ) { @@ -1813,6 +2096,31 @@ public abstract class GLContextImpl extends GLContext { return true; } + private static final void addStickyQuirkAlways(final AbstractGraphicsDevice adevice, + final GLRendererQuirks quirks, + final int quirk, + final boolean withinGLVersionsMapping) { + quirks.addQuirk( quirk ); + if( withinGLVersionsMapping ) { + // Thread safe due to single threaded initialization! + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } else { + // FIXME: Remove when moving EGL/ES to ARB ctx creation + synchronized(GLContextImpl.class) { + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } + } + } + private static final void addStickyQuirkAtMapping(final AbstractGraphicsDevice adevice, + final GLRendererQuirks quirks, + final int quirk, + final boolean withinGLVersionsMapping) { + quirks.addQuirk( quirk ); + if( withinGLVersionsMapping ) { + // Thread safe due to single threaded initialization! + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } + } private final void setRendererQuirks(final AbstractGraphicsDevice adevice, final GLDrawableFactoryImpl factory, final int reqMajor, final int reqMinor, final int reqCTP, final int major, final int minor, final int ctp, final VersionNumberString vendorVersion, @@ -1822,10 +2130,10 @@ 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 isES = 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 "); + final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium ") || glVersion.contains(MesaSP); final boolean isDriverATICatalyst; final boolean isDriverNVIDIAGeForce; @@ -1845,22 +2153,13 @@ public abstract class GLContextImpl extends GLContext { // // General Quirks // - if( esCtx ) { + if( isES ) { if( 2 == reqMajor && 2 < major ) { final int quirk = GLRendererQuirks.GLES3ViaEGLES2Config; if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES req "+reqMajor+" and 2 < "+major); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } else { - // FIXME: Remove when moving EGL/ES to ARB ctx creation - synchronized(GLContextImpl.class) { - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } - } + addStickyQuirkAlways(adevice, quirks, quirk, withinGLVersionsMapping); } } if( GLProfile.disableSurfacelessContext ) { @@ -1868,32 +2167,14 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: disabled"); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } else { - // FIXME: Remove when moving EGL/ES to ARB ctx creation - synchronized(GLContextImpl.class) { - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } - } + addStickyQuirkAlways(adevice, quirks, quirk, withinGLVersionsMapping); } if( GLProfile.disableOpenGLARBContext ) { final int quirk = GLRendererQuirks.NoARBCreateContext; if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: disabled"); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } else { - // FIXME: Remove when moving EGL/ES to ARB ctx creation - synchronized(GLContextImpl.class) { - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } - } + addStickyQuirkAlways(adevice, quirks, quirk, withinGLVersionsMapping); } // @@ -1922,11 +2203,7 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", req "+reqMajor+"."+reqMinor); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); } if( isDriverNVIDIAGeForce ) { final VersionNumber osxVersionNVFlushClean = new VersionNumber(10,7,3); // < OSX 10.7.3 w/ NV needs glFlush @@ -1984,11 +2261,7 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+", Renderer "+glRenderer+" and Version "+glVersion+"]"); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); } } } else if( isDriverIntel && glRenderer.equals("Intel Bear Lake B") ) { @@ -2054,6 +2327,17 @@ public abstract class GLContextImpl extends GLContext { } } } + if( isDriverNVIDIAGeForce ) { + // Bug 1200: Crash on GNU/Linux x86_64 'NVidia beta driver 355.06' @ probeSurfacelessCtx + // final VersionNumber nvSafeVersion = new VersionNumber(356, 0, 0); // FIXME: Add safe version! + if( !isES && !(adevice instanceof EGLGraphicsDevice) /* && vendorVersion.compareTo(nvSafeVersion) < 0 */ ) { + final int quirk = GLRendererQuirks.NoSurfacelessCtx; + if(DEBUG) { + System.err.print("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: !ES, !EGL, Vendor " + glVendor +", X11 Renderer " + glRenderer+", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]"); + } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); + } + } } @@ -2063,8 +2347,10 @@ public abstract class GLContextImpl extends GLContext { if( isDriverMesa ) { final VersionNumber mesaSafeFBOVersion = new VersionNumber(8, 0, 0); final VersionNumber mesaIntelBuggySharedCtx921 = new VersionNumber(9, 2, 1); + final VersionNumber mesaSafeDoubleBufferedPBuffer = new VersionNumber(18, 2, 2); // Mesa 18.2.2 + final VersionNumber mesaSafeSetSwapIntervalPostRetarget = mesaSafeDoubleBufferedPBuffer; // Mesa 18.2.2 - { + if( vendorVersion.compareTo(mesaSafeSetSwapIntervalPostRetarget) < 0 ) { final int quirk = GLRendererQuirks.NoSetSwapIntervalPostRetarget; if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer); @@ -2073,11 +2359,13 @@ public abstract class GLContextImpl extends GLContext { } if( hwAccel ) { // hardware-acceleration - final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer; - if(DEBUG) { - System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer); + if( vendorVersion.compareTo(mesaSafeDoubleBufferedPBuffer) < 0 ) { + final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer; + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer); + } + quirks.addQuirk( quirk ); } - quirks.addQuirk( quirk ); } else { // software if( vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { // FIXME: Is it fixed in >= 8.0.0 ? @@ -2111,11 +2399,7 @@ public abstract class GLContextImpl extends GLContext { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Vendor "+glVendor); } - quirks.addQuirk( quirk ); - if( withinGLVersionsMapping ) { - // Thread safe due to single threaded initialization! - GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); - } + addStickyQuirkAtMapping(adevice, quirks, quirk, withinGLVersionsMapping); } if( isWindows && glRenderer.contains("SVGA3D") && vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { final int quirk = GLRendererQuirks.NoFullFBOSupport; @@ -2157,7 +2441,7 @@ public abstract class GLContextImpl extends GLContext { if( !GLRendererQuirks.areSameStickyDevice(factoryDefaultDevice, adevice) ) { GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, quirks); } - if( esCtx ) { + if( isES ) { final AbstractGraphicsDevice eglFactoryDefaultDevice = GLDrawableFactory.getEGLFactory().getDefaultDevice(); if( !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, adevice) && !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, factoryDefaultDevice) ) { @@ -2233,11 +2517,6 @@ public abstract class GLContextImpl extends GLContext { return isHardwareRasterizer; } - /** - * Updates the platform's 'GLX' function cache - */ - protected abstract void updateGLXProcAddressTable(); - protected abstract StringBuilder getPlatformExtensionsStringImpl(); @Override @@ -2262,7 +2541,10 @@ public abstract class GLContextImpl extends GLContext { } // dynamic function lookup at last incl name aliasing (not cached) - final DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper(); + final DynamicLookupHelper dynLookup = getGLDynamicLookupHelper(ctxVersion.getMajor(), ctxOptions); + if( null == dynLookup ) { + throw new GLException("No GLDynamicLookupHelper for "+this); + } final String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true); return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override @@ -2378,6 +2660,40 @@ public abstract class GLContextImpl extends GLContext { } //---------------------------------------------------------------------- + // SwapBuffer + + @Override + public final boolean setSwapInterval(final int interval) throws GLException { + validateCurrent(); + return setSwapIntervalNC(interval); + } + protected final boolean setSwapIntervalNC(final int interval) throws GLException { + if( !drawableRetargeted || + !hasRendererQuirk(GLRendererQuirks.NoSetSwapIntervalPostRetarget) + ) + { + final Integer usedInterval = setSwapIntervalImpl2(interval); + if( null != usedInterval ) { + currentSwapInterval = usedInterval.intValue(); + return true; + } + } + return false; + } + protected abstract Integer setSwapIntervalImpl2(final int interval); + + @Override + public final int getSwapInterval() { + return currentSwapInterval; + } + @Override + protected final void setDefaultSwapInterval() { + currentSwapInterval = 0; + setSwapIntervalNC(1); + } + + + //---------------------------------------------------------------------- // Helpers for buffer object optimizations public final GLBufferObjectTracker getBufferObjectTracker() { @@ -2536,8 +2852,8 @@ public abstract class GLContextImpl extends GLContext { @Override public final void glDebugMessageControl(final int source, final int type, final int severity, final int count, final IntBuffer ids, final boolean enabled) { - if(glDebugHandler.isExtensionARB()) { - gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, enabled); + if(glDebugHandler.isExtensionKHRARB()) { + gl.getGL2ES2().glDebugMessageControl(source, type, severity, count, ids, enabled); } else if(glDebugHandler.isExtensionAMD()) { gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, enabled); } @@ -2545,8 +2861,8 @@ public abstract class GLContextImpl extends GLContext { @Override public final void glDebugMessageControl(final int source, final int type, final int severity, final int count, final int[] ids, final int ids_offset, final boolean enabled) { - if(glDebugHandler.isExtensionARB()) { - gl.getGL2GL3().glDebugMessageControl(source, type, severity, count, ids, ids_offset, enabled); + if(glDebugHandler.isExtensionKHRARB()) { + gl.getGL2ES2().glDebugMessageControl(source, type, severity, count, ids, ids_offset, enabled); } else if(glDebugHandler.isExtensionAMD()) { gl.getGL2GL3().glDebugMessageEnableAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, count, ids, ids_offset, enabled); } @@ -2555,8 +2871,8 @@ public abstract class GLContextImpl extends GLContext { @Override public final void glDebugMessageInsert(final int source, final int type, final int id, final int severity, final String buf) { final int len = (null != buf) ? buf.length() : 0; - if(glDebugHandler.isExtensionARB()) { - gl.getGL2GL3().glDebugMessageInsert(source, type, id, severity, len, buf); + if(glDebugHandler.isExtensionKHRARB()) { + gl.getGL2ES2().glDebugMessageInsert(source, type, id, severity, len, buf); } else if(glDebugHandler.isExtensionAMD()) { gl.getGL2GL3().glDebugMessageInsertAMD(GLDebugMessage.translateARB2AMDCategory(source, type), severity, id, len, buf); } |