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
--- 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)
{