Bug 1506665 - Add more GLContext failure handling r=jgilbert a=RyanVM
authorsotaro <sotaro.ikeda.g@gmail.com>
Tue, 05 Mar 2019 17:49:33 +0100
changeset 516262 5a5a5edabc607ac53989adc80b350d9ee31bb591
parent 516261 acc4347ff88fd4ecbe67db744104a380c8e2e00f
child 516263 11e2231bb8196868a5cf546fefd1f5e209d0b7dc
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert, RyanVM
bugs1506665
milestone66.0
Bug 1506665 - Add more GLContext failure handling r=jgilbert a=RyanVM
dom/canvas/WebGLContext.cpp
gfx/layers/CanvasRenderer.cpp
gfx/layers/CanvasRenderer.h
gfx/layers/CopyableCanvasRenderer.cpp
gfx/layers/client/CanvasClient.cpp
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1133,16 +1133,21 @@ already_AddRefed<layers::Layer> WebGLCon
     userData = new WebGLContextUserData(mCanvasElement);
   }
 
   canvasLayer->SetUserData(&gWebGLLayerUserData, userData);
 
   CanvasRenderer* canvasRenderer = canvasLayer->CreateOrGetCanvasRenderer();
   if (!InitializeCanvasRenderer(builder, canvasRenderer)) return nullptr;
 
+  if (!gl) {
+    NS_WARNING("GLContext is null!");
+    return nullptr;
+  }
+
   uint32_t flags = gl->Caps().alpha ? 0 : Layer::CONTENT_OPAQUE;
   canvasLayer->SetContentFlags(flags);
 
   mResetLayer = false;
 
   return canvasLayer.forget();
 }
 
@@ -1186,20 +1191,20 @@ bool WebGLContext::InitializeCanvasRende
     // The userData will receive DidTransactionCallbacks, which flush the
     // the invalidation state to indicate that the canvas is up to date.
     data.mPreTransCallback = WebGLContextUserData::PreTransactionCallback;
     data.mPreTransCallbackData = this;
     data.mDidTransCallback = WebGLContextUserData::DidTransactionCallback;
     data.mDidTransCallbackData = this;
   }
 
-  data.mGLContext = gl;
   data.mSize = DrawingBufferSize();
   data.mHasAlpha = mOptions.alpha;
   data.mIsGLAlphaPremult = IsPremultAlpha() || !data.mHasAlpha;
+  data.mGLContext = gl;
 
   aRenderer->Initialize(data);
   aRenderer->SetDirty();
   mVRReady = true;
   return true;
 }
 
 layers::LayersBackend WebGLContext::GetCompositorBackendType() const {
--- a/gfx/layers/CanvasRenderer.cpp
+++ b/gfx/layers/CanvasRenderer.cpp
@@ -4,16 +4,19 @@
  * 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 "CanvasRenderer.h"
 
 namespace mozilla {
 namespace layers {
 
+CanvasInitializeData::CanvasInitializeData() = default;
+CanvasInitializeData::~CanvasInitializeData() = default;
+
 CanvasRenderer::CanvasRenderer()
     : mPreTransCallback(nullptr),
       mPreTransCallbackData(nullptr),
       mDidTransCallback(nullptr),
       mDidTransCallbackData(nullptr),
       mDirty(false) {
   MOZ_COUNT_CTOR(CanvasRenderer);
 }
--- a/gfx/layers/CanvasRenderer.h
+++ b/gfx/layers/CanvasRenderer.h
@@ -23,53 +23,43 @@ namespace mozilla {
 namespace layers {
 
 class AsyncCanvasRenderer;
 class ClientCanvasRenderer;
 class CopyableCanvasRenderer;
 class PersistentBufferProvider;
 class WebRenderCanvasRendererAsync;
 
-struct CanvasInitializeData {
-  CanvasInitializeData()
-      : mBufferProvider(nullptr),
-        mGLContext(nullptr),
-        mRenderer(nullptr),
-        mPreTransCallback(nullptr),
-        mPreTransCallbackData(nullptr),
-        mDidTransCallback(nullptr),
-        mDidTransCallbackData(nullptr),
-        mFrontbufferGLTex(0),
-        mSize(0, 0),
-        mHasAlpha(false),
-        mIsGLAlphaPremult(true) {}
+struct CanvasInitializeData final {
+  CanvasInitializeData();
+  ~CanvasInitializeData();
 
   // One of these three must be specified for Canvas2D, but never more than one
-  PersistentBufferProvider*
+  RefPtr<PersistentBufferProvider>
       mBufferProvider;  // A BufferProvider for the Canvas contents
-  mozilla::gl::GLContext* mGLContext;  // or this, for GL.
-  AsyncCanvasRenderer* mRenderer;      // or this, for OffscreenCanvas
+  RefPtr<mozilla::gl::GLContext> mGLContext;  // or this, for GL.
+  RefPtr<AsyncCanvasRenderer> mRenderer;      // or this, for OffscreenCanvas
 
   typedef void (*TransactionCallback)(void* closureData);
-  TransactionCallback mPreTransCallback;
-  void* mPreTransCallbackData;
-  TransactionCallback mDidTransCallback;
-  void* mDidTransCallbackData;
+  TransactionCallback mPreTransCallback = nullptr;
+  void* mPreTransCallbackData = nullptr;
+  TransactionCallback mDidTransCallback = nullptr;
+  void* mDidTransCallbackData = nullptr;
 
   // Frontbuffer override
-  uint32_t mFrontbufferGLTex;
+  uint32_t mFrontbufferGLTex = 0;
 
   // The size of the canvas content
-  gfx::IntSize mSize;
+  gfx::IntSize mSize = {0,0};
 
   // Whether the canvas drawingbuffer has an alpha channel.
-  bool mHasAlpha;
+  bool mHasAlpha = false;
 
   // Whether mGLContext contains data that is alpha-premultiplied.
-  bool mIsGLAlphaPremult;
+  bool mIsGLAlphaPremult = true;
 };
 
 // Based class which used for canvas rendering. There are many derived classes
 // for different purposes. such as:
 //
 // CopyableCanvasRenderer provides a utility which readback canvas content to a
 // SourceSurface. BasicCanvasLayer uses CopyableCanvasRenderer.
 //
--- a/gfx/layers/CopyableCanvasRenderer.cpp
+++ b/gfx/layers/CopyableCanvasRenderer.cpp
@@ -49,16 +49,19 @@ CopyableCanvasRenderer::~CopyableCanvasR
   Destroy();
   MOZ_COUNT_DTOR(CopyableCanvasRenderer);
 }
 
 void CopyableCanvasRenderer::Initialize(const CanvasInitializeData& aData) {
   CanvasRenderer::Initialize(aData);
 
   if (aData.mGLContext) {
+    if (aData.mGLContext->IsDestroyed()) {
+      return;
+    }
     mGLContext = aData.mGLContext;
     mIsAlphaPremultiplied = aData.mIsGLAlphaPremult;
     mOriginPos = gl::OriginPos::BottomLeft;
 
     MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
 
     if (aData.mFrontbufferGLTex) {
       gfx::IntSize size(aData.mSize.width, aData.mSize.height);
@@ -66,20 +69,16 @@ void CopyableCanvasRenderer::Initialize(
           aData.mGLContext, size, aData.mHasAlpha, aData.mFrontbufferGLTex);
       mBufferProvider = aData.mBufferProvider;
     }
   } else if (aData.mBufferProvider) {
     mBufferProvider = aData.mBufferProvider;
   } else if (aData.mRenderer) {
     mAsyncRenderer = aData.mRenderer;
     mOriginPos = gl::OriginPos::BottomLeft;
-  } else {
-    MOZ_CRASH(
-        "GFX: CanvasRenderer created without BufferProvider, DrawTarget or "
-        "GLContext?");
   }
 
   mOpaque = !aData.mHasAlpha;
 }
 
 bool CopyableCanvasRenderer::IsDataValid(const CanvasInitializeData& aData) {
   return mGLContext == aData.mGLContext &&
          mBufferProvider == aData.mBufferProvider;
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -289,18 +289,20 @@ static already_AddRefed<TextureClient> T
     } else if (readFormat == LOCAL_GL_RGBA &&
                readType == LOCAL_GL_UNSIGNED_BYTE) {
       // [RR, GG, BB, AA]
       texClient = factory.CreateR8G8B8AX8();
     } else {
       MOZ_CRASH("GFX: Bad `read{Format,Type}`.");
     }
 
-    MOZ_ASSERT(texClient);
-    if (!texClient) return nullptr;
+    if (!texClient) {
+      gfxWarning() << "Couldn't create texClient for readback.";
+      return nullptr;
+    }
 
     // With a texClient, we can lock for writing.
     TextureClientAutoLock autoLock(texClient, OpenMode::OPEN_WRITE);
     DebugOnly<bool> succeeded = autoLock.Succeeded();
     MOZ_ASSERT(succeeded, "texture should have locked");
 
     MappedTextureData mapped;
     texClient->BorrowMappedData(mapped);
@@ -456,20 +458,19 @@ void CanvasClientSharedSurface::UpdateRe
     //
     // Otherwise, if surface type isn't Basic, we will read from
     // SharedSurface directly from main-thread. We still pass
     // mReadbackClient which is nullptr here to tell
     // AsyncCanvasRenderer reset some properties.
     asyncRenderer->CopyFromTextureClient(mReadbackClient);
   }
 
-  MOZ_ASSERT(newFront);
   if (!newFront) {
     // May happen in a release build in case of memory pressure.
-    gfxCriticalError()
+    gfxWarning()
         << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: "
         << aSize;
     return;
   }
 
   mNewFront = newFront;
 }