Bug 1386965 - Support async painting component-alpha layers. r=dvander
authorMason Chang <mchang@mozilla.com>
Wed, 09 Aug 2017 09:39:07 -0700
changeset 643359 b72ee82614a903048578b1e4d4535ad1820aa896
parent 643358 f2f297d544fff3de5778d12f2b099e740e44dc36
child 643360 7deb1f1572f961432b9836333298a2cde431c226
child 643369 1de7f5d2deccc57ac8f8f4eb4c92baa92823c123
push id73068
push usergpascutto@mozilla.com
push dateWed, 09 Aug 2017 16:52:24 +0000
reviewersdvander
bugs1386965
milestone57.0a1
Bug 1386965 - Support async painting component-alpha layers. r=dvander
gfx/layers/RotatedBuffer.cpp
gfx/layers/RotatedBuffer.h
gfx/layers/client/ClientPaintedLayer.cpp
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -309,16 +309,17 @@ RotatedContentBuffer::BorrowDrawTargetFo
                                         -quadrantRect.y);
 
   if (aSetTransform) {
     mLoanedDrawTarget->SetTransform(transform);
   } else {
     MOZ_ASSERT(aOutMatrix);
     *aOutMatrix = transform;
   }
+
   return mLoanedDrawTarget;
 }
 
 void
 BorrowDrawTarget::ReturnDrawTarget(gfx::DrawTarget*& aReturned)
 {
   MOZ_ASSERT(mLoanedDrawTarget);
   MOZ_ASSERT(aReturned == mLoanedDrawTarget);
@@ -746,36 +747,39 @@ RotatedContentBuffer::BorrowDrawTargetFo
 {
   if (aPaintState.mMode == SurfaceMode::SURFACE_NONE) {
     return nullptr;
   }
 
   Matrix transform;
   DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(aPaintState.mRegionToDraw.GetBounds(),
                                                          BUFFER_BOTH, aIter,
-                                                         false, &transform);
+                                                         false,
+                                                         &transform);
   if (!result) {
     return nullptr;
   }
 
-  ExpandDrawRegion(aPaintState, aIter, result->GetBackendType());
+  nsIntRegion regionToDraw =
+    ExpandDrawRegion(aPaintState, aIter, result->GetBackendType());
 
   RefPtr<CapturedPaintState> state =
-    new CapturedPaintState(aPaintState.mRegionToDraw,
+    new CapturedPaintState(regionToDraw,
                            result,
-                           nullptr, /* aTargetOnWhite */
+                           mDTBufferOnWhite,
                            transform,
                            aPaintState.mMode,
                            aPaintState.mContentType);
   return state;
 }
 
 /*static */ bool
 RotatedContentBuffer::PrepareDrawTargetForPainting(CapturedPaintState* aState)
 {
+  MOZ_ASSERT(aState);
   RefPtr<DrawTarget> target = aState->mTarget;
   RefPtr<DrawTarget> whiteTarget = aState->mTargetOnWhite;
 
   if (aState->mSurfaceMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
     if (!target || !target->IsValid() ||
         !whiteTarget || !whiteTarget->IsValid()) {
       // This can happen in release builds if allocating one of the two buffers
       // failed. This in turn can happen if unreasonably large textures are
@@ -796,17 +800,17 @@ RotatedContentBuffer::PrepareDrawTargetF
       const IntRect& rect = iter.Get();
       target->ClearRect(Rect(rect.x, rect.y, rect.width, rect.height));
     }
   }
 
   return true;
 }
 
-void
+nsIntRegion
 RotatedContentBuffer::ExpandDrawRegion(PaintState& aPaintState,
                                        DrawIterator* aIter,
                                        BackendType aBackendType)
 {
   nsIntRegion* drawPtr = &aPaintState.mRegionToDraw;
   if (aIter) {
     // The iterators draw region currently only contains the bounds of the region,
     // this makes it the precise region.
@@ -814,51 +818,39 @@ RotatedContentBuffer::ExpandDrawRegion(P
     drawPtr = &aIter->mDrawRegion;
   }
   if (aBackendType == BackendType::DIRECT2D ||
       aBackendType == BackendType::DIRECT2D1_1) {
     // Simplify the draw region to avoid hitting expensive drawing paths
     // for complex regions.
     drawPtr->SimplifyOutwardByArea(100 * 100);
   }
+  return *drawPtr;
 }
 
 DrawTarget*
 RotatedContentBuffer::BorrowDrawTargetForPainting(PaintState& aPaintState,
                                                   DrawIterator* aIter /* = nullptr */)
 {
-  if (aPaintState.mMode == SurfaceMode::SURFACE_NONE) {
-    return nullptr;
-  }
+  RefPtr<CapturedPaintState> capturedState =
+    BorrowDrawTargetForRecording(aPaintState, aIter);
 
-  DrawTarget* result = BorrowDrawTargetForQuadrantUpdate(aPaintState.mRegionToDraw.GetBounds(),
-                                                         BUFFER_BOTH, aIter);
-  if (!result) {
+  if (!capturedState) {
     return nullptr;
   }
 
-  ExpandDrawRegion(aPaintState, aIter, result->GetBackendType());
-
-  nsIntRegion regionToDraw = aIter ? aIter->mDrawRegion
-                                   : aPaintState.mRegionToDraw;
+  // BorrowDrawTargetForRecording doesn't apply the transform, so we have to.
+  RefPtr<DrawTarget> target = capturedState->mTarget;
+  target->SetTransform(capturedState->mTargetTransform);
 
-  // Can't stack allocate refcounted objects.
-  RefPtr<CapturedPaintState> capturedPaintState =
-    MakeAndAddRef<CapturedPaintState>(regionToDraw,
-                                      mDTBuffer,
-                                      mDTBufferOnWhite,
-                                      Matrix(),
-                                      aPaintState.mMode,
-                                      aPaintState.mContentType);
-
-  if (!RotatedContentBuffer::PrepareDrawTargetForPainting(capturedPaintState)) {
+  if (!RotatedContentBuffer::PrepareDrawTargetForPainting(capturedState)) {
     return nullptr;
   }
 
-  return result;
+  return target;
 }
 
 already_AddRefed<SourceSurface>
 RotatedContentBuffer::GetSourceSurface(ContextSource aSource) const
 {
   if (!mDTBuffer || !mDTBuffer->IsValid()) {
     gfxCriticalNote << "Invalid buffer in RotatedContentBuffer::GetSourceSurface " << gfx::hexa(mDTBuffer);
     return nullptr;
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -300,19 +300,19 @@ public:
   /**
    * Borrow a draw target for recording. The aOutTransform is not applied
    * to the returned DrawTarget, BUT it is required to be painting in the right
    * location whenever drawing does happen.
    */
   RefPtr<CapturedPaintState> BorrowDrawTargetForRecording(PaintState& aPaintState,
                                                           DrawIterator* aIter);
 
-  void ExpandDrawRegion(PaintState& aPaintState,
-                        DrawIterator* aIter,
-                        gfx::BackendType aBackendType);
+  nsIntRegion ExpandDrawRegion(PaintState& aPaintState,
+                               DrawIterator* aIter,
+                               gfx::BackendType aBackendType);
 
   static bool PrepareDrawTargetForPainting(CapturedPaintState*);
   enum {
     BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
                                   // component alpha.
   };
   /**
    * Return a new surface of |aSize| and |aType|.
--- a/gfx/layers/client/ClientPaintedLayer.cpp
+++ b/gfx/layers/client/ClientPaintedLayer.cpp
@@ -66,22 +66,16 @@ ClientPaintedLayer::CanRecordLayer(Readb
   }
 
   // If we have mask layers, we have to render those first
   // In this case, don't record for now.
   if (GetMaskLayer()) {
     return false;
   }
 
-  // Component alpha layers aren't supported yet since we have to
-  // hold onto both the front/back buffer of a texture client.
-  if (GetSurfaceMode() == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
-    return false;
-  }
-
   return GetAncestorMaskLayerCount() == 0;
 }
 
 void
 ClientPaintedLayer::UpdateContentClient(PaintState& aState)
 {
   Mutated();