Bug 1449982 - Move the WebRenderScrollData storage from WebRenderBridgeParent to APZUpdater. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 10 Apr 2018 12:29:56 -0400
changeset 779790 ec150cdf65042878ad83d4acd082e4fd1ec13de0
parent 779789 2252362cadab2f26810a4fa743c6cc1066717ac3
child 779791 e7842d8b554bdd2e9d1a37e8d8c5679d31099098
push id105878
push userkgupta@mozilla.com
push dateTue, 10 Apr 2018 16:32:25 +0000
reviewersbotond
bugs1449982
milestone61.0a1
Bug 1449982 - Move the WebRenderScrollData storage from WebRenderBridgeParent to APZUpdater. r?botond This allows us to easily store a handle to the APZUpdater on the WebRenderScrollDataWrapper class and walk around in the scroll data tree without having to query other classes like CompositorBridgeParent or WebRenderBridgeParent when we encounter a reflayer boundary. MozReview-Commit-ID: 6l7oMb7tBlW
gfx/layers/apz/public/APZSampler.h
gfx/layers/apz/public/APZUpdater.h
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/layers/apz/src/APZSampler.cpp
gfx/layers/apz/src/APZUpdater.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/layers/wr/WebRenderScrollDataWrapper.h
--- a/gfx/layers/apz/public/APZSampler.h
+++ b/gfx/layers/apz/public/APZSampler.h
@@ -70,22 +70,22 @@ public:
   void MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer);
   bool HasUnusedAsyncTransform(const LayerMetricsWrapper& aLayer);
 
   /**
    * This can be used to assert that the current thread is the
    * sampler thread (which samples the async transform).
    * This does nothing if thread assertions are disabled.
    */
-  void AssertOnSamplerThread();
+  void AssertOnSamplerThread() const;
 
   /**
    * Returns true if currently on the APZSampler's "sampler thread".
    */
-  bool IsSamplerThread();
+  bool IsSamplerThread() const;
 
 protected:
   virtual ~APZSampler();
 
 private:
   RefPtr<APZCTreeManager> mApz;
 };
 
--- a/gfx/layers/apz/public/APZUpdater.h
+++ b/gfx/layers/apz/public/APZUpdater.h
@@ -8,16 +8,17 @@
 #define mozilla_layers_APZUpdater_h
 
 #include <deque>
 #include <unordered_map>
 
 #include "base/platform_thread.h"   // for PlatformThreadId
 #include "LayersTypes.h"
 #include "mozilla/layers/APZTestData.h"
+#include "mozilla/layers/WebRenderScrollData.h"
 #include "mozilla/StaticMutex.h"
 #include "nsThreadUtils.h"
 #include "Units.h"
 
 namespace mozilla {
 
 namespace wr {
 struct WrWindowId;
@@ -59,53 +60,60 @@ public:
   void UpdateFocusState(LayersId aRootLayerTreeId,
                         LayersId aOriginatingLayersId,
                         const FocusTarget& aFocusTarget);
   void UpdateHitTestingTree(LayersId aRootLayerTreeId,
                             Layer* aRoot,
                             bool aIsFirstPaint,
                             LayersId aOriginatingLayersId,
                             uint32_t aPaintSequenceNumber);
-  void UpdateHitTestingTree(LayersId aRootLayerTreeId,
-                            const WebRenderScrollData& aScrollData,
-                            bool aIsFirstPaint,
-                            LayersId aOriginatingLayersId,
-                            uint32_t aPaintSequenceNumber);
+  /**
+   * This should be called (in the WR-enabled case) when the compositor receives
+   * a new WebRenderScrollData for a layers id. The |aScrollData| parameter is
+   * the scroll data for |aOriginatingLayersId|. This function will store
+   * the new scroll data and update the focus state and hit-testing tree.
+   */
+  void UpdateScrollDataAndTreeState(LayersId aRootLayerTreeId,
+                                    LayersId aOriginatingLayersId,
+                                    WebRenderScrollData&& aScrollData);
 
   void NotifyLayerTreeAdopted(LayersId aLayersId,
                               const RefPtr<APZUpdater>& aOldUpdater);
   void NotifyLayerTreeRemoved(LayersId aLayersId);
 
   bool GetAPZTestData(LayersId aLayersId, APZTestData* aOutData);
 
   void SetTestAsyncScrollOffset(LayersId aLayersId,
                                 const FrameMetrics::ViewID& aScrollId,
                                 const CSSPoint& aOffset);
   void SetTestAsyncZoom(LayersId aLayersId,
                         const FrameMetrics::ViewID& aScrollId,
                         const LayerToParentLayerScale& aZoom);
 
+  // This can only be called on the updater thread.
+  const WebRenderScrollData* GetScrollData(LayersId aLayersId) const;
+
   /**
    * This can be used to assert that the current thread is the
    * updater thread (which samples the async transform).
    * This does nothing if thread assertions are disabled.
    */
-  void AssertOnUpdaterThread();
+  void AssertOnUpdaterThread() const;
 
   /**
    * Runs the given task on the APZ "updater thread" for this APZUpdater. If
    * this function is called from the updater thread itself then the task is
    * run immediately without getting queued.
    */
   void RunOnUpdaterThread(already_AddRefed<Runnable> aTask);
 
   /**
    * Returns true if currently on the APZUpdater's "updater thread".
    */
-  bool IsUpdaterThread();
+  bool IsUpdaterThread() const;
 
   /**
    * Dispatches the given task to the APZ "controller thread", but does it *from*
    * the updater thread. That is, if the thread on which this function is called
    * is not the updater thread, the task is first dispatched to the updater thread.
    * When the updater thread runs it (or if this is called directly on the updater
    * thread), that is when the task gets dispatched to the controller thread.
    * The controller thread then actually runs the task.
@@ -116,16 +124,22 @@ protected:
   virtual ~APZUpdater();
 
   bool UsingWebRenderUpdaterThread() const;
   static already_AddRefed<APZUpdater> GetUpdater(const wr::WrWindowId& aWindowId);
 
 private:
   RefPtr<APZCTreeManager> mApz;
 
+  // Map from layers id to WebRenderScrollData. This can only be touched on
+  // the updater thread.
+  std::unordered_map<LayersId,
+                     WebRenderScrollData,
+                     LayersId::HashFn> mScrollData;
+
   // Used to manage the mapping from a WR window id to APZUpdater. These are only
   // used if WebRender is enabled. Both sWindowIdMap and mWindowId should only
   // be used while holding the sWindowIdLock.
   static StaticMutex sWindowIdLock;
   static std::unordered_map<uint64_t, APZUpdater*> sWindowIdMap;
   Maybe<wr::WrWindowId> mWindowId;
 
   // If WebRender and async scene building are enabled, this holds the thread id
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -514,25 +514,24 @@ APZCTreeManager::UpdateHitTestingTree(La
 
   LayerMetricsWrapper root(aRoot);
   UpdateHitTestingTreeImpl(aRootLayerTreeId, root, aIsFirstPaint,
                            aOriginatingLayersId, aPaintSequenceNumber);
 }
 
 void
 APZCTreeManager::UpdateHitTestingTree(LayersId aRootLayerTreeId,
-                                      const WebRenderScrollData& aScrollData,
+                                      const WebRenderScrollDataWrapper& aScrollWrapper,
                                       bool aIsFirstPaint,
                                       LayersId aOriginatingLayersId,
                                       uint32_t aPaintSequenceNumber)
 {
   AssertOnUpdaterThread();
 
-  WebRenderScrollDataWrapper wrapper(&aScrollData);
-  UpdateHitTestingTreeImpl(aRootLayerTreeId, wrapper, aIsFirstPaint,
+  UpdateHitTestingTreeImpl(aRootLayerTreeId, aScrollWrapper, aIsFirstPaint,
                            aOriginatingLayersId, aPaintSequenceNumber);
 }
 
 bool
 APZCTreeManager::PushStateToWR(wr::TransactionBuilder& aTxn,
                                const TimeStamp& aSampleTime,
                                nsTArray<wr::WrTransformProperty>& aTransformArray)
 {
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -52,17 +52,17 @@ class OverscrollHandoffChain;
 struct OverscrollHandoffState;
 class FocusTarget;
 struct FlingHandoffState;
 struct ScrollableLayerGuidHash;
 class LayerMetricsWrapper;
 class InputQueue;
 class GeckoContentController;
 class HitTestingTreeNode;
-class WebRenderScrollData;
+class WebRenderScrollDataWrapper;
 struct AncestorTransform;
 struct ScrollThumbData;
 
 /**
  * ****************** NOTE ON LOCK ORDERING IN APZ **************************
  *
  * There are two main kinds of locks used by APZ: APZCTreeManager::mTreeLock
  * ("the tree lock") and AsyncPanZoomController::mRecursiveMutex ("APZC locks").
@@ -184,17 +184,17 @@ public:
 
   /**
    * Same as the above UpdateHitTestingTree, except slightly modified to take
    * the scrolling data passed over PWebRenderBridge instead of the raw layer
    * tree. This version is used when WebRender is enabled because we don't have
    * shadow layers in that scenario.
    */
   void UpdateHitTestingTree(LayersId aRootLayerTreeId,
-                            const WebRenderScrollData& aScrollData,
+                            const WebRenderScrollDataWrapper& aScrollWrapper,
                             bool aIsFirstPaint,
                             LayersId aOriginatingLayersId,
                             uint32_t aPaintSequenceNumber);
 
   /**
    * Called when webrender is enabled, from the sampler thread. This function
    * walks through the tree of APZC instances and tells webrender about the
    * async scroll position. It also advances APZ animations to the specified
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -141,23 +141,23 @@ APZSampler::HasUnusedAsyncTransform(cons
 
   AsyncPanZoomController* apzc = aLayer.GetApzc();
   return apzc
       && !apzc->GetAsyncTransformAppliedToContent()
       && !AsyncTransformComponentMatrix(apzc->GetCurrentAsyncTransform(AsyncPanZoomController::eForCompositing)).IsIdentity();
 }
 
 void
-APZSampler::AssertOnSamplerThread()
+APZSampler::AssertOnSamplerThread() const
 {
   if (APZThreadUtils::GetThreadAssertionsEnabled()) {
     MOZ_ASSERT(IsSamplerThread());
   }
 }
 
 bool
-APZSampler::IsSamplerThread()
+APZSampler::IsSamplerThread() const
 {
   return CompositorThreadHolder::IsInCompositorThread();
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/src/APZUpdater.cpp
+++ b/gfx/layers/apz/src/APZUpdater.cpp
@@ -7,17 +7,17 @@
 #include "mozilla/layers/APZUpdater.h"
 
 #include "APZCTreeManager.h"
 #include "AsyncPanZoomController.h"
 #include "base/task.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/SynchronousTask.h"
-#include "mozilla/layers/WebRenderScrollData.h"
+#include "mozilla/layers/WebRenderScrollDataWrapper.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 
 namespace mozilla {
 namespace layers {
 
 StaticMutex APZUpdater::sWindowIdLock;
 std::unordered_map<uint64_t, APZUpdater*> APZUpdater::sWindowIdMap;
@@ -128,43 +128,39 @@ APZUpdater::UpdateHitTestingTree(LayersI
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   AssertOnUpdaterThread();
   mApz->UpdateHitTestingTree(aRootLayerTreeId, aRoot, aIsFirstPaint,
       aOriginatingLayersId, aPaintSequenceNumber);
 }
 
 void
-APZUpdater::UpdateHitTestingTree(LayersId aRootLayerTreeId,
-                                 const WebRenderScrollData& aScrollData,
-                                 bool aIsFirstPaint,
-                                 LayersId aOriginatingLayersId,
-                                 uint32_t aPaintSequenceNumber)
+APZUpdater::UpdateScrollDataAndTreeState(LayersId aRootLayerTreeId,
+                                         LayersId aOriginatingLayersId,
+                                         WebRenderScrollData&& aScrollData)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  // use the local variable to resolve the function overload.
-  auto func = static_cast<void (APZCTreeManager::*)(LayersId,
-                                                    const WebRenderScrollData&,
-                                                    bool,
-                                                    LayersId,
-                                                    uint32_t)>
-      (&APZCTreeManager::UpdateHitTestingTree);
-  RunOnUpdaterThread(NewRunnableMethod<LayersId,
-                                       WebRenderScrollData,
-                                       bool,
-                                       LayersId,
-                                       uint32_t>(
-      "APZUpdater::UpdateHitTestingTree",
-      mApz,
-      func,
-      aRootLayerTreeId,
-      aScrollData,
-      aIsFirstPaint,
-      aOriginatingLayersId,
-      aPaintSequenceNumber));
+  RefPtr<APZUpdater> self = this;
+  RunOnUpdaterThread(NS_NewRunnableFunction(
+    "APZUpdater::UpdateHitTestingTree",
+    [=,aScrollData=Move(aScrollData)]() {
+      self->mApz->UpdateFocusState(aRootLayerTreeId,
+          aOriginatingLayersId, aScrollData.GetFocusTarget());
+
+      self->mScrollData[aOriginatingLayersId] = aScrollData;
+      auto root = self->mScrollData.find(aRootLayerTreeId);
+      if (root == self->mScrollData.end()) {
+        return;
+      }
+      self->mApz->UpdateHitTestingTree(aRootLayerTreeId,
+          WebRenderScrollDataWrapper(*self, &(root->second)),
+          aScrollData.IsFirstPaint(), aOriginatingLayersId,
+          aScrollData.GetPaintSequenceNumber());
+    }
+  ));
 }
 
 void
 APZUpdater::NotifyLayerTreeAdopted(LayersId aLayersId,
                                    const RefPtr<APZUpdater>& aOldUpdater)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   RunOnUpdaterThread(NewRunnableMethod<LayersId, RefPtr<APZCTreeManager>>(
@@ -174,21 +170,24 @@ APZUpdater::NotifyLayerTreeAdopted(Layer
       aLayersId,
       aOldUpdater ? aOldUpdater->mApz : nullptr));
 }
 
 void
 APZUpdater::NotifyLayerTreeRemoved(LayersId aLayersId)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  RunOnUpdaterThread(NewRunnableMethod<LayersId>(
-      "APZUpdater::NotifyLayerTreeRemoved",
-      mApz,
-      &APZCTreeManager::NotifyLayerTreeRemoved,
-      aLayersId));
+  RefPtr<APZUpdater> self = this;
+  RunOnUpdaterThread(NS_NewRunnableFunction(
+    "APZUpdater::NotifyLayerTreeRemoved",
+    [=]() {
+      self->mScrollData.erase(aLayersId);
+      self->mApz->NotifyLayerTreeRemoved(aLayersId);
+    }
+  ));
 }
 
 bool
 APZUpdater::GetAPZTestData(LayersId aLayersId,
                            APZTestData* aOutData)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
 
@@ -244,18 +243,26 @@ APZUpdater::SetTestAsyncZoom(LayersId aL
         apzc->SetTestAsyncZoom(aZoom);
       } else {
         NS_WARNING("Unable to find APZC in SetTestAsyncZoom");
       }
     }
   ));
 }
 
+const WebRenderScrollData*
+APZUpdater::GetScrollData(LayersId aLayersId) const
+{
+  AssertOnUpdaterThread();
+  auto it = mScrollData.find(aLayersId);
+  return (it == mScrollData.end() ? nullptr : &(it->second));
+}
+
 void
-APZUpdater::AssertOnUpdaterThread()
+APZUpdater::AssertOnUpdaterThread() const
 {
   if (APZThreadUtils::GetThreadAssertionsEnabled()) {
     MOZ_ASSERT(IsUpdaterThread());
   }
 }
 
 void
 APZUpdater::RunOnUpdaterThread(already_AddRefed<Runnable> aTask)
@@ -295,17 +302,17 @@ APZUpdater::RunOnUpdaterThread(already_A
     loop->PostTask(task.forget());
   } else {
     // Could happen during startup
     NS_WARNING("Dropping task posted to updater thread");
   }
 }
 
 bool
-APZUpdater::IsUpdaterThread()
+APZUpdater::IsUpdaterThread() const
 {
   if (UsingWebRenderUpdaterThread()) {
     return PlatformThread::CurrentId() == *mUpdaterThreadId;
   }
   return CompositorThreadHolder::IsInCompositorThread();
 }
 
 void
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -501,35 +501,38 @@ WebRenderBridgeParent::GetRootCompositor
       CompositorBridgeParent::GetIndirectShadowTree(GetLayersId());
   if (!lts) {
     return nullptr;
   }
   return lts->mParent;
 }
 
 void
-WebRenderBridgeParent::UpdateAPZ(bool aUpdateHitTestingTree)
+WebRenderBridgeParent::UpdateAPZFocusState(const FocusTarget& aFocus)
 {
   CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
   if (!cbp) {
     return;
   }
   LayersId rootLayersId = cbp->RootLayerTreeId();
-  RefPtr<WebRenderBridgeParent> rootWrbp = cbp->GetWebRenderBridgeParent();
-  if (!rootWrbp) {
+  if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
+    apz->UpdateFocusState(rootLayersId, GetLayersId(), aFocus);
+  }
+}
+
+void
+WebRenderBridgeParent::UpdateAPZScrollData(WebRenderScrollData&& aData)
+{
+  CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
+  if (!cbp) {
     return;
   }
+  LayersId rootLayersId = cbp->RootLayerTreeId();
   if (RefPtr<APZUpdater> apz = cbp->GetAPZUpdater()) {
-    apz->UpdateFocusState(rootLayersId, GetLayersId(),
-                          mScrollData.GetFocusTarget());
-    if (aUpdateHitTestingTree) {
-      apz->UpdateHitTestingTree(rootLayersId, rootWrbp->GetScrollData(),
-          mScrollData.IsFirstPaint(), GetLayersId(),
-          mScrollData.GetPaintSequenceNumber());
-    }
+    apz->UpdateScrollDataAndTreeState(rootLayersId, GetLayersId(), Move(aData));
   }
 }
 
 bool
 WebRenderBridgeParent::PushAPZStateToWR(wr::TransactionBuilder& aTxn,
                                         nsTArray<wr::WrTransformProperty>& aTransformArray)
 {
   CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
@@ -545,23 +548,16 @@ WebRenderBridgeParent::PushAPZStateToWR(
     if (frameInterval != TimeDuration::Forever()) {
       animationTime += frameInterval;
     }
     return apz->PushStateToWR(aTxn, animationTime, aTransformArray);
   }
   return false;
 }
 
-const WebRenderScrollData&
-WebRenderBridgeParent::GetScrollData() const
-{
-  MOZ_ASSERT(mozilla::layers::CompositorThreadHolder::IsInCompositorThread());
-  return mScrollData;
-}
-
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
                                           InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                           InfallibleTArray<OpDestroy>&& aToDestroy,
                                           const uint64_t& aFwdTransactionId,
                                           const uint64_t& aTransactionId,
                                           const wr::LayoutSize& aContentSize,
                                           ipc::ByteBuf&& dl,
@@ -623,18 +619,21 @@ WebRenderBridgeParent::RecvSetDisplayLis
 
     if (ShouldParentObserveEpoch()) {
       mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
     }
   }
 
   HoldPendingTransactionId(wrEpoch, aTransactionId, aTxnStartTime, aFwdTime);
 
-  mScrollData = aScrollData;
-  UpdateAPZ(true);
+  // aScrollData is moved into this function but that is not reflected by the
+  // function signature due to the way the IPDL generator works. We remove the
+  // const so that we can move this structure all the way to the desired
+  // destination.
+  UpdateAPZScrollData(Move(const_cast<WebRenderScrollData&>(aScrollData)));
 
   if (mIdNamespace != aIdNamespace) {
     // Pretend we composited since someone is wating for this event,
     // though DisplayList was not pushed to webrender.
     TimeStamp now = TimeStamp::Now();
     mCompositorBridge->DidComposite(GetLayersId(), now, now);
   }
 
@@ -668,18 +667,17 @@ WebRenderBridgeParent::RecvEmptyTransact
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
 
   if (!aCommands.IsEmpty()) {
     mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
     ProcessWebRenderParentCommands(aCommands);
     ScheduleGenerateFrame();
   }
 
-  mScrollData.SetFocusTarget(aFocusTarget);
-  UpdateAPZ(false);
+  UpdateAPZFocusState(aFocusTarget);
 
   if (!aCommands.IsEmpty()) {
     wr::TransactionBuilder txn;
     wr::Epoch wrEpoch = GetNextWrEpoch();
     txn.UpdateEpoch(mPipelineId, wrEpoch);
     mApi->SendTransaction(txn);
 
     HoldPendingTransactionId(wrEpoch, aTransactionId, aTxnStartTime, aFwdTime);
@@ -698,18 +696,17 @@ WebRenderBridgeParent::RecvEmptyTransact
   }
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetFocusTarget(const FocusTarget& aFocusTarget)
 {
-  mScrollData.SetFocusTarget(aFocusTarget);
-  UpdateAPZ(false);
+  UpdateAPZFocusState(aFocusTarget);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvParentCommands(nsTArray<WebRenderParentCommand>&& aCommands)
 {
   if (mDestroyed) {
     return IPC_OK();
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -165,18 +165,18 @@ public:
 
   void ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications);
 
   wr::IdNamespace GetIdNamespace()
   {
     return mIdNamespace;
   }
 
-  void UpdateAPZ(bool aUpdateHitTestingTree);
-  const WebRenderScrollData& GetScrollData() const;
+  void UpdateAPZFocusState(const FocusTarget& aFocus);
+  void UpdateAPZScrollData(WebRenderScrollData&& aData);
 
   void FlushRendering();
   void FlushRenderingAsync();
 
   /**
    * Schedule generating WebRender frame definitely at next composite timing.
    *
    * WebRenderBridgeParent uses composite timing to check if there is an update
@@ -266,17 +266,14 @@ private:
   std::queue<PendingTransactionId> mPendingTransactionIds;
   wr::Epoch mWrEpoch;
   wr::IdNamespace mIdNamespace;
 
   bool mPaused;
   bool mDestroyed;
   bool mForceRendering;
   bool mReceivedDisplayList;
-
-  // Can only be accessed on the compositor thread.
-  WebRenderScrollData mScrollData;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_WebRenderBridgeParent_h
--- a/gfx/layers/wr/WebRenderScrollDataWrapper.h
+++ b/gfx/layers/wr/WebRenderScrollDataWrapper.h
@@ -39,18 +39,20 @@ namespace layers {
  * This class being declared a MOZ_STACK_CLASS should help with that.
  *
  * Refer to LayerMetricsWrapper.h for actual documentation on the exposed API.
  */
 class MOZ_STACK_CLASS WebRenderScrollDataWrapper {
 public:
   // Basic constructor for external callers. Starts the walker at the root of
   // the tree.
-  explicit WebRenderScrollDataWrapper(const WebRenderScrollData* aData = nullptr)
-    : mData(aData)
+  explicit WebRenderScrollDataWrapper(const APZUpdater& aUpdater,
+                                      const WebRenderScrollData* aData = nullptr)
+    : mUpdater(&aUpdater)
+    , mData(aData)
     , mLayerIndex(0)
     , mContainingSubtreeLastIndex(0)
     , mLayer(nullptr)
     , mMetadataIndex(0)
   {
     if (!mData) {
       return;
     }
@@ -70,20 +72,22 @@ public:
       mMetadataIndex--;
     }
   }
 
 private:
   // Internal constructor for walking from one WebRenderLayerScrollData to
   // another. In this case we need to recompute the mMetadataIndex to be the
   // "topmost" scroll metadata on the new layer.
-  WebRenderScrollDataWrapper(const WebRenderScrollData* aData,
+  WebRenderScrollDataWrapper(const APZUpdater* aUpdater,
+                             const WebRenderScrollData* aData,
                              size_t aLayerIndex,
                              size_t aContainingSubtreeLastIndex)
-    : mData(aData)
+    : mUpdater(aUpdater)
+    , mData(aData)
     , mLayerIndex(aLayerIndex)
     , mContainingSubtreeLastIndex(aContainingSubtreeLastIndex)
     , mLayer(nullptr)
     , mMetadataIndex(0)
   {
     MOZ_ASSERT(mData);
     mLayer = mData->GetLayerData(mLayerIndex);
     MOZ_ASSERT(mLayer);
@@ -93,22 +97,24 @@ private:
     mMetadataIndex = mLayer->GetScrollMetadataCount();
     if (mMetadataIndex > 0) {
       mMetadataIndex--;
     }
   }
 
   // Internal constructor for walking from one metadata to another metadata on
   // the same WebRenderLayerScrollData.
-  WebRenderScrollDataWrapper(const WebRenderScrollData* aData,
+  WebRenderScrollDataWrapper(const APZUpdater* aUpdater,
+                             const WebRenderScrollData* aData,
                              size_t aLayerIndex,
                              size_t aContainingSubtreeLastIndex,
                              const WebRenderLayerScrollData* aLayer,
                              uint32_t aMetadataIndex)
-    : mData(aData)
+    : mUpdater(aUpdater)
+    , mData(aData)
     , mLayerIndex(aLayerIndex)
     , mContainingSubtreeLastIndex(aContainingSubtreeLastIndex)
     , mLayer(aLayer)
     , mMetadataIndex(aMetadataIndex)
   {
     MOZ_ASSERT(mData);
     MOZ_ASSERT(mLayer);
     MOZ_ASSERT(mLayer == mData->GetLayerData(mLayerIndex));
@@ -129,66 +135,63 @@ public:
   WebRenderScrollDataWrapper GetLastChild() const
   {
     MOZ_ASSERT(IsValid());
 
     if (!AtBottomLayer()) {
       // If we're still walking around in the virtual container layers created
       // by the ScrollMetadata array, we just need to update the metadata index
       // and that's it.
-      return WebRenderScrollDataWrapper(mData, mLayerIndex,
+      return WebRenderScrollDataWrapper(mUpdater, mData, mLayerIndex,
           mContainingSubtreeLastIndex, mLayer, mMetadataIndex - 1);
     }
 
     // Otherwise, we need to walk to a different WebRenderLayerScrollData in
     // mData.
 
     // Since mData contains the layer in depth-first, last-to-first order,
     // the index after mLayerIndex must be mLayerIndex's last child, if it
     // has any children (indicated by GetDescendantCount() > 0). Furthermore
     // we compute the first index outside the subtree rooted at this node
     // (in |subtreeLastIndex|) and pass that in to the child wrapper to use as
     // its mContainingSubtreeLastIndex.
     if (mLayer->GetDescendantCount() > 0) {
       size_t prevSiblingIndex = mLayerIndex + 1 + mLayer->GetDescendantCount();
       size_t subtreeLastIndex = std::min(mContainingSubtreeLastIndex, prevSiblingIndex);
-      return WebRenderScrollDataWrapper(mData, mLayerIndex + 1, subtreeLastIndex);
+      return WebRenderScrollDataWrapper(mUpdater, mData, mLayerIndex + 1, subtreeLastIndex);
     }
 
     // We've run out of descendants. But! If the original layer was a RefLayer,
     // then it connects to another layer tree and we need to traverse that too.
     // So return a WebRenderScrollDataWrapper for the root of the child layer
     // tree.
     if (mLayer->GetReferentId()) {
-      CompositorBridgeParent::LayerTreeState* lts =
-          CompositorBridgeParent::GetIndirectShadowTree(mLayer->GetReferentId().value());
-      if (lts && lts->mWrBridge) {
-        return WebRenderScrollDataWrapper(&(lts->mWrBridge->GetScrollData()));
-      }
+      return WebRenderScrollDataWrapper(*mUpdater,
+          mUpdater->GetScrollData(*mLayer->GetReferentId()));
     }
 
-    return WebRenderScrollDataWrapper();
+    return WebRenderScrollDataWrapper(*mUpdater);
   }
 
   WebRenderScrollDataWrapper GetPrevSibling() const
   {
     MOZ_ASSERT(IsValid());
 
     if (!AtTopLayer()) {
       // The virtual container layers don't have siblings
-      return WebRenderScrollDataWrapper();
+      return WebRenderScrollDataWrapper(*mUpdater);
     }
 
     // Skip past the descendants to get to the previous sibling. However, we
     // might be at the last sibling already.
     size_t prevSiblingIndex = mLayerIndex + 1 + mLayer->GetDescendantCount();
     if (prevSiblingIndex < mContainingSubtreeLastIndex) {
-      return WebRenderScrollDataWrapper(mData, prevSiblingIndex, mContainingSubtreeLastIndex);
+      return WebRenderScrollDataWrapper(mUpdater, mData, prevSiblingIndex, mContainingSubtreeLastIndex);
     }
-    return WebRenderScrollDataWrapper();
+    return WebRenderScrollDataWrapper(*mUpdater);
   }
 
   const ScrollMetadata& Metadata() const
   {
     MOZ_ASSERT(IsValid());
 
     if (mMetadataIndex >= mLayer->GetScrollMetadataCount()) {
       return *ScrollMetadata::sNullMetadata;
@@ -335,16 +338,17 @@ private:
   }
 
   bool AtTopLayer() const
   {
     return mLayer->GetScrollMetadataCount() == 0 || mMetadataIndex == mLayer->GetScrollMetadataCount() - 1;
   }
 
 private:
+  const APZUpdater* mUpdater;
   const WebRenderScrollData* mData;
   // The index (in mData->mLayerScrollData) of the WebRenderLayerScrollData this
   // wrapper is pointing to.
   size_t mLayerIndex;
   // The upper bound on the set of valid indices inside the subtree rooted at
   // the parent of this "layer". That is, any layer index |i| in the range
   // mLayerIndex <= i < mContainingSubtreeLastIndex is guaranteed to point to
   // a layer that is a descendant of "parent", where "parent" is the parent