aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java475
1 files changed, 475 insertions, 0 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
new file mode 100644
index 000000000..a643d81a9
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -0,0 +1,475 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+import java.util.IdentityHashMap;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+
+import com.jogamp.common.os.Platform;
+
+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.
+ * <p>
+ * Using centralized quirk identifier enables us to
+ * locate code dealing w/ it and hence eases it's maintenance.
+ * </p>
+ * <p>
+ * <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>
+ */
+public class GLRendererQuirks {
+ /**
+ * Crashes XServer when using double buffered PBuffer with GL_RENDERER:
+ * <ul>
+ * <li>Mesa DRI Intel(R) Sandybridge Desktop</li>
+ * <li>Mesa DRI Intel(R) Ivybridge Mobile - 3.0 Mesa 8.0.4</li>
+ * <li>Gallium 0.4 on AMD CYPRESS</li>
+ * </ul>
+ * For now, it is safe to disable it w/ hw-acceleration.
+ */
+ public static final int NoDoubleBufferedPBuffer = 0;
+
+ /** On Windows no double buffered bitmaps are guaranteed to be available. */
+ public static final int NoDoubleBufferedBitmap = 1;
+
+ /** Crashes application when trying to set EGL swap interval on Android 4.0.3 / Pandaboard ES / PowerVR SGX 540 */
+ public static final int NoSetSwapInterval = 2;
+
+ /** No offscreen bitmap available, currently true for JOGL's OSX implementation. */
+ public static final int NoOffscreenBitmap = 3;
+
+ /** SIGSEGV on setSwapInterval() after changing the context's drawable w/ 'Mesa 8.0.4' dri2SetSwapInterval/DRI2 (soft & intel) */
+ public static final int NoSetSwapIntervalPostRetarget = 4;
+
+ /**
+ * GLSL <code>discard</code> command leads to undefined behavior or won't get compiled if being used.
+ * <p>
+ * Appears to <i>have</i> happened on Nvidia Tegra2, but seems to be fine now.<br/>
+ * FIXME: Constrain version.
+ * </p>
+ */
+ public static final int GLSLBuggyDiscard = 5;
+
+ /**
+ * Non compliant GL 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
+ * output at all. For now, this context is not trusted.
+ * </p>
+ * The above has been confirmed for the following Mesa 9.* GL_RENDERER strings:
+ * <ul>
+ * <li>Mesa .* Intel(R) Sandybridge Desktop</li>
+ * <li>Gallium 0.4 on AMD RS880</li>
+ * </ul>
+ * </p>
+ * <p>
+ * It still has to be verified whether the AMD OpenGL 3.1 core driver is compliant enought.
+ */
+ public static final int GLNonCompliant = 6;
+
+ /**
+ * The OpenGL Context needs a <code>glFlush()</code> before releasing it, otherwise driver may freeze:
+ * <ul>
+ * <li>OSX < 10.7.3 - NVidia Driver. Bug 533 and Bug 548 @ https://jogamp.org/bugzilla/.</li>
+ * </ul>
+ */
+ public static final int GLFlushBeforeRelease = 7;
+
+ /**
+ * Closing X11 displays may cause JVM crashes or X11 errors with some buggy drivers
+ * while being used in concert w/ OpenGL.
+ * <p>
+ * Some drivers may require X11 displays to be closed in the same order as they were created,
+ * some may not allow them to be closed at all while resources are being used somehow.
+ * </p>
+ * <p>
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>Mesa &lt; 8.0 _with_ X11 software renderer <code>Mesa X11</code>, not with GLX/DRI renderer.</li>
+ * <li>ATI proprietary Catalyst X11 driver versions:
+ * <ul>
+ * <li>8.78.6</li>
+ * <li>8.881</li>
+ * <li>8.911</li>
+ * <li>9.01.8</li>
+ * </ul></li>
+ * </ul>
+ * </p>
+ * <p>
+ * See Bug 515 - https://jogamp.org/bugzilla/show_bug.cgi?id=515
+ * and {@link jogamp.nativewindow.x11.X11Util#ATI_HAS_XCLOSEDISPLAY_BUG}.
+ * </p>
+ * <p>
+ * See Bug 705 - https://jogamp.org/bugzilla/show_bug.cgi?id=705
+ * </p>
+ */
+ public static final int DontCloseX11Display = 8;
+
+ /**
+ * Need current GL Context when calling new ARB <i>pixel format query</i> functions,
+ * otherwise driver crashes the VM.
+ * <p>
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>ATI proprietary Catalyst driver on Windows version &le; XP.
+ * TODO: Validate if bug actually relates to 'old' ATI Windows drivers for old GPU's like X300
+ * regardless of the Windows version.</li>
+ * </ul>
+ * <p>
+ * See Bug 480 - https://jogamp.org/bugzilla/show_bug.cgi?id=480
+ * </p>
+ */
+ public static final int NeedCurrCtx4ARBPixFmtQueries = 9;
+
+ /**
+ * Need current GL Context when calling new ARB <i>CreateContext</i> function,
+ * otherwise driver crashes the VM.
+ * <p>
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>ATI proprietary Catalyst Windows driver on laptops with a driver version as reported in <i>GL_VERSION</i>:
+ * <ul>
+ * <li> <i>null</i> </li>
+ * <li> &lt; <code>12.102.3.0</code> ( <i>amd_catalyst_13.5_mobility_beta2</i> ) </li>
+ * </ul></li>
+ * </ul>
+ * </p>
+ * <p>
+ * See Bug 706 - https://jogamp.org/bugzilla/show_bug.cgi?id=706<br/>
+ * See Bug 520 - https://jogamp.org/bugzilla/show_bug.cgi?id=520
+ * </p>
+ */
+ public static final int NeedCurrCtx4ARBCreateContext = 10;
+
+ /**
+ * No full FBO support, i.e. not compliant w/
+ * <ul>
+ * <li>GL_ARB_framebuffer_object</li>
+ * <li>EXT_framebuffer_object</li>
+ * <li>EXT_framebuffer_multisample</li>
+ * <li>EXT_framebuffer_blit</li>
+ * <li>EXT_packed_depth_stencil</li>
+ * </ul>.
+ * Drivers known exposing such bug:
+ * <ul>
+ * <li>Mesa <i>7.12-devel</i> on Windows with VMware <i>SVGA3D</i> renderer:
+ * <ul>
+ * <li>GL_VERSION: <i>2.1 Mesa 7.12-devel (git-d6c318e)</i> </li>
+ * <li>GL_RENDERER: <i>Gallium 0.4 on SVGA3D; build: RELEASE;</i> </li>
+ * </ul></li>
+ * </ul>
+ * Quirk can also be enabled via property: <code>jogl.fbo.force.min</code>.
+ */
+ public static final int NoFullFBOSupport = 11;
+
+ /**
+ * GLSL is not compliant or even not stable (crash)
+ * <ul>
+ * <li>OSX < 10.7.0 (?) - NVidia Driver. Bug 818 @ https://jogamp.org/bugzilla/.</li>
+ * </ul>
+ */
+ public static final int GLSLNonCompliant = 12;
+
+ /**
+ * GL4 context needs to be requested via GL3 profile attribute
+ * <ul>
+ * <li>OSX >= 10.9.0 - kCGLOGLPVersion_GL4_Core may not produce hw-accel context. Bug 867 @ https://jogamp.org/bugzilla/.</li>
+ * </ul>
+ */
+ public static final int GL4NeedsGL3Request = 13;
+
+ /**
+ * Buggy shared OpenGL context support within a multithreaded use-case, not suitable for stable usage.
+ * <p>
+ * <i>X11 Mesa DRI Intel(R) driver >= 9.2.1</i> cannot handle multithreaded shared GLContext usage
+ * with non-blocking exclusive X11 display connections.
+ * References:
+ * <ul>
+ * <li>Bug 873: https://jogamp.org/bugzilla/show_bug.cgi?id=873</li>
+ * <li>https://bugs.freedesktop.org/show_bug.cgi?id=41736#c8</li>
+ * </ul>
+ * <p>
+ * However, not all multithreaded use-cases are broken, e.g. our GLMediaPlayer does work.
+ * </p>
+ * The above has been confirmed for the following Mesa 9.* strings:
+ * <ul>
+ * <li>GL_VENDOR Intel Open Source Technology Center</li>
+ * <li>GL_RENDERER Mesa DRI Intel(R) Sandybridge Desktop</li>
+ * <li>GL_RENDERER Mesa DRI Intel(R) Ivybridge Mobile</li>
+ * <li>GL_VERSION 3.1 (Core Profile) Mesa 9.2.1</li>
+ * </ul>
+ * </p>
+ * <p>
+ * On Android 4.*, <i>Huawei's Ascend G615 w/ Immersion.16</i> could not make a shared context
+ * current, which uses a pbuffer drawable:
+ * <ul>
+ * <li>Android 4.*</li>
+ * <li>GL_VENDOR Hisilicon Technologies</li>
+ * <li>GL_RENDERER Immersion.16</li>
+ * <li>GL_VERSION OpenGL ES 2.0</li>
+ * </ul>
+ * </p>
+ * <p>
+ * </p>
+ */
+ 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;
+
+ /**
+ * Bug 948 - NVIDIA 331.38 (Linux X11) EGL impl. only supports _one_ EGL Device via {@link EGL#eglGetDisplay(long)}.
+ * <p>
+ * Subsequent calls to {@link EGL#eglGetDisplay(long)} fail.
+ * </p>
+ * <p>
+ * Reusing global EGL display works.
+ * </p>
+ * <p>
+ * The quirk is autodetected within EGLDrawableFactory's initial default device setup!
+ * </p>
+ * <p>
+ * Appears on:
+ * <ul>
+ * <li>EGL_VENDOR NVIDIA</li>
+ * <li>EGL_VERSION 1.4</li>
+ * <li>GL_VENDOR NVIDIA Corporation</li>
+ * <li>GL_VERSION OpenGL ES 3.0 331.38 (probably w/ 1st NV EGL lib on x86)</li>
+ * <li>Platform X11</li>
+ * <li>CPU Family {@link Platform.CPUFamily#X86}</li>
+ * </ul>
+ * </p>
+ */
+ public static final int SingletonEGLDisplayOnly = 16;
+
+ /** Number of quirks known. */
+ public static final int COUNT = 17;
+
+ private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
+ "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
+ "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display",
+ "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext",
+ "NoFullFBOSupport", "GLSLNonCompliant", "GL4NeedsGL3Request",
+ "GLSharedContextBuggy", "GLES3ViaEGLES2Config", "SingletonEGLDisplayOnly"
+ };
+
+ private static final IdentityHashMap<String, GLRendererQuirks> stickyDeviceQuirks = new IdentityHashMap<String, GLRendererQuirks>();
+
+ /**
+ * Retrieval of sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}.
+ * <p>
+ * The {@link AbstractGraphicsDevice}s are mapped via their {@link AbstractGraphicsDevice#getUniqueID()}.
+ * </p>
+ * <p>
+ * Not thread safe.
+ * </p>
+ * @see #areSameStickyDevice(AbstractGraphicsDevice, AbstractGraphicsDevice)
+ */
+ public static GLRendererQuirks getStickyDeviceQuirks(AbstractGraphicsDevice device) {
+ final String key = device.getUniqueID();
+ final GLRendererQuirks has = stickyDeviceQuirks.get(key);
+ final GLRendererQuirks res;
+ if( null == has ) {
+ res = new GLRendererQuirks();
+ stickyDeviceQuirks.put(key, res);
+ } else {
+ res = has;
+ }
+ return res;
+ }
+
+ /**
+ * Returns true if both devices have the same {@link AbstractGraphicsDevice#getUniqueID()},
+ * otherwise false.
+ */
+ public static boolean areSameStickyDevice(AbstractGraphicsDevice device1, AbstractGraphicsDevice device2) {
+ return device1.getUniqueID() == device2.getUniqueID();
+ }
+
+ /**
+ * {@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(AbstractGraphicsDevice device, int[] quirks, int offset, 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.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ 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.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ public static boolean existStickyDeviceQuirk(AbstractGraphicsDevice device, int quirk) {
+ return getStickyDeviceQuirks(device).exist(quirk);
+ }
+ /**
+ * {@link #addQuirks(GLRendererQuirks) Pushing} the sticky {@link AbstractGraphicsDevice}'s {@link GLRendererQuirks}
+ * to the given {@link GLRendererQuirks destination}.
+ * <p>
+ * Not thread safe. However, use after changing the sticky quirks is safe.
+ * </p>
+ * @see #getStickyDeviceQuirks(AbstractGraphicsDevice)
+ */
+ public static void pushStickyDeviceQuirks(AbstractGraphicsDevice device, GLRendererQuirks dest) {
+ dest.addQuirks(getStickyDeviceQuirks(device));
+ }
+
+ private int _bitmask;
+
+ public GLRendererQuirks() {
+ _bitmask = 0;
+ }
+
+ /**
+ * @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(int[] quirks, int offset, int len) throws IllegalArgumentException {
+ this();
+ addQuirks(quirks, offset, len);
+ }
+
+ /**
+ * @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(int[] quirks, int offset, 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;
+ }
+
+ /**
+ * @param quirks valid GLRendererQuirks to be added
+ */
+ public final void addQuirks(GLRendererQuirks quirks) {
+ _bitmask |= quirks._bitmask;
+ }
+
+ /**
+ * @param quirk the quirk to be tested
+ * @return true if quirk exist, otherwise false
+ * @throws IllegalArgumentException if quirk is out of range
+ */
+ public final boolean exist(int quirk) throws IllegalArgumentException {
+ validateQuirk(quirk);
+ return 0 != ( ( 1 << quirk ) & _bitmask );
+ }
+
+ public final StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("[");
+ boolean first=true;
+ for(int i=0; i<COUNT; i++) {
+ final int testmask = 1 << i;
+ if( 0 != ( _bitmask & testmask ) ) {
+ if(!first) { sb.append(", "); }
+ sb.append(toString(i));
+ first=false;
+ }
+ }
+ sb.append("]");
+ return sb;
+ }
+
+ @Override
+ public final String toString() {
+ return toString(null).toString();
+ }
+
+ /**
+ * @param quirk 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(int quirk) throws IllegalArgumentException {
+ if( !( 0 <= quirk && quirk < COUNT ) ) {
+ throw new IllegalArgumentException("Quirks must be in range [0.."+COUNT+"[, but quirk: "+quirk);
+ }
+ }
+
+ /**
+ * @param quirk 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(int quirk) throws IllegalArgumentException {
+ validateQuirk(quirk);
+ return _names[quirk];
+ }
+}