Bug 897105 - Part 2: Add layer fields for sticky positioning. r=roc
authorCorey Ford <cford@mozilla.com>
Wed, 11 Sep 2013 21:17:58 -0700
changeset 159928 7bb106e846bb2589583eb7ad9868e389cf29a30a
parent 159927 6b69bc8e40dd3c20dcbcaba7c7f44e6cf6653ee3
child 159929 fdf8a3e61e3f5bba01f7a14980772fca6e80cbf7
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs897105
milestone26.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 897105 - Part 2: Add layer fields for sticky positioning. r=roc
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/composite/ThebesLayerComposite.cpp
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/ShadowLayers.cpp
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -181,16 +181,17 @@ Layer::Layer(LayerManager* aManager, voi
   mPostXScale(1.0f),
   mPostYScale(1.0f),
   mOpacity(1.0),
   mContentFlags(0),
   mUseClipRect(false),
   mUseTileSourceRect(false),
   mIsFixedPosition(false),
   mMargins(0, 0, 0, 0),
+  mStickyPositionData(nullptr),
   mDebugColorIndex(0),
   mAnimationGeneration(0)
 {}
 
 Layer::~Layer()
 {}
 
 Animation*
@@ -1275,16 +1276,24 @@ Layer::PrintInfo(nsACString& aTo, const 
     aTo += " [opaqueContent]";
   }
   if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
     aTo += " [componentAlpha]";
   }
   if (GetIsFixedPosition()) {
     aTo.AppendPrintf(" [isFixedPosition anchor=%f,%f]", mAnchor.x, mAnchor.y);
   }
+  if (GetIsStickyPosition()) {
+    aTo.AppendPrintf(" [isStickyPosition scrollId=%d outer=%f,%f %fx%f "
+                     "inner=%f,%f %fx%f]", mStickyPositionData->mScrollId,
+                     mStickyPositionData->mOuter.x, mStickyPositionData->mOuter.y,
+                     mStickyPositionData->mOuter.width, mStickyPositionData->mOuter.height,
+                     mStickyPositionData->mInner.x, mStickyPositionData->mInner.y,
+                     mStickyPositionData->mInner.width, mStickyPositionData->mInner.height);
+  }
 
   return aTo;
 }
 
 nsACString&
 ThebesLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   Layer::PrintInfo(aTo, aPrefix);
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -904,16 +904,42 @@ public:
   {
     if (mMargins != aMargins) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FixedPositionMargins", this));
       mMargins = aMargins;
       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
+   * rectangles |aOuter| and |aInner| is treated as two intervals in each
+   * dimension, with the current scroll position at the origin. For each
+   * dimension, while that component of the scroll position lies within either
+   * interval, the layer should not move relative to its scrolling container.
+   */
+  void SetStickyPositionData(FrameMetrics::ViewID aScrollId, LayerRect aOuter,
+                             LayerRect aInner)
+  {
+    if (!mStickyPositionData ||
+        !mStickyPositionData->mOuter.IsEqualEdges(aOuter) ||
+        !mStickyPositionData->mInner.IsEqualEdges(aInner)) {
+      MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) StickyPositionData", this));
+      if (!mStickyPositionData) {
+        mStickyPositionData = new StickyPositionData;
+      }
+      mStickyPositionData->mScrollId = aScrollId;
+      mStickyPositionData->mOuter = aOuter;
+      mStickyPositionData->mInner = aInner;
+      Mutated();
+    }
+  }
+
   // These getters can be used anytime.
   float GetOpacity() { return mOpacity; }
   const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; }
   uint32_t GetContentFlags() { return mContentFlags; }
   const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
   ContainerLayer* GetParent() { return mParent; }
   Layer* GetNextSibling() { return mNextSibling; }
   const Layer* GetNextSibling() const { return mNextSibling; }
@@ -921,18 +947,22 @@ public:
   const Layer* GetPrevSibling() const { return mPrevSibling; }
   virtual Layer* GetFirstChild() const { return nullptr; }
   virtual Layer* GetLastChild() const { return nullptr; }
   const gfx3DMatrix GetTransform() const;
   const gfx3DMatrix& GetBaseTransform() const { return mTransform; }
   float GetPostXScale() const { return mPostXScale; }
   float GetPostYScale() const { return mPostYScale; }
   bool GetIsFixedPosition() { return mIsFixedPosition; }
+  bool GetIsStickyPosition() { return mStickyPositionData; }
   LayerPoint GetFixedPositionAnchor() { return mAnchor; }
   const LayerMargin& GetFixedPositionMargins() { return mMargins; }
+  FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
+  const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
+  const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
   Layer* GetMaskLayer() const { return mMaskLayer; }
 
   // Note that all lengths in animation data are either in CSS pixels or app
   // units and must be converted to device pixels by the compositor.
   AnimationArray& GetAnimations() { return mAnimations; }
   InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
 
   uint64_t GetAnimationGeneration() { return mAnimationGeneration; }
@@ -1278,16 +1308,22 @@ protected:
   nsIntRect mTileSourceRect;
   nsIntRegion mInvalidRegion;
   uint32_t mContentFlags;
   bool mUseClipRect;
   bool mUseTileSourceRect;
   bool mIsFixedPosition;
   LayerPoint mAnchor;
   LayerMargin mMargins;
+  struct StickyPositionData {
+    FrameMetrics::ViewID mScrollId;
+    LayerRect mOuter;
+    LayerRect mInner;
+  };
+  nsAutoPtr<StickyPositionData> mStickyPositionData;
   DebugOnly<uint32_t> mDebugColorIndex;
   // If this layer is used for OMTA, then this counter is used to ensure we
   // stay in sync with the animation manager
   uint64_t mAnimationGeneration;
 };
 
 /**
  * A Layer which we can draw into using Thebes. It is a conceptually
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -126,17 +126,17 @@ ThebesLayerComposite::RenderLayer(const 
   TiledLayerProperties tiledLayerProps;
   if (mRequiresTiledProperties) {
     // calculating these things can be a little expensive, so don't
     // do them if we don't have to
     tiledLayerProps.mVisibleRegion = visibleRegion;
     tiledLayerProps.mDisplayPort = GetDisplayPort();
     tiledLayerProps.mEffectiveResolution = GetEffectiveResolution();
     tiledLayerProps.mCompositionBounds = GetCompositionBounds();
-    tiledLayerProps.mRetainTiles = !mIsFixedPosition;
+    tiledLayerProps.mRetainTiles = !(mIsFixedPosition || mStickyPositionData);
     tiledLayerProps.mValidRegion = mValidRegion;
   }
 
   mBuffer->SetPaintWillResample(MayResample());
 
   mBuffer->Composite(effectChain,
                      GetEffectiveOpacity(),
                      transform,
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -267,16 +267,21 @@ LayerTransactionParent::RecvUpdate(const
       layer->SetContentFlags(common.contentFlags());
       layer->SetOpacity(common.opacity());
       layer->SetClipRect(common.useClipRect() ? &common.clipRect() : nullptr);
       layer->SetBaseTransform(common.transform().value());
       layer->SetPostScale(common.postXScale(), common.postYScale());
       layer->SetIsFixedPosition(common.isFixedPosition());
       layer->SetFixedPositionAnchor(common.fixedPositionAnchor());
       layer->SetFixedPositionMargins(common.fixedPositionMargin());
+      if (common.isStickyPosition()) {
+        layer->SetStickyPositionData(common.stickyScrollContainerId(),
+                                     common.stickyScrollRangeOuter(),
+                                     common.stickyScrollRangeInner());
+      }
       if (PLayerParent* maskLayer = common.maskLayerParent()) {
         layer->SetMaskLayer(cast(maskLayer)->AsLayer());
       } else {
         layer->SetMaskLayer(nullptr);
       }
       layer->SetAnimations(common.animations());
 
       typedef SpecificLayerAttributes Specific;
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -28,16 +28,17 @@ using nsPoint;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 using mozilla::ScreenRotation;
 using nsCSSProperty;
 using mozilla::dom::ScreenOrientation;
 using mozilla::layers::TextureInfo;
 using mozilla::LayerMargin;
 using mozilla::LayerPoint;
+using mozilla::LayerRect;
 using mozilla::layers::ScaleMode;
 using mozilla::layers::DiagnosticTypes;
 
 namespace mozilla {
 namespace layers {
 
 struct TargetConfig {
   nsIntRect naturalBounds;
@@ -187,16 +188,20 @@ struct CommonLayerAttributes {
   float postYScale;
   uint32_t contentFlags;
   float opacity;
   bool useClipRect;
   nsIntRect clipRect;
   bool isFixedPosition;
   LayerPoint fixedPositionAnchor;
   LayerMargin fixedPositionMargin;
+  bool isStickyPosition;
+  uint64_t stickyScrollContainerId;
+  LayerRect stickyScrollRangeOuter;
+  LayerRect stickyScrollRangeInner;
   nullable PLayer maskLayer;
   // Animated colors will only honored for ColorLayers.
   Animation[] animations;
  };
 
 struct ThebesLayerAttributes {
   nsIntRegion validRegion;
 };
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -491,16 +491,22 @@ ShadowLayerForwarder::EndTransaction(Inf
     common.contentFlags() = mutant->GetContentFlags();
     common.opacity() = mutant->GetOpacity();
     common.useClipRect() = !!mutant->GetClipRect();
     common.clipRect() = (common.useClipRect() ?
                          *mutant->GetClipRect() : nsIntRect());
     common.isFixedPosition() = mutant->GetIsFixedPosition();
     common.fixedPositionAnchor() = mutant->GetFixedPositionAnchor();
     common.fixedPositionMargin() = mutant->GetFixedPositionMargins();
+    common.isStickyPosition() = mutant->GetIsStickyPosition();
+    if (mutant->GetIsStickyPosition()) {
+      common.stickyScrollContainerId() = mutant->GetStickyScrollContainerId();
+      common.stickyScrollRangeOuter() = mutant->GetStickyScrollRangeOuter();
+      common.stickyScrollRangeInner() = mutant->GetStickyScrollRangeInner();
+    }
     if (Layer* maskLayer = mutant->GetMaskLayer()) {
       common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer());
     } else {
       common.maskLayerChild() = nullptr;
     }
     common.maskLayerParent() = nullptr;
     common.animations() = mutant->GetAnimations();
     attrs.specific() = null_t();