Bug 1166301 - Store a flag on Layer to tell fixed background layers apart from fixed position layers. r=mattwoodrow draft
authorBotond Ballo <botond@mozilla.com>
Mon, 31 Aug 2015 21:42:21 -0400
changeset 289357 93841515f598bbc4c3cb5372aea2b989ee78c29f
parent 289356 0fbcfff395aa85064555ff72c7003552e5830d16
child 289358 3f582e8b20998430450383dcc839ef005d96a312
push id4975
push userbballo@mozilla.com
push dateTue, 01 Sep 2015 01:57:17 +0000
reviewersmattwoodrow
bugs1166301
milestone43.0a1
Bug 1166301 - Store a flag on Layer to tell fixed background layers apart from fixed position layers. r=mattwoodrow
gfx/layers/Layers.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayersMessages.ipdlh
layout/base/FrameLayerBuilder.cpp
layout/base/nsDisplayList.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1158,27 +1158,30 @@ public:
    *     with respect to.
    *
    *   - |aAnchor| is the point on the layer that is considered the "anchor"
    *     point, that is, the point which remains in the same position when
    *     compositing the layer tree with a transformation (such as when
    *     asynchronously scrolling and zooming).
    */
   void SetFixedPositionData(FrameMetrics::ViewID aScrollId,
-                            const LayerPoint& aAnchor)
+                            const LayerPoint& aAnchor,
+                            bool aFixedBackground)
   {
     if (!mFixedPositionData ||
         mFixedPositionData->mScrollId != aScrollId ||
-        mFixedPositionData->mAnchor != aAnchor) {
+        mFixedPositionData->mAnchor != aAnchor ||
+        mFixedPositionData->mFixedBackground != aFixedBackground) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FixedPositionData", this));
       if (!mFixedPositionData) {
         mFixedPositionData = MakeUnique<FixedPositionData>();
       }
       mFixedPositionData->mScrollId = aScrollId;
       mFixedPositionData->mAnchor = aAnchor;
+      mFixedPositionData->mFixedBackground = aFixedBackground;
       Mutated();
     }
   }
 
   /**
    * CONSTRUCTION PHASE ONLY
    * If a layer is "sticky position", |aScrollId| holds the scroll identifier
    * of the scrollable content that contains it. The difference between the two
@@ -1262,16 +1265,17 @@ public:
   const gfx::Matrix4x4& GetBaseTransform() const { return mTransform; }
   // Note: these are virtual because ContainerLayerComposite overrides them.
   virtual float GetPostXScale() const { return mPostXScale; }
   virtual float GetPostYScale() const { return mPostYScale; }
   bool GetIsFixedPosition() { return mIsFixedPosition; }
   bool GetIsStickyPosition() { return mStickyPositionData; }
   FrameMetrics::ViewID GetFixedPositionScrollContainerId() { return mFixedPositionData ? mFixedPositionData->mScrollId : FrameMetrics::NULL_SCROLL_ID; }
   LayerPoint GetFixedPositionAnchor() { return mFixedPositionData ? mFixedPositionData->mAnchor : LayerPoint(); }
+  bool IsFixedBackground() { return mFixedPositionData ? mFixedPositionData->mFixedBackground : false; }
   FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
   const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
   const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
   FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
   ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
   float GetScrollbarThumbRatio() { return mScrollbarThumbRatio; }
   bool IsScrollbarContainer() { return mIsScrollbarContainer; }
   Layer* GetMaskLayer() const { return mMaskLayer; }
@@ -1765,16 +1769,21 @@ protected:
   nsIntRegion mInvalidRegion;
   nsTArray<nsRefPtr<AsyncPanZoomController> > mApzcs;
   uint32_t mContentFlags;
   bool mUseTileSourceRect;
   bool mIsFixedPosition;
   struct FixedPositionData {
     FrameMetrics::ViewID mScrollId;
     LayerPoint mAnchor;
+    // This is true for fixed background layers, and false for fixed position
+    // layers. The compositor needs to tell them apart because async scroll
+    // transforms should be applied to the clip rects of fixed background
+    // layers, but not to the clip rects of fixed position layers.
+    bool mFixedBackground;
   };
   UniquePtr<FixedPositionData> mFixedPositionData;
   struct StickyPositionData {
     FrameMetrics::ViewID mScrollId;
     LayerRect mOuter;
     LayerRect mInner;
   };
   nsAutoPtr<StickyPositionData> mStickyPositionData;
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -326,17 +326,18 @@ LayerTransactionParent::RecvUpdate(Infal
       layer->SetContentFlags(common.contentFlags());
       layer->SetOpacity(common.opacity());
       layer->SetClipRect(common.useClipRect() ? Some(common.clipRect()) : Nothing());
       layer->SetBaseTransform(common.transform().value());
       layer->SetPostScale(common.postXScale(), common.postYScale());
       layer->SetIsFixedPosition(common.isFixedPosition());
       if (common.isFixedPosition()) {
         layer->SetFixedPositionData(common.fixedPositionScrollContainerId(),
-                                    common.fixedPositionAnchor());
+                                    common.fixedPositionAnchor(),
+                                    common.isFixedBackground());
       }
       if (common.isStickyPosition()) {
         layer->SetStickyPositionData(common.stickyScrollContainerId(),
                                      common.stickyScrollRangeOuter(),
                                      common.stickyScrollRangeInner());
       }
       layer->SetScrollbarData(common.scrollbarTargetContainerId(),
         static_cast<Layer::ScrollDirection>(common.scrollbarDirection()),
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -212,16 +212,17 @@ struct CommonLayerAttributes {
   float postYScale;
   uint32_t contentFlags;
   float opacity;
   bool useClipRect;
   ParentLayerIntRect clipRect;
   bool isFixedPosition;
   uint64_t fixedPositionScrollContainerId;
   LayerPoint fixedPositionAnchor;
+  bool isFixedBackground;
   bool isStickyPosition;
   uint64_t stickyScrollContainerId;
   LayerRect stickyScrollRangeOuter;
   LayerRect stickyScrollRangeInner;
   uint64_t scrollbarTargetContainerId;
   uint32_t scrollbarDirection;
   float scrollbarThumbRatio;
   int8_t mixBlendMode;
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1222,17 +1222,18 @@ protected:
    * are directly on the viewport (e.g. background-attachment:fixed backgrounds).
    */
   const nsIFrame* FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
                                                 bool aDisplayItemFixedToViewport);
   /**
    * Set fixed-pos layer metadata on aLayer according to the data for aFixedPosFrame.
    */
   void SetFixedPositionLayerData(Layer* aLayer,
-                                 const nsIFrame* aFixedPosFrame);
+                                 const nsIFrame* aFixedPosFrame,
+                                 bool aFixedBackground);
 
   /**
    * Returns true if aItem's opaque area (in aOpaque) covers the entire
    * scrollable area of its presshell.
    */
   bool ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque);
 
   /**
@@ -2912,17 +2913,18 @@ ContainerState::FindFixedPosFrameForLaye
       return nullptr;
     }
   }
   return nullptr;
 }
 
 void
 ContainerState::SetFixedPositionLayerData(Layer* aLayer,
-                                          const nsIFrame* aFixedPosFrame)
+                                          const nsIFrame* aFixedPosFrame,
+                                          bool aFixedBackground)
 {
   aLayer->SetIsFixedPosition(aFixedPosFrame != nullptr);
   if (!aFixedPosFrame) {
     return;
   }
 
   nsPresContext* presContext = aFixedPosFrame->PresContext();
 
@@ -2943,17 +2945,18 @@ ContainerState::SetFixedPositionLayerDat
     // For background-attachment:fixed items, the anchor point is always the
     // top-left of the viewport currently.
     viewportFrame = aFixedPosFrame;
   }
   // The anchorRect top-left is always the viewport top-left.
   anchorRect.MoveTo(viewportFrame->GetOffsetToCrossDoc(mContainerReferenceFrame));
 
   nsLayoutUtils::SetFixedPositionLayerData(aLayer,
-      viewportFrame, anchorRect, aFixedPosFrame, presContext, mParameters);
+      viewportFrame, anchorRect, aFixedPosFrame, presContext, mParameters,
+      aFixedBackground);
 }
 
 static bool
 CanOptimizeAwayPaintedLayer(PaintedLayerData* aData,
                            FrameLayerBuilder* aLayerBuilder)
 {
   if (!aLayerBuilder->IsBuildingRetainedLayers()) {
     return false;
@@ -3210,17 +3213,18 @@ void ContainerState::FinishPaintedLayerD
   } else if (data->mNeedComponentAlpha && !hidpi) {
     flags |= Layer::CONTENT_COMPONENT_ALPHA;
   }
   if (data->mDisableFlattening) {
     flags |= Layer::CONTENT_DISABLE_FLATTENING;
   }
   layer->SetContentFlags(flags);
 
-  SetFixedPositionLayerData(layer, data->mFixedPosFrameForLayerData);
+  SetFixedPositionLayerData(layer, data->mFixedPosFrameForLayerData,
+                            data->mSingleItemFixedToViewport);
 
   PaintedLayerData* containingPaintedLayerData =
      mLayerBuilder->GetContainingPaintedLayerData();
   if (containingPaintedLayerData) {
     if (!data->mDispatchToContentHitRegion.GetBounds().IsEmpty()) {
       nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor(
         mContainerReferenceFrame,
         data->mDispatchToContentHitRegion.GetBounds(),
@@ -3940,17 +3944,17 @@ ContainerState::ProcessDisplayItems(nsDi
         continue;
       }
 
       NS_ASSERTION(!ownLayer->AsPaintedLayer(),
                    "Should never have created a dedicated Painted layer!");
 
       const nsIFrame* fixedPosFrame =
         FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport);
-      SetFixedPositionLayerData(ownLayer, fixedPosFrame);
+      SetFixedPositionLayerData(ownLayer, fixedPosFrame, shouldFixToViewport);
 
       nsRect invalid;
       if (item->IsInvalid(invalid)) {
         ownLayer->SetInvalidRectToVisibleRegion();
       }
 
       // If it's not a ContainerLayer, we need to apply the scale transform
       // ourselves.
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -4412,17 +4412,17 @@ nsDisplayStickyPosition::BuildLayer(nsDi
   if (scrollFrame == presContext->PresShell()->GetRootScrollFrame() &&
       presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
     scrollFrameSize = presContext->PresShell()->
       GetScrollPositionClampingScrollPortSize();
   }
 
   nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame,
     nsRect(scrollFrame->GetOffsetToCrossDoc(ReferenceFrame()), scrollFrameSize),
-    mFrame, presContext, aContainerParameters);
+    mFrame, presContext, aContainerParameters, /* fixed background = */ false);
 
   ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor(
     stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent());
 
   float factor = presContext->AppUnitsPerDevPixel();
   nsRect outer;
   nsRect inner;
   stickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1708,17 +1708,18 @@ nsLayoutUtils::GetScrollableFrameFor(con
 }
 
 /* static */ void
 nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer,
                                          const nsIFrame* aViewportFrame,
                                          const nsRect& aAnchorRect,
                                          const nsIFrame* aFixedPosFrame,
                                          nsPresContext* aPresContext,
-                                         const ContainerLayerParameters& aContainerParameters) {
+                                         const ContainerLayerParameters& aContainerParameters,
+                                         bool aFixedBackground) {
   // Find out the rect of the viewport frame relative to the reference frame.
   // This, in conjunction with the container scale, will correspond to the
   // coordinate-space of the built layer.
   float factor = aPresContext->AppUnitsPerDevPixel();
   Rect anchorRect(NSAppUnitsToFloatPixels(aAnchorRect.x, factor) *
                     aContainerParameters.mXScale,
                   NSAppUnitsToFloatPixels(aAnchorRect.y, factor) *
                     aContainerParameters.mYScale,
@@ -1762,17 +1763,17 @@ nsLayoutUtils::SetFixedPositionLayerData
   }
 
   ViewID id = FrameMetrics::NULL_SCROLL_ID;
   if (nsIFrame* rootScrollFrame = aPresContext->PresShell()->GetRootScrollFrame()) {
     if (nsIContent* content = rootScrollFrame->GetContent()) {
       id = FindOrCreateIDFor(content);
     }
   }
-  aLayer->SetFixedPositionData(id, anchor);
+  aLayer->SetFixedPositionData(id, anchor, aFixedBackground);
 }
 
 bool
 nsLayoutUtils::ViewportHasDisplayPort(nsPresContext* aPresContext, nsRect* aDisplayPort)
 {
   nsIFrame* rootScrollFrame =
     aPresContext->PresShell()->GetRootScrollFrame();
   return rootScrollFrame &&
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -490,22 +490,25 @@ public:
    * Sets the fixed-pos metadata properties on aLayer.
    * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a viewport
    * frame, then we pick a corner of aAnchorRect to as the anchor point for the
    * fixed-pos layer (i.e. the point to remain stable during zooming), based
    * on which of the fixed-pos frame's CSS absolute positioning offset
    * properties (top, left, right, bottom) are auto. aAnchorRect is in the
    * coordinate space of aLayer's container layer (i.e. relative to the reference
    * frame of the display item which is building aLayer's container layer).
+   * aFixedBackground if true if the layer is for a fixed background (as opposed
+   * to a fixed position-element).
    */
   static void SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame,
                                         const nsRect& aAnchorRect,
                                         const nsIFrame* aFixedPosFrame,
                                         nsPresContext* aPresContext,
-                                        const ContainerLayerParameters& aContainerParameters);
+                                        const ContainerLayerParameters& aContainerParameters,
+                                        bool aFixedBackground);
 
   /**
    * Return true if aPresContext's viewport has a displayport.
    * Fills in aDisplayPort with the displayport rectangle if non-null.
    */
   static bool ViewportHasDisplayPort(nsPresContext* aPresContext,
                                      nsRect* aDisplayPort = nullptr);