Bug 1524554: Ensure Canvas surfaces are initialized on the main thread and ensure their validity. r=rhunt a=lizzard DEVEDITION_66_0b5_BUILD1 DEVEDITION_66_0b5_RELEASE FENNEC_66_0b5_BUILD1 FENNEC_66_0b5_RELEASE FIREFOX_66_0b5_BUILD1 FIREFOX_66_0b5_RELEASE
authorBas Schouten <bschouten@mozilla.com>
Fri, 01 Feb 2019 13:18:55 +0100
changeset 515726 02146faf5ac13099a1e6a9d2ef1251f8b6bda0f3
parent 515725 9ab060b915fbe70bdf85fd48d783d80cc76b189c
child 515727 bdc2e1fdc63d96fdb1e4e6c9fb4e8df0b3cc75db
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)
reviewersrhunt, lizzard
bugs1524554
milestone66.0
Bug 1524554: Ensure Canvas surfaces are initialized on the main thread and ensure their validity. r=rhunt a=lizzard This isn't the prettiest solution but it's minimally invasive. More long-term a better solution may be to expose a call on DrawTargets to ensure their initialization even if they're on the main thread. IsValid probably isn't a good candidate for this as we want it to be usable freely on the main thread to ensure none of the basic conditions of the surface are still valid. Differential Revision: https://phabricator.services.mozilla.com/D18339
gfx/2d/DrawTargetD2D1.cpp
gfx/layers/PersistentBufferProvider.cpp
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -339,16 +339,22 @@ void DrawTargetD2D1::DrawSurfaceWithShad
                    D2DCompositionMode(aOperator));
   }
 }
 
 void DrawTargetD2D1::ClearRect(const Rect &aRect) {
   if (!EnsureInitialized()) {
     return;
   }
+
+  if (aRect.IsEmpty()) {
+    // Nothing to be done.
+    return;
+  }
+
   MarkChanged();
 
   PopAllClips();
 
   PushClipRect(aRect);
 
   if (mTransformDirty || !mTransform.IsIdentity()) {
     mDC->SetTransform(D2D1::IdentityMatrix());
--- a/gfx/layers/PersistentBufferProvider.cpp
+++ b/gfx/layers/PersistentBufferProvider.cpp
@@ -72,17 +72,23 @@ void PersistentBufferProviderBasic::Dest
 already_AddRefed<PersistentBufferProviderBasic>
 PersistentBufferProviderBasic::Create(gfx::IntSize aSize,
                                       gfx::SurfaceFormat aFormat,
                                       gfx::BackendType aBackend) {
   RefPtr<DrawTarget> dt =
       gfxPlatform::GetPlatform()->CreateDrawTargetForBackend(aBackend, aSize,
                                                              aFormat);
 
-  if (!dt) {
+  if (dt) {
+    // This is simply to ensure the DrawTarget gets initialized, and will detect a
+    // device reset, even if we're on the main thread.
+    dt->ClearRect(Rect(0, 0, 0, 0));
+  }
+
+  if (!dt || !dt->IsValid()) {
     return nullptr;
   }
 
   RefPtr<PersistentBufferProviderBasic> provider =
       new PersistentBufferProviderBasic(dt);
 
   return provider.forget();
 }
@@ -334,16 +340,26 @@ PersistentBufferProviderShared::BorrowDr
       MOZ_ASSERT(success);
 
       previous->Unlock();
     }
   }
 
   mDrawTarget = tex->BorrowDrawTarget();
 
+  if (mDrawTarget) {
+    // This is simply to ensure the DrawTarget gets initialized, and will detect a
+    // device reset, even if we're on the main thread.
+    mDrawTarget->ClearRect(Rect(0, 0, 0, 0));
+
+    if (!mDrawTarget->IsValid()) {
+      mDrawTarget = nullptr;
+    }
+  }
+
   RefPtr<gfx::DrawTarget> dt(mDrawTarget);
   return dt.forget();
 }
 
 bool PersistentBufferProviderShared::ReturnDrawTarget(
     already_AddRefed<gfx::DrawTarget> aDT) {
   RefPtr<gfx::DrawTarget> dt(aDT);
   MOZ_ASSERT(mDrawTarget == dt);