From bb553f0d581aba96b7eb8fef423e8634c0492dbe Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 31 Jan 2018 12:00:19 -0500 Subject: [PATCH] Bug 1433579 - Allow recursively holding the APZ tree lock. r=botond MozReview-Commit-ID: DzLgqb2wMN9 --HG-- extra : rebase_source : 6d7ba7bf5d574fefdd9e17a2c54ff2a48671701f --- gfx/layers/apz/src/APZCTreeManager.cpp | 57 +++++++++++++------------- gfx/layers/apz/src/APZCTreeManager.h | 4 +- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 6e44d33b5947..e18caa760114 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -158,7 +158,7 @@ APZCTreeManager::CheckerboardFlushObserver::Observe(nsISupports* aSubject, MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mTreeManager.get()); - MutexAutoLock lock(mTreeManager->mTreeLock); + RecursiveMutexAutoLock lock(mTreeManager->mTreeLock); if (mTreeManager->mRootNode) { ForEachNode(mTreeManager->mRootNode.get(), [](HitTestingTreeNode* aNode) @@ -294,7 +294,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId, { APZThreadUtils::AssertOnCompositorThread(); - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); // For testing purposes, we log some data to the APZTestData associated with // the layers id that originated this update. @@ -344,7 +344,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId, state.mLayersIdsToDestroy.erase(aRootLayerTreeId); mApzcTreeLog << "[start]\n"; - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); ForEachNode(aRoot, [&](ScrollNode aLayerMetrics) @@ -502,7 +502,7 @@ APZCTreeManager::PushStateToWR(wr::TransactionBuilder& aTxn, { APZThreadUtils::AssertOnCompositorThread(); - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); // During the first pass through the tree, we build a cache of guid->HTTN so // that we can find the relevant APZC instances quickly in subsequent passes, @@ -778,7 +778,7 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, HitTestingTreeNode* aNextSibling, TreeBuildingState& aState) { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); bool needsApzc = true; if (!aMetrics.IsScrollable()) { @@ -1074,7 +1074,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, MOZ_ASSERT(mToolbarAnimator); ScreenPoint scrollOffset; { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); RefPtr apzc = FindRootContentOrRootApzc(); if (apzc) { scrollOffset = ViewAs(apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForHitTesting), @@ -1124,7 +1124,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, // When the mouse is outside the window we still want to handle dragging // but we won't find an APZC. Fallback to root APZC then. { // scope lock - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); if (!apzc && mRootNode) { apzc = mRootNode->GetApzc(); } @@ -1739,7 +1739,7 @@ APZCTreeManager::SetupScrollbarDrag(MouseInput& aMouseInput, // due to async scrolling, so look that up and apply it. LayerToParentLayerMatrix4x4 thumbTransform; { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); thumbTransform = ComputeTransformForNode(aScrollThumbNode); } // Only consider the translation, since we do not support both @@ -1903,7 +1903,7 @@ void APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid, const Maybe& aConstraints) { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); RefPtr node = GetTargetNode(aGuid, nullptr); MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC @@ -1962,8 +1962,7 @@ APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform() // matched APZCs is the same. It is simplest to ensure that by flushing the // pending repaint requests, which makes all of the untransforms empty (and // therefore equal). - MutexAutoLock lock(mTreeLock); - mTreeLock.AssertCurrentThreadOwns(); + RecursiveMutexAutoLock lock(mTreeLock); ForEachNode(mRootNode.get(), [](HitTestingTreeNode* aNode) @@ -1987,7 +1986,7 @@ APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid) void APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift) { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); RefPtr apzc = FindRootContentOrRootApzc(); if (apzc) { apzc->AdjustScrollForSurfaceShift(aShift); @@ -2003,7 +2002,7 @@ APZCTreeManager::ClearTree() APZThreadUtils::RunOnControllerThread(NewRunnableMethod( "layers::InputQueue::Clear", mInputQueue, &InputQueue::Clear)); - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); // Collect the nodes into a list, and then destroy each one. // We can't destroy them as we collect them, because ForEachNode() @@ -2032,7 +2031,7 @@ APZCTreeManager::ClearTree() RefPtr APZCTreeManager::GetRootNode() const { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); return mRootNode; } @@ -2235,7 +2234,7 @@ APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint) already_AddRefed APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid) { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); RefPtr node = GetTargetNode(aGuid, nullptr); MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC RefPtr apzc = node ? node->GetApzc() : nullptr; @@ -2253,7 +2252,7 @@ already_AddRefed APZCTreeManager::GetTargetAPZC(const uint64_t& aLayersId, const FrameMetrics::ViewID& aScrollId) { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); ScrollableLayerGuid guid(aLayersId, 0, aScrollId); RefPtr node = GetTargetNode(guid, &GuidComparatorIgnoringPresShell); MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC @@ -2265,7 +2264,7 @@ already_AddRefed APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid, GuidComparator aComparator) const { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); RefPtr target = DepthFirstSearchPostOrder(mRootNode.get(), [&aGuid, &aComparator](HitTestingTreeNode* node) { @@ -2288,7 +2287,7 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, CompositorHitTestInfo* aOutHitResult, RefPtr* aOutScrollbarNode) { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); CompositorHitTestInfo hitResult = CompositorHitTestInfo::eInvisibleToHitTest; HitTestingTreeNode* scrollbarNode = nullptr; @@ -2385,7 +2384,7 @@ APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr APZCTreeManager::FindScrollThumbNode(const AsyncDragMetrics& aDragMetrics) { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); return DepthFirstSearch(mRootNode.get(), [&aDragMetrics](HitTestingTreeNode* aNode) { @@ -2493,7 +2492,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, CompositorHitTestInfo* aOutHitResult, HitTestingTreeNode** aOutScrollbarNode) { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); // This walks the tree in depth-first, reverse order, so that it encounters // APZCs front-to-back on the screen. @@ -2586,7 +2585,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, AsyncPanZoomController* APZCTreeManager::FindRootApzcForLayersId(uint64_t aLayersId) const { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); HitTestingTreeNode* resultNode = BreadthFirstSearch(mRootNode.get(), [aLayersId](HitTestingTreeNode* aNode) { @@ -2601,7 +2600,7 @@ APZCTreeManager::FindRootApzcForLayersId(uint64_t aLayersId) const AsyncPanZoomController* APZCTreeManager::FindRootContentApzcForLayersId(uint64_t aLayersId) const { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); HitTestingTreeNode* resultNode = BreadthFirstSearch(mRootNode.get(), [aLayersId](HitTestingTreeNode* aNode) { @@ -2616,7 +2615,7 @@ APZCTreeManager::FindRootContentApzcForLayersId(uint64_t aLayersId) const AsyncPanZoomController* APZCTreeManager::FindRootContentOrRootApzc() const { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); // Note: this is intended to find the same "root" that would be found // by AsyncCompositionManager::ApplyAsyncContentTransformToTree inside @@ -2738,7 +2737,7 @@ ScreenToParentLayerMatrix4x4 APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const { Matrix4x4 result; - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); // The comments below assume there is a chain of layers L..R with L and P having APZC instances as // explained in the comment above. This function is called with aApzc at L, and the loop @@ -2779,7 +2778,7 @@ ParentLayerToScreenMatrix4x4 APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const { Matrix4x4 result; - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); // The comments below assume there is a chain of layers L..R with L and P having APZC instances as // explained in the comment above. This function is called with aApzc at L, and the loop @@ -2814,7 +2813,7 @@ APZCTreeManager::GetCurrentMousePosition() const already_AddRefed APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const { - MutexAutoLock lock(mTreeLock); + RecursiveMutexAutoLock lock(mTreeLock); RefPtr apzc; // For now, we only ever want to do pinching on the root-content APZC for // a given layers id. @@ -2838,7 +2837,7 @@ APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoo already_AddRefed APZCTreeManager::CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); RefPtr ancestor; // If either aApzc1 or aApzc2 is null, min(depth1, depth2) will be 0 and this function @@ -2884,7 +2883,7 @@ APZCTreeManager::CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomCont LayerToParentLayerMatrix4x4 APZCTreeManager::ComputeTransformForNode(const HitTestingTreeNode* aNode) const { - mTreeLock.AssertCurrentThreadOwns(); + mTreeLock.AssertCurrentThreadIn(); if (AsyncPanZoomController* apzc = aNode->GetApzc()) { // If the node represents scrollable content, apply the async transform // from its APZC. diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index b4a92f07d4c5..8d82784537de 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -18,7 +18,7 @@ #include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager #include "mozilla/layers/KeyboardMap.h" // for KeyboardMap #include "mozilla/layers/FocusState.h" // for FocusState -#include "mozilla/Mutex.h" // for Mutex +#include "mozilla/RecursiveMutex.h" // for RecursiveMutex #include "mozilla/RefPtr.h" // for RefPtr #include "mozilla/TimeStamp.h" // for mozilla::TimeStamp #include "nsCOMPtr.h" // for already_AddRefed @@ -649,7 +649,7 @@ private: * is considered part of the APZC tree management state. * Finally, the lock needs to be held when accessing mZoomConstraints. * IMPORTANT: See the note about lock ordering at the top of this file. */ - mutable mozilla::Mutex mTreeLock; + mutable mozilla::RecursiveMutex mTreeLock; RefPtr mRootNode; /* Holds the zoom constraints for scrollable layers, as determined by the * the main-thread gecko code. */