Bug 1510286 - Cache nsIFrame::BackfaceIsHidden() and nsIFrame::Combines3DTransformWithAncestors() in display items r=mattwoodrow
authorMiko Mynttinen <mikokm@gmail.com>
Wed, 13 Mar 2019 16:52:18 +0000
changeset 521732 9c7c3ca1638713bec7857c25eafa4b2099594d29
parent 521731 1af088f5fc34935f780c2153f1d279ca482e735a
child 521733 7314b493edd359db107d335fb79adbc73e30bfd1
push id10867
push userdvarga@mozilla.com
push dateThu, 14 Mar 2019 15:20:45 +0000
treeherdermozilla-beta@abad13547875 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1510286
milestone67.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 1510286 - Cache nsIFrame::BackfaceIsHidden() and nsIFrame::Combines3DTransformWithAncestors() in display items r=mattwoodrow Differential Revision: https://phabricator.services.mozilla.com/D13077
layout/painting/FrameLayerBuilder.cpp
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -4678,20 +4678,19 @@ void ContainerState::ProcessDisplayItems
       // into its buffer even if they're currently covered.
       if (itemVisibleRect.IsEmpty() &&
           !item->ShouldBuildLayerEvenIfInvisible(mBuilder)) {
         continue;
       }
 
       // 3D-transformed layers don't necessarily draw in the order in which
       // they're added to their parent container layer.
-      bool mayDrawOutOfOrder =
-          itemType == DisplayItemType::TYPE_TRANSFORM &&
-          (item->Frame()->Combines3DTransformWithAncestors() ||
-           item->Frame()->Extend3DContext());
+      bool mayDrawOutOfOrder = itemType == DisplayItemType::TYPE_TRANSFORM &&
+                               (item->Combines3DTransformWithAncestors() ||
+                                item->Frame()->Extend3DContext());
 
       // Let mPaintedLayerDataTree know about this item, so that
       // FindPaintedLayerFor and FindOpaqueBackgroundColor are aware of this
       // item, even though it's not in any PaintedLayerDataStack.
       // Ideally we'd only need the "else" case here and have
       // mPaintedLayerDataTree figure out the right clip from the animated
       // geometry root that we give it, but it can't easily figure about
       // overflow:hidden clips on ancestors just by looking at the frame.
@@ -4964,18 +4963,18 @@ void ContainerState::ProcessDisplayItems
       // layer visible region.
       NS_ASSERTION(itemType != DisplayItemType::TYPE_TRANSFORM ||
                        layerContentsVisibleRect.width >= 0,
                    "Transform items must set layerContentsVisibleRect!");
       if (mLayerBuilder->IsBuildingRetainedLayers()) {
         newLayerEntry->mLayerContentsVisibleRect = layerContentsVisibleRect;
         if (itemType == DisplayItemType::TYPE_PERSPECTIVE ||
             (itemType == DisplayItemType::TYPE_TRANSFORM &&
-             (item->Frame()->Extend3DContext() ||
-              item->Frame()->Combines3DTransformWithAncestors() ||
+             (item->Combines3DTransformWithAncestors() ||
+              item->Frame()->Extend3DContext() ||
               item->Frame()->HasPerspective()))) {
           // Give untransformed visible region as outer visible region
           // to avoid failure caused by singular transforms.
           newLayerEntry->mUntransformedVisibleRegion = true;
           newLayerEntry->mVisibleRegion =
               item->GetBuildingRectForChildren().ScaleToOutsidePixels(
                   contentXScale, contentYScale, mAppUnitsPerDevPixel);
         } else {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -3081,29 +3081,32 @@ struct ContentComparator {
                                               mCommonAncestor) < 0;
   }
 };
 
 void nsDisplayList::SortByContentOrder(nsIContent* aCommonAncestor) {
   Sort<nsDisplayItem*>(ContentComparator(aCommonAncestor));
 }
 
+#ifndef DEBUG
+static_assert(sizeof(nsDisplayItem) <= 176, "nsDisplayItem has grown");
+#endif
+
 nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame, aBuilder->CurrentActiveScrolledRoot()) {}
 
 nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                              const ActiveScrolledRoot* aActiveScrolledRoot,
                              bool aAnonymous)
     : mFrame(aFrame),
       mActiveScrolledRoot(aActiveScrolledRoot),
       mAnimatedGeometryRoot(nullptr),
       mForceNotVisible(aBuilder->IsBuildingInvisibleItems()),
       mDisableSubpixelAA(false),
       mReusedItem(false),
-      mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden()),
       mPaintRectValid(false),
       mCanBeReused(true)
 #ifdef MOZ_DUMP_PAINTING
       ,
       mPainted(false)
 #endif
 {
   MOZ_COUNT_CTOR(nsDisplayItem);
@@ -3124,16 +3127,21 @@ nsDisplayItem::nsDisplayItem(nsDisplayLi
   nsDisplayItem::SetClipChain(
       aBuilder->ClipState().GetCurrentCombinedClipChain(aBuilder), true);
 
   // The visible rect is for mCurrentFrame, so we have to use
   // mCurrentOffsetToReferenceFrame
   nsRect visible = aBuilder->GetVisibleRect() +
                    aBuilder->GetCurrentFrameOffsetToReferenceFrame();
   SetBuildingRect(visible);
+
+  const nsStyleDisplay* disp = mFrame->StyleDisplay();
+  mBackfaceIsHidden = mFrame->BackfaceIsHidden(disp);
+  mCombines3DTransformWithAncestors =
+      mFrame->Combines3DTransformWithAncestors(disp);
 }
 
 /* static */
 bool nsDisplayItem::ForceActiveLayers() {
   static bool sForce = false;
   static bool sForceCached = false;
 
   if (!sForceCached) {
@@ -7919,17 +7927,17 @@ const Matrix4x4& nsDisplayTransform::Get
   return *mTransformPreserves3D;
 }
 
 bool nsDisplayTransform::ShouldBuildLayerEvenIfInvisible(
     nsDisplayListBuilder* aBuilder) const {
   // The visible rect of a Preserves-3D frame is just an intermediate
   // result.  It should always build a layer to make sure it is
   // rendering correctly.
-  return MayBeAnimated(aBuilder) || mFrame->Combines3DTransformWithAncestors();
+  return MayBeAnimated(aBuilder) || Combines3DTransformWithAncestors();
 }
 
 bool nsDisplayTransform::CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc, RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
   // We want to make sure we don't pollute the transform property in the WR
@@ -8098,17 +8106,17 @@ bool nsDisplayTransform::MayBeAnimated(n
 nsDisplayItem::LayerState nsDisplayTransform::GetLayerState(
     nsDisplayListBuilder* aBuilder, LayerManager* aManager,
     const ContainerLayerParameters& aParameters) {
   // If the transform is 3d, the layer takes part in preserve-3d
   // sorting, or the layer is a separator then we *always* want this
   // to be an active layer.
   // Checking HasPerspective() is needed to handle perspective value 0 when
   // the transform is 2D.
-  if (!GetTransform().Is2D() || mFrame->Combines3DTransformWithAncestors() ||
+  if (!GetTransform().Is2D() || Combines3DTransformWithAncestors() ||
       mIsTransformSeparator || mFrame->HasPerspective()) {
     return LAYER_ACTIVE_FORCE;
   }
 
   if (MayBeAnimated(aBuilder)) {
     // Returns LAYER_ACTIVE_FORCE to avoid flatterning the layer for async
     // animations.
     return LAYER_ACTIVE_FORCE;
@@ -8124,17 +8132,17 @@ nsDisplayItem::LayerState nsDisplayTrans
 }
 
 bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                            nsRegion* aVisibleRegion) {
   // nsDisplayTransform::GetBounds() returns an empty rect in nested 3d context.
   // Calling mStoredList.RecomputeVisibility below for such transform causes the
   // child display items to end up with empty visible rect.
   // We avoid this by bailing out always if we are dealing with a 3d context.
-  if (mFrame->Extend3DContext() || mFrame->Combines3DTransformWithAncestors()) {
+  if (mFrame->Extend3DContext() || Combines3DTransformWithAncestors()) {
     return true;
   }
 
   /* As we do this, we need to be sure to
    * untransform the visible rect, since we want everything that's painting to
    * think that it's painting in its original rectangular coordinate space.
    * If we can't untransform, take the entire overflow rect */
   nsRect untransformedVisibleRect;
@@ -8217,17 +8225,17 @@ void nsDisplayTransform::UpdateBounds(ns
   UpdateUntransformedBounds(aBuilder);
 
   if (IsTransformSeparator()) {
     MOZ_ASSERT(GetTransform().IsIdentity());
     mBounds = mChildBounds;
     return;
   }
 
-  if (!mFrame->Combines3DTransformWithAncestors()) {
+  if (!Combines3DTransformWithAncestors()) {
     if (mFrame->Extend3DContext()) {
       // The transform establishes a 3D context. |UpdateBoundsFor3D()| will
       // collect the bounds from the child transforms.
       UpdateBoundsFor3D(aBuilder);
     } else {
       // A stand-alone transform.
       mBounds = TransformUntransformedBounds(aBuilder, GetTransform());
     }
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2095,17 +2095,19 @@ class nsDisplayItem : public nsDisplayIt
         mClipChain(nullptr),
         mClip(nullptr),
         mActiveScrolledRoot(nullptr),
         mReferenceFrame(nullptr),
         mAnimatedGeometryRoot(nullptr),
         mForceNotVisible(false),
         mDisableSubpixelAA(false),
         mReusedItem(false),
-        mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden()),
+        mBackfaceIsHidden(mFrame->BackfaceIsHidden()),
+        mCombines3DTransformWithAncestors(
+            mFrame->Combines3DTransformWithAncestors()),
         mPaintRectValid(false),
         mCanBeReused(true)
 #ifdef MOZ_DUMP_PAINTING
         ,
         mPainted(false)
 #endif
   {
     MOZ_COUNT_CTOR(nsDisplayItem);
@@ -2170,17 +2172,19 @@ class nsDisplayItem : public nsDisplayIt
         mReferenceFrame(aOther.mReferenceFrame),
         mAnimatedGeometryRoot(aOther.mAnimatedGeometryRoot),
         mToReferenceFrame(aOther.mToReferenceFrame),
         mBuildingRect(aOther.mBuildingRect),
         mPaintRect(aOther.mPaintRect),
         mForceNotVisible(aOther.mForceNotVisible),
         mDisableSubpixelAA(aOther.mDisableSubpixelAA),
         mReusedItem(false),
-        mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden()),
+        mBackfaceIsHidden(aOther.mBackfaceIsHidden),
+        mCombines3DTransformWithAncestors(
+            aOther.mCombines3DTransformWithAncestors),
         mPaintRectValid(false),
         mCanBeReused(true)
 #ifdef MOZ_DUMP_PAINTING
         ,
         mPainted(false)
 #endif
   {
     MOZ_COUNT_CTOR(nsDisplayItem);
@@ -2820,19 +2824,25 @@ class nsDisplayItem : public nsDisplayIt
 
   /**
    * Intersect all clips in our clip chain up to (and including) aASR and set
    * set the intersection as this item's clip.
    */
   void FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
                          const ActiveScrolledRoot* aASR);
 
-  bool BackfaceIsHidden() const { return mFrame->BackfaceIsHidden(); }
-
-  bool In3DContextAndBackfaceIsHidden() { return mBackfaceHidden; }
+  bool BackfaceIsHidden() const { return mBackfaceIsHidden; }
+
+  bool Combines3DTransformWithAncestors() const {
+    return mCombines3DTransformWithAncestors;
+  }
+
+  bool In3DContextAndBackfaceIsHidden() const {
+    return mBackfaceIsHidden && mCombines3DTransformWithAncestors;
+  }
 
   bool HasDifferentFrame(const nsDisplayItem* aOther) const {
     return mFrame != aOther->mFrame;
   }
 
   bool HasSameTypeAndClip(const nsDisplayItem* aOther) const {
     return GetPerFrameKey() == aOther->GetPerFrameKey() &&
            GetClipChain() == aOther->GetClipChain();
@@ -2942,44 +2952,47 @@ class nsDisplayItem : public nsDisplayIt
   nsRect mBuildingRect;
 
   // nsDisplayList::ComputeVisibility sets this to the visible region
   // of the item by intersecting the visible region with the bounds
   // of the item. Paint implementations can use this to limit their drawing.
   // Guaranteed to be contained in GetBounds().
   nsRect mPaintRect;
 
+  OldListIndex mOldListIndex;
+  uintptr_t mOldList = 0;
+
  protected:
+  struct {
+    RefPtr<const DisplayItemClipChain> mClipChain;
+    const DisplayItemClip* mClip;
+  } mState;
+
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
  public:
   uint32_t mOldListKey = 0;
   uint32_t mOldNestingDepth = 0;
   bool mMergedItem = false;
   bool mPreProcessedItem = false;
 
  protected:
 #endif
-  OldListIndex mOldListIndex;
-  uintptr_t mOldList = 0;
 
   bool mForceNotVisible;
   bool mDisableSubpixelAA;
   bool mReusedItem;
-  bool mBackfaceHidden;
+  bool mBackfaceIsHidden;
+  bool mCombines3DTransformWithAncestors;
   bool mPaintRectValid;
   bool mCanBeReused;
+
 #ifdef MOZ_DUMP_PAINTING
   // True if this frame has been painted.
   bool mPainted;
 #endif
-
-  struct {
-    RefPtr<const DisplayItemClipChain> mClipChain;
-    const DisplayItemClip* mClip;
-  } mState;
 };
 
 /**
  * Manages a singly-linked list of display list items.
  *
  * mSentinel is the sentinel list value, the first value in the null-terminated
  * linked list of items. mTop is the last item in the list (whose 'above'
  * pointer is null). This class has no virtual methods. So list objects are just
@@ -6778,26 +6791,24 @@ class nsDisplayTransform : public nsDisp
    */
   bool IsTransformSeparator() const { return mIsTransformSeparator; }
   /**
    * This item is the boundary between parent and child 3D rendering
    * context.
    */
   bool IsLeafOf3DContext() {
     return (IsTransformSeparator() ||
-            (!mFrame->Extend3DContext() &&
-             mFrame->Combines3DTransformWithAncestors()));
+            (!mFrame->Extend3DContext() && Combines3DTransformWithAncestors()));
   }
   /**
    * The backing frame of this item participates a 3D rendering
    * context.
    */
   bool IsParticipating3DContext() {
-    return mFrame->Extend3DContext() ||
-           mFrame->Combines3DTransformWithAncestors();
+    return mFrame->Extend3DContext() || Combines3DTransformWithAncestors();
   }
 
  private:
   void ComputeBounds(nsDisplayListBuilder* aBuilder);
   nsRect TransformUntransformedBounds(nsDisplayListBuilder* aBuilder,
                                       const Matrix4x4Flagged& aMatrix) const;
   void UpdateUntransformedBounds(nsDisplayListBuilder* aBuilder);