1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef GFX_CLIPMANAGER_H
8 #define GFX_CLIPMANAGER_H
11 #include <unordered_map>
13 #include "mozilla/Attributes.h"
14 #include "mozilla/webrender/WebRenderAPI.h"
19 struct ActiveScrolledRoot
;
20 struct DisplayItemClipChain
;
23 class DisplayListBuilder
;
28 class StackingContextHelper
;
29 class WebRenderLayerManager
;
32 * This class manages creating and assigning scroll layers and clips in
33 * WebRender based on the gecko display list. It has a few public functions that
34 * are intended to be invoked while traversing the Gecko display list, and it
35 * uses the ASR and clip information from the display list to create the
36 * necessary clip state in WebRender.
38 * The structure of the clip state in WebRender ends up quite similar to how
39 * it is in Gecko. For each ASR in Gecko, we create a scroll layer (i.e. a
40 * scrolling clip) in WebRender; these form a tree structure similar to the
41 * ASR tree structure. Ancestors of scroll layers are always other scroll
42 * layers, or the root scroll node.
43 * The DisplayItemClipChain list of clips from the gecko display list is
44 * converted to a WR clip chain and pushed on the stack prior to creating
45 * any WR commands for that item, and is popped afterwards. In addition,
46 * the WR clip chain has a parent pointer, which points to the clip chain for
47 * any enclosing stacking context. This again results in a strucuture very
48 * similar to that in Gecko, where the clips from container display items get
49 * applied to the contained display items.
55 void BeginBuild(WebRenderLayerManager
* aManager
,
56 wr::DisplayListBuilder
& aBuilder
);
59 void BeginList(const StackingContextHelper
& aStackingContext
);
60 void EndList(const StackingContextHelper
& aStackingContext
);
62 wr::WrSpaceAndClipChain
SwitchItem(nsDisplayListBuilder
* aBuilder
,
63 nsDisplayItem
* aItem
);
66 void PushOverrideForASR(const ActiveScrolledRoot
* aASR
,
67 const wr::WrSpatialId
& aSpatialId
);
68 void PopOverrideForASR(const ActiveScrolledRoot
* aASR
);
71 wr::WrSpatialId
SpatialIdAfterOverride(const wr::WrSpatialId
& aSpatialId
);
72 wr::WrSpatialId
GetScrollLayer(const ActiveScrolledRoot
* aASR
);
74 Maybe
<wr::WrSpatialId
> DefineScrollLayers(const ActiveScrolledRoot
* aASR
,
75 nsDisplayItem
* aItem
);
77 Maybe
<wr::WrClipChainId
> DefineClipChain(const DisplayItemClipChain
* aChain
,
78 int32_t aAppUnitsPerDevPixel
);
80 WebRenderLayerManager
* MOZ_NON_OWNING_REF mManager
;
81 wr::DisplayListBuilder
* mBuilder
;
83 // Stack of clip caches. Each cache contains a map from gecko
84 // DisplayItemClipChain objects to webrender WrClipIds, which allows us to
85 // avoid redefining identical clips in WR. However, the gecko
86 // DisplayItemClipChain items get deduplicated quite aggressively, without
87 // regard to things like the enclosing reference frame or mask. On the WR
88 // side, we cannot deduplicate clips that aggressively. So what we do is
89 // any time we enter a new reference frame (for example) we create a new clip
90 // cache on mCacheStack. This ensures we continue caching stuff within a given
91 // reference frame, but disallow caching stuff across reference frames. In
92 // general we need to do this anytime PushOverrideForASR is called, as that is
93 // called for the same set of conditions for which we cannot deduplicate
95 using ClipIdMap
= std::unordered_map
<const DisplayItemClipChain
*,
96 AutoTArray
<wr::WrClipId
, 4>>;
97 std::stack
<ClipIdMap
> mCacheStack
;
99 // A map that holds the cache overrides created by (a) "out of band" clips,
100 // i.e. clips that are generated by display items but that ClipManager
101 // doesn't know about and (b) stacking contexts that affect clip positioning.
102 // These are called "cache overrides" because while we're inside these things,
103 // we cannot use the ASR from the gecko display list as-is. Fundamentally this
104 // results from a mismatch between the ASR+clip items on the gecko side and
105 // the ClipScrollTree on the WR side; the WR side incorporates things like
106 // transforms and stacking context origins while the gecko side manages those
108 // Any time ClipManager wants to define a new clip as a child of ASR X, it
109 // should first check the cache overrides to see if there is a cache override
110 // item ((a) or (b) above) that is already a child of X, and then define that
111 // clip as a child of Y instead. This map stores X -> Y, which allows
112 // ClipManager to do the necessary lookup. Note that there theoretically might
113 // be multiple different "Y" clips (in case of nested cache overrides), which
114 // is why we need a stack.
115 std::unordered_map
<wr::WrSpatialId
, std::stack
<wr::WrSpatialId
>> mASROverride
;
117 // This holds some clip state for a single nsDisplayItem
119 ItemClips(const ActiveScrolledRoot
* aASR
,
120 const DisplayItemClipChain
* aChain
, int32_t aAppUnitsPerDevPixel
,
123 // These are the "inputs" - they come from the nsDisplayItem
124 const ActiveScrolledRoot
* mASR
;
125 const DisplayItemClipChain
* mChain
;
126 int32_t mAppUnitsPerDevPixel
;
129 // These are the "outputs" - they are pushed to WR as needed
130 wr::WrSpatialId mScrollId
;
131 Maybe
<wr::WrClipChainId
> mClipChainId
;
133 void UpdateSeparateLeaf(wr::DisplayListBuilder
& aBuilder
,
134 int32_t aAppUnitsPerDevPixel
);
135 bool HasSameInputs(const ItemClips
& aOther
);
136 wr::WrSpaceAndClipChain
GetSpaceAndClipChain() const;
139 // A stack of ItemClips corresponding to the nsDisplayItem ancestry. Each
140 // time we recurse into a nsDisplayItem's child list, this stack size
141 // increases by one. The topmost item on the stack is for the display item
142 // we are currently processing and items deeper on the stack are for that
143 // display item's ancestors.
144 std::stack
<ItemClips
> mItemClipStack
;
147 } // namespace layers
148 } // namespace mozilla