Bug 1447299 - Ensure all APZSampler functions run on the sampler thread. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 22 Mar 2018 16:35:23 -0400
changeset 771269 8aab11873e268797ea45b464a7b67bdfc60bf081
parent 771268 71c22c316850825ad91c32f21c16c42dea9700f8
push id103646
push userkgupta@mozilla.com
push dateThu, 22 Mar 2018 21:38:36 +0000
reviewersbotond
bugs1447299
milestone61.0a1
Bug 1447299 - Ensure all APZSampler functions run on the sampler thread. r?botond Functions in APZSampler that are only invoked without WR (e.g. from AsyncCompositionManager only) can be asserted as running on the sampler thread. Functions that are invoked with WR need to be bounced onto the sampler thread. In all cases the functions are called from the compositor thread, and so we assert that as well. MozReview-Commit-ID: 6Xy0QMqnq39
gfx/layers/apz/src/APZSampler.cpp
--- a/gfx/layers/apz/src/APZSampler.cpp
+++ b/gfx/layers/apz/src/APZSampler.cpp
@@ -6,16 +6,17 @@
 
 #include "mozilla/layers/APZSampler.h"
 
 #include "APZCTreeManager.h"
 #include "AsyncPanZoomController.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/LayerMetricsWrapper.h"
+#include "mozilla/layers/SynchronousTask.h"
 #include "TreeTraversal.h"
 
 namespace mozilla {
 namespace layers {
 
 APZSampler::APZSampler(const RefPtr<APZCTreeManager>& aApz)
   : mApz(aApz)
 {
@@ -32,65 +33,102 @@ APZSampler::HasTreeManager(const RefPtr<
 {
   return aApz.get() == mApz.get();
 }
 
 void
 APZSampler::ClearTree()
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->ClearTree();
+  RunOnSamplerThread(NewRunnableMethod(
+      "APZSampler::ClearTree",
+      mApz,
+      &APZCTreeManager::ClearTree));
 }
 
 void
 APZSampler::UpdateFocusState(uint64_t aRootLayerTreeId,
                              uint64_t aOriginatingLayersId,
                              const FocusTarget& aFocusTarget)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->UpdateFocusState(aRootLayerTreeId, aOriginatingLayersId, aFocusTarget);
+  RunOnSamplerThread(NewRunnableMethod<uint64_t, uint64_t, FocusTarget>(
+      "APZSampler::UpdateFocusState",
+      mApz,
+      &APZCTreeManager::UpdateFocusState,
+      aRootLayerTreeId,
+      aOriginatingLayersId,
+      aFocusTarget));
 }
 
 void
 APZSampler::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
                                  Layer* aRoot,
                                  bool aIsFirstPaint,
                                  uint64_t aOriginatingLayersId,
                                  uint32_t aPaintSequenceNumber)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
   mApz->UpdateHitTestingTree(aRootLayerTreeId, aRoot, aIsFirstPaint,
       aOriginatingLayersId, aPaintSequenceNumber);
 }
 
 void
 APZSampler::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
                                  const WebRenderScrollData& aScrollData,
                                  bool aIsFirstPaint,
                                  uint64_t aOriginatingLayersId,
                                  uint32_t aPaintSequenceNumber)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->UpdateHitTestingTree(aRootLayerTreeId, aScrollData, aIsFirstPaint,
-      aOriginatingLayersId, aPaintSequenceNumber);
+  // use the local variable to resolve the function overload.
+  auto func = static_cast<void (APZCTreeManager::*)(uint64_t,
+                                                    const WebRenderScrollData&,
+                                                    bool,
+                                                    uint64_t,
+                                                    uint32_t)>
+      (&APZCTreeManager::UpdateHitTestingTree);
+  RunOnSamplerThread(NewRunnableMethod<uint64_t,
+                                       WebRenderScrollData,
+                                       bool,
+                                       uint64_t,
+                                       uint32_t>(
+      "APZSampler::UpdateHitTestingTree",
+      mApz,
+      func,
+      aRootLayerTreeId,
+      aScrollData,
+      aIsFirstPaint,
+      aOriginatingLayersId,
+      aPaintSequenceNumber));
 }
 
 void
 APZSampler::NotifyLayerTreeAdopted(uint64_t aLayersId,
                                    const RefPtr<APZSampler>& aOldSampler)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->NotifyLayerTreeAdopted(aLayersId, aOldSampler ? aOldSampler->mApz : nullptr);
+  RunOnSamplerThread(NewRunnableMethod<uint64_t, RefPtr<APZCTreeManager>>(
+      "APZSampler::NotifyLayerTreeAdopted",
+      mApz,
+      &APZCTreeManager::NotifyLayerTreeAdopted,
+      aLayersId,
+      aOldSampler ? aOldSampler->mApz : nullptr));
 }
 
 void
 APZSampler::NotifyLayerTreeRemoved(uint64_t aLayersId)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->NotifyLayerTreeRemoved(aLayersId);
+  RunOnSamplerThread(NewRunnableMethod<uint64_t>(
+      "APZSampler::NotifyLayerTreeRemoved",
+      mApz,
+      &APZCTreeManager::NotifyLayerTreeRemoved,
+      aLayersId));
 }
 
 bool
 APZSampler::PushStateToWR(wr::TransactionBuilder& aTxn,
                           const TimeStamp& aSampleTime,
                           nsTArray<wr::WrTransformProperty>& aTransformArray)
 {
   // This function will be removed eventually since we'll have WR pull
@@ -98,52 +136,80 @@ APZSampler::PushStateToWR(wr::Transactio
   return mApz->PushStateToWR(aTxn, aSampleTime, aTransformArray);
 }
 
 bool
 APZSampler::GetAPZTestData(uint64_t aLayersId,
                            APZTestData* aOutData)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  return mApz->GetAPZTestData(aLayersId, aOutData);
+
+  RefPtr<APZCTreeManager> apz = mApz;
+  bool ret = false;
+  SynchronousTask waiter("APZSampler::GetAPZTestData");
+  RunOnSamplerThread(NS_NewRunnableFunction(
+    "APZSampler::GetAPZTestData",
+    [&]() {
+      AutoCompleteTask notifier(&waiter);
+      ret = apz->GetAPZTestData(aLayersId, aOutData);
+    }
+  ));
+
+  // Wait until the task posted above has run and populated aOutData and ret
+  waiter.Wait();
+
+  return ret;
 }
 
 void
 APZSampler::SetTestAsyncScrollOffset(uint64_t aLayersId,
                                      const FrameMetrics::ViewID& aScrollId,
                                      const CSSPoint& aOffset)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  RefPtr<AsyncPanZoomController> apzc = mApz->GetTargetAPZC(aLayersId, aScrollId);
-  if (apzc) {
-    apzc->SetTestAsyncScrollOffset(aOffset);
-  } else {
-    NS_WARNING("Unable to find APZC in SetTestAsyncScrollOffset");
-  }
+  RefPtr<APZSampler> self = this;
+  RunOnSamplerThread(NS_NewRunnableFunction(
+    "APZSampler::SetTestAsyncScrollOffset",
+    [=]() {
+      RefPtr<AsyncPanZoomController> apzc = self->mApz->GetTargetAPZC(aLayersId, aScrollId);
+      if (apzc) {
+        apzc->SetTestAsyncScrollOffset(aOffset);
+      } else {
+        NS_WARNING("Unable to find APZC in SetTestAsyncScrollOffset");
+      }
+    }
+  ));
 }
 
 void
 APZSampler::SetTestAsyncZoom(uint64_t aLayersId,
                              const FrameMetrics::ViewID& aScrollId,
                              const LayerToParentLayerScale& aZoom)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  RefPtr<AsyncPanZoomController> apzc = mApz->GetTargetAPZC(aLayersId, aScrollId);
-  if (apzc) {
-    apzc->SetTestAsyncZoom(aZoom);
-  } else {
-    NS_WARNING("Unable to find APZC in SetTestAsyncZoom");
-  }
+  RefPtr<APZSampler> self = this;
+  RunOnSamplerThread(NS_NewRunnableFunction(
+    "APZSampler::SetTestAsyncZoom",
+    [=]() {
+      RefPtr<AsyncPanZoomController> apzc = self->mApz->GetTargetAPZC(aLayersId, aScrollId);
+      if (apzc) {
+        apzc->SetTestAsyncZoom(aZoom);
+      } else {
+        NS_WARNING("Unable to find APZC in SetTestAsyncZoom");
+      }
+    }
+  ));
 }
 
 bool
 APZSampler::SampleAnimations(const LayerMetricsWrapper& aLayer,
                              const TimeStamp& aSampleTime)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
 
   // TODO: eventually we can drop the aLayer argument and just walk the APZ
   // tree directly in mApz.
 
   bool activeAnimations = false;
 
   ForEachNodePostOrder<ForwardIterator>(aLayer,
       [&activeAnimations, &aSampleTime](LayerMetricsWrapper aLayerMetrics)
@@ -161,63 +227,83 @@ APZSampler::SampleAnimations(const Layer
 LayerToParentLayerMatrix4x4
 APZSampler::ComputeTransformForScrollThumb(const LayerToParentLayerMatrix4x4& aCurrentTransform,
                                            const LayerMetricsWrapper& aContent,
                                            const ScrollThumbData& aThumbData,
                                            bool aScrollbarIsDescendant,
                                            AsyncTransformComponentMatrix* aOutClipTransform)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
   return mApz->ComputeTransformForScrollThumb(aCurrentTransform,
                                               aContent.GetTransform(),
                                               aContent.GetApzc(),
                                               aContent.Metrics(),
                                               aThumbData,
                                               aScrollbarIsDescendant,
                                               aOutClipTransform);
 }
 
 ParentLayerPoint
 APZSampler::GetCurrentAsyncScrollOffset(const LayerMetricsWrapper& aLayer)
 {
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForCompositing);
 }
 
 AsyncTransform
 APZSampler::GetCurrentAsyncTransform(const LayerMetricsWrapper& aLayer)
 {
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetCurrentAsyncTransform(AsyncPanZoomController::eForCompositing);
 }
 
 AsyncTransformComponentMatrix
 APZSampler::GetOverscrollTransform(const LayerMetricsWrapper& aLayer)
 {
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetOverscrollTransform(AsyncPanZoomController::eForCompositing);
 }
 
 AsyncTransformComponentMatrix
 APZSampler::GetCurrentAsyncTransformWithOverscroll(const LayerMetricsWrapper& aLayer)
 {
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
   MOZ_ASSERT(aLayer.GetApzc());
   return aLayer.GetApzc()->GetCurrentAsyncTransformWithOverscroll(AsyncPanZoomController::eForCompositing);
 }
 
 void
 APZSampler::MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer)
 {
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
   MOZ_ASSERT(aLayer.GetApzc());
   aLayer.GetApzc()->MarkAsyncTransformAppliedToContent();
 }
 
 bool
 APZSampler::HasUnusedAsyncTransform(const LayerMetricsWrapper& aLayer)
 {
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
+
   AsyncPanZoomController* apzc = aLayer.GetApzc();
   return apzc
       && !apzc->GetAsyncTransformAppliedToContent()
       && !AsyncTransformComponentMatrix(apzc->GetCurrentAsyncTransform(AsyncPanZoomController::eForCompositing)).IsIdentity();
 }
 
 void
 APZSampler::AssertOnSamplerThread()