Backed out 4 changesets (bug 1399501) per developer's request for causing Bug 1502286 on Android,Bug 1502305 and Bug 1502292 a=backout
authorNoemi Erli <nerli@mozilla.com>
Fri, 26 Oct 2018 19:30:48 +0300
changeset 443133 28a4562cb5173c543cce6b58480ac80fcce3763a
parent 443132 a79126bab347bcb78193e156800178f9227ab294
child 443158 cffa05ba11d20f7ed3e3696f84ab5b47a59adba2
push id34941
push usernerli@mozilla.com
push dateFri, 26 Oct 2018 16:31:31 +0000
treeherdermozilla-central@28a4562cb517 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1399501, 1502286, 1502305, 1502292
milestone65.0a1
backs out7f1abf24702dc68a85b6d4fdaec4c741565ebfd5
5cb0aeccd4cc8d6417d9c92d04c2ee60ce244cbd
7b88a6284d31c87ee25d782d869c936cb0b7648d
c498bd18345d9061826a752b43d95a72e1593ceb
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1399501) per developer's request for causing Bug 1502286 on Android,Bug 1502305 and Bug 1502292 a=backout Backed out changeset 7f1abf24702d (bug 1399501) Backed out changeset 5cb0aeccd4cc (bug 1399501) Backed out changeset 7b88a6284d31 (bug 1399501) Backed out changeset c498bd18345d (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
@@ -11112,16 +11112,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
@@ -11407,17 +11408,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
@@ -11587,17 +11588,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,28 +153,29 @@ is_power_of_two(int v)
 
     if (v == 0)
         return true;
 
     return (v & (v-1)) == 0;
 }
 
 static void
-DestroySurface(const EGLSurface surf)
-{
-    if (!surf)
-        return;
+DestroySurface(EGLSurface oldSurface) {
+    auto* egl = gl::GLLibraryEGL::Get();
 
-    const 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!";
@@ -278,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);
@@ -320,19 +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);
-    DestroySurface(mSurface);
-    MOZ_ASSERT(!mFallbackSurface || mFallbackSurface != mSurface);
-    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
@@ -345,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);
 
@@ -396,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();
@@ -454,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);
 
@@ -477,23 +474,24 @@ GLContextEGL::RenewSurface(CompositorWid
             return false;
         }
     }
 
     return MakeCurrent(true);
 }
 
 void
-GLContextEGL::ReleaseSurface()
-{
-    if (!mOwnsContext)
-        return;
-
-    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
 {