Bug 1357754 - Extract a template function from UpdateHitTestingTree. r=botond
Currently the public UpdateHitTestingTree function takes a Layer* which
assumes there is a layer tree to traverse. However, with WebRender, that
is not the case. This patch has two conceptual changes.
The first change is to extract the innards of UpdateHitTestingTree to take
a LayerMetricsWrapper instead of a Layer* and traverse the layer tree
using that. This was already mostly happening but this makes the
Layer*/LayerMetricsWrapper boundary a little more explicit.
The second change is to make the extracted helper function templated, so
it accepts anything that is template-compatible with
LayerMetricsWrapper. I chose to use a template rather inheritance to
avoid the performance hit of virtual functions, since this code runs
relatively often.
This paves the way for adding a different kind of tree-traversal object
instead of the LayerMetricsWrapper while reusing the same logic to build
the hit-testing tree and APZC nodes.
MozReview-Commit-ID: 6SmnX6Bn2QV
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -208,22 +208,22 @@ APZCTreeManager::GetFrameTime()
void
APZCTreeManager::SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags> &aValues)
{
mInputQueue->SetAllowedTouchBehavior(aInputBlockId, aValues);
}
-void
-APZCTreeManager::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
- Layer* aRoot,
- bool aIsFirstPaint,
- uint64_t aOriginatingLayersId,
- uint32_t aPaintSequenceNumber)
+template<class ScrollNode> void // ScrollNode is a LayerMetricsWrapper
+APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
+ const ScrollNode& aRoot,
+ bool aIsFirstPaint,
+ uint64_t aOriginatingLayersId,
+ uint32_t aPaintSequenceNumber)
{
APZThreadUtils::AssertOnCompositorThread();
MutexAutoLock lock(mTreeLock);
// For testing purposes, we log some data to the APZTestData associated with
// the layers id that originated this update.
APZTestData* testData = nullptr;
@@ -263,21 +263,20 @@ APZCTreeManager::UpdateHitTestingTree(ui
std::stack<gfx::TreeAutoIndent> indents;
std::stack<gfx::Matrix4x4> ancestorTransforms;
HitTestingTreeNode* parent = nullptr;
HitTestingTreeNode* next = nullptr;
uint64_t layersId = aRootLayerTreeId;
ancestorTransforms.push(Matrix4x4());
mApzcTreeLog << "[start]\n";
- LayerMetricsWrapper root(aRoot);
mTreeLock.AssertCurrentThreadOwns();
- ForEachNode<ReverseIterator>(root,
- [&](LayerMetricsWrapper aLayerMetrics)
+ ForEachNode<ReverseIterator>(aRoot,
+ [&](ScrollNode aLayerMetrics)
{
mApzcTreeLog << aLayerMetrics.Name() << '\t';
HitTestingTreeNode* node = PrepareNodeForLayer(aLayerMetrics,
aLayerMetrics.Metrics(), layersId, ancestorTransforms.top(),
parent, next, state);
MOZ_ASSERT(node);
AsyncPanZoomController* apzc = node->GetApzc();
@@ -303,17 +302,17 @@ APZCTreeManager::UpdateHitTestingTree(ui
// Note that |node| at this point will not have any children, otherwise we
// we would have to set next to node->GetFirstChild().
MOZ_ASSERT(!node->GetFirstChild());
parent = node;
next = nullptr;
layersId = (aLayerMetrics.AsRefLayer() ? aLayerMetrics.AsRefLayer()->GetReferentId() : layersId);
indents.push(gfx::TreeAutoIndent(mApzcTreeLog));
},
- [&](LayerMetricsWrapper aLayerMetrics)
+ [&](ScrollNode aLayerMetrics)
{
next = parent;
parent = parent->GetParent();
layersId = next->GetLayersId();
ancestorTransforms.pop();
indents.pop();
});
@@ -332,38 +331,50 @@ APZCTreeManager::UpdateHitTestingTree(ui
#if ENABLE_APZCTM_LOGGING
// Make the hit-test tree line up with the layer dump
printf_stderr("APZCTreeManager (%p)\n", this);
mRootNode->Dump(" ");
#endif
}
+void
+APZCTreeManager::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
+ Layer* aRoot,
+ bool aIsFirstPaint,
+ uint64_t aOriginatingLayersId,
+ uint32_t aPaintSequenceNumber)
+{
+ LayerMetricsWrapper root(aRoot);
+ UpdateHitTestingTreeImpl(aRootLayerTreeId, root, aIsFirstPaint,
+ aOriginatingLayersId, aPaintSequenceNumber);
+}
+
// Compute the clip region to be used for a layer with an APZC. This function
// is only called for layers which actually have scrollable metrics and an APZC.
-static ParentLayerIntRegion
+template<class ScrollNode> static ParentLayerIntRegion
ComputeClipRegion(GeckoContentController* aController,
- const LayerMetricsWrapper& aLayer)
+ const ScrollNode& aLayer)
{
ParentLayerIntRegion clipRegion;
if (aLayer.GetClipRect()) {
clipRegion = *aLayer.GetClipRect();
} else {
// if there is no clip on this layer (which should only happen for the
// root scrollable layer in a process, or for some of the LayerMetrics
// expansions of a multi-metrics layer), fall back to using the comp
// bounds which should be equivalent.
clipRegion = RoundedToInt(aLayer.Metrics().GetCompositionBounds());
}
return clipRegion;
}
-void
-APZCTreeManager::PrintAPZCInfo(const LayerMetricsWrapper& aLayer,
+template<class ScrollNode> void
+APZCTreeManager::PrintAPZCInfo(const ScrollNode& aLayer,
const AsyncPanZoomController* apzc)
{
const FrameMetrics& metrics = aLayer.Metrics();
mApzcTreeLog << "APZC " << apzc->GetGuid()
<< "\tcb=" << metrics.GetCompositionBounds()
<< "\tsr=" << metrics.GetScrollableRect()
<< (aLayer.IsScrollInfoLayer() ? "\tscrollinfo" : "")
<< (apzc->HasScrollgrab() ? "\tscrollgrab" : "") << "\t"
@@ -381,18 +392,18 @@ APZCTreeManager::AttachNodeToTree(HitTes
aParent->SetLastChild(aNode);
} else {
MOZ_ASSERT(!mRootNode);
mRootNode = aNode;
aNode->MakeRoot();
}
}
-static EventRegions
-GetEventRegions(const LayerMetricsWrapper& aLayer)
+template<class ScrollNode> static EventRegions
+GetEventRegions(const ScrollNode& aLayer)
{
if (aLayer.IsScrollInfoLayer()) {
ParentLayerIntRect compositionBounds(RoundedToInt(aLayer.Metrics().GetCompositionBounds()));
nsIntRegion hitRegion(compositionBounds.ToUnknownRect());
EventRegions eventRegions(hitRegion);
eventRegions.mDispatchToContentHitRegion = eventRegions.mHitRegion;
return eventRegions;
}
@@ -414,19 +425,19 @@ APZCTreeManager::RecycleOrCreateNode(Tre
node->RecycleWith(aApzc, aLayersId);
return node.forget();
}
}
RefPtr<HitTestingTreeNode> node = new HitTestingTreeNode(aApzc, false, aLayersId);
return node.forget();
}
-static EventRegionsOverride
+template<class ScrollNode> static EventRegionsOverride
GetEventRegionsOverride(HitTestingTreeNode* aParent,
- const LayerMetricsWrapper& aLayer)
+ const ScrollNode& aLayer)
{
// Make it so that if the flag is set on the layer tree, it automatically
// propagates to all the nodes in the corresponding subtree rooted at that
// layer in the hit-test tree. This saves having to walk up the tree every
// we want to see if a hit-test node is affected by this flag.
EventRegionsOverride result = aLayer.GetEventRegionsOverride();
if (aParent) {
result |= aParent->GetEventRegionsOverride();
@@ -452,18 +463,18 @@ APZCTreeManager::StartScrollbarDrag(cons
void
APZCTreeManager::NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const
{
const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aGuid.mLayersId);
MOZ_ASSERT(state && state->mController);
state->mController->NotifyAsyncScrollbarDragRejected(aGuid.mScrollId);
}
-HitTestingTreeNode*
-APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
+template<class ScrollNode> HitTestingTreeNode*
+APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer,
const FrameMetrics& aMetrics,
uint64_t aLayersId,
const gfx::Matrix4x4& aAncestorTransform,
HitTestingTreeNode* aParent,
HitTestingTreeNode* aNextSibling,
TreeBuildingState& aState)
{
mTreeLock.AssertCurrentThreadOwns();
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -431,16 +431,23 @@ public:
* is occurring such as when the toolbar is being hidden/shown in Fennec.
* This function can be called to have the y axis' velocity queue updated.
*/
void ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY) override;
private:
typedef bool (*GuidComparator)(const ScrollableLayerGuid&, const ScrollableLayerGuid&);
/* Helpers */
+ template<class ScrollNode>
+ void UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
+ const ScrollNode& aRoot,
+ bool aIsFirstPaint,
+ uint64_t aOriginatingLayersId,
+ uint32_t aPaintSequenceNumber);
+
void AttachNodeToTree(HitTestingTreeNode* aNode,
HitTestingTreeNode* aParent,
HitTestingTreeNode* aNextSibling);
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
already_AddRefed<HitTestingTreeNode> GetTargetNode(const ScrollableLayerGuid& aGuid,
GuidComparator aComparator);
HitTestingTreeNode* FindTargetNode(HitTestingTreeNode* aNode,
const ScrollableLayerGuid& aGuid,
@@ -461,25 +468,27 @@ private:
nsEventStatus ProcessTouchInput(MultiTouchInput& aInput,
ScrollableLayerGuid* aOutTargetGuid,
uint64_t* aOutInputBlockId);
void FlushRepaintsToClearScreenToGeckoTransform();
already_AddRefed<HitTestingTreeNode> RecycleOrCreateNode(TreeBuildingState& aState,
AsyncPanZoomController* aApzc,
uint64_t aLayersId);
- HitTestingTreeNode* PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
+ template<class ScrollNode>
+ HitTestingTreeNode* PrepareNodeForLayer(const ScrollNode& aLayer,
const FrameMetrics& aMetrics,
uint64_t aLayersId,
const gfx::Matrix4x4& aAncestorTransform,
HitTestingTreeNode* aParent,
HitTestingTreeNode* aNextSibling,
TreeBuildingState& aState);
- void PrintAPZCInfo(const LayerMetricsWrapper& aLayer,
+ template<class ScrollNode>
+ void PrintAPZCInfo(const ScrollNode& aLayer,
const AsyncPanZoomController* apzc);
void NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const;
protected:
/* The input queue where input events are held until we know enough to
* figure out where they're going. Protected so gtests can access it.
*/