--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -153,17 +153,17 @@ NS_IMPL_ISUPPORTS(APZCTreeManager::Check
NS_IMETHODIMP
APZCTreeManager::CheckerboardFlushObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t*)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mTreeManager.get());
- MutexAutoLock lock(mTreeManager->mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeManager->mTreeLock);
if (mTreeManager->mRootNode) {
ForEachNode<ReverseIterator>(mTreeManager->mRootNode.get(),
[](HitTestingTreeNode* aNode)
{
if (aNode->IsPrimaryHolder()) {
MOZ_ASSERT(aNode->GetApzc());
aNode->GetApzc()->FlushActiveCheckerboardReport();
}
@@ -289,17 +289,17 @@ template<class ScrollNode> void // Scrol
APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
const ScrollNode& aRoot,
bool aIsFirstPaint,
uint64_t aOriginatingLayersId,
uint32_t aPaintSequenceNumber)
{
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.
APZTestData* testData = nullptr;
if (gfxPrefs::APZTestLoggingEnabled()) {
if (LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aOriginatingLayersId)) {
testData = &state->mApzTestData;
testData->StartNewPaint(aPaintSequenceNumber);
@@ -339,17 +339,17 @@ APZCTreeManager::UpdateHitTestingTreeImp
HitTestingTreeNode* next = nullptr;
uint64_t layersId = aRootLayerTreeId;
ancestorTransforms.push(AncestorTransform());
state.mParentHasPerspective.push(false);
state.mLayersIdsToDestroy.erase(aRootLayerTreeId);
mApzcTreeLog << "[start]\n";
- mTreeLock.AssertCurrentThreadOwns();
+ mTreeLock.AssertCurrentThreadIn();
ForEachNode<ReverseIterator>(aRoot,
[&](ScrollNode aLayerMetrics)
{
mApzcTreeLog << aLayerMetrics.Name() << '\t';
HitTestingTreeNode* node = PrepareNodeForLayer(aLayerMetrics,
aLayerMetrics.Metrics(), layersId, ancestorTransforms.top(),
@@ -497,17 +497,17 @@ APZCTreeManager::UpdateHitTestingTree(ui
bool
APZCTreeManager::PushStateToWR(wr::TransactionBuilder& aTxn,
const TimeStamp& aSampleTime,
nsTArray<wr::WrTransformProperty>& aTransformArray)
{
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,
// such as the one below to generate scrollbar transforms. Without this, perf
// could end up being O(n^2) instead of O(n log n) because we'd have to search
// the tree to find the corresponding APZC every time we hit a thumb node.
std::unordered_map<ScrollableLayerGuid, HitTestingTreeNode*, ScrollableLayerGuidHash> httnMap;
@@ -773,17 +773,17 @@ template<class ScrollNode> HitTestingTre
APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer,
const FrameMetrics& aMetrics,
uint64_t aLayersId,
const AncestorTransform& aAncestorTransform,
HitTestingTreeNode* aParent,
HitTestingTreeNode* aNextSibling,
TreeBuildingState& aState)
{
- mTreeLock.AssertCurrentThreadOwns();
+ mTreeLock.AssertCurrentThreadIn();
bool needsApzc = true;
if (!aMetrics.IsScrollable()) {
needsApzc = false;
}
const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!(state && state->mController.get())) {
@@ -1069,17 +1069,17 @@ APZCTreeManager::ReceiveInputEvent(Input
// Use a RAII class for updating the focus sequence number of this event
AutoFocusSequenceNumberSetter focusSetter(mFocusState, aEvent);
#if defined(MOZ_WIDGET_ANDROID)
MOZ_ASSERT(mToolbarAnimator);
ScreenPoint scrollOffset;
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc = FindRootContentOrRootApzc();
if (apzc) {
scrollOffset = ViewAs<ScreenPixel>(apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForHitTesting),
PixelCastJustification::ScreenIsParentLayerForRoot);
}
}
nsEventStatus isConsumed = mToolbarAnimator->ReceiveInputEvent(aEvent, scrollOffset);
// Check if the mToolbarAnimator consumed the event.
@@ -1119,17 +1119,17 @@ APZCTreeManager::ReceiveInputEvent(Input
RefPtr<HitTestingTreeNode> hitScrollbarNode = nullptr;
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(mouseInput.mOrigin,
&hitResult, &hitScrollbarNode);
bool hitScrollbar = hitScrollbarNode;
// 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();
}
}
if (apzc) {
if (gfxPrefs::APZTestLoggingEnabled() && mouseInput.mType == MouseInput::MOUSE_HITTEST) {
ScrollableLayerGuid guid = apzc->GetGuid();
@@ -1734,17 +1734,17 @@ APZCTreeManager::SetupScrollbarDrag(Mous
// ConvertScrollbarPoint() got the drag start offset relative to
// the scroll track. Now get it relative to the thumb.
// ScrollThumbData::mThumbStart stores the offset of the thumb
// relative to the scroll track at the time of the last paint.
// Since that paint, the thumb may have acquired an async transform
// 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
// zooming and scrollbar dragging on any platform.
CSSCoord thumbStart = thumbData.mThumbStart
+ ((*thumbData.mDirection == ScrollDirection::eHorizontal)
? thumbTransform._41 : thumbTransform._42);
dragStart -= thumbStart;
@@ -1898,17 +1898,17 @@ APZCTreeManager::SetTargetAPZC(uint64_t
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aTarget);
mInputQueue->SetConfirmedTargetApzc(aInputBlockId, apzc);
}
void
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
const Maybe<ZoomConstraints>& aConstraints)
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
// Propagate the zoom constraints down to the subtree, stopping at APZCs
// which have their own zoom constraints or are in a different layers id.
if (aConstraints) {
APZCTM_LOG("Recording constraints %s for guid %s\n",
Stringify(aConstraints.value()).c_str(), Stringify(aGuid).c_str());
@@ -1957,18 +1957,17 @@ APZCTreeManager::FlushRepaintsToClearScr
// hits a dispatch-to-content region then that's an ambiguous result and we
// need to ask Gecko what actually got hit. In order to do this we need to
// untransform the input event into Gecko space - but to do that we need to
// know which APZC got hit! This leads to a circular dependency; the only way
// to get out of it is to make sure that the untransform for all the possible
// 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<ReverseIterator>(mRootNode.get(),
[](HitTestingTreeNode* aNode)
{
if (aNode->IsPrimaryHolder()) {
MOZ_ASSERT(aNode->GetApzc());
aNode->GetApzc()->FlushRepaintForNewInputBlock();
}
@@ -1982,33 +1981,33 @@ APZCTreeManager::CancelAnimation(const S
if (apzc) {
apzc->CancelAnimation();
}
}
void
APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift)
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc = FindRootContentOrRootApzc();
if (apzc) {
apzc->AdjustScrollForSurfaceShift(aShift);
}
}
void
APZCTreeManager::ClearTree()
{
// Ensure that no references to APZCs are alive in any lingering input
// blocks. This breaks cycles from InputBlockState::mTargetApzc back to
// the InputQueue.
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()
// does a pre-order traversal of the tree, and Destroy() nulls out
// the fields needed to reach the children of the node.
nsTArray<RefPtr<HitTestingTreeNode>> nodesToDestroy;
ForEachNode<ReverseIterator>(mRootNode.get(),
[&nodesToDestroy](HitTestingTreeNode* aNode)
@@ -2027,17 +2026,17 @@ APZCTreeManager::ClearTree()
self->mFlushObserver->Unregister();
self->mFlushObserver = nullptr;
}));
}
RefPtr<HitTestingTreeNode>
APZCTreeManager::GetRootNode() const
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
return mRootNode;
}
/**
* Transform a displacement from the ParentLayer coordinates of a source APZC
* to the ParentLayer coordinates of a target APZC.
* @param aTreeManager the tree manager for the APZC tree containing |aSource|
* and |aTarget|
@@ -2230,17 +2229,17 @@ APZCTreeManager::HitTestAPZC(const Scree
{
RefPtr<AsyncPanZoomController> target = GetTargetAPZC(aPoint, nullptr);
return target != nullptr;
}
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
RefPtr<AsyncPanZoomController> apzc = node ? node->GetApzc() : nullptr;
return apzc.forget();
}
static bool
GuidComparatorIgnoringPresShell(const ScrollableLayerGuid& aOne, const ScrollableLayerGuid& aTwo)
@@ -2248,29 +2247,29 @@ GuidComparatorIgnoringPresShell(const Sc
return aOne.mLayersId == aTwo.mLayersId
&& aOne.mScrollId == aTwo.mScrollId;
}
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const uint64_t& aLayersId,
const FrameMetrics::ViewID& aScrollId)
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
ScrollableLayerGuid guid(aLayersId, 0, aScrollId);
RefPtr<HitTestingTreeNode> node = GetTargetNode(guid, &GuidComparatorIgnoringPresShell);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
RefPtr<AsyncPanZoomController> apzc = node ? node->GetApzc() : nullptr;
return apzc.forget();
}
already_AddRefed<HitTestingTreeNode>
APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid,
GuidComparator aComparator) const
{
- mTreeLock.AssertCurrentThreadOwns();
+ mTreeLock.AssertCurrentThreadIn();
RefPtr<HitTestingTreeNode> target = DepthFirstSearchPostOrder<ReverseIterator>(mRootNode.get(),
[&aGuid, &aComparator](HitTestingTreeNode* node)
{
bool matches = false;
if (node->GetApzc()) {
if (aComparator) {
matches = aComparator(aGuid, node->GetApzc()->GetGuid());
} else {
@@ -2283,17 +2282,17 @@ APZCTreeManager::GetTargetNode(const Scr
return target.forget();
}
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint,
CompositorHitTestInfo* aOutHitResult,
RefPtr<HitTestingTreeNode>* aOutScrollbarNode)
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
CompositorHitTestInfo hitResult = CompositorHitTestInfo::eInvisibleToHitTest;
HitTestingTreeNode* scrollbarNode = nullptr;
RefPtr<AsyncPanZoomController> target;
if (gfx::gfxVars::UseWebRender() && gfxPrefs::WebRenderHitTest()) {
target = GetAPZCAtPointWR(aPoint, &hitResult, &scrollbarNode);
} else {
target = GetAPZCAtPoint(mRootNode, aPoint, &hitResult, &scrollbarNode);
@@ -2380,17 +2379,17 @@ APZCTreeManager::BuildOverscrollHandoffC
// something higher up in the tree.
// It's not sufficient to just find the initial target, however, as
// overscroll can be handed off to another APZC. Without scroll grabbing,
// handoff just occurs from child to parent. With scroll grabbing, the
// handoff order can be different, so we build a chain of APZCs in the
// order in which scroll will be handed off to them.
// Grab tree lock since we'll be walking the APZC tree.
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
// Build the chain. If there is a scroll parent link, we use that. This is
// needed to deal with scroll info layers, because they participate in handoff
// but do not follow the expected layer tree structure. If there are no
// scroll parent links we just walk up the tree to find the scroll parent.
OverscrollHandoffChain* result = new OverscrollHandoffChain;
AsyncPanZoomController* apzc = aInitialTarget;
while (apzc != nullptr) {
@@ -2454,17 +2453,17 @@ APZCTreeManager::SetLongTapEnabled(bool
APZThreadUtils::RunOnControllerThread(
NewRunnableFunction("SetLongTapEnabledRunnable",
GestureEventListener::SetLongTapEnabled, aLongTapEnabled));
}
RefPtr<HitTestingTreeNode>
APZCTreeManager::FindScrollThumbNode(const AsyncDragMetrics& aDragMetrics)
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
return DepthFirstSearch<ReverseIterator>(mRootNode.get(),
[&aDragMetrics](HitTestingTreeNode* aNode) {
return aNode->MatchesScrollDragMetrics(aDragMetrics);
});
}
AsyncPanZoomController*
@@ -2488,17 +2487,17 @@ APZCTreeManager::GetTargetApzcForNode(Hi
}
AsyncPanZoomController*
APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
const ScreenPoint& aHitTestPoint,
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.
HitTestingTreeNode* resultNode;
HitTestingTreeNode* root = aNode;
std::stack<LayerPoint> hitTestPoints;
ParentLayerPoint point = ViewAs<ParentLayerPixel>(aHitTestPoint,
PixelCastJustification::ScreenIsParentLayerForRoot);
@@ -2581,47 +2580,47 @@ APZCTreeManager::GetAPZCAtPoint(HitTesti
}
return nullptr;
}
AsyncPanZoomController*
APZCTreeManager::FindRootApzcForLayersId(uint64_t aLayersId) const
{
- mTreeLock.AssertCurrentThreadOwns();
+ mTreeLock.AssertCurrentThreadIn();
HitTestingTreeNode* resultNode = BreadthFirstSearch<ReverseIterator>(mRootNode.get(),
[aLayersId](HitTestingTreeNode* aNode) {
AsyncPanZoomController* apzc = aNode->GetApzc();
return apzc
&& apzc->GetLayersId() == aLayersId
&& apzc->IsRootForLayersId();
});
return resultNode ? resultNode->GetApzc() : nullptr;
}
AsyncPanZoomController*
APZCTreeManager::FindRootContentApzcForLayersId(uint64_t aLayersId) const
{
- mTreeLock.AssertCurrentThreadOwns();
+ mTreeLock.AssertCurrentThreadIn();
HitTestingTreeNode* resultNode = BreadthFirstSearch<ReverseIterator>(mRootNode.get(),
[aLayersId](HitTestingTreeNode* aNode) {
AsyncPanZoomController* apzc = aNode->GetApzc();
return apzc
&& apzc->GetLayersId() == aLayersId
&& apzc->IsRootContent();
});
return resultNode ? resultNode->GetApzc() : nullptr;
}
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
// the MOZ_WIDGET_ANDROID block. That is, it should find the RCD node if there
// is one, or the root APZC if there is not.
// Since BreadthFirstSearch is a pre-order search, we first do a search for
// the RCD, and then if we don't find one, we do a search for the root APZC.
HitTestingTreeNode* resultNode = BreadthFirstSearch<ReverseIterator>(mRootNode.get(),
@@ -2733,17 +2732,17 @@ APZCTreeManager::FindRootContentOrRootAp
/*
* See the long comment above for a detailed explanation of this function.
*/
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
// below performs one iteration, where parent is at P. The comments explain what values are stored
// in the variables at these two levels. All the comments use standard matrix notation where the
// leftmost matrix in a multiplication is applied first.
// ancestorUntransform is PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse()
@@ -2774,17 +2773,17 @@ APZCTreeManager::GetScreenToApzcTransfor
/*
* See the long comment above GetScreenToApzcTransform() for a detailed
* explanation of this function.
*/
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
// below performs one iteration, where parent is at P. The comments explain what values are stored
// in the variables at these two levels. All the comments use standard matrix notation where the
// leftmost matrix in a multiplication is applied first.
// asyncUntransform is LA.Inverse()
@@ -2809,17 +2808,17 @@ ScreenPoint
APZCTreeManager::GetCurrentMousePosition() const
{
return mCurrentMousePosition;
}
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
{
- MutexAutoLock lock(mTreeLock);
+ RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc;
// For now, we only ever want to do pinching on the root-content APZC for
// a given layers id.
if (aApzc1 && aApzc2 && aApzc1->GetLayersId() == aApzc2->GetLayersId()) {
// If the two APZCs have the same layers id, find the root-content APZC
// for that layers id. Don't call CommonAncestor() because there may not
// be a common ancestor for the layers id (e.g. if one APZCs is inside a
// fixed-position element).
@@ -2833,17 +2832,17 @@ APZCTreeManager::GetMultitouchTarget(Asy
}
}
return apzc.forget();
}
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
{
- mTreeLock.AssertCurrentThreadOwns();
+ mTreeLock.AssertCurrentThreadIn();
RefPtr<AsyncPanZoomController> ancestor;
// If either aApzc1 or aApzc2 is null, min(depth1, depth2) will be 0 and this function
// will return null.
// Calculate depth of the APZCs in the tree
int depth1 = 0, depth2 = 0;
for (AsyncPanZoomController* parent = aApzc1; parent; parent = parent->GetParent()) {
@@ -2879,17 +2878,17 @@ APZCTreeManager::CommonAncestor(AsyncPan
aApzc2 = aApzc2->GetParent();
}
return ancestor.forget();
}
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.
return aNode->GetTransform() *
CompleteAsyncTransform(
apzc->GetCurrentAsyncTransformWithOverscroll(AsyncPanZoomController::eForHitTesting));
} else if (aNode->IsScrollThumbNode()) {
// If the node represents a scrollbar thumb, compute and apply the