Bug 1253860 - Add machinery to update APZ's scroll offset without a main-thread paint. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 09 Mar 2016 18:29:16 -0500
changeset 338733 b35a29c043bf1caf8fe9722bc16f55c80dfa5780
parent 338732 cf648eed68cc4de2f5e465987ff9c8edecc800ab
child 338734 f4c460f2332d4a0e3a0b19bc0c199b6a668dfd71
push id12574
push userkgupta@mozilla.com
push dateWed, 09 Mar 2016 23:29:35 +0000
reviewersbotond
bugs1253860
milestone48.0a1
Bug 1253860 - Add machinery to update APZ's scroll offset without a main-thread paint. r?botond MozReview-Commit-ID: ABnEJPzyJ5w
gfx/layers/FrameMetrics.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/PLayerTransaction.ipdl
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -228,16 +228,22 @@ public:
 
   void CopySmoothScrollInfoFrom(const FrameMetrics& aOther)
   {
     mSmoothScrollOffset = aOther.mSmoothScrollOffset;
     mScrollGeneration = aOther.mScrollGeneration;
     mDoSmoothScroll = aOther.mDoSmoothScroll;
   }
 
+  void UpdateScrollInfo(uint32_t aScrollGeneration, const CSSPoint& aScrollOffset)
+  {
+    mScrollOffset = aScrollOffset;
+    mScrollGeneration = aScrollGeneration;
+  }
+
   // Make a copy of this FrameMetrics object which does not have any pointers
   // to heap-allocated memory (i.e. is Plain Old Data, or 'POD'), and is
   // therefore safe to be placed into shared memory.
   FrameMetrics MakePODObject() const
   {
     FrameMetrics copy = *this;
     copy.mContentDescription.Truncate();
     return copy;
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3462,16 +3462,45 @@ void AsyncPanZoomController::NotifyLayer
 
   if (needContentRepaint) {
     RequestContentRepaint();
   }
   UpdateSharedCompositorFrameMetrics();
 }
 
 void
+AsyncPanZoomController::UpdateScrollOffset(uint32_t aScrollGeneration,
+                                           const CSSPoint& aScrollOffset)
+{
+  APZThreadUtils::AssertOnCompositorThread();
+  ReentrantMonitorAutoEnter lock(mMonitor);
+
+  APZC_LOG("%p UpdateScrollOffset(%d, %s)\n", this, aScrollGeneration,
+      Stringify(aScrollOffset).c_str());
+
+  bool scrollOffsetUpdated = aScrollGeneration != mFrameMetrics.GetScrollGeneration();
+  if (!scrollOffsetUpdated) {
+    return;
+  }
+  APZC_LOG("%p updating scroll offset from %s to %s\n", this,
+      Stringify(mFrameMetrics.GetScrollOffset()).c_str(),
+      Stringify(aScrollOffset).c_str());
+
+  mFrameMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset);
+  AcknowledgeScrollUpdate();
+  mExpectedGeckoMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset);
+  CancelAnimation();
+  RequestContentRepaint();
+  UpdateSharedCompositorFrameMetrics();
+  // We don't call ScheduleComposite() here because that happens higher up
+  // in the call stack, when LayerTransactionParent handles this message.
+  // If we did it here it would incur an extra message posting unnecessarily.
+}
+
+void
 AsyncPanZoomController::AcknowledgeScrollUpdate() const
 {
   // Once layout issues a scroll offset update, it becomes impervious to
   // scroll offset updates from APZ until we acknowledge the update it sent.
   // This prevents APZ updates from clobbering scroll updates from other
   // more "legitimate" sources like content scripts.
   RefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -183,16 +183,23 @@ public:
    * |aIsFirstPaint| is a flag passed from the shadow
    * layers code indicating that the frame metrics being sent with this call are
    * the initial metrics and the initial paint of the frame has just happened.
    */
   void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint,
                            bool aThisLayerTreeUpdated);
 
   /**
+   * A lightweight version of NotifyLayersUpdated that allows just the scroll
+   * offset and scroll generation from the main thread to be propagated to APZ.
+   */
+  void UpdateScrollOffset(uint32_t aScrollGeneration,
+                          const CSSPoint& aScrollOffset);
+
+  /**
    * The platform implementation must set the compositor parent so that we can
    * request composites.
    */
   void SetCompositorParent(CompositorParent* aCompositorParent);
 
   /**
    * Inform this APZC that it will be sharing its FrameMetrics with a cross-process
    * compositor so that the associated content process can access it. This is only
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -794,16 +794,35 @@ GetAPZCForViewID(Layer* aLayer, FrameMet
         return c;
       }
     }
   }
   return nullptr;
 }
 
 bool
+LayerTransactionParent::RecvUpdateScrollOffset(
+    const FrameMetrics::ViewID& aScrollID,
+    const uint32_t& aScrollGeneration,
+    const CSSPoint& aScrollOffset)
+{
+  if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
+    return false;
+  }
+
+  AsyncPanZoomController* controller = GetAPZCForViewID(mRoot, aScrollID);
+  if (!controller) {
+    return false;
+  }
+  controller->UpdateScrollOffset(aScrollGeneration, aScrollOffset);
+  mShadowLayersManager->ForceComposite(this);
+  return true;
+}
+
+bool
 LayerTransactionParent::RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aScrollID,
                                                  const float& aX, const float& aY)
 {
   if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
     return false;
   }
 
   AsyncPanZoomController* controller = GetAPZCForViewID(mRoot, aScrollID);
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -123,16 +123,19 @@ protected:
   virtual bool RecvForceComposite() override;
   virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) override;
   virtual bool RecvLeaveTestMode() override;
   virtual bool RecvGetOpacity(PLayerParent* aParent,
                               float* aOpacity) override;
   virtual bool RecvGetAnimationTransform(PLayerParent* aParent,
                                          MaybeTransform* aTransform)
                                          override;
+  virtual bool RecvUpdateScrollOffset(const FrameMetrics::ViewID& aScrollId,
+                                      const uint32_t& aScrollGeneration,
+                                      const CSSPoint& aScrollOffset) override;
   virtual bool RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aId,
                                         const float& aX, const float& aY) override;
   virtual bool RecvSetAsyncZoom(const FrameMetrics::ViewID& aId,
                                 const float& aValue) override;
   virtual bool RecvFlushApzRepaints() override;
   virtual bool RecvGetAPZTestData(APZTestData* aOutData) override;
   virtual bool RecvRequestProperty(const nsString& aProperty, float* aValue) override;
   virtual bool RecvSetConfirmedTargetAPZC(const uint64_t& aBlockId,
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -17,16 +17,17 @@ include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
 using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
+using mozilla::CSSPoint from "Units.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
  */
@@ -84,16 +85,20 @@ parent:
 
   // Returns the value of the transform applied to the layer by animation after
   // factoring out translation components introduced to account for the offset
   // of the corresponding frame and transform origin and after converting to CSS
   // pixels. If the layer is not transformed by animation, the return value will
   // be void_t.
   sync GetAnimationTransform(PLayer layer) returns (MaybeTransform transform);
 
+  // Updates the scroll offset and generation counter on the APZC for the
+  // given scroll id.
+  sync UpdateScrollOffset(ViewID id, uint32_t generation, CSSPoint offset);
+
   // The next time the layer tree is composited, add this async scroll offset in
   // CSS pixels for the given ViewID.
   // Useful for testing rendering of async scrolling.
   sync SetAsyncScrollOffset(ViewID id, float x, float y);
 
   // The next time the layer tree is composited, include this async zoom in
   // for the given ViewID.
   // Useful for testing rendering of async zooming.