Bug 1441916 - Move APZTestData from the LayerTreeState structure into the APZ. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 01 Mar 2018 23:00:40 -0500
changeset 406300 5b0855476e63525730ba4374b3445b55f1eda38f
parent 406299 1ecd27281e6bd0c84a97e0aa518fbd0e634a86bb
child 406301 243444effec32210c60750978e980c39d80d8648
push id33553
push usershindli@mozilla.com
push dateFri, 02 Mar 2018 23:05:47 +0000
treeherdermozilla-central@9d34236d48ff [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1441916
milestone60.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 1441916 - Move APZTestData from the LayerTreeState structure into the APZ. r=botond This encapsulates the APZTestData better inside APZCTreeManager, which we will want once we allow the hit-test tree update to happen on a thread other than the compositor thread. MozReview-Commit-ID: 66uSsagVfEu
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -229,17 +229,18 @@ APZCTreeManager::CalculatePendingDisplay
 
 APZCTreeManager::APZCTreeManager(uint64_t aRootLayersId)
     : mInputQueue(new InputQueue()),
       mRootLayersId(aRootLayersId),
       mTreeLock("APZCTreeLock"),
       mHitResultForInputBlock(CompositorHitTestInfo::eInvisibleToHitTest),
       mRetainedTouchIdentifier(-1),
       mInScrollbarTouchDrag(false),
-      mApzcTreeLog("apzctree")
+      mApzcTreeLog("apzctree"),
+      mTestDataLock("APZTestDataLock")
 {
   RefPtr<APZCTreeManager> self(this);
   NS_DispatchToMainThread(
     NS_NewRunnableFunction("layers::APZCTreeManager::APZCTreeManager", [self] {
       self->mFlushObserver = new CheckerboardFlushObserver(self);
     }));
   AsyncPanZoomController::InitializeGlobalState();
   mApzcTreeLog.ConditionOnPrefFunction(gfxPrefs::APZPrintTree);
@@ -265,24 +266,43 @@ APZCTreeManager::NotifyLayerTreeAdopted(
 {
   APZThreadUtils::AssertOnCompositorThread();
 
   MOZ_ASSERT(aOldApzcTreeManager);
   aOldApzcTreeManager->mFocusState.RemoveFocusTarget(aLayersId);
   // While we could move the focus target information from the old APZC tree
   // manager into this one, it's safer to not do that, as we'll probably have
   // that information repopulated soon anyway (on the next layers update).
+
+  UniquePtr<APZTestData> adoptedData;
+  { // scope lock for removal on oldApzcTreeManager
+    MutexAutoLock lock(aOldApzcTreeManager->mTestDataLock);
+    auto it = aOldApzcTreeManager->mTestData.find(aLayersId);
+    if (it != aOldApzcTreeManager->mTestData.end()) {
+      adoptedData = Move(it->second);
+      aOldApzcTreeManager->mTestData.erase(it);
+    }
+  }
+  if (adoptedData) {
+    MutexAutoLock lock(mTestDataLock);
+    mTestData[aLayersId] = Move(adoptedData);
+  }
 }
 
 void
 APZCTreeManager::NotifyLayerTreeRemoved(uint64_t aLayersId)
 {
   APZThreadUtils::AssertOnCompositorThread();
 
   mFocusState.RemoveFocusTarget(aLayersId);
+
+  { // scope lock
+    MutexAutoLock lock(mTestDataLock);
+    mTestData.erase(aLayersId);
+  }
 }
 
 AsyncPanZoomController*
 APZCTreeManager::NewAPZCInstance(uint64_t aLayersId,
                                  GeckoContentController* aController)
 {
   return new AsyncPanZoomController(aLayersId, this, mInputQueue,
     aController, AsyncPanZoomController::USE_GESTURE_DETECTOR);
@@ -311,20 +331,21 @@ APZCTreeManager::UpdateHitTestingTreeImp
   APZThreadUtils::AssertOnCompositorThread();
 
   RecursiveMutexAutoLock lock(mTreeLock);
 
   // For testing purposes, we log some data to the APZTestData associated with
   // the layers id that originated this update.
   APZTestData* testData = nullptr;
   if (gfxPrefs::APZTestLoggingEnabled()) {
-    if (LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aOriginatingLayersId)) {
-      testData = &state->mApzTestData;
-      testData->StartNewPaint(aPaintSequenceNumber);
-    }
+    MutexAutoLock lock(mTestDataLock);
+    UniquePtr<APZTestData> ptr = MakeUnique<APZTestData>();
+    auto result = mTestData.insert(std::make_pair(aOriginatingLayersId, Move(ptr)));
+    testData = result.first->second.get();
+    testData->StartNewPaint(aPaintSequenceNumber);
   }
 
   const LayerTreeState* treeState =
     CompositorBridgeParent::GetIndirectShadowTree(aRootLayerTreeId);
   MOZ_ASSERT(treeState);
   TreeBuildingState state(treeState, aIsFirstPaint, aOriginatingLayersId,
                           testData, aPaintSequenceNumber);
 
@@ -1133,20 +1154,21 @@ APZCTreeManager::ReceiveInputEvent(Input
         if (!apzc && mRootNode) {
           apzc = mRootNode->GetApzc();
         }
       }
 
       if (apzc) {
         if (gfxPrefs::APZTestLoggingEnabled() && mouseInput.mType == MouseInput::MOUSE_HITTEST) {
           ScrollableLayerGuid guid = apzc->GetGuid();
-          CompositorBridgeParent::CallWithIndirectShadowTree(guid.mLayersId,
-            [&](LayerTreeState& aState) -> void {
-              aState.mApzTestData.RecordHitResult(mouseInput.mOrigin, hitResult, guid.mScrollId);
-            });
+
+          MutexAutoLock lock(mTestDataLock);
+          auto it = mTestData.find(guid.mLayersId);
+          MOZ_ASSERT(it != mTestData.end());
+          it->second->RecordHitResult(mouseInput.mOrigin, hitResult, guid.mScrollId);
         }
 
         TargetConfirmationFlags confFlags{hitResult};
         bool apzDragEnabled = gfxPrefs::APZDragEnabled();
         if (apzDragEnabled && hitScrollbar) {
           // If scrollbar dragging is enabled and we hit a scrollbar, wait
           // for the main-thread confirmation because it contains drag metrics
           // that we need.
@@ -2937,16 +2959,30 @@ APZCTreeManager::GetContentController(ui
   RefPtr<GeckoContentController> controller;
   CompositorBridgeParent::CallWithIndirectShadowTree(aLayersId,
     [&](LayerTreeState& aState) -> void {
       controller = aState.mController;
     });
   return controller.forget();
 }
 
+bool
+APZCTreeManager::GetAPZTestData(uint64_t aLayersId,
+                                APZTestData* aOutData)
+{
+  APZThreadUtils::AssertOnCompositorThread();
+  MutexAutoLock lock(mTestDataLock);
+  auto it = mTestData.find(aLayersId);
+  if (it == mTestData.end()) {
+    return false;
+  }
+  *aOutData = *(it->second);
+  return true;
+}
+
 #if defined(MOZ_WIDGET_ANDROID)
 void
 APZCTreeManager::InitializeDynamicToolbarAnimator(const int64_t& aRootLayerTreeId)
 {
   MOZ_ASSERT(mToolbarAnimator);
   mToolbarAnimator->Initialize(aRootLayerTreeId);
 }
 
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -9,23 +9,25 @@
 
 #include <unordered_map>                          // for std::unordered_map
 
 #include "gfxPoint.h"                   // for gfxPoint
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
 #include "mozilla/gfx/CompositorHitTestInfo.h"
 #include "mozilla/gfx/Logging.h"        // for gfx::TreeLog
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
-#include "mozilla/layers/TouchCounter.h"// for TouchCounter
+#include "mozilla/layers/APZTestData.h" // for APZTestData
+#include "mozilla/layers/FocusState.h"  // for FocusState
 #include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager
 #include "mozilla/layers/KeyboardMap.h" // for KeyboardMap
-#include "mozilla/layers/FocusState.h"  // for FocusState
+#include "mozilla/layers/TouchCounter.h"// for TouchCounter
 #include "mozilla/RecursiveMutex.h"     // for RecursiveMutex
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/TimeStamp.h"          // for mozilla::TimeStamp
+#include "mozilla/UniquePtr.h"          // for UniquePtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 
 #if defined(MOZ_WIDGET_ANDROID)
 #include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
 #endif // defined(MOZ_WIDGET_ANDROID)
 
 namespace mozilla {
 class MultiTouchInput;
@@ -52,22 +54,23 @@ class InputQueue;
 class GeckoContentController;
 class HitTestingTreeNode;
 class WebRenderScrollData;
 struct AncestorTransform;
 
 /**
  * ****************** NOTE ON LOCK ORDERING IN APZ **************************
  *
- * There are two kinds of locks used by APZ: APZCTreeManager::mTreeLock
+ * There are two main kinds of locks used by APZ: APZCTreeManager::mTreeLock
  * ("the tree lock") and AsyncPanZoomController::mRecursiveMutex ("APZC locks").
+ * There is also the APZCTreeManager::mTestDataLock ("test lock").
  *
  * To avoid deadlock, we impose a lock ordering between these locks, which is:
  *
- *      tree lock -> APZC locks
+ *      tree lock -> APZC locks -> test lock
  *
  * The interpretation of the lock ordering is that if lock A precedes lock B
  * in the ordering sequence, then you must NOT wait on A while holding B.
  *
  * **************************************************************************
  */
 
 /**
@@ -489,16 +492,18 @@ public:
       LayoutDeviceIntPoint* aRefPoint,
       ScrollableLayerGuid*  aOutTargetGuid,
       uint64_t*             aOutFocusSequenceNumber) override;
 
   void UpdateWheelTransaction(
       LayoutDeviceIntPoint aRefPoint,
       EventMessage aEventMessage) override;
 
+  bool GetAPZTestData(uint64_t aLayersId, APZTestData* aOutData);
+
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~APZCTreeManager();
 
   // Protected hooks for gtests subclass
   virtual AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId,
                                                   GeckoContentController* aController);
 public:
@@ -713,16 +718,21 @@ private:
   /* For logging the APZC tree for debugging (enabled by the apz.printtree
    * pref). */
   gfx::TreeLog mApzcTreeLog;
 
   class CheckerboardFlushObserver;
   friend class CheckerboardFlushObserver;
   RefPtr<CheckerboardFlushObserver> mFlushObserver;
 
+  // Map from layers id to APZTestData. Accesses and mutations must be
+  // protected by the mTestDataLock.
+  std::unordered_map<uint64_t, UniquePtr<APZTestData>> mTestData;
+  mutable mozilla::Mutex mTestDataLock;
+
   static float sDPI;
 
 #if defined(MOZ_WIDGET_ANDROID)
 public:
   void InitializeDynamicToolbarAnimator(const int64_t& aRootLayerTreeId);
   AndroidDynamicToolbarAnimator* GetAndroidDynamicToolbarAnimator();
 
 private:
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1371,19 +1371,20 @@ CompositorBridgeParent::FlushApzRepaints
     "layers::CompositorBridgeParent::FlushApzRepaints",
     [=]() { self->mApzcTreeManager->FlushApzRepaints(layersId); }));
 }
 
 void
 CompositorBridgeParent::GetAPZTestData(const uint64_t& aLayersId,
                                        APZTestData* aOutData)
 {
-  MOZ_ASSERT(aLayersId == 0 || aLayersId == mRootLayerTreeID);
-  MonitorAutoLock lock(*sIndirectLayerTreesLock);
-  *aOutData = sIndirectLayerTrees[mRootLayerTreeID].mApzTestData;
+  uint64_t layersId = (aLayersId == 0 ? mRootLayerTreeID : aLayersId);
+  if (mApzcTreeManager) {
+    mApzcTreeManager->GetAPZTestData(layersId, aOutData);
+  }
 }
 
 void
 CompositorBridgeParent::SetConfirmedTargetAPZC(const uint64_t& aLayersId,
                                                const uint64_t& aInputBlockId,
                                                const nsTArray<ScrollableLayerGuid>& aTargets)
 {
   if (!mApzcTreeManager) {
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -355,17 +355,16 @@ public:
     RefPtr<CompositorBridgeParent> mParent;
     HostLayerManager* mLayerManager;
     RefPtr<WebRenderBridgeParent> mWrBridge;
     // Pointer to the CrossProcessCompositorBridgeParent. Used by APZCs to share
     // their FrameMetrics with the corresponding child process that holds
     // the PCompositorBridgeChild
     CrossProcessCompositorBridgeParent* mCrossProcessParent;
     TargetConfig mTargetConfig;
-    APZTestData mApzTestData;
     LayerTransactionParent* mLayerTree;
     nsTArray<PluginWindowData> mPluginData;
     bool mUpdatedPluginDataAvailable;
 
     CompositorController* GetCompositorController() const;
     MetricsSharingController* CrossProcessSharingController() const;
     MetricsSharingController* InProcessSharingController() const;
     RefPtr<UiCompositorControllerParent> mUiControllerParent;
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -481,18 +481,23 @@ CrossProcessCompositorBridgeParent::Flus
 }
 
 void
 CrossProcessCompositorBridgeParent::GetAPZTestData(
   const uint64_t& aLayersId,
   APZTestData* aOutData)
 {
   MOZ_ASSERT(aLayersId != 0);
-  MonitorAutoLock lock(*sIndirectLayerTreesLock);
-  *aOutData = sIndirectLayerTrees[aLayersId].mApzTestData;
+  const CompositorBridgeParent::LayerTreeState* state =
+    CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
+  if (!state || !state->mParent) {
+    return;
+  }
+
+  state->mParent->GetAPZTestData(aLayersId, aOutData);
 }
 
 void
 CrossProcessCompositorBridgeParent::SetConfirmedTargetAPZC(
   const uint64_t& aLayersId,
   const uint64_t& aInputBlockId,
   const nsTArray<ScrollableLayerGuid>& aTargets)
 {