Backed out 3 changesets (bug 1399501) for aseertions failures on GLContextProviderEGL.
authorCosmin Sabou <csabou@mozilla.com>
Tue, 23 Oct 2018 23:38:21 +0300
changeset 490917 12e986367fe985de767c4a32a9e5c7fadf824bdd
parent 490916 59160a8260a02fda2bc625b02c3132d9330e2dd7
child 490918 918d2aeb31eb7d18603be0c5f6ae9b27c12b6fc2
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
bugs1399501
milestone65.0a1
backs out7c110571ab1a8a33e8c072f690d30a7a8e488163
b7e7638dbfd10f04f0eea8f9d886266abe791378
b4c2cdd8d03bafba7ad2854968ba07df070dc440
Backed out 3 changesets (bug 1399501) for aseertions failures on GLContextProviderEGL. Backed out changeset 7c110571ab1a (bug 1399501) Backed out changeset b7e7638dbfd1 (bug 1399501) Backed out changeset b4c2cdd8d03b (bug 1399501)
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContextValidate.cpp
dom/canvas/WebGLShaderValidator.cpp
dom/canvas/test/webgl-conf/generated-mochitest.ini
dom/canvas/test/webgl-conf/mochitest-errata.ini
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
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -596,26 +596,18 @@ WebGLContext::CreateAndInitGL(bool force
     // --
 
     typedef decltype(gl::GLContextProviderEGL::CreateOffscreen) fnCreateOffscreenT;
     const auto fnCreate = [&](fnCreateOffscreenT* const pfnCreateOffscreen,
                               const char* const info)
     {
         const gfx::IntSize dummySize(1, 1);
         nsCString failureId;
-        RefPtr<GLContext> gl = pfnCreateOffscreen(dummySize, surfaceCaps, flags,
-                                                  &failureId);
-        if (gl && gl->IsCoreProfile() &&
-            !(flags & gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE) &&
-            !gl->IsSupported(gl::GLFeature::gpu_shader5))
-        {
-            // See comment on "constant-index-expression" in WebGLShaderValidator.cpp.
-            const auto compatFlags = flags | gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE;
-            gl = pfnCreateOffscreen(dummySize, surfaceCaps, compatFlags, &failureId);
-        }
+        const RefPtr<GLContext> gl = pfnCreateOffscreen(dummySize, surfaceCaps, flags,
+                                                        &failureId);
         if (!gl) {
             out_failReasons->push_back(WebGLContext::FailureReason(failureId, info));
         }
         return gl;
     };
 
     const auto newGL = [&]() -> RefPtr<gl::GLContext> {
         if (tryNativeGL) {
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -300,32 +300,33 @@ WebGLContext::ValidateUniformMatrixArray
     return true;
 }
 
 bool
 WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
 {
     MOZ_RELEASE_ASSERT(gl, "GFX: GL not initialized");
 
-    if (!gl->MakeCurrent(true)) {
-        MOZ_ASSERT(false);
-        *out_failReason = { "FEATURE_FAILURE_WEBGL_MAKECURRENT",
-                            "Failed to MakeCurrent for init." };
-        return false;
-    }
-
     // Unconditionally create a new format usage authority. This is
     // important when restoring contexts and extensions need to add
     // formats back into the authority.
     mFormatUsage = CreateFormatUsage(gl);
-    MOZ_RELEASE_ASSERT(mFormatUsage);
+    if (!mFormatUsage) {
+        *out_failReason = { "FEATURE_FAILURE_WEBGL_FORMAT",
+                            "Failed to create mFormatUsage." };
+        return false;
+    }
 
-    {
-        const auto error = gl->fGetError();
-        MOZ_ALWAYS_TRUE(!error);
+    GLenum error = gl->fGetError();
+    if (error != LOCAL_GL_NO_ERROR) {
+        const nsPrintfCString reason("GL error 0x%x occurred during OpenGL context"
+                                     " initialization, before WebGL initialization!",
+                                     error);
+        *out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_1", reason };
+        return false;
     }
 
     mDisableExtensions = gfxPrefs::WebGLDisableExtensions();
     mLoseContextOnMemoryPressure = gfxPrefs::WebGLLoseContextOnMemoryPressure();
     mCanLoseContextInForeground = gfxPrefs::WebGLCanLoseContextInForeground();
     mRestoreWhenVisible = gfxPrefs::WebGLRestoreWhenVisible();
 
     // These are the default values, see 6.2 State tables in the
@@ -598,19 +599,23 @@ WebGLContext::InitAndValidateGL(FailureR
     // Mesa can only be detected with the GL_VERSION string, of the form
     // "2.1 Mesa 7.11.0"
     const char* versionStr = (const char*)(gl->fGetString(LOCAL_GL_VERSION));
     mIsMesa = strstr(versionStr, "Mesa");
 
     // Notice that the point of calling fGetError here is not only to check for
     // errors, but also to reset the error flags so that a subsequent WebGL
     // getError call will give the correct result.
-    {
-        const auto error = gl->fGetError();
-        MOZ_ALWAYS_TRUE(!error);
+    error = gl->fGetError();
+    if (error != LOCAL_GL_NO_ERROR) {
+        const nsPrintfCString reason("GL error 0x%x occurred during WebGL context"
+                                     " initialization!",
+                                     error);
+        *out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_2", reason };
+        return false;
     }
 
     if (IsWebGL2() &&
         !InitWebGL2(out_failReason))
     {
         // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
         return false;
     }
--- a/dom/canvas/WebGLShaderValidator.cpp
+++ b/dom/canvas/WebGLShaderValidator.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLShaderValidator.h"
 
-#include <algorithm>
 #include "gfxPrefs.h"
 #include "GLContext.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/Preferences.h"
 #include "MurmurHash3.h"
 #include "nsPrintfCString.h"
 #include <string>
 #include <vector>
@@ -97,32 +96,22 @@ ChooseValidatorCompileOptions(const ShBu
     return options;
 }
 
 } // namespace webgl
 
 ////////////////////////////////////////
 
 static ShShaderOutput
-ShaderOutput(gl::GLContext* const gl)
+ShaderOutput(gl::GLContext* gl)
 {
     if (gl->IsGLES()) {
         return SH_ESSL_OUTPUT;
     } else {
         uint32_t version = gl->ShadingLanguageVersion();
-
-        // Version 130 starts to require integral constant expressions for loop indices,
-        // instead of "constant-index-expression".
-        // Both version 400 and gpu_shader5 remove this restrictions.
-        // gpu_shader5 went core in 400, so we can just check for the GLFeature.
-        // If we're compiling for webglsl1, even for webgl2, we need gpu_shader5, or GLSL_COMPAT.
-        if (!gl->IsSupported(gl::GLFeature::gpu_shader5)) {
-            version = std::min<uint32_t>(version, 120);
-        }
-
         switch (version) {
         case 100: return SH_GLSL_COMPATIBILITY_OUTPUT;
         case 120: return SH_GLSL_COMPATIBILITY_OUTPUT;
         case 130: return SH_GLSL_130_OUTPUT;
         case 140: return SH_GLSL_140_OUTPUT;
         case 150: return SH_GLSL_150_CORE_OUTPUT;
         case 330: return SH_GLSL_330_CORE_OUTPUT;
         case 400: return SH_GLSL_400_CORE_OUTPUT;
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -11111,16 +11111,17 @@ subsuite = webgl1-ext
 subsuite = webgl1-ext
 skip-if = (os == 'android')
 [generated/test_conformance__glsl__bugs__qualcomm-loop-with-continue-crash.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__bugs__sampler-array-struct-function-arg.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html]
 subsuite = webgl1-ext
+fail-if = (os == 'linux')
 [generated/test_conformance__glsl__bugs__sampler-struct-function-arg.html]
 subsuite = webgl1-ext
 skip-if = (os == 'linux') || (os == 'android')
 [generated/test_conformance__glsl__bugs__sequence-operator-evaluation-order.html]
 subsuite = webgl1-ext
 skip-if = (os == 'android')
 [generated/test_conformance__glsl__bugs__sketchfab-lighting-shader-crash.html]
 subsuite = webgl1-ext
@@ -11406,17 +11407,17 @@ subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__empty-declaration.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__empty_main.vert.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__expression-list-in-declarator-initializer.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__fragcolor-fragdata-invariant.html]
 subsuite = webgl1-ext
-fail-if = (os == 'linux') || (os == 'mac')
+fail-if = (os == 'mac')
 [generated/test_conformance__glsl__misc__gl_position_unset.vert.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__global-variable-init.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__glsl-function-nodes.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__glsl-long-variable-names.html]
 subsuite = webgl1-ext
@@ -11586,17 +11587,16 @@ subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shader-with-while-loop.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shader-without-precision.frag.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shaders-with-constant-expression-loop-conditions.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shaders-with-invariance.html]
 subsuite = webgl1-ext
-fail-if = (os == 'linux')
 [generated/test_conformance__glsl__misc__shaders-with-mis-matching-uniforms.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shaders-with-mis-matching-varyings.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shaders-with-missing-varyings.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shaders-with-name-conflicts.html]
 subsuite = webgl1-ext
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -188,17 +188,19 @@ skip-if = (os == 'linux') || (os == 'mac
 [generated/test_conformance__glsl__constructors__glsl-construct-ivec4.html]
 # Assume crashes like ivec3
 skip-if = (os == 'linux') || (os == 'mac')
 
 [generated/test_conformance__glsl__constructors__glsl-construct-mat2.html]
 # Crashes on Linux ASAN
 skip-if = ((os == 'linux') && asan)
 
-[generated/test_conformance__glsl__misc__shaders-with-invariance.html]
+[generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html]
+# Testfail on Linux after removing SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX.
+# Only happen on tryserver
 fail-if = (os == 'linux')
 
 [generated/test_conformance__misc__type-conversion-test.html]
 fail-if = (os == 'linux')
 # Resets device on Android 2.3.
 # Crashes on desktop Linux.
 skip-if = (os == 'android') || (os == 'linux')
 
@@ -353,17 +355,17 @@ fail-if = (os == 'mac') || (verify && de
 skip-if = (os == 'win')
 [generated/test_2_conformance__rendering__rendering-stencil-large-viewport.html]
 # same as webgl1 test
 fail-if = (os == 'mac')
 skip-if = (os == 'win')
 
 [generated/test_conformance__glsl__misc__fragcolor-fragdata-invariant.html]
 # [unexpected fragment shader compile status] (expected: true) Declaring both gl_FragColor and gl_FragData invariant should succeed.
-fail-if = (os == 'linux') || (os == 'mac')
+fail-if = (os == 'mac')
 
 ########################################################################
 # "tst-linux{32,64}-spot-NNN" Slaves:
 #   Android 2.3 and Linux.
 # Android: os == 'android'. (Not enough info to separate out 2.3)
 # Linux: os == 'linux'.
 [generated/test_conformance__glsl__bugs__temp-expressions-should-not-crash.html]
 # Coincidentally enough, crashes on Linux and Android 4.0.
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -92,17 +92,16 @@ static const char* const sExtensionNames
     "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_gpu_shader5",
     "GL_ARB_half_float_pixel",
     "GL_ARB_instanced_arrays",
     "GL_ARB_internalformat_query",
     "GL_ARB_invalidate_subdata",
     "GL_ARB_map_buffer_range",
     "GL_ARB_occlusion_query2",
     "GL_ARB_pixel_buffer_object",
     "GL_ARB_robust_buffer_access_behavior",
@@ -135,17 +134,16 @@ static const char* const sExtensionNames
     "GL_EXT_draw_instanced",
     "GL_EXT_draw_range_elements",
     "GL_EXT_frag_depth",
     "GL_EXT_framebuffer_blit",
     "GL_EXT_framebuffer_multisample",
     "GL_EXT_framebuffer_object",
     "GL_EXT_framebuffer_sRGB",
     "GL_EXT_gpu_shader4",
-    "GL_EXT_gpu_shader5",
     "GL_EXT_multisampled_render_to_texture",
     "GL_EXT_occlusion_query_boolean",
     "GL_EXT_packed_depth_stencil",
     "GL_EXT_read_format_bgra",
     "GL_EXT_robustness",
     "GL_EXT_sRGB",
     "GL_EXT_sRGB_write_control",
     "GL_EXT_shader_texture_lod",
@@ -169,17 +167,16 @@ static const char* const sExtensionNames
     "GL_KHR_robust_buffer_access_behavior",
     "GL_KHR_robustness",
     "GL_KHR_texture_compression_astc_hdr",
     "GL_KHR_texture_compression_astc_ldr",
     "GL_NV_draw_instanced",
     "GL_NV_fence",
     "GL_NV_framebuffer_blit",
     "GL_NV_geometry_program4",
-    "GL_NV_gpu_shader5",
     "GL_NV_half_float",
     "GL_NV_instanced_arrays",
     "GL_NV_primitive_restart",
     "GL_NV_texture_barrier",
     "GL_NV_transform_feedback",
     "GL_NV_transform_feedback2",
     "GL_OES_EGL_image",
     "GL_OES_EGL_image_external",
@@ -376,20 +373,16 @@ GLContext::LoadFeatureSymbols(const char
         return false;
     }
     return true;
 };
 
 bool
 GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
 {
-    // see bug 929506 comment 29. wglGetProcAddress requires a current context.
-    if (!MakeCurrent(true))
-        return false;
-
     mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
 
     const SymLoadStruct coreSymbols[] = {
         { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
@@ -516,16 +509,20 @@ GLContext::InitWithPrefixImpl(const char
         END_SYMBOLS
     };
 
     if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL"))
         return false;
 
     ////////////////
 
+    if (!MakeCurrent()) {
+        return false;
+    }
+
     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");
@@ -2049,19 +2046,21 @@ GLContext::MarkDestroyed()
         return;
 
     // Null these before they're naturally nulled after dtor, as we want GLContext to
     // still be alive in *their* dtors.
     mScreen = nullptr;
     mBlitHelper = nullptr;
     mReadTexImageHelper = nullptr;
 
-    mIsDestroyed = true;
+    if (!MakeCurrent()) {
+        NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
+    }
+
     mSymbols = {};
-    (void)MakeCurrent(true); // Clear current context.
 }
 
 #ifdef MOZ_GL_DEBUG
 /* static */ void
 GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr)
 {
   int somethingOnTheStack;
   const void* someStackPtr = &somethingOnTheStack;
@@ -2937,36 +2936,36 @@ GetBytesPerTexel(GLenum format, GLenum t
         return 2;
     }
 
     gfxCriticalError() << "Unknown texture type " << type << " or format " << format;
     return 0;
 }
 
 bool
-GLContext::MakeCurrent(const bool aForce) const
+GLContext::MakeCurrent(bool aForce) const
 {
-    if (MOZ_LIKELY( !aForce & !IsDestroyed() )) {
-        bool isCurrent = false;
+    if (MOZ_UNLIKELY( IsDestroyed() ))
+        return false;
+
+    if (MOZ_LIKELY( !aForce )) {
+        bool isCurrent;
         if (mUseTLSIsCurrent) {
             isCurrent = (sCurrentContext.get() == reinterpret_cast<uintptr_t>(this));
-        }
-        if (MOZ_UNLIKELY( !isCurrent )) {
+        } else {
             isCurrent = IsCurrentImpl();
         }
         if (MOZ_LIKELY( isCurrent )) {
             MOZ_ASSERT(IsCurrentImpl());
             return true;
         }
     }
 
-    if (MOZ_UNLIKELY( !MakeCurrentImpl() )) {
-        ClearGetCurrentContextTLS();
+    if (!MakeCurrentImpl())
         return false;
-    }
 
     sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
     return true;
 }
 
 void
 GLContext::ResetSyncCallCount(const char* resetReason) const
 {
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -98,17 +98,16 @@ enum class GLFeature {
     framebuffer_multisample,
     framebuffer_object,
     framebuffer_object_EXT_OES,
     get_integer_indexed,
     get_integer64_indexed,
     get_query_object_i64v,
     get_query_object_iv,
     gpu_shader4,
-    gpu_shader5,
     instanced_arrays,
     instanced_non_arrays,
     internalformat_query,
     invalidate_framebuffer,
     map_buffer_range,
     occlusion_query,
     occlusion_query_boolean,
     occlusion_query2,
@@ -196,20 +195,16 @@ class GLContext
     : public GLLibraryLoader
     , public GenericAtomicRefCounted
     , public SupportsWeakPtr<GLContext>
 {
 public:
     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLContext)
     static MOZ_THREAD_LOCAL(uintptr_t) sCurrentContext;
 
-    static void ClearGetCurrentContextTLS() {
-        sCurrentContext.set(0);
-    }
-
     bool mImplicitMakeCurrent = false;
     bool mUseTLSIsCurrent;
 
     class TlsScope final {
         const WeakPtr<GLContext> mGL;
         const bool mWasTlsOk;
     public:
         explicit TlsScope(GLContext* const gl)
@@ -341,17 +336,16 @@ public:
      */
     virtual GLuint GetDefaultFramebuffer() {
         return 0;
     }
 
 protected:
     bool mIsOffscreen;
     mutable bool mContextLost = false;
-    bool mIsDestroyed = false;
 
     /**
      * 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 = 0;
     ContextProfile mProfile = ContextProfile::Unknown;
 
@@ -399,17 +393,16 @@ public:
         ARB_compatibility,
         ARB_copy_buffer,
         ARB_depth_texture,
         ARB_draw_buffers,
         ARB_draw_instanced,
         ARB_framebuffer_object,
         ARB_framebuffer_sRGB,
         ARB_geometry_shader4,
-        ARB_gpu_shader5,
         ARB_half_float_pixel,
         ARB_instanced_arrays,
         ARB_internalformat_query,
         ARB_invalidate_subdata,
         ARB_map_buffer_range,
         ARB_occlusion_query2,
         ARB_pixel_buffer_object,
         ARB_robust_buffer_access_behavior,
@@ -442,17 +435,16 @@ public:
         EXT_draw_instanced,
         EXT_draw_range_elements,
         EXT_frag_depth,
         EXT_framebuffer_blit,
         EXT_framebuffer_multisample,
         EXT_framebuffer_object,
         EXT_framebuffer_sRGB,
         EXT_gpu_shader4,
-        EXT_gpu_shader5,
         EXT_multisampled_render_to_texture,
         EXT_occlusion_query_boolean,
         EXT_packed_depth_stencil,
         EXT_read_format_bgra,
         EXT_robustness,
         EXT_sRGB,
         EXT_sRGB_write_control,
         EXT_shader_texture_lod,
@@ -476,17 +468,16 @@ public:
         KHR_robust_buffer_access_behavior,
         KHR_robustness,
         KHR_texture_compression_astc_hdr,
         KHR_texture_compression_astc_ldr,
         NV_draw_instanced,
         NV_fence,
         NV_framebuffer_blit,
         NV_geometry_program4,
-        NV_gpu_shader5,
         NV_half_float,
         NV_instanced_arrays,
         NV_primitive_restart,
         NV_texture_barrier,
         NV_transform_feedback,
         NV_transform_feedback2,
         OES_EGL_image,
         OES_EGL_image_external,
@@ -3378,17 +3369,18 @@ protected:
 public:
     virtual bool Init() = 0;
 
     virtual bool SetupLookupFunction() = 0;
 
     virtual void ReleaseSurface() {}
 
     bool IsDestroyed() const {
-        return mIsDestroyed;
+        // MarkDestroyed will mark all these as null.
+        return mSymbols.fUseProgram == nullptr;
     }
 
     GLContext* GetSharedContext() { return mSharedContext; }
 
     /**
      * Returns true if the thread on which this context was created is the currently
      * executing thread.
      */
--- a/gfx/gl/GLContextCGL.h
+++ b/gfx/gl/GLContextCGL.h
@@ -19,17 +19,17 @@ typedef void NSOpenGLContext;
 
 namespace mozilla {
 namespace gl {
 
 class GLContextCGL : public GLContext
 {
     friend class GLContextProviderCGL;
 
-    NSOpenGLContext* const mContext;
+    NSOpenGLContext* mContext;
 
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, override)
     GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps,
                  NSOpenGLContext* context, bool isOffscreen);
 
     ~GLContextCGL();
 
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -317,28 +317,16 @@ static const FeatureInfo sFeatureInfoArr
         GLESVersion::ES3,
         GLContext::Extension_None,
         {
             GLContext::EXT_gpu_shader4,
             GLContext::Extensions_End
         }
     },
     {
-        "gpu_shader5",
-        GLVersion::GL4,
-        GLESVersion::NONE,
-        GLContext::Extension_None,
-        {
-            GLContext::ARB_gpu_shader5,
-            GLContext::EXT_gpu_shader5,
-            GLContext::NV_gpu_shader5,
-            GLContext::Extensions_End
-        }
-    },
-    {
         "instanced_arrays",
         GLVersion::GL3_3,
         GLESVersion::ES3,
         GLContext::Extension_None,
         {
             GLContext::ARB_instanced_arrays,
             GLContext::NV_instanced_arrays,
             GLContext::ANGLE_instanced_arrays,
--- a/gfx/gl/GLContextGLX.h
+++ b/gfx/gl/GLContextGLX.h
@@ -82,17 +82,16 @@ private:
                  GLXContext aContext,
                  bool aDeleteDrawable,
                  bool aDoubleBuffered,
                  gfxXlibSurface* aPixmap);
 
     GLXContext mContext;
     Display* mDisplay;
     GLXDrawable mDrawable;
-    Maybe<GLXDrawable> mOverrideDrawable;
     bool mDeleteDrawable;
     bool mDoubleBuffered;
 
     GLXLibrary* mGLX;
 
     RefPtr<gfxXlibSurface> mPixmap;
     bool mOwnsContext = true;
 };
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -71,39 +71,46 @@ GLContextCGL::GLContextCGL(CreateContext
     : GLContext(flags, caps, nullptr, isOffscreen)
     , mContext(context)
 {
 }
 
 GLContextCGL::~GLContextCGL()
 {
     MarkDestroyed();
-    [mContext release];
+
+    if (mContext) {
+        if ([NSOpenGLContext currentContext] == mContext) {
+            // Clear the current context before releasing. If we don't do
+            // this, the next time we call [NSOpenGLContext currentContext],
+            // "invalid context" will be printed to the console.
+            [NSOpenGLContext clearCurrentContext];
+        }
+        [mContext release];
+    }
 }
 
 bool
 GLContextCGL::Init()
 {
-    return InitWithPrefix("gl", true);
+    if (!InitWithPrefix("gl", true))
+        return false;
+
+    return true;
 }
 
 CGLContextObj
 GLContextCGL::GetCGLContext() const
 {
     return static_cast<CGLContextObj>([mContext CGLContextObj]);
 }
 
 bool
 GLContextCGL::MakeCurrentImpl() const
 {
-    if (IsDestroyed()) {
-        [NSOpenGLContext clearCurrentContext];
-        return false;
-    }
-
     if (mContext) {
         [mContext makeCurrentContext];
         MOZ_ASSERT(IsCurrentImpl());
         // Use non-blocking swap in "ASAP mode".
         // ASAP mode means that rendering is iterated as fast as possible.
         // ASAP mode is entered when layout.frame_rate=0 (requires restart).
         // If swapInt is 1, then glSwapBuffers will block and wait for a vblank signal.
         // When we're iterating as fast as possible, however, we want a non-blocking
--- a/gfx/gl/GLContextProviderEAGL.mm
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -27,36 +27,45 @@ GLContextEAGL::GLContextEAGL(CreateConte
                              bool isOffscreen)
     : GLContext(flags, caps, sharedContext, isOffscreen)
     , mContext(context)
 {
 }
 
 GLContextEAGL::~GLContextEAGL()
 {
-    if (MakeCurrent()) {
-        if (mBackbufferFB) {
-            fDeleteFramebuffers(1, &mBackbufferFB);
-        }
+    MakeCurrent();
 
-        if (mBackbufferRB) {
-            fDeleteRenderbuffers(1, &mBackbufferRB);
-        }
+    if (mBackbufferFB) {
+        fDeleteFramebuffers(1, &mBackbufferFB);
+    }
+
+    if (mBackbufferRB) {
+        fDeleteRenderbuffers(1, &mBackbufferRB);
     }
 
-    mLayer = nil;
+    MarkDestroyed();
 
-    MarkDestroyed();
-    [mContext release];
+    if (mLayer) {
+      mLayer = nil;
+    }
+
+    if (mContext) {
+      [EAGLContext setCurrentContext:nil];
+      [mContext release];
+    }
 }
 
 bool
 GLContextEAGL::Init()
 {
-    return InitWithPrefix("gl", true);
+    if (!InitWithPrefix("gl", true))
+        return false;
+
+    return true;
 }
 
 bool
 GLContextEAGL::AttachToWindow(nsIWidget* aWidget)
 {
     // This should only be called once
     MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB);
 
@@ -98,21 +107,22 @@ GLContextEAGL::RecreateRB()
                              LOCAL_GL_RENDERBUFFER, mBackbufferRB);
 
     return LOCAL_GL_FRAMEBUFFER_COMPLETE == fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
 }
 
 bool
 GLContextEAGL::MakeCurrentImpl() const
 {
-    if (IsDestroyed()) {
-        [EAGLContext setCurrentContext:nil];
-        return false;
+    if (mContext) {
+        if(![EAGLContext setCurrentContext:mContext]) {
+            return false;
+        }
     }
-    return [EAGLContext setCurrentContext:mContext];
+    return true;
 }
 
 bool
 GLContextEAGL::IsCurrentImpl() const
 {
     return [EAGLContext currentContext] == mContext;
 }
 
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -153,26 +153,29 @@ is_power_of_two(int v)
 
     if (v == 0)
         return true;
 
     return (v & (v-1)) == 0;
 }
 
 static void
-DestroySurface(const EGLSurface surf)
-{
-    MOZ_ASSERT(surf);
-    const auto& egl = gl::GLLibraryEGL::Get();
+DestroySurface(EGLSurface oldSurface) {
+    auto* egl = gl::GLLibraryEGL::Get();
 
-    // TODO: This breaks TLS MakeCurrent caching.
-    MOZ_ALWAYS_TRUE( egl->fDestroySurface(EGL_DISPLAY(), surf) );
+    if (oldSurface != EGL_NO_SURFACE) {
+        // TODO: This breaks TLS MakeCurrent caching.
+        egl->fMakeCurrent(EGL_DISPLAY(),
+                          EGL_NO_SURFACE, EGL_NO_SURFACE,
+                          EGL_NO_CONTEXT);
+        egl->fDestroySurface(EGL_DISPLAY(), oldSurface);
 #if defined(MOZ_WAYLAND)
-    DeleteWaylandGLSurface(surf);
+        DeleteWaylandGLSurface(oldSurface);
 #endif
+    }
 }
 
 static EGLSurface
 CreateFallbackSurface(const EGLConfig& config)
 {
     nsCString discardFailureId;
     if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
         gfxCriticalNote << "Failed to load EGL library 3!";
@@ -276,17 +279,17 @@ GLContextEGLFactory::Create(EGLNativeWin
     if (aWebRender) {
         flags |= CreateContextFlags::PREFER_ES3;
     }
     SurfaceCaps caps = SurfaceCaps::Any();
     RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, caps, false, config,
                                                             surface, &discardFailureId);
     if (!gl) {
         gfxCriticalNote << "Failed to create EGLContext!";
-        DestroySurface(surface);
+        mozilla::gl::DestroySurface(surface);
         return nullptr;
     }
 
     gl->MakeCurrent();
     gl->SetIsDoubleBuffered(doubleBuffered);
     if (aWebRender && egl->IsANGLE()) {
         MOZ_ASSERT(doubleBuffered);
         egl->fSwapInterval(EGL_DISPLAY(), 0);
@@ -318,22 +321,19 @@ GLContextEGL::~GLContextEGL()
         return;
     }
 
 #ifdef DEBUG
     printf_stderr("Destroying context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
 
     mEgl->fDestroyContext(EGL_DISPLAY(), mContext);
-    if (mSurface) {
-        DestroySurface(mSurface);
-    }
-    if (mFallbackSurface) {
-        DestroySurface(mFallbackSurface);
-    }
+
+    mozilla::gl::DestroySurface(mSurface);
+    mozilla::gl::DestroySurface(mFallbackSurface);
 }
 
 bool
 GLContextEGL::Init()
 {
 #if defined(ANDROID)
     // We can't use LoadApitraceLibrary here because the GLContext
     // expects its own handle to the GL library
@@ -346,17 +346,23 @@ GLContextEGL::Init()
                 return false;
             }
 #endif
         }
 
     SetupLookupFunction();
     if (!InitWithPrefix("gl", true))
         return false;
-    MOZ_ASSERT(IsCurrent());
+
+    bool current = MakeCurrent();
+    if (!current) {
+        gfx::LogFailure(NS_LITERAL_CSTRING(
+            "Couldn't get device attachments for device."));
+        return false;
+    }
 
     static_assert(sizeof(GLint) >= sizeof(int32_t), "GLint is smaller than int32_t");
     mMaxTextureImageSize = INT32_MAX;
 
     mShareWithEGLImage = mEgl->HasKHRImageBase() &&
                          mEgl->HasKHRImageTexture2D() &&
                          IsExtensionSupported(OES_EGL_image);
 
@@ -397,45 +403,36 @@ GLContextEGL::ReleaseTexImage()
     if (success == LOCAL_EGL_FALSE)
         return false;
 
     mBound = false;
     return true;
 }
 
 void
-GLContextEGL::SetEGLSurfaceOverride(const EGLSurface surf)
-{
-    MOZ_ASSERT(!surf || surf != mSurface);
-
+GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
     if (Screen()) {
         /* Blit `draw` to `read` if we need to, before we potentially juggle
           * `read` around. If we don't, we might attach a different `read`,
           * and *then* hit AssureBlitted, which will blit a dirty `draw` onto
           * the wrong `read`!
           */
         Screen()->AssureBlitted();
     }
 
     mSurfaceOverride = surf;
-    MOZ_ALWAYS_TRUE( MakeCurrent(true) );
+    DebugOnly<bool> ok = MakeCurrent(true);
+    MOZ_ASSERT(ok);
 }
 
 bool
 GLContextEGL::MakeCurrentImpl() const
 {
-    if (IsDestroyed()) {
-        MOZ_ALWAYS_TRUE( mEgl->fMakeCurrent(EGL_DISPLAY(), nullptr, nullptr, nullptr) );
-        return false;
-    }
-
-    auto surface = mSurface;
-    if (mSurfaceOverride) {
-        surface = mSurfaceOverride;
-    }
+    EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride
+                                                              : mSurface;
     if (!surface) {
         surface = mFallbackSurface;
     }
 
     const bool succeeded = mEgl->fMakeCurrent(EGL_DISPLAY(), surface, surface,
                                               mContext);
     if (!succeeded) {
         const auto eglError = mEgl->fGetError();
@@ -455,18 +452,17 @@ GLContextEGL::MakeCurrentImpl() const
 
 bool
 GLContextEGL::IsCurrentImpl() const
 {
     return mEgl->fGetCurrentContext() == mContext;
 }
 
 bool
-GLContextEGL::RenewSurface(CompositorWidget* const aWidget)
-{
+GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
     if (!mOwnsContext) {
         return false;
     }
     // unconditionally release the surface and create a new one. Don't try to optimize this away.
     // If we get here, then by definition we know that we want to get a new surface.
     ReleaseSurface();
     MOZ_ASSERT(aWidget);
 
@@ -478,23 +474,24 @@ GLContextEGL::RenewSurface(CompositorWid
             return false;
         }
     }
 
     return MakeCurrent(true);
 }
 
 void
-GLContextEGL::ReleaseSurface()
-{
-    if (!mOwnsContext)
-        return;
-
-    mozilla::gl::DestroySurface(mSurface);
-    mSurface = nullptr;
+GLContextEGL::ReleaseSurface() {
+    if (mOwnsContext) {
+        mozilla::gl::DestroySurface(mSurface);
+    }
+    if (mSurface == mSurfaceOverride) {
+        mSurfaceOverride = EGL_NO_SURFACE;
+    }
+    mSurface = EGL_NO_SURFACE;
 }
 
 bool
 GLContextEGL::SetupLookupFunction()
 {
     mLookupFunc = mEgl->GetLookupFunction();
     return true;
 }
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -582,22 +582,30 @@ GLContextGLX::~GLContextGLX()
 {
     MarkDestroyed();
 
     // Wrapped context should not destroy glxContext/Surface
     if (!mOwnsContext) {
         return;
     }
 
+    // see bug 659842 comment 76
+#ifdef DEBUG
+    bool success =
+#endif
+    mGLX->fMakeCurrent(mDisplay, X11None, nullptr);
+    MOZ_ASSERT(success,
+               "glXMakeCurrent failed to release GL context before we call "
+               "glXDestroyContext!");
+
     mGLX->fDestroyContext(mDisplay, mContext);
 
     if (mDeleteDrawable) {
         mGLX->fDestroyPixmap(mDisplay, mDrawable);
     }
-    MOZ_ASSERT(!mOverrideDrawable);
 }
 
 
 bool
 GLContextGLX::Init()
 {
     SetupLookupFunction();
     if (!InitWithPrefix("gl", true)) {
@@ -616,26 +624,17 @@ bool
 GLContextGLX::MakeCurrentImpl() const
 {
     if (mGLX->IsMesa()) {
         // Read into the event queue to ensure that Mesa receives a
         // DRI2InvalidateBuffers event before drawing. See bug 1280653.
         Unused << XPending(mDisplay);
     }
 
-    if (IsDestroyed()) {
-        MOZ_ALWAYS_TRUE( mGLX->fMakeCurrent(mDisplay, X11None, nullptr) );
-        return false; // Did not MakeCurrent mContext, but that's what we wanted!
-    }
-
-    auto drawable = mDrawable;
-    if (mOverrideDrawable) {
-        drawable = mOverrideDrawable.ref();
-    }
-    const bool succeeded = mGLX->fMakeCurrent(mDisplay, drawable, mContext);
+    const bool succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
     NS_ASSERTION(succeeded, "Failed to make GL context current!");
 
     if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
         // Many GLX implementations default to blocking until the next
         // VBlank when calling glXSwapBuffers. We want to run unthrottled
         // in ASAP mode. See bug 1280744.
         const bool isASAP = (gfxPrefs::LayoutFrameRate() == 0);
         mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1);
@@ -690,28 +689,26 @@ GLContextGLX::GetWSIInfo(nsCString* cons
 
     out->AppendLiteral("\nExtensions: ");
     out->Append(sGLXLibrary.fQueryExtensionsString(display, screen));
 }
 
 bool
 GLContextGLX::OverrideDrawable(GLXDrawable drawable)
 {
-    if (Screen()) {
+    if (Screen())
         Screen()->AssureBlitted();
-    }
-    mOverrideDrawable = Some(drawable);
-    return MakeCurrent(true);
+    Bool result = mGLX->fMakeCurrent(mDisplay, drawable, mContext);
+    return result;
 }
 
 bool
 GLContextGLX::RestoreDrawable()
 {
-    mOverrideDrawable = Nothing();
-    return MakeCurrent(true);
+    return mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
 }
 
 GLContextGLX::GLContextGLX(
                   CreateContextFlags flags,
                   const SurfaceCaps& caps,
                   bool isOffscreen,
                   Display* aDisplay,
                   GLXDrawable aDrawable,
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -158,16 +158,17 @@ WGLLibrary::EnsureInitialized()
 
     // create rendering context
     mDummyGlrc = mSymbols.fCreateContext(mRootDc);
     if (!mDummyGlrc)
         return false;
 
     const auto curCtx = mSymbols.fGetCurrentContext();
     const auto curDC = mSymbols.fGetCurrentDC();
+
     if (!mSymbols.fMakeCurrent(mRootDc, mDummyGlrc)) {
         NS_WARNING("wglMakeCurrent failed");
         return false;
     }
     const auto resetContext = MakeScopeExit([&]() {
         mSymbols.fMakeCurrent(curDC, curCtx);
     });
 
@@ -293,16 +294,17 @@ GLContextWGL::GLContextWGL(CreateContext
       mPBuffer(aPbuffer),
       mPixelFormat(aPixelFormat)
 {
 }
 
 GLContextWGL::~GLContextWGL()
 {
     MarkDestroyed();
+
     (void)sWGLLib.mSymbols.fDeleteContext(mContext);
 
     if (mPBuffer) {
         (void)sWGLLib.mSymbols.fReleasePbufferDC(mPBuffer, mDC);
         (void)sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer);
     }
     if (mWnd) {
         (void)ReleaseDC(mWnd, mDC);
@@ -311,28 +313,30 @@ GLContextWGL::~GLContextWGL()
 }
 
 bool
 GLContextWGL::Init()
 {
     if (!mDC || !mContext)
         return false;
 
+    // see bug 929506 comment 29. wglGetProcAddress requires a current context.
+    if (!sWGLLib.mSymbols.fMakeCurrent(mDC, mContext))
+        return false;
+
     SetupLookupFunction();
-    return InitWithPrefix("gl", true);
+    if (!InitWithPrefix("gl", true))
+        return false;
+
+    return true;
 }
 
 bool
 GLContextWGL::MakeCurrentImpl() const
 {
-    if (IsDestroyed()) {
-        MOZ_ALWAYS_TRUE( sWGLLib.mSymbols.fMakeCurrent(0, 0) );
-        return false;
-    }
-
     const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext);
     NS_ASSERTION(succeeded, "Failed to make GL context current!");
     return succeeded;
 }
 
 bool
 GLContextWGL::IsCurrentImpl() const
 {