Bug 1451183 - Add GLLibraryEGL::Shutdown() r=jgilbert
authorsotaro <sotaro.ikeda.g@gmail.com>
Mon, 04 Jun 2018 11:09:52 +0900
changeset 421006 886f2a6dc76dc0f1613fc30f2a3c566fbadcbf87
parent 421005 db10936e9f8dc579e104cc6ca8e718e7e8dd4499
child 421007 841c624e3dafeb64654b869f59797d462eb7aa80
push id103964
push usersikeda@mozilla.com
push dateMon, 04 Jun 2018 02:10:15 +0000
treeherdermozilla-inbound@886f2a6dc76d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1451183
milestone62.0a1
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
Bug 1451183 - Add GLLibraryEGL::Shutdown() r=jgilbert
gfx/gl/GLContextEGL.h
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLLibraryEGL.cpp
gfx/gl/GLLibraryEGL.h
gfx/ipc/GPUParent.cpp
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -98,29 +98,32 @@ public:
     EGLDisplay GetEGLDisplay() const {
         return GLLibraryEGL::Get()->Display();
     }
 
     bool BindTex2DOffscreen(GLContext* aOffscreen);
     void UnbindTex2DOffscreen(GLContext* aOffscreen);
     void BindOffscreenFramebuffer();
 
+    void Destroy();
+
     static already_AddRefed<GLContextEGL>
     CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
                                      const gfx::IntSize& size,
                                      const SurfaceCaps& minCaps,
                                      nsACString* const out_FailureId);
 
 protected:
     friend class GLContextProviderEGL;
     friend class GLContextEGLFactory;
 
 public:
     const EGLConfig mConfig;
 protected:
+    const RefPtr<GLLibraryEGL> mEgl;
     EGLSurface mSurface;
     const EGLSurface mFallbackSurface;
 public:
     const EGLContext mContext;
 protected:
     EGLSurface mSurfaceOverride;
     RefPtr<gfxASurface> mThebesSurface;
     bool mBound;
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -291,16 +291,17 @@ GLContextEGLFactory::Create(EGLNativeWin
     return gl.forget();
 }
 
 GLContextEGL::GLContextEGL(CreateContextFlags flags, const SurfaceCaps& caps,
                            bool isOffscreen, EGLConfig config, EGLSurface surface,
                            EGLContext context)
     : GLContext(flags, caps, nullptr, isOffscreen, false)
     , mConfig(config)
+    , mEgl(gl::GLLibraryEGL::Get())
     , mSurface(surface)
     , mFallbackSurface(CreateFallbackSurface(config))
     , mContext(context)
     , mSurfaceOverride(EGL_NO_SURFACE)
     , mThebesSurface(nullptr)
     , mBound(false)
     , mIsPBuffer(false)
     , mIsDoubleBuffered(false)
@@ -321,19 +322,17 @@ GLContextEGL::~GLContextEGL()
     if (!mOwnsContext) {
         return;
     }
 
 #ifdef DEBUG
     printf_stderr("Destroying context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
 
-    auto* egl = gl::GLLibraryEGL::Get();
-
-    egl->fDestroyContext(EGL_DISPLAY(), mContext);
+    mEgl->fDestroyContext(EGL_DISPLAY(), mContext);
 
     mozilla::gl::DestroySurface(mSurface);
     mozilla::gl::DestroySurface(mFallbackSurface);
 }
 
 bool
 GLContextEGL::Init()
 {
@@ -360,37 +359,33 @@ GLContextEGL::Init()
         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;
 
-    auto* egl = gl::GLLibraryEGL::Get();
-
-    mShareWithEGLImage = egl->HasKHRImageBase() &&
-                         egl->HasKHRImageTexture2D() &&
+    mShareWithEGLImage = mEgl->HasKHRImageBase() &&
+                         mEgl->HasKHRImageTexture2D() &&
                          IsExtensionSupported(OES_EGL_image);
 
     return true;
 }
 
 bool
 GLContextEGL::BindTexImage()
 {
     if (!mSurface)
         return false;
 
     if (mBound && !ReleaseTexImage())
         return false;
 
-    auto* egl = gl::GLLibraryEGL::Get();
-
-    EGLBoolean success = egl->fBindTexImage(EGL_DISPLAY(),
+    EGLBoolean success = mEgl->fBindTexImage(EGL_DISPLAY(),
         (EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
     if (success == LOCAL_EGL_FALSE)
         return false;
 
     mBound = true;
     return true;
 }
 
@@ -398,22 +393,20 @@ bool
 GLContextEGL::ReleaseTexImage()
 {
     if (!mBound)
         return true;
 
     if (!mSurface)
         return false;
 
-    auto* egl = gl::GLLibraryEGL::Get();
-
     EGLBoolean success;
-    success = egl->fReleaseTexImage(EGL_DISPLAY(),
-                                    (EGLSurface)mSurface,
-                                    LOCAL_EGL_BACK_BUFFER);
+    success = mEgl->fReleaseTexImage(EGL_DISPLAY(),
+                                     (EGLSurface)mSurface,
+                                     LOCAL_EGL_BACK_BUFFER);
     if (success == LOCAL_EGL_FALSE)
         return false;
 
     mBound = false;
     return true;
 }
 
 void
@@ -436,22 +429,20 @@ bool
 GLContextEGL::MakeCurrentImpl() const
 {
     EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride
                                                               : mSurface;
     if (!surface) {
         surface = mFallbackSurface;
     }
 
-    auto* egl = gl::GLLibraryEGL::Get();
-
-    const bool succeeded = egl->fMakeCurrent(EGL_DISPLAY(), surface, surface,
-                                             mContext);
+    const bool succeeded = mEgl->fMakeCurrent(EGL_DISPLAY(), surface, surface,
+                                              mContext);
     if (!succeeded) {
-        const auto eglError = egl->fGetError();
+        const auto eglError = mEgl->fGetError();
         if (eglError == LOCAL_EGL_CONTEXT_LOST) {
             mContextLost = true;
             NS_WARNING("EGL context has been lost.");
         } else {
             NS_WARNING("Failed to make GL context current!");
 #ifdef DEBUG
             printf_stderr("EGL Error: 0x%04x\n", eglError);
 #endif
@@ -459,18 +450,17 @@ GLContextEGL::MakeCurrentImpl() const
     }
 
     return succeeded;
 }
 
 bool
 GLContextEGL::IsCurrentImpl() const
 {
-    auto* egl = gl::GLLibraryEGL::Get();
-    return egl->fGetCurrentContext() == mContext;
+    return mEgl->fGetCurrentContext() == mContext;
 }
 
 bool
 GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
     if (!mOwnsContext) {
         return false;
     }
     // unconditionally release the surface and create a new one. Don't try to optimize this away.
@@ -499,53 +489,48 @@ GLContextEGL::ReleaseSurface() {
         mSurfaceOverride = EGL_NO_SURFACE;
     }
     mSurface = EGL_NO_SURFACE;
 }
 
 bool
 GLContextEGL::SetupLookupFunction()
 {
-    auto* egl = gl::GLLibraryEGL::Get();
-
-    mLookupFunc = egl->GetLookupFunction();
+    mLookupFunc = mEgl->GetLookupFunction();
     return true;
 }
 
 bool
 GLContextEGL::SwapBuffers()
 {
-    auto* egl = gl::GLLibraryEGL::Get();
     EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE
                           ? mSurfaceOverride
                           : mSurface;
     if (surface) {
-        return egl->fSwapBuffers(EGL_DISPLAY(), surface);
+        return mEgl->fSwapBuffers(EGL_DISPLAY(), surface);
     } else {
         return false;
     }
 }
 
 void
 GLContextEGL::GetWSIInfo(nsCString* const out) const
 {
-    auto* egl = gl::GLLibraryEGL::Get();
-
     out->AppendLiteral("EGL_VENDOR: ");
-    out->Append((const char*)egl->fQueryString(EGL_DISPLAY(), LOCAL_EGL_VENDOR));
+    out->Append((const char*)mEgl->fQueryString(EGL_DISPLAY(), LOCAL_EGL_VENDOR));
 
     out->AppendLiteral("\nEGL_VERSION: ");
-    out->Append((const char*)egl->fQueryString(EGL_DISPLAY(), LOCAL_EGL_VERSION));
+    out->Append((const char*)mEgl->fQueryString(EGL_DISPLAY(), LOCAL_EGL_VERSION));
 
     out->AppendLiteral("\nEGL_EXTENSIONS: ");
-    out->Append((const char*)egl->fQueryString(EGL_DISPLAY(), LOCAL_EGL_EXTENSIONS));
+    out->Append((const char*)mEgl->fQueryString(EGL_DISPLAY(), LOCAL_EGL_EXTENSIONS));
 
 #ifndef ANDROID // This query will crash some old android.
     out->AppendLiteral("\nEGL_EXTENSIONS(nullptr): ");
-    out->Append((const char*)egl->fQueryString(nullptr, LOCAL_EGL_EXTENSIONS));
+    out->Append((const char*)mEgl->fQueryString(nullptr, LOCAL_EGL_EXTENSIONS));
 #endif
 }
 
 // hold a reference to the given surface
 // for the lifetime of this context.
 void
 GLContextEGL::HoldSurface(gfxASurface* aSurf) {
     mThebesSurface = aSurf;
@@ -1206,14 +1191,18 @@ GLContextProviderEGL::CreateOffscreen(co
 GLContextProviderEGL::GetGlobalContext()
 {
     return nullptr;
 }
 
 /*static*/ void
 GLContextProviderEGL::Shutdown()
 {
+    const RefPtr<GLLibraryEGL> egl = GLLibraryEGL::Get();
+    if (egl) {
+        egl->Shutdown();
+    }
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
 
 #undef EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -371,16 +371,22 @@ GLLibraryEGL::EnsureInitialized(bool for
         sEGLLibrary = new GLLibraryEGL();
     }
     return sEGLLibrary->DoEnsureInitialized(forceAccel, out_failureId);
 }
 
 bool
 GLLibraryEGL::DoEnsureInitialized(bool forceAccel, nsACString* const out_failureId)
 {
+    if (mInitialized && !mSymbols.fTerminate) {
+        *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_DESTROYED");
+        MOZ_ASSERT(false);
+        return false;
+    }
+
     if (mInitialized) {
         return true;
     }
 
     mozilla::ScopedGfxFeatureReporter reporter("EGL");
 
 #ifdef XP_WIN
     if (!mEGLLibrary) {
@@ -675,16 +681,30 @@ GLLibraryEGL::DoEnsureInitialized(bool f
     mInitialized = true;
     reporter.SetSuccessful();
     return true;
 }
 
 #undef SYMBOL
 #undef END_OF_SYMBOLS
 
+void
+GLLibraryEGL::Shutdown()
+{
+    if (this != sEGLLibrary) {
+        return;
+    }
+    if (mEGLDisplay) {
+        fTerminate(mEGLDisplay);
+        mEGLDisplay = EGL_NO_DISPLAY;
+    }
+    mSymbols = {};
+    sEGLLibrary = nullptr;
+}
+
 EGLDisplay
 GLLibraryEGL::CreateDisplay(bool forceAccel, const nsCOMPtr<nsIGfxInfo>& gfxInfo, nsACString* const out_failureId)
 {
     MOZ_ASSERT(!mInitialized);
 
     EGLDisplay chosenDisplay = nullptr;
 
     if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -372,16 +372,18 @@ public:
     bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);
 
     inline static GLLibraryEGL* Get() {
         return sEGLLibrary;
     }
 
     static bool EnsureInitialized(bool forceAccel, nsACString* const out_failureId);
 
+    void Shutdown();
+
     void DumpEGLConfig(EGLConfig cfg);
     void DumpEGLConfigs();
 
 private:
     struct {
         EGLCastToRelevantPtr (GLAPIENTRY * fGetProcAddress)(const char* procname);
         EGLDisplay (GLAPIENTRY * fGetDisplay)(void* display_id);
         EGLDisplay (GLAPIENTRY * fGetPlatformDisplayEXT)(EGLenum platform,
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -6,16 +6,17 @@
 #ifdef XP_WIN
 #include "WMF.h"
 #endif
 #include "GPUParent.h"
 #include "gfxConfig.h"
 #include "gfxCrashReporterUtils.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
+#include "GLContextProvider.h"
 #include "GPUProcessHost.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/VideoDecoderManagerChild.h"
 #include "mozilla/dom/VideoDecoderManagerParent.h"
 #include "mozilla/gfx/2D.h"
@@ -493,16 +494,30 @@ GPUParent::ActorDestroy(ActorDestroyReas
   dom::VideoDecoderManagerParent::ShutdownVideoBridge();
   CompositorThreadHolder::Shutdown();
   VRListenerThreadHolder::Shutdown();
   // There is a case that RenderThread exists when gfxVars::UseWebRender() is false.
   // This could happen when WebRender was fallbacked to compositor.
   if (wr::RenderThread::Get()) {
     wr::RenderThread::ShutDown();
   }
+
+  // Shut down the default GL context provider.
+  gl::GLContextProvider::Shutdown();
+
+#if defined(XP_WIN)
+  // The above shutdown calls operate on the available context providers on
+  // most platforms.  Windows is a "special snowflake", though, and has three
+  // context providers available, so we have to shut all of them down.
+  // We should only support the default GL provider on Windows; then, this
+  // could go away. Unfortunately, we currently support WGL (the default) for
+  // WebGL on Optimus.
+  gl::GLContextProviderEGL::Shutdown();
+#endif
+
   Factory::ShutDown();
 #if defined(XP_WIN)
   DeviceManagerDx::Shutdown();
 #endif
   LayerTreeOwnerTracker::Shutdown();
   gfxVars::Shutdown();
   gfxConfig::Shutdown();
   gfxPrefs::DestroySingleton();