Bug 1347679 - Determine ContextProfile from driver and simplify version parsing. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 15 Mar 2017 13:14:03 -0700
changeset 499625 7c709ab39ee323422f3c6271058c700ef4ecf270
parent 499337 8c89d1991786625a64d868798281610872a2bc26
child 549400 4bb14d16c82e0d06922f332eba4d67207d749627
push id49460
push userbmo:jgilbert@mozilla.com
push dateThu, 16 Mar 2017 00:57:06 +0000
reviewersdaoshengmu
bugs1347679
milestone55.0a1
Bug 1347679 - Determine ContextProfile from driver and simplify version parsing. - r=daoshengmu MozReview-Commit-ID: 4mBdJmsxQvD
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextCGL.h
gfx/gl/GLContextFeatures.cpp
gfx/gl/GLContextGLX.h
gfx/gl/GLContextProviderCGL.mm
gfx/gl/GLContextProviderEAGL.mm
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderGLX.cpp
gfx/gl/GLContextProviderWGL.cpp
gfx/thebes/gfxPlatformGtk.cpp
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GLContext.h"
 
 #include <algorithm>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <regex>
+#include <string>
 #include <vector>
 #ifdef MOZ_WIDGET_ANDROID
 #include <sys/mman.h>
 #endif
 
 #include "GLBlitHelper.h"
 #include "GLReadTexImageHelper.h"
 #include "GLScreenBuffer.h"
@@ -84,16 +86,17 @@ static const char* const sExtensionNames
     "GL_APPLE_client_storage",
     "GL_APPLE_framebuffer_multisample",
     "GL_APPLE_sync",
     "GL_APPLE_texture_range",
     "GL_APPLE_vertex_array_object",
     "GL_ARB_ES2_compatibility",
     "GL_ARB_ES3_compatibility",
     "GL_ARB_color_buffer_float",
+    "GL_ARB_compatibility",
     "GL_ARB_copy_buffer",
     "GL_ARB_depth_texture",
     "GL_ARB_draw_buffers",
     "GL_ARB_draw_instanced",
     "GL_ARB_framebuffer_object",
     "GL_ARB_framebuffer_sRGB",
     "GL_ARB_geometry_shader4",
     "GL_ARB_half_float_pixel",
@@ -190,230 +193,28 @@ static const char* const sExtensionNames
     "GL_OES_texture_float_linear",
     "GL_OES_texture_half_float",
     "GL_OES_texture_half_float_linear",
     "GL_OES_texture_npot",
     "GL_OES_vertex_array_object"
 };
 
 static bool
-ParseGLSLVersion(GLContext* gl, uint32_t* out_version)
+ParseVersion(const std::string& versionStr, uint32_t* const out_major,
+             uint32_t* const out_minor)
 {
-    if (gl->fGetError() != LOCAL_GL_NO_ERROR) {
-        MOZ_ASSERT(false, "An OpenGL error has been triggered before.");
-        return false;
-    }
-
-    /**
-     * OpenGL 2.x, 3.x, 4.x specifications:
-     *  The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows:
-     *
-     *    <version number><space><vendor-specific information>
-     *
-     *  The version number is either of the form major_number.minor_number or
-     *  major_number.minor_number.release_number, where the numbers all have
-     *  one or more digits.
-     *
-     * SHADING_LANGUAGE_VERSION is *almost* identical to VERSION. The
-     * difference is that the minor version always has two digits and the
-     * prefix has an additional 'GLSL ES'
-     *
-     *
-     * OpenGL ES 2.0, 3.0 specifications:
-     *  The VERSION string is laid out as follows:
-     *
-     *     "OpenGL ES N.M vendor-specific information"
-     *
-     *  The version number is either of the form major_number.minor_number or
-     *  major_number.minor_number.release_number, where the numbers all have
-     *  one or more digits.
-     *
-     *
-     * Note:
-     *  We don't care about release_number.
-     */
-    const char* versionString = (const char*) gl->fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
-
-    if (gl->fGetError() != LOCAL_GL_NO_ERROR) {
-        MOZ_ASSERT(false, "glGetString(GL_SHADING_LANGUAGE_VERSION) has generated an error");
-        return false;
-    }
-
-    if (!versionString) {
-        // This happens on the Android emulators. We'll just return 100
-        *out_version = 100;
-        return true;
-    }
-
-    const auto fnSkipPrefix = [&versionString](const char* prefix) {
-        const auto len = strlen(prefix);
-        if (strncmp(versionString, prefix, len) == 0)
-            versionString += len;
-    };
-
-    const char kGLESVersionPrefix[] = "OpenGL ES GLSL ES";
-    fnSkipPrefix(kGLESVersionPrefix);
-
-    if (gl->WorkAroundDriverBugs()) {
-        // Nexus 7 2013 (bug 1234441)
-        const char kBadGLESVersionPrefix[] = "OpenGL ES GLSL";
-        fnSkipPrefix(kBadGLESVersionPrefix);
-    }
-
-    const char* itr = versionString;
-    char* end = nullptr;
-    auto majorVersion = strtol(itr, &end, 10);
-
-    if (!end) {
-        MOZ_ASSERT(false, "Failed to parse the GL major version number.");
-        return false;
-    }
-
-    if (*end != '.') {
-        MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator.");
-        return false;
-    }
-
-    // we skip the '.' between the major and the minor version
-    itr = end + 1;
-    end = nullptr;
-
-    auto minorVersion = strtol(itr, &end, 10);
-    if (!end) {
-        MOZ_ASSERT(false, "Failed to parse GL's minor version number.");
-        return false;
-    }
-
-    if (majorVersion <= 0 || majorVersion >= 100) {
-        MOZ_ASSERT(false, "Invalid major version.");
-        return false;
-    }
-
-    if (minorVersion < 0 || minorVersion >= 100) {
-        MOZ_ASSERT(false, "Invalid minor version.");
-        return false;
-    }
-
-    *out_version = (uint32_t) majorVersion * 100 + (uint32_t) minorVersion;
-    return true;
-}
-
-static bool
-ParseGLVersion(GLContext* gl, uint32_t* out_version)
-{
-    if (gl->fGetError() != LOCAL_GL_NO_ERROR) {
-        MOZ_ASSERT(false, "An OpenGL error has been triggered before.");
+    static const std::regex kVersionRegex("([0-9]+)\\.([0-9]+)");
+    std::smatch match;
+    if (!std::regex_search(versionStr, match, kVersionRegex))
         return false;
-    }
-
-    /**
-     * B2G emulator bug work around: The emulator implements OpenGL ES 2.0 on
-     * OpenGL 3.2. The bug is that GetIntegerv(LOCAL_GL_{MAJOR,MINOR}_VERSION)
-     * returns OpenGL 3.2 instead of generating an error.
-     */
-    if (!gl->IsGLES()) {
-        /**
-         * OpenGL 3.1 and OpenGL ES 3.0 both introduce GL_{MAJOR,MINOR}_VERSION
-         * with GetIntegerv. So we first try those constants even though we
-         * might not have an OpenGL context supporting them, as this is a
-         * better way than parsing GL_VERSION.
-         */
-        GLint majorVersion = 0;
-        GLint minorVersion = 0;
-
-        const bool ok = (gl->GetPotentialInteger(LOCAL_GL_MAJOR_VERSION,
-                                                 &majorVersion) &&
-                         gl->GetPotentialInteger(LOCAL_GL_MINOR_VERSION,
-                                                 &minorVersion));
-
-        // If it's not an OpenGL (ES) 3.0 context, we will have an error
-        if (ok &&
-            majorVersion > 0 &&
-            minorVersion >= 0)
-        {
-            *out_version = majorVersion * 100 + minorVersion * 10;
-            return true;
-        }
-    }
-
-    /**
-     * We were not able to use GL_{MAJOR,MINOR}_VERSION, so we parse
-     * GL_VERSION.
-     *
-     *
-     * OpenGL 2.x, 3.x, 4.x specifications:
-     *  The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows:
-     *
-     *    <version number><space><vendor-specific information>
-     *
-     *  The version number is either of the form major_number.minor_number or
-     *  major_number.minor_number.release_number, where the numbers all have
-     *  one or more digits.
-     *
-     *
-     * OpenGL ES 2.0, 3.0 specifications:
-     *  The VERSION string is laid out as follows:
-     *
-     *     "OpenGL ES N.M vendor-specific information"
-     *
-     *  The version number is either of the form major_number.minor_number or
-     *  major_number.minor_number.release_number, where the numbers all have
-     *  one or more digits.
-     *
-     *
-     * Note:
-     *  We don't care about release_number.
-     */
-    const char* versionString = (const char*)gl->fGetString(LOCAL_GL_VERSION);
-
-    if (gl->fGetError() != LOCAL_GL_NO_ERROR) {
-        MOZ_ASSERT(false, "glGetString(GL_VERSION) has generated an error");
-        return false;
-    } else if (!versionString) {
-        MOZ_ASSERT(false, "glGetString(GL_VERSION) has returned 0");
-        return false;
-    }
-
-    const char kGLESVersionPrefix[] = "OpenGL ES ";
-    if (strncmp(versionString, kGLESVersionPrefix, strlen(kGLESVersionPrefix)) == 0) {
-        versionString += strlen(kGLESVersionPrefix);
-    }
-
-    const char* itr = versionString;
-    char* end = nullptr;
-    auto majorVersion = strtol(itr, &end, 10);
-
-    if (!end) {
-        MOZ_ASSERT(false, "Failed to parse the GL major version number.");
-        return false;
-    } else if (*end != '.') {
-        MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator.");
-        return false;
-    }
-
-    // we skip the '.' between the major and the minor version
-    itr = end + 1;
-
-    end = nullptr;
-
-    auto minorVersion = strtol(itr, &end, 10);
-    if (!end) {
-        MOZ_ASSERT(false, "Failed to parse GL's minor version number.");
-        return false;
-    }
-
-    if (majorVersion <= 0 || majorVersion >= 100) {
-        MOZ_ASSERT(false, "Invalid major version.");
-        return false;
-    } else if (minorVersion < 0 || minorVersion >= 10) {
-        MOZ_ASSERT(false, "Invalid minor version.");
-        return false;
-    }
-
-    *out_version = (uint32_t)majorVersion * 100 + (uint32_t)minorVersion * 10;
+
+    const auto& majorStr = match.str(1);
+    const auto& minorStr = match.str(2);
+    *out_major = atoi(majorStr.c_str());
+    *out_minor = atoi(minorStr.c_str());
     return true;
 }
 
 static uint8_t
 ChooseDebugFlags(CreateContextFlags createFlags)
 {
     uint8_t debugFlags = 0;
 
@@ -716,42 +517,62 @@ GLContext::InitWithPrefixImpl(const char
     };
 
     if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL"))
         return false;
 
     ////////////////
 
     MakeCurrent();
-    MOZ_ASSERT(mProfile != ContextProfile::Unknown);
-
-    uint32_t version = 0;
-    ParseGLVersion(this, &version);
-
-    mShadingLanguageVersion = 100;
-    ParseGLSLVersion(this, &mShadingLanguageVersion);
+
+    const std::string versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
+    if (versionStr.find("OpenGL ES") == 0) {
+        mProfile = ContextProfile::OpenGLES;
+    }
+
+    uint32_t majorVer, minorVer;
+    if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
+        MOZ_ASSERT(false, "Failed to parse GL_VERSION");
+        return false;
+    }
+    MOZ_ASSERT(majorVer < 10);
+    MOZ_ASSERT(minorVer < 10);
+    mVersion = majorVer*100 + minorVer*10;
+    if (mVersion < 200) {
+        // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but
+        // have all the GL2+ extensions that we need.
+        mVersion = 200;
+    }
+
+    ////
+
+    const auto glslVersionStr = (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
+    if (!glslVersionStr) {
+        // This happens on the Android emulators. We'll just return 100
+        mShadingLanguageVersion = 100;
+    } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) {
+        MOZ_ASSERT(majorVer < 10);
+        MOZ_ASSERT(minorVer < 100);
+        mShadingLanguageVersion = majorVer*100 + minorVer;
+    } else {
+        MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
+        return false;
+    }
 
     if (ShouldSpew()) {
-        printf_stderr("OpenGL version detected: %u\n", version);
-        printf_stderr("OpenGL shading language version detected: %u\n", mShadingLanguageVersion);
+        printf_stderr("GL version detected: %u\n", mVersion);
+        printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion);
         printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
         printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
     }
 
-    if (version >= mVersion) {
-        mVersion = version;
-    }
-    // Don't fail if version < mVersion, see bug 999445,
-    // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but
-    // have all the GL2+ extensions that we need.
-
     ////////////////
 
     // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
-    if (IsGLES()) {
+    if (mProfile == ContextProfile::OpenGLES) {
         const SymLoadStruct symbols[] = {
             { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
             { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
             { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
             END_SYMBOLS
         };
 
         if (!LoadGLSymbols(this, prefix, trygl, symbols, "OpenGL ES"))
@@ -851,32 +672,52 @@ GLContext::InitWithPrefixImpl(const char
         printf_stderr("GL_VENDOR: %s\n", glVendorString);
         printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]);
         printf_stderr("GL_RENDERER: %s\n", glRendererString);
         printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]);
     }
 
     ////////////////
 
-    // We need this for retrieving the list of extensions on Core profiles.
-    if (IsFeatureProvidedByCoreSymbols(GLFeature::get_string_indexed)) {
+    if (mVersion >= 300) { // Both GL3 and ES3.
         const SymLoadStruct symbols[] = {
             { (PRFuncPtr*) &mSymbols.fGetStringi, { "GetStringi", nullptr } },
             END_SYMBOLS
         };
 
-        if (!LoadGLSymbols(this, prefix, trygl, symbols, "get_string_indexed")) {
-            MOZ_RELEASE_ASSERT(false, "GFX: get_string_indexed is required!");
+        if (!LoadGLSymbols(this, prefix, trygl, symbols, "GetStringi")) {
+            MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
             return false;
         }
     }
 
     InitExtensions();
+    if (mProfile != ContextProfile::OpenGLES) {
+        if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) {
+            mProfile = ContextProfile::OpenGLCore;
+        } else {
+            mProfile = ContextProfile::OpenGLCompatibility;
+        }
+    }
+    MOZ_ASSERT(mProfile != ContextProfile::Unknown);
+
+    if (ShouldSpew()) {
+        const char* profileStr = "";
+        if (mProfile == ContextProfile::OpenGLES) {
+            profileStr = " es";
+        } else if (mProfile == ContextProfile::OpenGLCore) {
+            profileStr = " core";
+        }
+        printf_stderr("Detected profile: %u%s\n", mVersion, profileStr);
+    }
+
     InitFeatures();
 
+    ////
+
     // Disable extensions with partial or incorrect support.
     if (WorkAroundDriverBugs()) {
         if (Renderer() == GLRenderer::AdrenoTM320) {
             MarkUnsupported(GLFeature::standard_derivatives);
         }
 
         if (Vendor() == GLVendor::Vivante) {
             // bug 958256
@@ -1116,18 +957,16 @@ GLContext::InitWithPrefixImpl(const char
         fDebugMessageCallback(&StaticDebugCallback, (void*)this);
         fDebugMessageControl(LOCAL_GL_DONT_CARE,
                              LOCAL_GL_DONT_CARE,
                              LOCAL_GL_DONT_CARE,
                              0, nullptr,
                              true);
     }
 
-    mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10,
-                                     mVersion % 10);
     return true;
 }
 
 void
 GLContext::LoadMoreSymbols(const char* prefix, bool trygl)
 {
     const auto fnLoadForExt = [this, prefix, trygl](const SymLoadStruct* list,
                                                     GLExtensions ext)
@@ -1765,17 +1604,17 @@ GLContext::DebugCallback(GLenum source,
 
 void
 GLContext::InitExtensions()
 {
     MOZ_ASSERT(IsCurrent());
 
     std::vector<nsCString> driverExtensionList;
 
-    if (IsFeatureProvidedByCoreSymbols(GLFeature::get_string_indexed)) {
+    if (mSymbols.fGetStringi) {
         GLuint count = 0;
         GetUIntegerv(LOCAL_GL_NUM_EXTENSIONS, &count);
         for (GLuint i = 0; i < count; i++) {
             // This is UTF-8.
             const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
 
             // We CANNOT use nsDependentCString here, because the spec doesn't guarantee
             // that the pointers returned are different, only that their contents are.
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -97,17 +97,16 @@ enum class GLFeature {
     framebuffer_blit,
     framebuffer_multisample,
     framebuffer_object,
     framebuffer_object_EXT_OES,
     get_integer_indexed,
     get_integer64_indexed,
     get_query_object_i64v,
     get_query_object_iv,
-    get_string_indexed,
     gpu_shader4,
     instanced_arrays,
     instanced_non_arrays,
     internalformat_query,
     invalidate_framebuffer,
     map_buffer_range,
     occlusion_query,
     occlusion_query_boolean,
@@ -146,17 +145,16 @@ enum class GLFeature {
     uniform_buffer_object,
     uniform_matrix_nonsquare,
     vertex_array_object,
     EnumMax
 };
 
 enum class ContextProfile : uint8_t {
     Unknown = 0,
-    OpenGL, // only for IsAtLeast's <profile> parameter
     OpenGLCore,
     OpenGLCompatibility,
     OpenGLES
 };
 
 enum class GLVendor {
     Intel,
     NVIDIA,
@@ -236,89 +234,44 @@ public:
      * (legacy profile 2.1 on Max OS X)
      */
     inline bool IsCompatibilityProfile() const {
         MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
 
         return mProfile == ContextProfile::OpenGLCompatibility;
     }
 
-    /**
-     * Return true if the context is a true OpenGL ES context or an ANGLE context
-     */
     inline bool IsGLES() const {
         MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
 
         return mProfile == ContextProfile::OpenGLES;
     }
 
-    static const char* GetProfileName(ContextProfile profile)
-    {
-        switch (profile)
-        {
-            case ContextProfile::OpenGL:
-                return "OpenGL";
-            case ContextProfile::OpenGLCore:
-                return "OpenGL Core";
-            case ContextProfile::OpenGLCompatibility:
-                return "OpenGL Compatibility";
-            case ContextProfile::OpenGLES:
-                return "OpenGL ES";
-            default:
-                break;
-        }
-
-        MOZ_ASSERT(profile != ContextProfile::Unknown, "unknown context profile");
-        return "OpenGL unknown profile";
-    }
-
-    /**
-     * Return true if we are running on a OpenGL core profile context
-     */
-    const char* ProfileString() const {
-        return GetProfileName(mProfile);
-    }
-
-    /**
-     * Return true if the context is compatible with given parameters
-     *
-     * IsAtLeast(ContextProfile::OpenGL, N) is exactly same as
-     * IsAtLeast(ContextProfile::OpenGLCore, N) || IsAtLeast(ContextProfile::OpenGLCompatibility, N)
-     */
     inline bool IsAtLeast(ContextProfile profile, unsigned int version) const
     {
         MOZ_ASSERT(profile != ContextProfile::Unknown, "IsAtLeast: bad <profile> parameter");
         MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
         MOZ_ASSERT(mVersion != 0, "unknown context version");
 
         if (version > mVersion) {
             return false;
         }
 
-        if (profile == ContextProfile::OpenGL) {
-            return mProfile == ContextProfile::OpenGLCore ||
-                   mProfile == ContextProfile::OpenGLCompatibility;
-        }
-
         return profile == mProfile;
     }
 
     /**
      * Return the version of the context.
      * Example :
      *   If this a OpenGL 2.1, that will return 210
      */
     inline uint32_t Version() const {
         return mVersion;
     }
 
-    const char* VersionString() const {
-        return mVersionString.get();
-    }
-
     inline uint32_t ShadingLanguageVersion() const {
         return mShadingLanguageVersion;
     }
 
     GLVendor Vendor() const {
         return mVendor;
     }
 
@@ -356,37 +309,23 @@ protected:
     bool mIsOffscreen;
     bool mContextLost;
 
     /**
      * mVersion store the OpenGL's version, multiplied by 100. For example, if
      * the context is an OpenGL 2.1 context, mVersion value will be 210.
      */
     uint32_t mVersion;
-    nsCString mVersionString;
     ContextProfile mProfile;
 
     uint32_t mShadingLanguageVersion;
 
     GLVendor mVendor;
     GLRenderer mRenderer;
 
-    void SetProfileVersion(ContextProfile profile, uint32_t version) {
-        MOZ_ASSERT(!mSymbols.fBindFramebuffer,
-                   "SetProfileVersion can only be called before initialization!");
-        MOZ_ASSERT(profile != ContextProfile::Unknown &&
-                   profile != ContextProfile::OpenGL,
-                   "Invalid `profile` for SetProfileVersion");
-        MOZ_ASSERT(version >= 100, "Invalid `version` for SetProfileVersion");
-
-        mVersion = version;
-        mProfile = profile;
-    }
-
-
 // -----------------------------------------------------------------------------
 // Extensions management
 /**
  * This mechanism is designed to know if an extension is supported. In the long
  * term, we would like to only use the extension group queries XXX_* to have
  * full compatibility with context version and profiles (especialy the core that
  * officialy don't bring any extensions).
  */
@@ -412,16 +351,17 @@ public:
         APPLE_client_storage,
         APPLE_framebuffer_multisample,
         APPLE_sync,
         APPLE_texture_range,
         APPLE_vertex_array_object,
         ARB_ES2_compatibility,
         ARB_ES3_compatibility,
         ARB_color_buffer_float,
+        ARB_compatibility,
         ARB_copy_buffer,
         ARB_depth_texture,
         ARB_draw_buffers,
         ARB_draw_instanced,
         ARB_framebuffer_object,
         ARB_framebuffer_sRGB,
         ARB_geometry_shader4,
         ARB_half_float_pixel,
@@ -3174,17 +3114,17 @@ public:
         mSymbols.fCompressedTexSubImage3D(target, level,
                                           xoffset, yoffset, zoffset,
                                           width, height, depth,
                                           format, imageSize, data);
         AFTER_GL_CALL;
     }
 
 // -----------------------------------------------------------------------------
-// get_string_indexed
+// GL3+, ES3+
 
     const GLubyte* fGetStringi(GLenum name, GLuint index) {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetStringi);
         const GLubyte* ret = mSymbols.fGetStringi(name, index);
         AFTER_GL_CALL;
         return ret;
     }
--- a/gfx/gl/GLContextCGL.h
+++ b/gfx/gl/GLContextCGL.h
@@ -24,17 +24,17 @@ class GLContextCGL : public GLContext
 {
     friend class GLContextProviderCGL;
 
     NSOpenGLContext* mContext;
 
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, override)
     GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps,
-                 NSOpenGLContext* context, bool isOffscreen, ContextProfile profile);
+                 NSOpenGLContext* context, bool isOffscreen);
 
     ~GLContextCGL();
 
     virtual GLContextType GetContextType() const override { return GLContextType::CGL; }
 
     static GLContextCGL* Cast(GLContext* gl) {
         MOZ_ASSERT(gl->GetContextType() == GLContextType::CGL);
         return static_cast<GLContextCGL*>(gl);
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -307,26 +307,16 @@ static const FeatureInfo sFeatureInfoArr
             GLContext::Extensions_End
         }
         /*
          * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
          * ARB_occlusion_query (added by OpenGL 2.0).
          */
     },
     {
-        "get_string_indexed",
-        GLVersion::GL3,
-        GLESVersion::ES3,
-        GLContext::Extension_None,
-        {
-            GLContext::Extensions_End
-        }
-        // glGetStringi
-    },
-    {
         "gpu_shader4",
         GLVersion::GL3,
         GLESVersion::ES3,
         GLContext::Extension_None,
         {
             GLContext::EXT_gpu_shader4,
             GLContext::Extensions_End
         }
--- a/gfx/gl/GLContextGLX.h
+++ b/gfx/gl/GLContextGLX.h
@@ -21,18 +21,17 @@ public:
     static already_AddRefed<GLContextGLX>
     CreateGLContext(CreateContextFlags flags,
                     const SurfaceCaps& caps,
                     bool isOffscreen,
                     Display* display,
                     GLXDrawable drawable,
                     GLXFBConfig cfg,
                     bool deleteDrawable,
-                    gfxXlibSurface* pixmap = nullptr,
-                    ContextProfile profile = ContextProfile::OpenGLCompatibility);
+                    gfxXlibSurface* pixmap);
 
     // Finds a GLXFBConfig compatible with the provided window.
     static bool
     FindFBConfigForWindow(Display* display, int screen, Window window,
                           ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
                           GLXFBConfig* const out_config, int* const out_visid,
                           bool aWebRender);
 
@@ -72,18 +71,17 @@ private:
     GLContextGLX(CreateContextFlags flags,
                  const SurfaceCaps& caps,
                  bool isOffscreen,
                  Display* aDisplay,
                  GLXDrawable aDrawable,
                  GLXContext aContext,
                  bool aDeleteDrawable,
                  bool aDoubleBuffered,
-                 gfxXlibSurface* aPixmap,
-                 ContextProfile profile);
+                 gfxXlibSurface* aPixmap);
 
     GLXContext mContext;
     Display* mDisplay;
     GLXDrawable mDrawable;
     bool mDeleteDrawable;
     bool mDoubleBuffered;
 
     GLXLibrary* mGLX;
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -68,22 +68,20 @@ private:
     bool mInitialized;
     bool mUseDoubleBufferedWindows;
     PRLibrary* mOGLLibrary;
 };
 
 CGLLibrary sCGLLibrary;
 
 GLContextCGL::GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps,
-                           NSOpenGLContext* context, bool isOffscreen,
-                           ContextProfile profile)
+                           NSOpenGLContext* context, bool isOffscreen)
     : GLContext(flags, caps, nullptr, isOffscreen)
     , mContext(context)
 {
-    SetProfileVersion(profile, 210);
 }
 
 GLContextCGL::~GLContextCGL()
 {
     MarkDestroyed();
 
     if (mContext) {
         if ([NSOpenGLContext currentContext] == mContext) {
@@ -287,20 +285,19 @@ GLContextProviderCGL::CreateForWindow(ns
     if (!context) {
         return nullptr;
     }
 
     // make the context transparent
     GLint opaque = 0;
     [context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
 
-    SurfaceCaps caps = SurfaceCaps::ForRGBA();
-    ContextProfile profile = ContextProfile::OpenGLCompatibility;
-    RefPtr<GLContextCGL> glContext = new GLContextCGL(CreateContextFlags::NONE, caps,
-                                                      context, false, profile);
+    RefPtr<GLContextCGL> glContext = new GLContextCGL(CreateContextFlags::NONE,
+                                                      SurfaceCaps::ForRGBA(), context,
+                                                      false);
 
     if (!glContext->Init()) {
         glContext = nullptr;
         [context release];
         return nullptr;
     }
 
     return glContext.forget();
@@ -308,26 +305,22 @@ GLContextProviderCGL::CreateForWindow(ns
 
 static already_AddRefed<GLContextCGL>
 CreateOffscreenFBOContext(CreateContextFlags flags)
 {
     if (!sCGLLibrary.EnsureInitialized()) {
         return nullptr;
     }
 
-    ContextProfile profile;
     NSOpenGLContext* context = nullptr;
 
     if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
-        profile = ContextProfile::OpenGLCore;
         context = CreateWithFormat(kAttribs_offscreen_coreProfile);
     }
     if (!context) {
-        profile = ContextProfile::OpenGLCompatibility;
-
         if (flags & CreateContextFlags::ALLOW_OFFLINE_RENDERER) {
           if (gfxPrefs::RequireHardwareGL())
               context = CreateWithFormat(kAttribs_singleBuffered);
           else
               context = CreateWithFormat(kAttribs_offscreen_allow_offline);
 
         } else {
           if (gfxPrefs::RequireHardwareGL())
@@ -336,19 +329,18 @@ CreateOffscreenFBOContext(CreateContextF
               context = CreateWithFormat(kAttribs_offscreen);
         }
     }
     if (!context) {
         NS_WARNING("Failed to create NSOpenGLContext.");
         return nullptr;
     }
 
-    SurfaceCaps dummyCaps = SurfaceCaps::Any();
-    RefPtr<GLContextCGL> glContext = new GLContextCGL(flags, dummyCaps, context, true,
-                                                      profile);
+    RefPtr<GLContextCGL> glContext = new GLContextCGL(flags, SurfaceCaps::Any(), context,
+                                                      true);
 
     if (gfxPrefs::GLMultithreaded()) {
         CGLEnable(glContext->GetCGLContext(), kCGLCEMPEngine);
     }
     return glContext.forget();
 }
 
 already_AddRefed<GLContext>
--- a/gfx/gl/GLContextProviderEAGL.mm
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -19,25 +19,23 @@
 
 namespace mozilla {
 namespace gl {
 
 using namespace mozilla::widget;
 
 GLContextEAGL::GLContextEAGL(CreateContextFlags flags, const SurfaceCaps& caps,
                              EAGLContext* context, GLContext* sharedContext,
-                             bool isOffscreen, ContextProfile profile)
+                             bool isOffscreen)
     : GLContext(flags, caps, sharedContext, isOffscreen)
     , mContext(context)
     , mBackbufferRB(0)
     , mBackbufferFB(0)
     , mLayer(nil)
 {
-    SetProfileVersion(ContextProfile::OpenGLES,
-                      [context API] == kEAGLRenderingAPIOpenGLES3 ? 300 : 200);
 }
 
 GLContextEAGL::~GLContextEAGL()
 {
     MakeCurrent();
 
     if (mBackbufferFB) {
         fDeleteFramebuffers(1, &mBackbufferFB);
@@ -193,23 +191,19 @@ CreateEAGLContext(CreateContextFlags fla
             break;
         }
     }
 
     if (!context) {
         return nullptr;
     }
 
-    SurfaceCaps caps = SurfaceCaps::ForRGBA();
-    ContextProfile profile = ContextProfile::OpenGLES;
-    RefPtr<GLContextEAGL> glContext = new GLContextEAGL(flags, caps, context,
-                                                        sharedContext,
-                                                        aOffscreen,
-                                                        profile);
-
+    RefPtr<GLContextEAGL> glContext = new GLContextEAGL(flags, SurfaceCaps::ForRGBA(),
+                                                        context, sharedContext,
+                                                        aOffscreen);
     if (!glContext->Init()) {
         glContext = nullptr;
         return nullptr;
     }
 
     return glContext.forget();
 }
 
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -213,19 +213,16 @@ GLContextEGL::GLContextEGL(CreateContext
     , mThebesSurface(nullptr)
     , mBound(false)
     , mIsPBuffer(false)
     , mIsDoubleBuffered(false)
     , mCanBindToTexture(false)
     , mShareWithEGLImage(false)
     , mOwnsContext(true)
 {
-    // any EGL contexts will always be GLESv2
-    SetProfileVersion(ContextProfile::OpenGLES, 200);
-
 #ifdef DEBUG
     printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
 }
 
 GLContextEGL::~GLContextEGL()
 {
     MarkDestroyed();
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -479,17 +479,17 @@ GLXLibrary::AfterGLXCall() const
         XSetErrorHandler(sOldErrorHandler);
     }
 }
 
 already_AddRefed<GLContextGLX>
 GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps,
                               bool isOffscreen, Display* display, GLXDrawable drawable,
                               GLXFBConfig cfg, bool deleteDrawable,
-                              gfxXlibSurface* pixmap, ContextProfile profile)
+                              gfxXlibSurface* pixmap)
 {
     GLXLibrary& glx = sGLXLibrary;
 
     int db = 0;
     int err = glx.fGetFBConfigAttrib(display, cfg,
                                       LOCAL_GLX_DOUBLEBUFFER, &db);
     if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
         if (ShouldSpew()) {
@@ -512,17 +512,17 @@ GLContextGLX::CreateGLContext(CreateCont
                 const int robust_attribs[] = {
                     LOCAL_GLX_CONTEXT_FLAGS_ARB,
                     LOCAL_GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB,
                     LOCAL_GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
                     LOCAL_GLX_LOSE_CONTEXT_ON_RESET_ARB,
                 };
                 attrib_list.AppendElements(robust_attribs, MOZ_ARRAY_LENGTH(robust_attribs));
             }
-            if (profile == ContextProfile::OpenGLCore) {
+            if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
                 int core_attribs[] = {
                     LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
                     LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB, 2,
                     LOCAL_GLX_CONTEXT_FLAGS_ARB, LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
                 };
                 attrib_list.AppendElements(core_attribs, MOZ_ARRAY_LENGTH(core_attribs));
             };
             attrib_list.AppendElement(0);
@@ -539,17 +539,17 @@ GLContextGLX::CreateGLContext(CreateCont
                 cfg,
                 LOCAL_GLX_RGBA_TYPE,
                 nullptr,
                 True);
         }
 
         if (context) {
             glContext = new GLContextGLX(flags, caps, isOffscreen, display, drawable,
-                                         context, deleteDrawable, db, pixmap, profile);
+                                         context, deleteDrawable, db, pixmap);
             if (!glContext->Init())
                 error = true;
         } else {
             error = true;
         }
 
         error |= xErrorHandler.SyncAndGetError(display);
 
@@ -705,31 +705,27 @@ GLContextGLX::GLContextGLX(
                   CreateContextFlags flags,
                   const SurfaceCaps& caps,
                   bool isOffscreen,
                   Display* aDisplay,
                   GLXDrawable aDrawable,
                   GLXContext aContext,
                   bool aDeleteDrawable,
                   bool aDoubleBuffered,
-                  gfxXlibSurface* aPixmap,
-                  ContextProfile profile)
+                  gfxXlibSurface* aPixmap)
     : GLContext(flags, caps, nullptr, isOffscreen),
       mContext(aContext),
       mDisplay(aDisplay),
       mDrawable(aDrawable),
       mDeleteDrawable(aDeleteDrawable),
       mDoubleBuffered(aDoubleBuffered),
       mGLX(&sGLXLibrary),
       mPixmap(aPixmap),
       mOwnsContext(true)
 {
-    MOZ_ASSERT(mGLX);
-    // See 899855
-    SetProfileVersion(profile, 200);
 }
 
 static bool
 AreCompatibleVisuals(Visual* one, Visual* two)
 {
     if (one->c_class != two->c_class) {
         return false;
     }
@@ -758,18 +754,17 @@ GLContextProviderGLX::CreateWrappingExis
         SurfaceCaps caps = SurfaceCaps::Any();
         RefPtr<GLContextGLX> glContext =
             new GLContextGLX(CreateContextFlags::NONE, caps,
                              false, // Offscreen
                              (Display*)DefaultXDisplay(), // Display
                              (GLXDrawable)aSurface, (GLXContext)aContext,
                              false, // aDeleteDrawable,
                              true,
-                             (gfxXlibSurface*)nullptr,
-                             ContextProfile::OpenGLCompatibility);
+                             (gfxXlibSurface*)nullptr);
 
         glContext->mOwnsContext = false;
         return glContext.forget();
     }
 
     return nullptr;
 }
 
@@ -800,32 +795,24 @@ CreateForWidget(Display* aXDisplay, Wind
     GLXFBConfig config;
     int visid;
     if (!GLContextGLX::FindFBConfigForWindow(aXDisplay, xscreen, aXWindow, &cfgs,
                                              &config, &visid, aWebRender))
     {
         return nullptr;
     }
 
-    SurfaceCaps caps = SurfaceCaps::Any();
-    RefPtr<GLContextGLX> gl;
+    CreateContextFlags flags;
     if (aWebRender) {
-      gl = GLContextGLX::CreateGLContext(CreateContextFlags::NONE,
-                                         caps, false,
-                                         aXDisplay, aXWindow, config,
-                                         //TODO: we might want to pass an additional bool to select GL core/compat
-                                         false, nullptr, ContextProfile::OpenGLCore); //WR: required GL 3.2+
+        flags = CreateContextFlags::NONE; // WR needs GL3.2+
     } else {
-      gl = GLContextGLX::CreateGLContext(CreateContextFlags::NONE,
-                                         caps, false,
-                                         aXDisplay, aXWindow, config,
-                                         false);
+        flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
     }
-
-    return gl.forget();
+    return GLContextGLX::CreateGLContext(flags, SurfaceCaps::Any(), false, aXDisplay,
+                                         aXWindow, config, false, nullptr);
 }
 
 already_AddRefed<GLContext>
 GLContextProviderGLX::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
 {
     X11CompositorWidget* compWidget = aCompositorWidget->AsX11();
     MOZ_ASSERT(compWidget);
 
@@ -996,18 +983,17 @@ GLContextGLX::FindFBConfigForWindow(Disp
     }
 
     NS_WARNING("[GLX] Couldn't find a FBConfig matching window visual");
     return false;
 }
 
 static already_AddRefed<GLContextGLX>
 CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size,
-                             const SurfaceCaps& minCaps, nsACString* const out_failureId,
-                             ContextProfile profile = ContextProfile::OpenGLCompatibility)
+                             const SurfaceCaps& minCaps, nsACString* const out_failureId)
 {
     GLXLibrary* glx = &sGLXLibrary;
     if (!glx->EnsureInitialized())
         return nullptr;
 
     Display* display = DefaultXDisplay();
     int screen = DefaultScreen(display);
 
@@ -1043,18 +1029,18 @@ CreateOffscreenPixmapContext(CreateConte
     if (pixmap == 0) {
         error = true;
     }
 
     bool serverError = xErrorHandler.SyncAndGetError(display);
     if (error || serverError)
         return nullptr;
 
-    return GLContextGLX::CreateGLContext(flags, minCaps, true, display,
-                                         pixmap, config, true, surface, profile);
+    return GLContextGLX::CreateGLContext(flags, minCaps, true, display, pixmap, config,
+                                         true, surface);
 }
 
 /*static*/ already_AddRefed<GLContext>
 GLContextProviderGLX::CreateHeadless(CreateContextFlags flags,
                                      nsACString* const out_failureId)
 {
     IntSize dummySize = IntSize(16, 16);
     SurfaceCaps dummyCaps = SurfaceCaps::Any();
@@ -1069,24 +1055,18 @@ GLContextProviderGLX::CreateOffscreen(co
 {
     SurfaceCaps minBackbufferCaps = minCaps;
     if (minCaps.antialias) {
         minBackbufferCaps.antialias = false;
         minBackbufferCaps.depth = false;
         minBackbufferCaps.stencil = false;
     }
 
-    ContextProfile profile = ContextProfile::OpenGLCore;
-    if (flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE) {
-        profile = ContextProfile::OpenGLCompatibility;
-    }
-
     RefPtr<GLContext> gl;
-    gl = CreateOffscreenPixmapContext(flags, size, minBackbufferCaps, out_failureId,
-                                      profile);
+    gl = CreateOffscreenPixmapContext(flags, size, minBackbufferCaps, out_failureId);
     if (!gl)
         return nullptr;
 
     if (!gl->InitOffscreen(size, minCaps)) {
         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_GLX_INIT");
         return nullptr;
     }
 
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -273,33 +273,29 @@ GLContextWGL::GLContextWGL(CreateContext
     : GLContext(flags, caps, nullptr, isOffscreen),
       mDC(aDC),
       mContext(aContext),
       mWnd(aWindow),
       mPBuffer(nullptr),
       mPixelFormat(0),
       mIsDoubleBuffered(false)
 {
-    // See 899855
-    SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
 }
 
 GLContextWGL::GLContextWGL(CreateContextFlags flags, const SurfaceCaps& caps,
                            bool isOffscreen, HANDLE aPbuffer, HDC aDC, HGLRC aContext,
                            int aPixelFormat)
     : GLContext(flags, caps, nullptr, isOffscreen),
       mDC(aDC),
       mContext(aContext),
       mWnd(nullptr),
       mPBuffer(aPbuffer),
       mPixelFormat(aPixelFormat),
       mIsDoubleBuffered(false)
 {
-    // See 899855
-    SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
 }
 
 GLContextWGL::~GLContextWGL()
 {
     MarkDestroyed();
 
     sWGLLib.mSymbols.fDeleteContext(mContext);
 
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -739,24 +739,20 @@ public:
         bool forWebRender = false;
         if (!gl::GLContextGLX::FindFBConfigForWindow(mXDisplay, screen, root,
                                                      &cfgs, &config, &visid,
                                                      forWebRender)) {
           lock.NotifyAll();
           return;
         }
 
-        mGLContext = gl::GLContextGLX::CreateGLContext(
-            gl::CreateContextFlags::NONE,
-            gl::SurfaceCaps::Any(),
-            false,
-            mXDisplay,
-            root,
-            config,
-            false);
+        mGLContext = gl::GLContextGLX::CreateGLContext(gl::CreateContextFlags::NONE,
+                                                       gl::SurfaceCaps::Any(), false,
+                                                       mXDisplay, root, config, false,
+                                                       nullptr);
 
         if (!mGLContext) {
           lock.NotifyAll();
           return;
         }
 
         mGLContext->MakeCurrent();