summaryrefslogtreecommitdiffstats
path: root/gfx/layers/wr/ClipManager.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/wr/ClipManager.h')
-rw-r--r--gfx/layers/wr/ClipManager.h150
1 files changed, 150 insertions, 0 deletions
diff --git a/gfx/layers/wr/ClipManager.h b/gfx/layers/wr/ClipManager.h
new file mode 100644
index 0000000000..7253fec8bb
--- /dev/null
+++ b/gfx/layers/wr/ClipManager.h
@@ -0,0 +1,150 @@
+/* -*- 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_CLIPMANAGER_H
+#define GFX_CLIPMANAGER_H
+
+#include <stack>
+#include <unordered_map>
+
+#include "mozilla/Attributes.h"
+#include "mozilla/webrender/WebRenderAPI.h"
+
+namespace mozilla {
+
+class nsDisplayItem;
+struct ActiveScrolledRoot;
+struct DisplayItemClipChain;
+
+namespace wr {
+class DisplayListBuilder;
+}
+
+namespace layers {
+
+class StackingContextHelper;
+class WebRenderLayerManager;
+
+/**
+ * This class manages creating and assigning scroll layers and clips in
+ * WebRender based on the gecko display list. It has a few public functions that
+ * are intended to be invoked while traversing the Gecko display list, and it
+ * uses the ASR and clip information from the display list to create the
+ * necessary clip state in WebRender.
+ *
+ * The structure of the clip state in WebRender ends up quite similar to how
+ * it is in Gecko. For each ASR in Gecko, we create a scroll layer (i.e. a
+ * scrolling clip) in WebRender; these form a tree structure similar to the
+ * ASR tree structure. Ancestors of scroll layers are always other scroll
+ * layers, or the root scroll node.
+ * The DisplayItemClipChain list of clips from the gecko display list is
+ * converted to a WR clip chain and pushed on the stack prior to creating
+ * any WR commands for that item, and is popped afterwards. In addition,
+ * the WR clip chain has a parent pointer, which points to the clip chain for
+ * any enclosing stacking context. This again results in a strucuture very
+ * similar to that in Gecko, where the clips from container display items get
+ * applied to the contained display items.
+ */
+class ClipManager {
+ public:
+ ClipManager();
+
+ void BeginBuild(WebRenderLayerManager* aManager,
+ wr::DisplayListBuilder& aBuilder);
+ void EndBuild();
+
+ void BeginList(const StackingContextHelper& aStackingContext);
+ void EndList(const StackingContextHelper& aStackingContext);
+
+ wr::WrSpaceAndClipChain SwitchItem(nsDisplayListBuilder* aBuilder,
+ nsDisplayItem* aItem);
+ ~ClipManager();
+
+ void PushOverrideForASR(const ActiveScrolledRoot* aASR,
+ const wr::WrSpatialId& aSpatialId);
+ void PopOverrideForASR(const ActiveScrolledRoot* aASR);
+
+ private:
+ wr::WrSpatialId SpatialIdAfterOverride(const wr::WrSpatialId& aSpatialId);
+ wr::WrSpatialId GetScrollLayer(const ActiveScrolledRoot* aASR);
+
+ Maybe<wr::WrSpatialId> DefineScrollLayers(const ActiveScrolledRoot* aASR,
+ nsDisplayItem* aItem);
+
+ Maybe<wr::WrClipChainId> DefineClipChain(const DisplayItemClipChain* aChain,
+ int32_t aAppUnitsPerDevPixel);
+
+ WebRenderLayerManager* MOZ_NON_OWNING_REF mManager;
+ wr::DisplayListBuilder* mBuilder;
+
+ // Stack of clip caches. Each cache contains a map from gecko
+ // DisplayItemClipChain objects to webrender WrClipIds, which allows us to
+ // avoid redefining identical clips in WR. However, the gecko
+ // DisplayItemClipChain items get deduplicated quite aggressively, without
+ // regard to things like the enclosing reference frame or mask. On the WR
+ // side, we cannot deduplicate clips that aggressively. So what we do is
+ // any time we enter a new reference frame (for example) we create a new clip
+ // cache on mCacheStack. This ensures we continue caching stuff within a given
+ // reference frame, but disallow caching stuff across reference frames. In
+ // general we need to do this anytime PushOverrideForASR is called, as that is
+ // called for the same set of conditions for which we cannot deduplicate
+ // clips.
+ using ClipIdMap = std::unordered_map<const DisplayItemClipChain*,
+ AutoTArray<wr::WrClipId, 4>>;
+ std::stack<ClipIdMap> mCacheStack;
+
+ // A map that holds the cache overrides created by (a) "out of band" clips,
+ // i.e. clips that are generated by display items but that ClipManager
+ // doesn't know about and (b) stacking contexts that affect clip positioning.
+ // These are called "cache overrides" because while we're inside these things,
+ // we cannot use the ASR from the gecko display list as-is. Fundamentally this
+ // results from a mismatch between the ASR+clip items on the gecko side and
+ // the ClipScrollTree on the WR side; the WR side incorporates things like
+ // transforms and stacking context origins while the gecko side manages those
+ // differently.
+ // Any time ClipManager wants to define a new clip as a child of ASR X, it
+ // should first check the cache overrides to see if there is a cache override
+ // item ((a) or (b) above) that is already a child of X, and then define that
+ // clip as a child of Y instead. This map stores X -> Y, which allows
+ // ClipManager to do the necessary lookup. Note that there theoretically might
+ // be multiple different "Y" clips (in case of nested cache overrides), which
+ // is why we need a stack.
+ std::unordered_map<wr::WrSpatialId, std::stack<wr::WrSpatialId>> mASROverride;
+
+ // This holds some clip state for a single nsDisplayItem
+ struct ItemClips {
+ ItemClips(const ActiveScrolledRoot* aASR,
+ const DisplayItemClipChain* aChain, int32_t aAppUnitsPerDevPixel,
+ bool aSeparateLeaf);
+
+ // These are the "inputs" - they come from the nsDisplayItem
+ const ActiveScrolledRoot* mASR;
+ const DisplayItemClipChain* mChain;
+ int32_t mAppUnitsPerDevPixel;
+ bool mSeparateLeaf;
+
+ // These are the "outputs" - they are pushed to WR as needed
+ wr::WrSpatialId mScrollId;
+ Maybe<wr::WrClipChainId> mClipChainId;
+
+ void UpdateSeparateLeaf(wr::DisplayListBuilder& aBuilder,
+ int32_t aAppUnitsPerDevPixel);
+ bool HasSameInputs(const ItemClips& aOther);
+ wr::WrSpaceAndClipChain GetSpaceAndClipChain() const;
+ };
+
+ // A stack of ItemClips corresponding to the nsDisplayItem ancestry. Each
+ // time we recurse into a nsDisplayItem's child list, this stack size
+ // increases by one. The topmost item on the stack is for the display item
+ // we are currently processing and items deeper on the stack are for that
+ // display item's ancestors.
+ std::stack<ItemClips> mItemClipStack;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif