summaryrefslogtreecommitdiffstats
path: root/gfx/layers/wr/WebRenderScrollDataWrapper.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/layers/wr/WebRenderScrollDataWrapper.h
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--gfx/layers/wr/WebRenderScrollDataWrapper.h424
1 files changed, 424 insertions, 0 deletions
diff --git a/gfx/layers/wr/WebRenderScrollDataWrapper.h b/gfx/layers/wr/WebRenderScrollDataWrapper.h
new file mode 100644
index 0000000000..1f681a7cff
--- /dev/null
+++ b/gfx/layers/wr/WebRenderScrollDataWrapper.h
@@ -0,0 +1,424 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_WEBRENDERSCROLLDATAWRAPPER_H
+#define GFX_WEBRENDERSCROLLDATAWRAPPER_H
+
+#include "FrameMetrics.h"
+#include "mozilla/layers/CompositorBridgeParent.h"
+#include "mozilla/layers/WebRenderBridgeParent.h"
+#include "mozilla/layers/WebRenderScrollData.h"
+
+namespace mozilla {
+namespace layers {
+
+/*
+ * This class is a wrapper to walk through a WebRenderScrollData object, with
+ * an exposed API that is template-compatible to LayerMetricsWrapper. This
+ * allows APZ to walk through both layer trees and WebRender scroll metadata
+ * structures without a lot of code duplication. (Note that not all functions
+ * from LayerMetricsWrapper are implemented here, only the ones we've needed in
+ * APZ code so far.)
+ *
+ * A WebRenderScrollData object is basically a flattened layer tree, with a
+ * number of WebRenderLayerScrollData objects that have a 1:1 correspondence
+ * to layers in a layer tree. Therefore the mLayer pointer in this class can
+ * be considered equivalent to the mLayer pointer in the LayerMetricsWrapper.
+ * There are some extra fields (mData, mLayerIndex, mContainingSubtreeLastIndex)
+ * to move around between these "layers" given the flattened representation.
+ * The mMetadataIndex field in this class corresponds to the mIndex field in
+ * LayerMetricsWrapper, as both classes also need to manage walking through
+ * "virtual" container layers implied by the list of ScrollMetadata objects.
+ *
+ * One important note here is that this class holds a pointer to the "owning"
+ * WebRenderScrollData. The caller must ensure that this class does not outlive
+ * the owning WebRenderScrollData, or this may result in use-after-free errors.
+ * This class being declared a MOZ_STACK_CLASS should help with that.
+ *
+ * Refer to LayerMetricsWrapper.h for actual documentation on the exposed API.
+ */
+class MOZ_STACK_CLASS WebRenderScrollDataWrapper final {
+ public:
+ // Basic constructor for external callers. Starts the walker at the root of
+ // the tree.
+ explicit WebRenderScrollDataWrapper(
+ const APZUpdater& aUpdater, const WebRenderScrollData* aData = nullptr)
+ : mUpdater(&aUpdater),
+ mData(aData),
+ mLayerIndex(0),
+ mContainingSubtreeLastIndex(0),
+ mLayer(nullptr),
+ mMetadataIndex(0) {
+ if (!mData) {
+ return;
+ }
+ mLayer = mData->GetLayerData(mLayerIndex);
+ if (!mLayer) {
+ return;
+ }
+
+ // sanity check on the data
+ MOZ_ASSERT(mData->GetLayerCount() ==
+ (size_t)(1 + mLayer->GetDescendantCount()));
+ mContainingSubtreeLastIndex = mData->GetLayerCount();
+
+ // See documentation in LayerMetricsWrapper.h about this. mMetadataIndex
+ // in this class is equivalent to mIndex in that class.
+ mMetadataIndex = mLayer->GetScrollMetadataCount();
+ if (mMetadataIndex > 0) {
+ mMetadataIndex--;
+ }
+ }
+
+ private:
+ // Internal constructor for walking from one WebRenderLayerScrollData to
+ // another. In this case we need to recompute the mMetadataIndex to be the
+ // "topmost" scroll metadata on the new layer.
+ WebRenderScrollDataWrapper(const APZUpdater* aUpdater,
+ const WebRenderScrollData* aData,
+ size_t aLayerIndex,
+ size_t aContainingSubtreeLastIndex)
+ : mUpdater(aUpdater),
+ mData(aData),
+ mLayerIndex(aLayerIndex),
+ mContainingSubtreeLastIndex(aContainingSubtreeLastIndex),
+ mLayer(nullptr),
+ mMetadataIndex(0) {
+ MOZ_ASSERT(mData);
+ mLayer = mData->GetLayerData(mLayerIndex);
+ MOZ_ASSERT(mLayer);
+
+ // See documentation in LayerMetricsWrapper.h about this. mMetadataIndex
+ // in this class is equivalent to mIndex in that class.
+ mMetadataIndex = mLayer->GetScrollMetadataCount();
+ if (mMetadataIndex > 0) {
+ mMetadataIndex--;
+ }
+ }
+
+ // Internal constructor for walking from one metadata to another metadata on
+ // the same WebRenderLayerScrollData.
+ WebRenderScrollDataWrapper(const APZUpdater* aUpdater,
+ const WebRenderScrollData* aData,
+ size_t aLayerIndex,
+ size_t aContainingSubtreeLastIndex,
+ const WebRenderLayerScrollData* aLayer,
+ uint32_t aMetadataIndex)
+ : mUpdater(aUpdater),
+ mData(aData),
+ mLayerIndex(aLayerIndex),
+ mContainingSubtreeLastIndex(aContainingSubtreeLastIndex),
+ mLayer(aLayer),
+ mMetadataIndex(aMetadataIndex) {
+ MOZ_ASSERT(mData);
+ MOZ_ASSERT(mLayer);
+ MOZ_ASSERT(mLayer == mData->GetLayerData(mLayerIndex));
+ MOZ_ASSERT(mMetadataIndex == 0 ||
+ mMetadataIndex < mLayer->GetScrollMetadataCount());
+ }
+
+ public:
+ bool IsValid() const { return mLayer != nullptr; }
+
+ explicit operator bool() const { return IsValid(); }
+
+ WebRenderScrollDataWrapper GetLastChild() const {
+ MOZ_ASSERT(IsValid());
+
+ if (!AtBottomLayer()) {
+ // If we're still walking around in the virtual container layers created
+ // by the ScrollMetadata array, we just need to update the metadata index
+ // and that's it.
+ return WebRenderScrollDataWrapper(mUpdater, mData, mLayerIndex,
+ mContainingSubtreeLastIndex, mLayer,
+ mMetadataIndex - 1);
+ }
+
+ // Otherwise, we need to walk to a different WebRenderLayerScrollData in
+ // mData.
+
+ // Since mData contains the layer in depth-first, last-to-first order,
+ // the index after mLayerIndex must be mLayerIndex's last child, if it
+ // has any children (indicated by GetDescendantCount() > 0). Furthermore
+ // we compute the first index outside the subtree rooted at this node
+ // (in |subtreeLastIndex|) and pass that in to the child wrapper to use as
+ // its mContainingSubtreeLastIndex.
+ if (mLayer->GetDescendantCount() > 0) {
+ size_t prevSiblingIndex = mLayerIndex + 1 + mLayer->GetDescendantCount();
+ size_t subtreeLastIndex =
+ std::min(mContainingSubtreeLastIndex, prevSiblingIndex);
+ return WebRenderScrollDataWrapper(mUpdater, mData, mLayerIndex + 1,
+ subtreeLastIndex);
+ }
+
+ // We've run out of descendants. But! If the original layer was a RefLayer,
+ // then it connects to another layer tree and we need to traverse that too.
+ // So return a WebRenderScrollDataWrapper for the root of the child layer
+ // tree.
+ if (mLayer->GetReferentId()) {
+ return WebRenderScrollDataWrapper(
+ *mUpdater, mUpdater->GetScrollData(*mLayer->GetReferentId()));
+ }
+
+ return WebRenderScrollDataWrapper(*mUpdater);
+ }
+
+ WebRenderScrollDataWrapper GetPrevSibling() const {
+ MOZ_ASSERT(IsValid());
+
+ if (!AtTopLayer()) {
+ // The virtual container layers don't have siblings
+ return WebRenderScrollDataWrapper(*mUpdater);
+ }
+
+ // Skip past the descendants to get to the previous sibling. However, we
+ // might be at the last sibling already.
+ size_t prevSiblingIndex = mLayerIndex + 1 + mLayer->GetDescendantCount();
+ if (prevSiblingIndex < mContainingSubtreeLastIndex) {
+ return WebRenderScrollDataWrapper(mUpdater, mData, prevSiblingIndex,
+ mContainingSubtreeLastIndex);
+ }
+ return WebRenderScrollDataWrapper(*mUpdater);
+ }
+
+ const ScrollMetadata& Metadata() const {
+ MOZ_ASSERT(IsValid());
+
+ if (mMetadataIndex >= mLayer->GetScrollMetadataCount()) {
+ return *ScrollMetadata::sNullMetadata;
+ }
+ return mLayer->GetScrollMetadata(*mData, mMetadataIndex);
+ }
+
+ const FrameMetrics& Metrics() const { return Metadata().GetMetrics(); }
+
+ AsyncPanZoomController* GetApzc() const { return nullptr; }
+
+ void SetApzc(AsyncPanZoomController* aApzc) const {}
+
+ const char* Name() const { return "WebRenderScrollDataWrapper"; }
+
+ gfx::Matrix4x4 GetTransform() const {
+ MOZ_ASSERT(IsValid());
+
+ // See WebRenderLayerScrollData::Initialize for more context. The ancestor
+ // transform is associated with the "topmost" layer, and the transform is
+ // associated with the "bottommost" layer. If there is only one
+ // scrollmetadata on the layer, then it is both "topmost" and "bottommost"
+ // and we combine the two transforms.
+
+ gfx::Matrix4x4 transform;
+ if (AtTopLayer()) {
+ transform = mLayer->GetAncestorTransform();
+ }
+ if (AtBottomLayer()) {
+ transform = transform * mLayer->GetTransform();
+ }
+ return transform;
+ }
+
+ CSSTransformMatrix GetTransformTyped() const {
+ return ViewAs<CSSTransformMatrix>(GetTransform());
+ }
+
+ bool TransformIsPerspective() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetTransformIsPerspective();
+ }
+ return false;
+ }
+
+ EventRegions GetEventRegions() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetEventRegions();
+ }
+ return EventRegions();
+ }
+
+ LayerIntRegion GetVisibleRegion() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetVisibleRegion();
+ }
+
+ return ViewAs<LayerPixel>(
+ TransformBy(mLayer->GetTransformTyped(), mLayer->GetVisibleRegion()),
+ PixelCastJustification::MovingDownToChildren);
+ }
+
+ LayerIntSize GetRemoteDocumentSize() const {
+ MOZ_ASSERT(IsValid());
+
+ if (mLayer->GetReferentId().isNothing()) {
+ return LayerIntSize();
+ }
+
+ if (AtBottomLayer()) {
+ return mLayer->GetRemoteDocumentSize();
+ }
+
+ return ViewAs<LayerPixel>(mLayer->GetRemoteDocumentSize(),
+ PixelCastJustification::MovingDownToChildren);
+ }
+
+ Maybe<LayersId> GetReferentId() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetReferentId();
+ }
+ return Nothing();
+ }
+
+ Maybe<ParentLayerIntRect> GetClipRect() const {
+ // TODO
+ return Nothing();
+ }
+
+ EventRegionsOverride GetEventRegionsOverride() const {
+ MOZ_ASSERT(IsValid());
+ // Only ref layers can have an event regions override.
+ if (GetReferentId()) {
+ return mLayer->GetEventRegionsOverride();
+ }
+ return EventRegionsOverride::NoOverride;
+ }
+
+ const ScrollbarData& GetScrollbarData() const {
+ MOZ_ASSERT(IsValid());
+ return mLayer->GetScrollbarData();
+ }
+
+ Maybe<uint64_t> GetScrollbarAnimationId() const {
+ MOZ_ASSERT(IsValid());
+ return mLayer->GetScrollbarAnimationId();
+ }
+
+ Maybe<uint64_t> GetFixedPositionAnimationId() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetFixedPositionAnimationId();
+ }
+ return Nothing();
+ }
+
+ ScrollableLayerGuid::ViewID GetFixedPositionScrollContainerId() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetFixedPositionScrollContainerId();
+ }
+ return ScrollableLayerGuid::NULL_SCROLL_ID;
+ }
+
+ SideBits GetFixedPositionSides() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetFixedPositionSides();
+ }
+ return SideBits::eNone;
+ }
+
+ ScrollableLayerGuid::ViewID GetStickyScrollContainerId() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetStickyPositionScrollContainerId();
+ }
+ return ScrollableLayerGuid::NULL_SCROLL_ID;
+ }
+
+ const LayerRectAbsolute& GetStickyScrollRangeOuter() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetStickyScrollRangeOuter();
+ }
+
+ static const LayerRectAbsolute empty;
+ return empty;
+ }
+
+ const LayerRectAbsolute& GetStickyScrollRangeInner() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetStickyScrollRangeInner();
+ }
+
+ static const LayerRectAbsolute empty;
+ return empty;
+ }
+
+ Maybe<uint64_t> GetStickyPositionAnimationId() const {
+ MOZ_ASSERT(IsValid());
+
+ if (AtBottomLayer()) {
+ return mLayer->GetStickyPositionAnimationId();
+ }
+ return Nothing();
+ }
+
+ Maybe<uint64_t> GetZoomAnimationId() const {
+ MOZ_ASSERT(IsValid());
+ return mLayer->GetZoomAnimationId();
+ }
+
+ bool IsBackfaceHidden() const {
+ // This is only used by APZCTM hit testing, and WR does its own
+ // hit testing, so no need to implement this.
+ return false;
+ }
+
+ bool IsAsyncZoomContainer() const {
+ MOZ_ASSERT(IsValid());
+ return mLayer->IsAsyncZoomContainer();
+ }
+
+ const void* GetLayer() const {
+ MOZ_ASSERT(IsValid());
+ return mLayer;
+ }
+
+ private:
+ bool AtBottomLayer() const { return mMetadataIndex == 0; }
+
+ bool AtTopLayer() const {
+ return mLayer->GetScrollMetadataCount() == 0 ||
+ mMetadataIndex == mLayer->GetScrollMetadataCount() - 1;
+ }
+
+ private:
+ const APZUpdater* mUpdater;
+ const WebRenderScrollData* mData;
+ // The index (in mData->mLayerScrollData) of the WebRenderLayerScrollData this
+ // wrapper is pointing to.
+ size_t mLayerIndex;
+ // The upper bound on the set of valid indices inside the subtree rooted at
+ // the parent of this "layer". That is, any layer index |i| in the range
+ // mLayerIndex <= i < mContainingSubtreeLastIndex is guaranteed to point to
+ // a layer that is a descendant of "parent", where "parent" is the parent
+ // layer of the layer at mLayerIndex. This is needed in order to implement
+ // GetPrevSibling() correctly.
+ size_t mContainingSubtreeLastIndex;
+ // The WebRenderLayerScrollData this wrapper is pointing to.
+ const WebRenderLayerScrollData* mLayer;
+ // The index of the scroll metadata within mLayer that this wrapper is
+ // pointing to.
+ uint32_t mMetadataIndex;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif /* GFX_WEBRENDERSCROLLDATAWRAPPER_H */