diff --git a/gfx/layers/LayerMetricsWrapper.h b/gfx/layers/LayerMetricsWrapper.h index e32c354f79aa..b3aab5c178ff 100644 --- a/gfx/layers/LayerMetricsWrapper.h +++ b/gfx/layers/LayerMetricsWrapper.h @@ -433,6 +433,15 @@ public: return mLayer->GetFixedPositionScrollContainerId(); } + Maybe GetZoomAnimationId() const + { + MOZ_ASSERT(IsValid()); + // This function is only really needed for template-compatibility with + // WebRenderScrollDataWrapper. Although it will be called, the return + // value is not used. + return Nothing(); + } + bool IsBackfaceHidden() const { MOZ_ASSERT(IsValid()); diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index ca26b1e0f283..22efbe6bb9d6 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -134,6 +134,16 @@ struct APZCTreeManager::TreeBuildingState { // children, meaning they are added to the children's ancestor transforms // instead. Those deferred transforms are tracked here. DeferredTransformMap mPerspectiveTransformsDeferredToChildren; + + // As we recurse down through the tree, this picks up the zoom animation id + // from a node in the layer tree, and propagates it downwards to the nearest + // APZC instance that is for an RCD node. Generally it will be set on the + // root node of the layers (sub-)tree, which may not be same as the RCD node + // for the subtree, and so we need this mechanism to ensure it gets propagated + // to the RCD's APZC instance. Once it is set on the APZC instance, the value + // is cleared back to Nothing(). Note that this is only used in the WebRender + // codepath. + Maybe mZoomAnimationId; }; class APZCTreeManager::CheckerboardFlushObserver : public nsIObserver { @@ -885,6 +895,10 @@ APZCTreeManager::PrepareNodeForLayer(const RecursiveMutexAutoLock& aProofOfTreeL bool parentHasPerspective = aState.mParentHasPerspective.top(); + if (Maybe zoomAnimationId = aLayer.GetZoomAnimationId()) { + aState.mZoomAnimationId = zoomAnimationId; + } + RefPtr node = nullptr; if (!needsApzc) { // Note: if layer properties must be propagated to nodes, RecvUpdate in @@ -995,6 +1009,11 @@ APZCTreeManager::PrepareNodeForLayer(const RecursiveMutexAutoLock& aProofOfTreeL node->SetLastChild(nullptr); } + if (aMetrics.IsRootContent()) { + apzc->SetZoomAnimationId(aState.mZoomAnimationId); + aState.mZoomAnimationId = Nothing(); + } + APZCTM_LOG("Using APZC %p for layer %p with identifiers %" PRIx64 " %" PRId64 "\n", apzc, aLayer.GetLayer(), uint64_t(aLayersId), aMetrics.GetScrollId()); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 4eeaac900d21..8d28ebb377c1 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -5038,5 +5038,15 @@ bool AsyncPanZoomController::MaybeAdjustDestinationForScrollSnapping( return false; } +void AsyncPanZoomController::SetZoomAnimationId(const Maybe& aZoomAnimationId) +{ + mZoomAnimationId = aZoomAnimationId; +} + +Maybe AsyncPanZoomController::GetZoomAnimationId() const +{ + return mZoomAnimationId; +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 9a492733ad64..b40656c9effc 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -982,6 +982,15 @@ private: UniquePtr mOverscrollEffect; + // Zoom animation id, used for zooming in WebRender. This should only be + // set on the APZC instance for the root content document (i.e. the one we + // support zooming on), and is only used if WebRender is enabled. The + // animation id itself refers to the transform animation id that was set on + // the stacking context in the WR display list. By changing the transform + // associated with this id, we can adjust the scaling that WebRender applies, + // thereby controlling the zoom. + Maybe mZoomAnimationId; + friend class Axis; public: @@ -999,6 +1008,9 @@ public: return callable(mLastContentPaintMetrics); } + void SetZoomAnimationId(const Maybe& aZoomAnimationId); + Maybe GetZoomAnimationId() const; + /* =================================================================== * The functions and members in this section are used to expose * the current async transform state to callers. diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp index ad65f09a0b9e..1da63f7c9481 100644 --- a/gfx/layers/wr/WebRenderCommandBuilder.cpp +++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp @@ -1339,6 +1339,9 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder // Make a "root" layer data that has everything else as descendants mLayerScrollData.emplace_back(); mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1); + if (mZoomProp) { + mLayerScrollData.back().SetZoomAnimationId(mZoomProp->id); + } auto callback = [&aScrollData](ScrollableLayerGuid::ViewID aScrollId) -> bool { return aScrollData.HasMetadataFor(aScrollId).isSome(); }; diff --git a/gfx/layers/wr/WebRenderScrollData.h b/gfx/layers/wr/WebRenderScrollData.h index 0ada8cc83cde..43098ce8a55e 100644 --- a/gfx/layers/wr/WebRenderScrollData.h +++ b/gfx/layers/wr/WebRenderScrollData.h @@ -87,6 +87,9 @@ public: void SetFixedPositionScrollContainerId(ScrollableLayerGuid::ViewID aId) { mFixedPosScrollContainerId = aId; } ScrollableLayerGuid::ViewID GetFixedPositionScrollContainerId() const { return mFixedPosScrollContainerId; } + void SetZoomAnimationId(const uint64_t& aId) { mZoomAnimationId = Some(aId); } + Maybe GetZoomAnimationId() const { return mZoomAnimationId; } + void Dump(const WebRenderScrollData& aOwner) const; friend struct IPC::ParamTraits; @@ -117,6 +120,7 @@ private: ScrollbarData mScrollbarData; uint64_t mScrollbarAnimationId; ScrollableLayerGuid::ViewID mFixedPosScrollContainerId; + Maybe mZoomAnimationId; }; // Data needed by APZ, for the whole layer tree. One instance of this class @@ -237,6 +241,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mScrollbarData); WriteParam(aMsg, aParam.mScrollbarAnimationId); WriteParam(aMsg, aParam.mFixedPosScrollContainerId); + WriteParam(aMsg, aParam.mZoomAnimationId); } static bool @@ -253,7 +258,8 @@ struct ParamTraits && ReadParam(aMsg, aIter, &aResult->mEventRegionsOverride) && ReadParam(aMsg, aIter, &aResult->mScrollbarData) && ReadParam(aMsg, aIter, &aResult->mScrollbarAnimationId) - && ReadParam(aMsg, aIter, &aResult->mFixedPosScrollContainerId); + && ReadParam(aMsg, aIter, &aResult->mFixedPosScrollContainerId) + && ReadParam(aMsg, aIter, &aResult->mZoomAnimationId); } }; diff --git a/gfx/layers/wr/WebRenderScrollDataWrapper.h b/gfx/layers/wr/WebRenderScrollDataWrapper.h index 8c1ddef64538..14c2b9c15194 100644 --- a/gfx/layers/wr/WebRenderScrollDataWrapper.h +++ b/gfx/layers/wr/WebRenderScrollDataWrapper.h @@ -316,6 +316,12 @@ public: return mLayer->GetFixedPositionScrollContainerId(); } + Maybe GetZoomAnimationId() const + { + MOZ_ASSERT(IsValid()); + return mLayer->GetZoomAnimationId(); + } + bool IsBackfaceHidden() const { // This is only used by APZCTM hit testing, and WR does its own