Bug 1562184. Convert window opaque region to a WeakFrameRegion. r=mattwoodrow a=RyanVM
authorTimothy Nikkel <tnikkel@gmail.com>
Wed, 24 Jul 2019 21:09:09 +0000
changeset 544863 2c3491f0154fcbc380418f8d41e226b1417037bf
parent 544862 ac03eafa39f462298cf22057954fdd3e61d936f7
child 544864 30a3d6b7d0dc191ba03ea8ee8fc669bc1fea6703
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, RyanVM
bugs1562184
milestone69.0
Bug 1562184. Convert window opaque region to a WeakFrameRegion. r=mattwoodrow a=RyanVM For retained display lists it needs to be a weak frame region to areas get removed for modified frames and the rest stick around. Each display item can contribute an opaque region but WeakFrameRegion can only track one rect per frame. It turns out that we only return rects from GetOpaqueRegion except in one hit testing case. This still means more than one display item per frame could be contributing to the opaque region, we would miss the second and further rects in that case. Differential Revision: https://phabricator.services.mozilla.com/D38589
gfx/layers/wr/WebRenderCommandBuilder.cpp
layout/painting/FrameLayerBuilder.cpp
layout/painting/RetainedDisplayListBuilder.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -2233,21 +2233,22 @@ WebRenderCommandBuilder::GenerateFallbac
     newGeometry = aItem->AllocateGeometry(aDisplayListBuilder);
     fallbackData->mGeometry = std::move(newGeometry);
 
     gfx::SurfaceFormat format = aItem->GetType() == DisplayItemType::TYPE_MASK
                                     ? gfx::SurfaceFormat::A8
                                     : gfx::SurfaceFormat::B8G8R8A8;
     if (useBlobImage) {
       bool snapped;
-      wr::OpacityType opacity =
-          aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped)
-                  .Contains(paintBounds)
-              ? wr::OpacityType::Opaque
-              : wr::OpacityType::HasAlphaChannel;
+      nsRegion opaqueRegion =
+          aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped);
+      MOZ_ASSERT(!opaqueRegion.IsComplex());
+      wr::OpacityType opacity = opaqueRegion.Contains(paintBounds)
+                                    ? wr::OpacityType::Opaque
+                                    : wr::OpacityType::HasAlphaChannel;
       std::vector<RefPtr<ScaledFont>> fonts;
       bool validFonts = true;
       RefPtr<WebRenderDrawEventRecorder> recorder =
           MakeAndAddRef<WebRenderDrawEventRecorder>(
               [&](MemStream& aStream,
                   std::vector<RefPtr<ScaledFont>>& aScaledFonts) {
                 size_t count = aScaledFonts.size();
                 aStream.write((const char*)&count, sizeof(count));
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -4289,16 +4289,17 @@ nsRect ContainerState::GetDisplayPortFor
 
 nsIntRegion ContainerState::ComputeOpaqueRect(
     nsDisplayItem* aItem, AnimatedGeometryRoot* aAnimatedGeometryRoot,
     const ActiveScrolledRoot* aASR, const DisplayItemClip& aClip,
     nsDisplayList* aList, bool* aHideAllLayersBelow,
     bool* aOpaqueForAnimatedGeometryRootParent) {
   bool snapOpaque;
   nsRegion opaque = aItem->GetOpaqueRegion(mBuilder, &snapOpaque);
+  MOZ_ASSERT(!opaque.IsComplex());
   if (opaque.IsEmpty()) {
     return nsIntRegion();
   }
 
   nsIntRegion opaquePixels;
   nsRegion opaqueClipped;
   for (auto iter = opaque.RectIter(); !iter.Done(); iter.Next()) {
     opaqueClipped.Or(opaqueClipped,
@@ -4309,17 +4310,17 @@ nsIntRegion ContainerState::ComputeOpaqu
     *aHideAllLayersBelow = true;
     aList->SetIsOpaque();
   }
   // Add opaque areas to the "exclude glass" region. Only do this when our
   // container layer is going to be the rootmost layer, otherwise transforms
   // etc will mess us up (and opaque contributions from other containers are
   // not needed).
   if (!nsLayoutUtils::GetCrossDocParentFrame(mContainerFrame)) {
-    mBuilder->AddWindowOpaqueRegion(opaqueClipped);
+    mBuilder->AddWindowOpaqueRegion(aItem->Frame(), opaqueClipped.GetBounds());
   }
   opaquePixels = ScaleRegionToInsidePixels(opaqueClipped, snapOpaque);
 
   if (IsInInactiveLayer()) {
     return opaquePixels;
   }
 
   const nsRect& displayport =
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -1418,17 +1418,16 @@ void RetainedDisplayListBuilder::ClearFr
   AutoClearFramePropsArray framesWithProps;
   GetModifiedAndFramesWithProps(&mBuilder, &modifiedFrames.Frames(),
                                 &framesWithProps.Frames());
 }
 
 PartialUpdateResult RetainedDisplayListBuilder::AttemptPartialUpdate(
     nscolor aBackstop, mozilla::DisplayListChecker* aChecker) {
   mBuilder.RemoveModifiedWindowRegions();
-  mBuilder.ClearWindowOpaqueRegion();
 
   if (mBuilder.ShouldSyncDecodeImages()) {
     MarkFramesWithItemsAndImagesModified(&mList);
   }
 
   InvalidateCaretFramesIfNeeded();
 
   mBuilder.EnterPresShell(mBuilder.RootReferenceFrame());
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2368,16 +2368,17 @@ void nsDisplayListBuilder::AddSizeOfExcl
   MallocSizeOf mallocSizeOf = aSizes.mState.mMallocSizeOf;
   n += mWillChangeBudget.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += mWillChangeBudgetSet.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += mAGRBudgetSet.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += mEffectsUpdates.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += mWindowExcludeGlassRegion.SizeOfExcludingThis(mallocSizeOf);
   n += mRetainedWindowDraggingRegion.SizeOfExcludingThis(mallocSizeOf);
   n += mRetainedWindowNoDraggingRegion.SizeOfExcludingThis(mallocSizeOf);
+  n += mWindowOpaqueRegion.SizeOfExcludingThis(mallocSizeOf);
   // XXX can't measure mClipDeduplicator since it uses std::unordered_set.
 
   aSizes.mLayoutRetainedDisplayListSize += n;
 }
 
 void RetainedDisplayList::AddSizeOfExcludingThis(nsWindowSizes& aSizes) const {
   for (nsDisplayItem* item : *this) {
     item->AddSizeOfExcludingThis(aSizes);
@@ -2436,24 +2437,26 @@ void nsDisplayListBuilder::WeakFrameRegi
   mFrames.TruncateLength(length);
   mRects.TruncateLength(length);
 }
 
 void nsDisplayListBuilder::RemoveModifiedWindowRegions() {
   mRetainedWindowDraggingRegion.RemoveModifiedFramesAndRects();
   mRetainedWindowNoDraggingRegion.RemoveModifiedFramesAndRects();
   mWindowExcludeGlassRegion.RemoveModifiedFramesAndRects();
+  mWindowOpaqueRegion.RemoveModifiedFramesAndRects();
 
   mHasGlassItemDuringPartial = false;
 }
 
 void nsDisplayListBuilder::ClearRetainedWindowRegions() {
   mRetainedWindowDraggingRegion.Clear();
   mRetainedWindowNoDraggingRegion.Clear();
   mWindowExcludeGlassRegion.Clear();
+  mWindowOpaqueRegion.Clear();
 
   mGlassDisplayItem = nullptr;
 }
 
 const uint32_t gWillChangeAreaMultiplier = 3;
 static uint32_t GetLayerizationCost(const nsSize& aSize) {
   // There's significant overhead for each layer created from Gecko
   // (IPC+Shared Objects) and from the backend (like an OpenGL texture).
@@ -2701,16 +2704,19 @@ bool nsDisplayList::ComputeVisibilityFor
   r.And(*aVisibleRegion, GetClippedBoundsWithRespectToASR(aBuilder, rootASR));
   return ComputeVisibilityForSublist(aBuilder, aVisibleRegion, r.GetBounds());
 }
 
 static nsRegion TreatAsOpaque(nsDisplayItem* aItem,
                               nsDisplayListBuilder* aBuilder) {
   bool snap;
   nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap);
+  MOZ_ASSERT(
+      (aBuilder->IsForEventDelivery() && aBuilder->HitTestIsForVisibility()) ||
+      !opaque.IsComplex());
   if (aBuilder->IsForPluginGeometry() &&
       aItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
     // Treat all leaf chrome items as opaque, unless their frames are opacity:0.
     // Since opacity:0 frames generate an nsDisplayOpacity, that item will
     // not be treated as opaque here, so opacity:0 chrome content will be
     // effectively ignored, as it should be.
     // We treat leaf chrome items as opaque to ensure that they cover
     // content plugins, for security reasons.
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1591,29 +1591,26 @@ class nsDisplayListBuilder {
    */
   nsRegion GetWindowExcludeGlassRegion() const {
     return mWindowExcludeGlassRegion.ToRegion();
   }
 
   /**
    * Accumulates opaque stuff into the window opaque region.
    */
-  void AddWindowOpaqueRegion(const nsRegion& bounds) {
-    mWindowOpaqueRegion.Or(mWindowOpaqueRegion, bounds);
+  void AddWindowOpaqueRegion(nsIFrame* aFrame, const nsRect& aBounds) {
+    mWindowOpaqueRegion.Add(aFrame, aBounds);
   }
   /**
    * Returns the window opaque region built so far. This may be incomplete
    * since the opaque region is built during layer construction.
    */
-  const nsRegion& GetWindowOpaqueRegion() { return mWindowOpaqueRegion; }
-
-  /**
-   * Clears the window opaque region.
-   */
-  void ClearWindowOpaqueRegion() { mWindowOpaqueRegion.SetEmpty(); }
+  const nsRegion GetWindowOpaqueRegion() {
+    return mWindowOpaqueRegion.ToRegion();
+  }
 
   void SetGlassDisplayItem(nsDisplayItem* aItem);
   void ClearGlassDisplayItem() { mGlassDisplayItem = nullptr; }
   nsDisplayItem* GetGlassDisplayItem() { return mGlassDisplayItem; }
 
   bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);
 
   void SetContainsPluginItem() { mContainsPluginItem = true; }
@@ -1907,23 +1904,23 @@ class nsDisplayListBuilder {
   nsRect mVisibleRect;
   nsRect mDirtyRect;
 
   // Tracked regions used for retained display list.
   WeakFrameRegion mWindowExcludeGlassRegion;
   WeakFrameRegion mRetainedWindowDraggingRegion;
   WeakFrameRegion mRetainedWindowNoDraggingRegion;
 
+  // Window opaque region is calculated during layer building.
+  WeakFrameRegion mWindowOpaqueRegion;
+
   // Optimized versions for non-retained display list.
   LayoutDeviceIntRegion mWindowDraggingRegion;
   LayoutDeviceIntRegion mWindowNoDraggingRegion;
 
-  // Window opaque region is calculated during layer building.
-  nsRegion mWindowOpaqueRegion;
-
   // The display item for the Windows window glass background, if any
   // Set during full display list builds or during display list merging only,
   // partial display list builds don't touch this.
   nsDisplayItem* mGlassDisplayItem;
   // If we've encountered a glass item yet, only used during partial display
   // list builds.
   bool mHasGlassItemDuringPartial;
 
@@ -2676,16 +2673,18 @@ class nsDisplayItem : public nsDisplayIt
    * @param aSnap set to true if the edges of the rectangles of the opaque
    * region would be snapped to device pixels when drawing
    * @return a region of the item that is opaque --- that is, every pixel
    * that is visible is painted with an opaque
    * color. This is useful for determining when one piece
    * of content completely obscures another so that we can do occlusion
    * culling.
    * This does not take clipping into account.
+   * This must return a simple region (1 rect) for painting display lists.
+   * It is only allowed to be a complex region for hit testing.
    */
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) const {
     *aSnap = false;
     return nsRegion();
   }
   /**
    * @return Some(nscolor) if the item is guaranteed to paint every pixel in its