Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 894bf2f

Browse files
committed
add design/usage comment to LayerStateStack
1 parent c648e4a commit 894bf2f

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

flow/layers/layer_state_stack.h

+92
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,98 @@
1212

1313
namespace flutter {
1414

15+
/// The LayerStateStack manages the inherited state passed down between
16+
/// |Layer| objects in a |LayerTree| during |Preroll| and |Paint|.
17+
///
18+
/// More specifically, it manages the clip and transform state during
19+
/// recursive rendering and will hold and lazily apply opacity, ImageFilter
20+
/// and ColorFilter attributes to recursive content. This is not a truly
21+
/// general state management mechnanism as it makes assumptions that code
22+
/// will be applying the attributes to rendered content that happens in
23+
/// recursive calls. The automatic save/restore mechanisms only work in
24+
/// a context where C++ auto-destruct calls will engage the restore at
25+
/// the end of a code block and that any applied attributes will only
26+
/// be applied to the content rendered inside that block. These restrictions
27+
/// match the organization of the |LayerTree| precisely.
28+
///
29+
/// The stack can manage a single state delegate. The stack will both
30+
/// record the state internally regardless of any delegate and will also
31+
/// apply it to a delegate as needed. The delegate can be swapped out
32+
/// on the fly (as is typically done by PlatformViewLayer when recording
33+
/// the state for multiple inter-embedded-view sub-trees) and the old
34+
/// delegate will be restored to its original state (before it became a
35+
/// delegate) and the new delegate will have all of the state recorded
36+
/// by the stack replayed into it to bring it up to speed with the
37+
/// current rendering context.
38+
///
39+
/// The delegate can be any one of:
40+
/// - MutatorsStack: used during Preroll to remember the outstanding
41+
/// state for embedded platform layers
42+
/// - SkCanvas: used during Paint for the default output to a Skia
43+
/// surface
44+
/// - DisplayListBuilder: used during Paint to construct a DisplayList
45+
/// for Impeller output
46+
/// The stack will know which state needs to be conveyed to any of these
47+
/// delegates and when is the best time to convey that state (i.e. lazy
48+
/// saveLayer calls for example).
49+
///
50+
/// The rendering state attributes will be automatically applied to the
51+
/// nested content using a |saveLayer| call at the point at which we
52+
/// encounter rendered content (i.e. various nested layers that exist only
53+
/// to apply new state will not trigger the |saveLayer| and the attributes
54+
/// can accumulate until we reach actual content that is rendered.) Some
55+
/// rendered content can avoid the |saveLayer| if it reports to the object
56+
/// that it is able to apply all of the attributes that happen to be
57+
/// outstanding (accumulated from parent state-modifiers). A |ContainerLayer|
58+
/// can also monitor the attribute rendering capabilities of a list of
59+
/// children and can ask the object to apply a protective |saveLayer| or
60+
/// not based on the negotiated capabilities of the entire group.
61+
///
62+
/// Any code that is planning to modify the clip, transform, or rendering
63+
/// attributes for its child content must start by calling the |save| method
64+
/// which returns a MutatorContext object. The methods that modify such
65+
/// state only exist on the MutatorContext object so it is difficult to get
66+
/// that wrong, but the caller must make sure that the call happens within
67+
/// a C++ code block that will define the "rendering scope" of those
68+
/// state changes as they will be automatically restored on exit from that
69+
/// block. Note that the layer might make similar state calls directly on
70+
/// the canvas or builder during the Paint cycle (via saveLayer, transform,
71+
/// or clip calls), but should avoid doing so if there is any nested content
72+
/// that needs to track or react to those state calls.
73+
///
74+
/// Code that needs to render content can simply inform the parent of their
75+
/// abilities by setting the |PrerollContext::renderable_state_flags| during
76+
/// |Preroll| and then render with those attributes during |Paint| by
77+
/// requesting the outstanding values of those attributes from the state_stack
78+
/// object. Individual leaf layers can ignore this feature as the default
79+
/// behavior during |Preroll| will have their parent |ContainerLayer| assume
80+
/// that they cannot render any outstanding state attributes and will apply
81+
/// the protective saveLayer on their behalf if needed. As such, this object
82+
/// only provides "opt-in" features for leaf layers and no responsibilities
83+
/// otherwise.
84+
/// See |LayerStateStack::fill|
85+
/// See |LayerStateStack::outstanding_opacity|
86+
/// See |LayerStateStack::outstanding_color_filter|
87+
/// See |LayerStateStack::outstanding_image_filter|
88+
///
89+
/// State-modifying layers should contain code similar to this pattern in both
90+
/// their |Preroll| and |Paint| methods.
91+
///
92+
/// void [LayerType]::[Preroll/Paint](context) {
93+
/// auto mutator = context.state_stack.save();
94+
/// mutator.translate(origin.x, origin.y);
95+
/// mutator.applyOpacity(content_bounds, opacity_value);
96+
/// mutator.applyColorFilter(content_bounds, color_filter);
97+
///
98+
/// // Children will react to the state applied above during their
99+
/// // Preroll/Paint methods or ContainerLayer will protect them
100+
/// // conservatively by default.
101+
/// [Preroll/Paint]Children(context);
102+
///
103+
/// // here the mutator will be auto-destructed and the state accumulated
104+
/// // by it will be restored out of the state_stack and its associated
105+
/// // delegates.
106+
/// }
15107
class LayerStateStack {
16108
public:
17109
explicit LayerStateStack(const SkRect* cull_rect = nullptr);

0 commit comments

Comments
 (0)