aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java191
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java9
2 files changed, 131 insertions, 69 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 7898566f3..d7f27f643 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -27,15 +27,19 @@
*/
package com.jogamp.opengl;
+import java.lang.reflect.Field;
import java.util.IdentityHashMap;
import com.jogamp.nativewindow.AbstractGraphicsDevice;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.opengl.egl.EGL;
import com.jogamp.opengl.egl.EGLExt;
+import jogamp.opengl.Debug;
+
/**
* GLRendererQuirks contains information of known bugs of various GL renderer.
* This information allows us to workaround them.
@@ -47,9 +51,45 @@ import com.jogamp.opengl.egl.EGLExt;
* <i>Some</i> <code>GL_VENDOR</code> and <code>GL_RENDERER</code> strings are
* listed here <http://feedback.wildfiregames.com/report/opengl/feature/GL_VENDOR>.
* </p>
+ * <p>
+ * For testing purpose or otherwise, you may override the implemented
+ * quirk bit setting behavior using {@link GLRendererQuirks.Override}.
+ * </p>
*/
public class GLRendererQuirks {
/**
+ * Allow overriding any quirk settings
+ * via the two properties:
+ * <ul>
+ * <li>jogl.quirks.force</li>
+ * <li>jogl.quirks.ignore</li>
+ * </ul>
+ * Both contain a list of capital sensitive quirk names separated by comma.
+ * Example:
+ * <pre>
+ * java -Djogl.quirks.force=GL3CompatNonCompliant,NoFullFBOSupport -cp my_classpath some.main.Class
+ * </pre>
+ * <p>
+ * Naturally, one quirk can only be listed in one override list.
+ * Hence the two override sets force and ignore are unique.
+ * </p>
+ */
+ public static enum Override {
+ /**
+ * No override.
+ */
+ NONE,
+ /**
+ * Enforce the quirk, i.e. allowing the code path to be injected w/o actual cause.
+ */
+ FORCE,
+ /**
+ * Ignore the quirk, i.e. don't set the quirk if otherwise caused.
+ */
+ IGNORE
+ }
+
+ /**
* Crashes XServer when using double buffered PBuffer with GL_RENDERER:
* <ul>
* <li>Mesa DRI Intel(R) Sandybridge Desktop</li>
@@ -82,7 +122,7 @@ public class GLRendererQuirks {
public static final int GLSLBuggyDiscard = 5;
/**
- * Non compliant GL context due to a buggy implementation not suitable for use.
+ * Non compliant GL3 compatibility context due to a buggy implementation not suitable for use.
* <p>
* Currently, Mesa >= 9.1.3 (may extend back as far as 9.0) OpenGL 3.1 compatibility
* context is not compliant. Most programs will give completely broken output (or no
@@ -97,7 +137,7 @@ public class GLRendererQuirks {
* <p>
* It still has to be verified whether the AMD OpenGL 3.1 core driver is compliant enought.
*/
- public static final int GLNonCompliant = 6;
+ public static final int GL3CompatNonCompliant = 6;
/**
* The OpenGL context needs a <code>glFlush()</code> before releasing it, otherwise driver may freeze:
@@ -447,12 +487,12 @@ public class GLRendererQuirks {
*/
public static final int NoSurfacelessCtx = 22;
- /** Return the number of known quirks. */
+ /** Return the number of known quirks, aka quirk bit count. */
public static final int getCount() { return 23; }
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
"NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
- "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display",
+ "GL3CompatNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display",
"NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext",
"NoFullFBOSupport", "GLSLNonCompliant", "GL4NeedsGL3Request",
"GLSharedContextBuggy", "GLES3ViaEGLES2Config", "SingletonEGLDisplayOnly",
@@ -505,17 +545,6 @@ public class GLRendererQuirks {
sq.addQuirk(quirk);
}
/**
- * {@link #addQuirks(int[], int, int) Adding given quirks} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
- * <p>
- * Not thread safe.
- * </p>
- * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
- */
- public static void addStickyDeviceQuirks(final AbstractGraphicsDevice device, final int[] quirks, final int offset, final int len) throws IllegalArgumentException {
- final GLRendererQuirks sq = getStickyDeviceQuirks(device);
- sq.addQuirks(quirks, offset, len);
- }
- /**
* {@link #addQuirks(GLRendererQuirks) Adding given quirks} of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
* <p>
* Not thread safe.
@@ -533,8 +562,8 @@ public class GLRendererQuirks {
* </p>
* @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
*/
- public static boolean existStickyDeviceQuirk(final AbstractGraphicsDevice device, final int quirk) {
- return getStickyDeviceQuirks(device).exist(quirk);
+ public static boolean existStickyDeviceQuirk(final AbstractGraphicsDevice device, final int quirkBit) {
+ return getStickyDeviceQuirks(device).exist(quirkBit);
}
/**
* {@link #addQuirks(GLRendererQuirks) Pushing} the sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}
@@ -548,6 +577,56 @@ public class GLRendererQuirks {
dest.addQuirks(getStickyDeviceQuirks(device));
}
+ public static final Override getOverride(final int quirkBit) throws IllegalArgumentException {
+ validateQuirk(quirkBit);
+ if( 0 != ( ( 1 << quirkBit ) & _bitmaskOverrideForce ) ) {
+ return Override.FORCE;
+ }
+ if( 0 != ( ( 1 << quirkBit ) & _bitmaskOverrideIgnore ) ) {
+ return Override.IGNORE;
+ }
+ return Override.NONE;
+ }
+ private static int _bitmaskOverrideForce = 0;
+ private static int _bitmaskOverrideIgnore = 0;
+ static {
+ _bitmaskOverrideForce = _queryQuirkMaskOfPropertyList("jogl.quirks.force", Override.FORCE);
+ _bitmaskOverrideIgnore = _queryQuirkMaskOfPropertyList("jogl.quirks.ignore", Override.IGNORE);
+ final int uniqueTest = _bitmaskOverrideForce & _bitmaskOverrideIgnore;
+ if( 0 != uniqueTest ) {
+ throw new InternalError("Override properties force 0x"+Integer.toHexString(_bitmaskOverrideForce)+
+ " and ignore 0x"+Integer.toHexString(_bitmaskOverrideIgnore)+
+ " have intersecting bits 0x"+Integer.toHexString(uniqueTest)+" "+Integer.toBinaryString(uniqueTest));
+ }
+ }
+ private static int _queryQuirkMaskOfPropertyList(final String propertyName, final Override override) {
+ final String quirkNameList = PropertyAccess.getProperty(propertyName, true);
+ if( null == quirkNameList ) {
+ return 0;
+ }
+ int res = 0;
+ final String quirkNames[] = quirkNameList.split(",");
+ for(int i=0; i<quirkNames.length; i++) {
+ final String name = quirkNames[i].trim();
+ try {
+ final Field field = GLRendererQuirks.class.getField(name);
+ final int quirkBit = field.getInt(null);
+ final Override preOverride = getOverride(quirkBit);
+ if( Override.NONE != preOverride ) {
+ System.err.println("Warning: Quirk '"+name+"' bit "+quirkBit+" skipped for override "+override+" mask, already set for override "+preOverride+". Has been included in given property "+propertyName);
+ } else {
+ res |= 1 << quirkBit;
+ System.err.println("Info: Quirk '"+name+"' bit "+quirkBit+" has been added to Override."+override+" mask as included in given property "+propertyName);
+ }
+ } catch (final NoSuchFieldException e) {
+ System.err.println("Warning: Failed to match given property "+propertyName+"'s quirk '"+name+"' with any supported quirk! "+e.getMessage());
+ } catch (SecurityException | IllegalAccessException e) {
+ System.err.println("Warning: Failed to access given property "+propertyName+"'s quirk '"+name+"' bit value! "+e.getMessage());
+ }
+ }
+ return res;
+ }
+
private int _bitmask;
public GLRendererQuirks() {
@@ -555,42 +634,12 @@ public class GLRendererQuirks {
}
/**
- * @param quirks an array of valid quirks
- * @param offset offset in quirks array to start reading
- * @param len number of quirks to read from offset within quirks array
- * @throws IllegalArgumentException if one of the quirks is out of range
- */
- public GLRendererQuirks(final int[] quirks, final int offset, final int len) throws IllegalArgumentException {
- this();
- addQuirks(quirks, offset, len);
- }
-
- /**
- * @param quirk valid quirk to be added
+ * @param quirkBit valid quirk to be added
* @throws IllegalArgumentException if the quirk is out of range
*/
- public final void addQuirk(final int quirk) throws IllegalArgumentException {
- validateQuirk(quirk);
- _bitmask |= 1 << quirk;
- }
-
- /**
- * @param quirks an array of valid quirks to be added
- * @param offset offset in quirks array to start reading
- * @param len number of quirks to read from offset within quirks array
- * @throws IllegalArgumentException if one of the quirks is out of range
- */
- public final void addQuirks(final int[] quirks, final int offset, final int len) throws IllegalArgumentException {
- int bitmask = 0;
- if( !( 0 <= offset + len && offset + len <= quirks.length ) ) {
- throw new IllegalArgumentException("offset and len out of bounds: offset "+offset+", len "+len+", array-len "+quirks.length);
- }
- for(int i=offset; i<offset+len; i++) {
- final int quirk = quirks[i];
- validateQuirk(quirk);
- bitmask |= 1 << quirk;
- }
- _bitmask |= bitmask;
+ public final void addQuirk(final int quirkBit) throws IllegalArgumentException {
+ validateQuirk(quirkBit);
+ _bitmask |= 1 << quirkBit;
}
/**
@@ -601,13 +650,19 @@ public class GLRendererQuirks {
}
/**
- * @param quirk the quirk to be tested
+ * Method tests whether the given quirk exists.
+ * <p>
+ * This methods respects the potential {@link GLRendererQuirks.Override}
+ * setting by user properties. Therefor this method returns {@code true}
+ * for {@code FORCE}'ed quirks and {@code false} for {@code IGNORE}'ed quirks.
+ * </p>
+ * @param quirkBit the quirk to be tested
* @return true if quirk exist, otherwise false
* @throws IllegalArgumentException if quirk is out of range
*/
- public final boolean exist(final int quirk) throws IllegalArgumentException {
- validateQuirk(quirk);
- return 0 != ( ( 1 << quirk ) & _bitmask );
+ public final boolean exist(final int quirkBit) throws IllegalArgumentException {
+ validateQuirk(quirkBit);
+ return 0 != ( ( 1 << quirkBit ) & ( ~_bitmaskOverrideIgnore & ( _bitmask | _bitmaskOverrideForce ) ) );
}
public final StringBuilder toString(StringBuilder sb) {
@@ -617,10 +672,14 @@ public class GLRendererQuirks {
sb.append("[");
boolean first=true;
for(int i=0; i<getCount(); i++) {
- final int testmask = 1 << i;
- if( 0 != ( _bitmask & testmask ) ) {
+ // list ignored and forced as well
+ if( 0 != ( ( 1 << i ) & ( _bitmask | _bitmaskOverrideForce ) ) ) {
if(!first) { sb.append(", "); }
sb.append(toString(i));
+ final Override override = getOverride(i);
+ if( Override.NONE != override ) {
+ sb.append("(").append(override.name().toLowerCase()).append("ed)");
+ }
first=false;
}
}
@@ -628,28 +687,28 @@ public class GLRendererQuirks {
return sb;
}
- @Override
+ // @Override
public final String toString() {
return toString(null).toString();
}
/**
- * @param quirk the quirk to be validated, i.e. whether it is out of range
+ * @param quirkBit the quirk to be validated, i.e. whether it is out of range
* @throws IllegalArgumentException if quirk is out of range
*/
- public static void validateQuirk(final int quirk) throws IllegalArgumentException {
- if( !( 0 <= quirk && quirk < getCount() ) ) {
- throw new IllegalArgumentException("Quirks must be in range [0.."+getCount()+"[, but quirk: "+quirk);
+ public static void validateQuirk(final int quirkBit) throws IllegalArgumentException {
+ if( !( 0 <= quirkBit && quirkBit < getCount() ) ) {
+ throw new IllegalArgumentException("Quirks must be in range [0.."+getCount()+"[, but quirk: "+quirkBit);
}
}
/**
- * @param quirk the quirk to be converted to String
+ * @param quirkBit the quirk to be converted to String
* @return the String equivalent of this quirk
* @throws IllegalArgumentException if quirk is out of range
*/
- public static final String toString(final int quirk) throws IllegalArgumentException {
- validateQuirk(quirk);
- return _names[quirk];
+ public static final String toString(final int quirkBit) throws IllegalArgumentException {
+ validateQuirk(quirkBit);
+ return _names[quirkBit];
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 84c62b95d..35c3eb266 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1928,9 +1928,12 @@ public abstract class GLContextImpl extends GLContext {
reqGLVersion.getMajor(), reqGLVersion.getMinor(), reqCtxProfileBits,
major, minor, ctxProfileBits, vendorVersion, withinGLVersionsMapping);
- if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) {
+ if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GL3CompatNonCompliant) &&
+ 0 != ( ctxProfileBits & GLContext.CTX_PROFILE_COMPAT) && (major > 3 || (major == 3 && minor >= 1))
+ )
+ {
if(DEBUG) {
- System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL is not compliant: "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)+", "+glRenderer);
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, compat GL3 is not compliant: "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)+", "+glRenderer);
}
return false;
}
@@ -2378,7 +2381,7 @@ public abstract class GLContextImpl extends GLContext {
}
if (compatCtx && (major > 3 || (major == 3 && minor >= 1))) {
// FIXME: Apply vendor version constraints!
- final int quirk = GLRendererQuirks.GLNonCompliant;
+ final int quirk = GLRendererQuirks.GL3CompatNonCompliant;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
}