Bug 1576499 - Move back buffer creation out of CreateRenderTargetForWindow into BeginFrame. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Tue, 27 Aug 2019 08:20:49 +0000
changeset 554277 8db81887ada851bf02ec21043f62d8707e5ac472
parent 554276 4c4cf1a9bd7a6ad2b1205cb6d752453bcbfb34c8
child 554278 4bba5287a59d59c915c02165ed025194ea731dcf
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1576499
milestone70.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 1576499 - Move back buffer creation out of CreateRenderTargetForWindow into BeginFrame. r=mattwoodrow This makes it clear that only one of the possible call paths of CreateRenderTargetForWindow can use a back buffer. It causes some unfortunate duplication of the clear region computation. Differential Revision: https://phabricator.services.mozilla.com/D43380
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/basic/BasicCompositor.h
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -291,45 +291,25 @@ already_AddRefed<CompositingRenderTarget
 BasicCompositor::CreateRenderTargetFromSource(
     const IntRect& aRect, const CompositingRenderTarget* aSource,
     const IntPoint& aSourcePoint) {
   MOZ_CRASH("GFX: Shouldn't be called!");
   return nullptr;
 }
 
 already_AddRefed<CompositingRenderTarget>
-BasicCompositor::CreateRenderTargetForWindow(const IntRect& aRect,
-                                             const IntRegion& aClearRegion,
-                                             BufferMode aBufferMode) {
-  MOZ_ASSERT(mDrawTarget);
-  MOZ_ASSERT(!aRect.IsZeroArea(),
-             "Trying to create a render target of invalid size");
-
-  if (aRect.IsZeroArea()) {
-    return nullptr;
-  }
-
-  RefPtr<BasicCompositingRenderTarget> rt;
-
-  bool isCleared = false;
-  if (aBufferMode != BufferMode::BUFFER_NONE) {
-    RefPtr<DrawTarget> target =
-        mWidget->GetBackBufferDrawTarget(mDrawTarget, aRect, &isCleared);
-    if (!target) {
-      return nullptr;
-    }
-    MOZ_ASSERT(target != mDrawTarget);
-    rt = new BasicCompositingRenderTarget(target, aRect);
-  } else {
-    rt = new BasicCompositingRenderTarget(mDrawTarget, mDrawTargetBounds);
-  }
+BasicCompositor::CreateRenderTargetAndClear(DrawTarget* aDrawTarget,
+                                            const IntRect& aDrawTargetRect,
+                                            const IntRegion& aClearRegion) {
+  RefPtr<BasicCompositingRenderTarget> rt =
+      new BasicCompositingRenderTarget(aDrawTarget, aDrawTargetRect);
 
   rt->mDrawTarget->SetTransform(Matrix::Translation(-rt->GetOrigin()));
 
-  if (!aClearRegion.IsEmpty() && !isCleared) {
+  if (!aClearRegion.IsEmpty()) {
     gfx::IntRect clearRect = aClearRegion.GetBounds();
     gfxUtils::ClipToRegion(rt->mDrawTarget, aClearRegion);
     rt->mDrawTarget->ClearRect(gfx::Rect(clearRect));
     rt->mDrawTarget->PopClip();
   }
 
   return rt.forget();
 }
@@ -907,26 +887,30 @@ Maybe<gfx::IntRect> BasicCompositor::Beg
     // Sometimes the invalid region is larger than we want to draw.
     invalidRegionSafe.And(aInvalidRegion, rect);
 
     mInvalidRegion = invalidRegionSafe;
   }
 
   mInvalidRect = mInvalidRegion.GetBounds();
 
-  BufferMode bufferMode = BufferMode::BUFFERED;
+  RefPtr<CompositingRenderTarget> target;
   if (mTarget) {
     MOZ_RELEASE_ASSERT(!mInvalidRect.IsEmpty());
 
     // If we have a copy target, render into that DrawTarget directly without
     // any intermediate buffer. We don't need to call StartRemoteDrawingInRegion
     // because we don't need a widget-provided DrawTarget.
     mDrawTarget = mTarget;
     mDrawTargetBounds = mTargetBounds;
-    bufferMode = BufferMode::BUFFER_NONE;
+    IntRegion clearRegion;
+    clearRegion.Sub(mInvalidRegion, aOpaqueRegion);
+    // Set up a render target for drawing directly to mDrawTarget.
+    target =
+        CreateRenderTargetAndClear(mDrawTarget, mDrawTargetBounds, clearRegion);
   } else if (aNativeLayer) {
 #ifdef XP_MACOSX
     if (mInvalidRect.IsEmpty()) {
       return Nothing();
     }
     NativeLayerCA* nativeLayer = aNativeLayer->AsNativeLayerCA();
     MOZ_RELEASE_ASSERT(nativeLayer, "Unexpected native layer type");
     nativeLayer->SetSurfaceIsFlipped(false);
@@ -938,68 +922,80 @@ Maybe<gfx::IntRect> BasicCompositor::Beg
     mInvalidRegion = nativeLayer->CurrentSurfaceInvalidRegion();
     mInvalidRect = mInvalidRegion.GetBounds();
     MOZ_RELEASE_ASSERT(!mInvalidRect.IsEmpty());
     mCurrentNativeLayer = aNativeLayer;
     mCurrentIOSurface = new MacIOSurface(std::move(surf));
     mCurrentIOSurface->Lock(false);
     mDrawTarget = mCurrentIOSurface->GetAsDrawTargetLocked(BackendType::SKIA);
     mDrawTargetBounds = IntRect(IntPoint(0, 0), mDrawTarget->GetSize());
-    bufferMode = BufferMode::BUFFER_NONE;
+    IntRegion clearRegion;
+    clearRegion.Sub(mInvalidRegion, aOpaqueRegion);
+    // Set up a render target for drawing directly to mDrawTarget.
+    target =
+        CreateRenderTargetAndClear(mDrawTarget, mDrawTargetBounds, clearRegion);
 #else
     MOZ_CRASH("Unexpected native layer on this platform");
 #endif
   } else {
     LayoutDeviceIntRegion invalidRegion =
         LayoutDeviceIntRegion::FromUnknownRegion(mInvalidRegion);
+    BufferMode bufferMode = BufferMode::BUFFERED;
     mDrawTarget =
         mWidget->StartRemoteDrawingInRegion(invalidRegion, &bufferMode);
     if (!mDrawTarget) {
       return Nothing();
     }
     mInvalidRegion = invalidRegion.ToUnknownRegion();
     mInvalidRect = mInvalidRegion.GetBounds();
     if (mInvalidRect.IsEmpty()) {
       mWidget->EndRemoteDrawingInRegion(mDrawTarget, invalidRegion);
       return Nothing();
     }
 
-    // The DrawTarget returned by StartRemoteDrawingInRegion can cover different
-    // rectangles in window space. It can either cover the entire window, or it
-    // can cover just the invalid region. We discern between the two cases by
-    // comparing the DrawTarget's size with the invalild region's size.
-    IntSize dtSize = mDrawTarget->GetSize();
-    if (bufferMode == BufferMode::BUFFER_NONE &&
-        dtSize == mInvalidRect.Size()) {
-      mDrawTargetBounds = mInvalidRect;
+    IntRegion clearRegion;
+    clearRegion.Sub(mInvalidRegion, aOpaqueRegion);
+
+    if (bufferMode == BufferMode::BUFFERED) {
+      // Buffer drawing via a back buffer.
+      bool isCleared = false;
+      RefPtr<DrawTarget> backBuffer = mWidget->GetBackBufferDrawTarget(
+          mDrawTarget, mInvalidRect, &isCleared);
+      if (!backBuffer) {
+        mWidget->EndRemoteDrawingInRegion(mDrawTarget, invalidRegion);
+        return Nothing();
+      }
+      // When using a back buffer, the final destination DrawTarget  is always
+      // located at 0,0. It covers the entire window, not just the invalid
+      // region. And the back buffer only covers mInvalidRect.
+      mDrawTargetBounds = IntRect(IntPoint(0, 0), mDrawTarget->GetSize());
+      target = CreateRenderTargetAndClear(
+          backBuffer, mInvalidRect, isCleared ? IntRegion() : clearRegion);
+      // We will copy the drawing from the back buffer into mDrawTarget (the
+      // widget) in TryToEndRemoteDrawing().
     } else {
-      mDrawTargetBounds = IntRect(IntPoint(0, 0), dtSize);
+      // In BufferMode::BUFFER_NONE, the DrawTarget returned by
+      // StartRemoteDrawingInRegion can cover different rectangles in window
+      // space. It can either cover the entire window, or it can cover just the
+      // invalid region. We discern between the two cases by comparing the
+      // DrawTarget's size with the invalild region's size.
+      IntSize dtSize = mDrawTarget->GetSize();
+      if (dtSize == mInvalidRect.Size()) {
+        mDrawTargetBounds = mInvalidRect;
+      } else {
+        mDrawTargetBounds = IntRect(IntPoint(0, 0), dtSize);
+      }
+
+      // Set up a render target for drawing directly to mDrawTarget.
+      target = CreateRenderTargetAndClear(mDrawTarget, mDrawTargetBounds,
+                                          clearRegion);
     }
   }
 
-  IntRegion clearRegion = mInvalidRegion;
-  if (!aOpaqueRegion.IsEmpty()) {
-    clearRegion.SubOut(aOpaqueRegion);
-  }
-
-  // Setup a render target for drawing. In cases where we need to buffer all
-  // compositing (bufferMode == BufferMode::BUFFERED), this will set up the back
-  // buffer. We will copy the drawing into mDrawTarget (the widget) in
-  // EndRemoteDrawing().
-  RefPtr<CompositingRenderTarget> target =
-      CreateRenderTargetForWindow(mInvalidRect, clearRegion, bufferMode);
-
-  if (!target) {
-    if (!mTarget && !aNativeLayer) {
-      mWidget->EndRemoteDrawingInRegion(
-          mDrawTarget,
-          LayoutDeviceIntRegion::FromUnknownRegion(mInvalidRegion));
-    }
-    return Nothing();
-  }
+  MOZ_RELEASE_ASSERT(target);
   SetRenderTarget(target);
 
   gfxUtils::ClipToRegion(mRenderTarget->mDrawTarget,
                          mInvalidRegion.ToUnknownRegion());
 
   mRenderTarget->mDrawTarget->PushClipRect(Rect(aClipRect.valueOr(rect)));
 
   return Some(rect);
@@ -1019,17 +1015,17 @@ void BasicCompositor::EndFrame() {
     mRenderTarget->mDrawTarget->FillRect(
         IntRectToRect(mInvalidRegion.GetBounds()).ToUnknownRect(),
         ColorPattern(Color(r, g, b, 0.2f)));
   }
 
   // Pop aInvalidregion
   mRenderTarget->mDrawTarget->PopClip();
 
-  // Reset the translation that was applied in CreateRenderTargetForWindow.
+  // Reset the translation that was applied in CreateRenderTargetAndClear.
   mRenderTarget->mDrawTarget->SetTransform(gfx::Matrix());
 
   if (mTarget) {
     mDrawTarget = nullptr;
     mRenderTarget = nullptr;
   } else if (mCurrentNativeLayer) {
 #ifdef XP_MACOSX
     NativeLayerCA* nativeLayer = mCurrentNativeLayer->AsNativeLayerCA();
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -62,19 +62,19 @@ class BasicCompositor : public Composito
 
   already_AddRefed<CompositingRenderTarget> CreateRenderTarget(
       const gfx::IntRect& aRect, SurfaceInitMode aInit) override;
 
   already_AddRefed<CompositingRenderTarget> CreateRenderTargetFromSource(
       const gfx::IntRect& aRect, const CompositingRenderTarget* aSource,
       const gfx::IntPoint& aSourcePoint) override;
 
-  virtual already_AddRefed<CompositingRenderTarget> CreateRenderTargetForWindow(
-      const gfx::IntRect& aRect, const gfx::IntRegion& aClearRegion,
-      BufferMode aBufferMode);
+  virtual already_AddRefed<CompositingRenderTarget> CreateRenderTargetAndClear(
+      gfx::DrawTarget* aDrawTarget, const gfx::IntRect& aDrawTargetRect,
+      const gfx::IntRegion& aClearRegion);
 
   already_AddRefed<DataTextureSource> CreateDataTextureSource(
       TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
 
   already_AddRefed<DataTextureSource> CreateDataTextureSourceAround(
       gfx::DataSourceSurface* aSurface) override;
 
   already_AddRefed<DataTextureSource> CreateDataTextureSourceAroundYCbCr(