Bug 1447299 - Ensure all APZSampler functions run on the sampler thread. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 28 Mar 2018 14:57:06 -0400
changeset 774007 66ca68292896c2a1bff42990b01abc5448103d63
parent 774006 a9ca5449ccbd298969d74b62b97a5e9c7d751ed6
push id104365
push userkgupta@mozilla.com
push dateWed, 28 Mar 2018 18:59:12 +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: JPgGlgUUsgg
gfx/layers/apz/src/APZSampler.cpp
gfx/layers/ipc/SynchronousTask.h
--- 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)
 {
@@ -33,65 +34,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(LayersId aRootLayerTreeId,
                              LayersId aOriginatingLayersId,
                              const FocusTarget& aFocusTarget)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->UpdateFocusState(aRootLayerTreeId, aOriginatingLayersId, aFocusTarget);
+  RunOnSamplerThread(NewRunnableMethod<LayersId, LayersId, FocusTarget>(
+      "APZSampler::UpdateFocusState",
+      mApz,
+      &APZCTreeManager::UpdateFocusState,
+      aRootLayerTreeId,
+      aOriginatingLayersId,
+      aFocusTarget));
 }
 
 void
 APZSampler::UpdateHitTestingTree(LayersId aRootLayerTreeId,
                                  Layer* aRoot,
                                  bool aIsFirstPaint,
                                  LayersId aOriginatingLayersId,
                                  uint32_t aPaintSequenceNumber)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  AssertOnSamplerThread();
   mApz->UpdateHitTestingTree(aRootLayerTreeId, aRoot, aIsFirstPaint,
       aOriginatingLayersId, aPaintSequenceNumber);
 }
 
 void
 APZSampler::UpdateHitTestingTree(LayersId aRootLayerTreeId,
                                  const WebRenderScrollData& aScrollData,
                                  bool aIsFirstPaint,
                                  LayersId 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::*)(LayersId,
+                                                    const WebRenderScrollData&,
+                                                    bool,
+                                                    LayersId,
+                                                    uint32_t)>
+      (&APZCTreeManager::UpdateHitTestingTree);
+  RunOnSamplerThread(NewRunnableMethod<LayersId,
+                                       WebRenderScrollData,
+                                       bool,
+                                       LayersId,
+                                       uint32_t>(
+      "APZSampler::UpdateHitTestingTree",
+      mApz,
+      func,
+      aRootLayerTreeId,
+      aScrollData,
+      aIsFirstPaint,
+      aOriginatingLayersId,
+      aPaintSequenceNumber));
 }
 
 void
 APZSampler::NotifyLayerTreeAdopted(LayersId aLayersId,
                                    const RefPtr<APZSampler>& aOldSampler)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->NotifyLayerTreeAdopted(aLayersId, aOldSampler ? aOldSampler->mApz : nullptr);
+  RunOnSamplerThread(NewRunnableMethod<LayersId, RefPtr<APZCTreeManager>>(
+      "APZSampler::NotifyLayerTreeAdopted",
+      mApz,
+      &APZCTreeManager::NotifyLayerTreeAdopted,
+      aLayersId,
+      aOldSampler ? aOldSampler->mApz : nullptr));
 }
 
 void
 APZSampler::NotifyLayerTreeRemoved(LayersId aLayersId)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mApz->NotifyLayerTreeRemoved(aLayersId);
+  RunOnSamplerThread(NewRunnableMethod<LayersId>(
+      "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
@@ -99,52 +137,80 @@ APZSampler::PushStateToWR(wr::Transactio
   return mApz->PushStateToWR(aTxn, aSampleTime, aTransformArray);
 }
 
 bool
 APZSampler::GetAPZTestData(LayersId 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(LayersId 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<APZCTreeManager> apz = mApz;
+  RunOnSamplerThread(NS_NewRunnableFunction(
+    "APZSampler::SetTestAsyncScrollOffset",
+    [=]() {
+      RefPtr<AsyncPanZoomController> apzc = apz->GetTargetAPZC(aLayersId, aScrollId);
+      if (apzc) {
+        apzc->SetTestAsyncScrollOffset(aOffset);
+      } else {
+        NS_WARNING("Unable to find APZC in SetTestAsyncScrollOffset");
+      }
+    }
+  ));
 }
 
 void
 APZSampler::SetTestAsyncZoom(LayersId 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<APZCTreeManager> apz = mApz;
+  RunOnSamplerThread(NS_NewRunnableFunction(
+    "APZSampler::SetTestAsyncZoom",
+    [=]() {
+      RefPtr<AsyncPanZoomController> apzc = apz->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)
@@ -162,63 +228,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()
--- a/gfx/layers/ipc/SynchronousTask.h
+++ b/gfx/layers/ipc/SynchronousTask.h
@@ -8,17 +8,16 @@
 #define MOZILLA_GFX_SYNCHRONOUSTASK_H
 
 #include "mozilla/ReentrantMonitor.h"   // for ReentrantMonitor, etc
 
 namespace mozilla {
 namespace layers {
 
 // Helper that creates a monitor and a "done" flag, then enters the monitor.
-// This can go away when we switch ImageBridge to an XPCOM thread.
 class MOZ_STACK_CLASS SynchronousTask
 {
   friend class AutoCompleteTask;
 
 public:
   explicit SynchronousTask(const char* name)
    : mMonitor(name),
      mAutoEnter(mMonitor),