| Flutter Impeller |

entity_pass.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef FLUTTER_IMPELLER_ENTITY_ENTITY_PASS_H_
6 #define FLUTTER_IMPELLER_ENTITY_ENTITY_PASS_H_
7
8 #include <cstdint>
9 #include <functional>
10 #include <memory>
11 #include <optional>
12 #include <vector>
13
14 #include "impeller/entity/contents/contents.h"
15 #include "impeller/entity/contents/filters/filter_contents.h"
16 #include "impeller/entity/entity.h"
17 #include "impeller/entity/entity_pass_clip_stack.h"
18 #include "impeller/entity/entity_pass_delegate.h"
19 #include "impeller/entity/inline_pass_context.h"
20 #include "impeller/renderer/render_target.h"
21
22 namespace impeller {
23
24 class ContentContext;
25
26 /// Specifies how much to trust the bounds rectangle provided for a list
27 /// of contents. Used by both |EntityPass| and |Canvas::SaveLayer|.
28 enum class ContentBoundsPromise {
29 /// @brief The caller makes no claims related to the size of the bounds.
30 kUnknown,
31
32 /// @brief The caller claims the bounds are a reasonably tight estimate
33 /// of the coverage of the contents and should contain all of the
34 /// contents.
35 kContainsContents,
36
37 /// @brief The caller claims the bounds are a subset of an estimate of
38 /// the reasonably tight bounds but likely clips off some of the
39 /// contents.
40 kMayClipContents,
41 };
42
43 class EntityPass {
44 public:
45 /// Elements are renderable items in the `EntityPass`. Each can either be an
46 /// `Entity` or a child `EntityPass`.
47 ///
48 /// When the element is a child `EntityPass`, it may be rendered to an
49 /// offscreen texture and converted into an `Entity` that draws the texture
50 /// into the current pass, or its children may be collapsed into the current
51 ///
52 /// `EntityPass`. Elements are converted to Entities in
53 /// `GetEntityForElement()`.
54 using Element = std::variant<Entity, std::unique_ptr<EntityPass>>;
55
56 static const std::string kCaptureDocumentName;
57
58 using BackdropFilterProc = std::function<std::shared_ptr<FilterContents>(
59 FilterInput::Ref,
60 const Matrix& effect_transform,
61 Entity::RenderingMode rendering_mode)>;
62
63 EntityPass();
64
65 ~EntityPass();
66
67 void SetDelegate(std::shared_ptr<EntityPassDelegate> delgate);
68
69 /// @brief Set the bounds limit, which is provided by the user when creating
70 /// a SaveLayer. This is a hint that allows the user to communicate
71 /// that it's OK to not render content outside of the bounds.
72 ///
73 /// For consistency with Skia, we effectively treat this like a
74 /// rectangle clip by forcing the subpass texture size to never exceed
75 /// it.
76 ///
77 /// The entity pass will assume that these bounds cause a clipping
78 /// effect on the layer unless this call is followed up with a
79 /// call to |SetBoundsClipsContent()| specifying otherwise.
80 void SetBoundsLimit(
81 std::optional<Rect> bounds_limit,
82 ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown);
83
84 /// @brief Get the bounds limit, which is provided by the user when creating
85 /// a SaveLayer.
86 std::optional<Rect> GetBoundsLimit() const;
87
88 /// @brief Indicates if the bounds limit set using |SetBoundsLimit()|
89 /// might clip the contents of the pass.
90 bool GetBoundsLimitMightClipContent() const;
91
92 /// @brief Indicates if the bounds limit set using |SetBoundsLimit()|
93 /// is a reasonably tight estimate of the bounds of the contents.
94 bool GetBoundsLimitIsSnug() const;
95
96 size_t GetSubpassesDepth() const;
97
98 /// @brief Add an entity to the current entity pass.
99 void AddEntity(Entity entity);
100
101 void PushClip(Entity entity);
102
103 void PopClips(size_t num_clips, uint64_t depth);
104
105 void PopAllClips(uint64_t depth);
106
107 void SetElements(std::vector<Element> elements);
108
109 //----------------------------------------------------------------------------
110 /// @brief Appends a given pass as a subpass.
111 ///
112 EntityPass* AddSubpass(std::unique_ptr<EntityPass> pass);
113
114 //----------------------------------------------------------------------------
115 /// @brief Merges a given pass into this pass. Useful for drawing
116 /// pre-recorded pictures that don't require rendering into a separate
117 /// subpass.
118 ///
119 void AddSubpassInline(std::unique_ptr<EntityPass> pass);
120
121 EntityPass* GetSuperpass() const;
122
123 bool Render(ContentContext& renderer,
124 const RenderTarget& render_target) const;
125
126 /// @brief Iterate all elements (entities and subpasses) in this pass,
127 /// recursively including elements of child passes. The iteration
128 /// order is depth-first. Whenever a subpass elements is encountered,
129 /// it's included in the stream before its children.
130 void IterateAllElements(const std::function<bool(Element&)>& iterator);
131
132 void IterateAllElements(
133 const std::function<bool(const Element&)>& iterator) const;
134
135 //----------------------------------------------------------------------------
136 /// @brief Iterate all entities in this pass, recursively including entities
137 /// of child passes. The iteration order is depth-first.
138 ///
139 void IterateAllEntities(const std::function<bool(Entity&)>& iterator);
140
141 //----------------------------------------------------------------------------
142 /// @brief Iterate all entities in this pass, recursively including entities
143 /// of child passes. The iteration order is depth-first and does not
144 /// allow modification of the entities.
145 ///
146 void IterateAllEntities(
147 const std::function<bool(const Entity&)>& iterator) const;
148
149 //----------------------------------------------------------------------------
150 /// @brief Iterate entities in this pass up until the first subpass is found.
151 /// This is useful for limiting look-ahead optimizations.
152 ///
153 /// @return Returns whether a subpass was encountered.
154 ///
155 bool IterateUntilSubpass(const std::function<bool(Entity&)>& iterator);
156
157 //----------------------------------------------------------------------------
158 /// @brief Return the number of elements on this pass.
159 ///
160 size_t GetElementCount() const;
161
162 void SetTransform(Matrix transform);
163
164 void SetClipDepth(size_t clip_depth);
165
166 size_t GetClipDepth() const;
167
168 void SetNewClipDepth(size_t clip_depth);
169
170 uint32_t GetNewClipDepth() const;
171
172 void SetBlendMode(BlendMode blend_mode);
173
174 /// @brief Return the premultiplied clear color of the pass entities, if any.
175 std::optional<Color> GetClearColor(ISize size = ISize::Infinite()) const;
176
177 /// @brief Return the premultiplied clear color of the pass entities.
178 ///
179 /// If the entity pass has no clear color, this will return transparent black.
180 Color GetClearColorOrDefault(ISize size = ISize::Infinite()) const;
181
182 void SetBackdropFilter(BackdropFilterProc proc);
183
184 void SetEnableOffscreenCheckerboard(bool enabled);
185
186 int32_t GetRequiredMipCount() const { return required_mip_count_; }
187
188 void SetRequiredMipCount(int32_t mip_count) {
189 required_mip_count_ = mip_count;
190 }
191
192 //----------------------------------------------------------------------------
193 /// @brief Computes the coverage of a given subpass. This is used to
194 /// determine the texture size of a given subpass before it's rendered
195 /// to and passed through the subpass ImageFilter, if any.
196 ///
197 /// @param[in] subpass The EntityPass for which to compute
198 /// pre-filteredcoverage.
199 /// @param[in] coverage_limit Confines coverage to a specified area. This
200 /// hint is used to trim coverage to the root
201 /// framebuffer area. `std::nullopt` means there
202 /// is no limit.
203 ///
204 /// @return The screen space pixel area that the subpass contents will render
205 /// into, prior to being transformed by the subpass ImageFilter, if
206 /// any. `std::nullopt` means rendering the subpass will have no
207 /// effect on the color attachment.
208 ///
209 std::optional<Rect> GetSubpassCoverage(
210 const EntityPass& subpass,
211 std::optional<Rect> coverage_limit) const;
212
213 std::optional<Rect> GetElementsCoverage(
214 std::optional<Rect> coverage_limit) const;
215
216 private:
217 struct EntityResult {
218 enum Status {
219 /// The entity was successfully resolved and can be rendered.
220 kSuccess,
221 /// An unexpected rendering error occurred while resolving the Entity.
222 kFailure,
223 /// The entity should be skipped because rendering it will contribute
224 /// nothing to the frame.
225 kSkip,
226 };
227
228 /// @brief The resulting entity that should be rendered. If `std::nullopt`,
229 /// there is nothing to render.
230 Entity entity;
231 /// @brief This is set to `false` if there was an unexpected rendering
232 /// error while resolving the Entity.
233 Status status = kFailure;
234
235 static EntityResult Success(Entity e) { return {std::move(e), kSuccess}; }
236 static EntityResult Failure() { return {{}, kFailure}; }
237 static EntityResult Skip() { return {{}, kSkip}; }
238 };
239
240 bool RenderElement(Entity& element_entity,
241 size_t clip_depth_floor,
242 InlinePassContext& pass_context,
243 int32_t pass_depth,
244 ContentContext& renderer,
245 EntityPassClipStack& clip_coverage_stack,
246 Point global_pass_position) const;
247
248 EntityResult GetEntityForElement(const EntityPass::Element& element,
249 ContentContext& renderer,
250 Capture& capture,
251 InlinePassContext& pass_context,
252 ISize root_pass_size,
253 Point global_pass_position,
254 uint32_t pass_depth,
255 EntityPassClipStack& clip_coverage_stack,
256 size_t clip_depth_floor) const;
257
258 //----------------------------------------------------------------------------
259 /// @brief OnRender is the internal command recording routine for
260 /// `EntityPass`. Its job is to walk through each `Element` which
261 /// was appended to the scene (either an `Entity` via `AddEntity()`
262 /// or a child `EntityPass` via `AddSubpass()`) and render them to
263 /// the given `pass_target`.
264 /// @param[in] renderer The Contents context, which manages
265 /// pipeline state.
266 /// @param[in] root_pass_size The size of the texture being
267 /// rendered into at the root of the
268 /// `EntityPass` tree. This is the size
269 /// of the `RenderTarget` color
270 /// attachment passed to the public
271 /// `EntityPass::Render` method.
272 /// @param[out] pass_target Stores the render target that should
273 /// be used for rendering.
274 /// @param[in] global_pass_position The position that this `EntityPass`
275 /// will be drawn to the parent pass
276 /// relative to the root pass origin.
277 /// Used for offsetting drawn `Element`s,
278 /// whose origins are all in root
279 /// pass/screen space,
280 /// @param[in] local_pass_position The position that this `EntityPass`
281 /// will be drawn to the parent pass
282 /// relative to the parent pass origin.
283 /// Used for positioning backdrop
284 /// filters.
285 /// @param[in] pass_depth The tree depth of the `EntityPass` at
286 /// render time. Only used for labeling
287 /// and debugging purposes. This can vary
288 /// depending on whether passes are
289 /// collapsed or not.
290 /// @param[in] clip_coverage_stack A global stack of coverage rectangles
291 /// for the clip buffer at each depth.
292 /// Higher depths are more restrictive.
293 /// Used to cull Elements that we
294 /// know won't result in a visible
295 /// change.
296 /// @param[in] clip_depth_floor The clip depth that a value of
297 /// zero corresponds to in the given
298 /// `pass_target` clip buffer.
299 /// When new `pass_target`s are created
300 /// for subpasses, their clip buffers are
301 /// initialized at zero, and so this
302 /// value is used to offset Entity clip
303 /// depths to match the clip buffer.
304 /// @param[in] backdrop_filter_contents Optional. Is supplied, this contents
305 /// is rendered prior to anything else in
306 /// the `EntityPass`, offset by the
307 /// `local_pass_position`.
308 /// @param[in] collapsed_parent_pass Optional. If supplied, this
309 /// `InlinePassContext` state is used to
310 /// begin rendering elements instead of
311 /// creating a new `RenderPass`. This
312 /// "collapses" the Elements into the
313 /// parent pass.
314 ///
315 bool OnRender(ContentContext& renderer,
316 Capture& capture,
317 ISize root_pass_size,
318 EntityPassTarget& pass_target,
319 Point global_pass_position,
320 Point local_pass_position,
321 uint32_t pass_depth,
322 EntityPassClipStack& clip_coverage_stack,
323 size_t clip_depth_floor = 0,
324 std::shared_ptr<Contents> backdrop_filter_contents = nullptr,
325 const std::optional<InlinePassContext::RenderPassResult>&
326 collapsed_parent_pass = std::nullopt) const;
327
328 /// The list of renderable items in the scene. Each of these items is
329 /// evaluated and recorded to an `EntityPassTarget` by the `OnRender` method.
330 std::vector<Element> elements_;
331
332 /// The stack of currently active clips (during Aiks recording time). Each
333 /// entry is an index into the `elements_` list. The depth value of a clip is
334 /// the max of all the entities it affects, so assignment of the depth value
335 /// is deferred until clip restore or end of the EntityPass.
336 std::vector<size_t> active_clips_;
337
338 EntityPass* superpass_ = nullptr;
339 Matrix transform_;
340 size_t clip_depth_ = 0u;
341 uint32_t new_clip_depth_ = 1u;
342 BlendMode blend_mode_ = BlendMode::kSourceOver;
343 bool flood_clip_ = false;
344 bool enable_offscreen_debug_checkerboard_ = false;
345 std::optional<Rect> bounds_limit_;
346 ContentBoundsPromise bounds_promise_ = ContentBoundsPromise::kUnknown;
347 int32_t required_mip_count_ = 1;
348
349 /// These values are incremented whenever something is added to the pass that
350 /// requires reading from the backdrop texture. Currently, this can happen in
351 /// the following scenarios:
352 /// 1. An entity with an "advanced blend" is added to the pass.
353 /// 2. A subpass with a backdrop filter is added to the pass.
354 /// These are tracked as separate values because we may ignore
355 /// blend_reads_from_pass_texture_ if the device supports framebuffer based
356 /// advanced blends.
357 uint32_t advanced_blend_reads_from_pass_texture_ = 0;
358 uint32_t backdrop_filter_reads_from_pass_texture_ = 0;
359
360 uint32_t GetTotalPassReads(ContentContext& renderer) const;
361
362 BackdropFilterProc backdrop_filter_proc_ = nullptr;
363
364 std::shared_ptr<EntityPassDelegate> delegate_ =
365 EntityPassDelegate::MakeDefault();
366
367 EntityPass(const EntityPass&) = delete;
368
369 EntityPass& operator=(const EntityPass&) = delete;
370 };
371
372 } // namespace impeller
373
374 #endif // FLUTTER_IMPELLER_ENTITY_ENTITY_PASS_H_
impeller::EntityPass::AddSubpassInline
void AddSubpassInline(std::unique_ptr< EntityPass > pass)
Merges a given pass into this pass. Useful for drawing pre-recorded pictures that don't require rende...
Definition: entity_pass.cc:291
impeller::EntityPass::IterateAllEntities
void IterateAllEntities(const std::function< bool(Entity &)> &iterator)
Iterate all entities in this pass, recursively including entities of child passes....
Definition: entity_pass.cc:1093
impeller::EntityPass::GetNewClipDepth
uint32_t GetNewClipDepth() const
Definition: entity_pass.cc:1174
impeller::EntityPass::SetBackdropFilter
void SetBackdropFilter(BackdropFilterProc proc)
Definition: entity_pass.cc:1208
contents.h
entity_pass_delegate.h
impeller::EntityPass::BackdropFilterProc
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
Definition: entity_pass.h:61
impeller::EntityPass::PopAllClips
void PopAllClips(uint64_t depth)
Definition: entity_pass.cc:141
impeller::EntityPass::GetSubpassCoverage
std::optional< Rect > GetSubpassCoverage(const EntityPass &subpass, std::optional< Rect > coverage_limit) const
Computes the coverage of a given subpass. This is used to determine the texture size of a given subpa...
Definition: entity_pass.cc:236
impeller::ContentBoundsPromise::kMayClipContents
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
entity.h
impeller::EntityPass::GetSubpassesDepth
size_t GetSubpassesDepth() const
Definition: entity_pass.cc:149
impeller::EntityPass::SetNewClipDepth
void SetNewClipDepth(size_t clip_depth)
Definition: entity_pass.cc:1170
impeller::BlendMode
BlendMode
Definition: color.h:59
impeller::Color
Definition: color.h:124
impeller::EntityPass::GetBoundsLimitMightClipContent
bool GetBoundsLimitMightClipContent() const
Indicates if the bounds limit set using |SetBoundsLimit()| might clip the contents of the pass.
Definition: entity_pass.cc:75
impeller::EntityPass::EntityPass
EntityPass()
impeller::EntityPassDelegate::MakeDefault
static std::unique_ptr< EntityPassDelegate > MakeDefault()
Definition: entity_pass_delegate.cc:51
impeller::EntityPass::AddSubpass
EntityPass * AddSubpass(std::unique_ptr< EntityPass > pass)
Appends a given pass as a subpass.
Definition: entity_pass.cc:272
impeller::EntityPass::IterateUntilSubpass
bool IterateUntilSubpass(const std::function< bool(Entity &)> &iterator)
Iterate entities in this pass up until the first subpass is found. This is useful for limiting look-a...
Definition: entity_pass.cc:1136
impeller::EntityPass::GetBoundsLimitIsSnug
bool GetBoundsLimitIsSnug() const
Indicates if the bounds limit set using |SetBoundsLimit()| is a reasonably tight estimate of the boun...
Definition: entity_pass.cc:94
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
impeller::EntityPass::IterateAllElements
void IterateAllElements(const std::function< bool(Element &)> &iterator)
Iterate all elements (entities and subpasses) in this pass, recursively including elements of child p...
Definition: entity_pass.cc:1058
impeller::ContentBoundsPromise
ContentBoundsPromise
Definition: entity_pass.h:28
impeller::ContentBoundsPromise::kUnknown
@ kUnknown
The caller makes no claims related to the size of the bounds.
impeller::EntityPass::GetElementsCoverage
std::optional< Rect > GetElementsCoverage(std::optional< Rect > coverage_limit) const
Definition: entity_pass.cc:160
impeller::EntityPass::~EntityPass
~EntityPass()
impeller::EntityPass::SetClipDepth
void SetClipDepth(size_t clip_depth)
Definition: entity_pass.cc:1162
impeller::EntityPass::SetBlendMode
void SetBlendMode(BlendMode blend_mode)
Definition: entity_pass.cc:1178
impeller::EntityPass::GetClipDepth
size_t GetClipDepth() const
Definition: entity_pass.cc:1166
impeller::Entity
Definition: entity.h:21
impeller::TSize< int64_t >
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
impeller::EntityPass::SetElements
void SetElements(std::vector< Element > elements)
Definition: entity_pass.cc:145
filter_contents.h
impeller::EntityPass::GetBoundsLimit
std::optional< Rect > GetBoundsLimit() const
Get the bounds limit, which is provided by the user when creating a SaveLayer.
Definition: entity_pass.cc:71
impeller::EntityPass::GetSuperpass
EntityPass * GetSuperpass() const
Definition: entity_pass.cc:268
impeller::EntityPass
Definition: entity_pass.h:43
impeller::EntityPass::Element
std::variant< Entity, std::unique_ptr< EntityPass > > Element
Definition: entity_pass.h:54
impeller::EntityPass::GetRequiredMipCount
int32_t GetRequiredMipCount() const
Definition: entity_pass.h:186
impeller::EntityPass::GetElementCount
size_t GetElementCount() const
Return the number of elements on this pass.
Definition: entity_pass.cc:1154
impeller::RenderTarget
Definition: render_target.h:38
impeller::EntityPass::SetTransform
void SetTransform(Matrix transform)
Definition: entity_pass.cc:1158
impeller::EntityPass::SetBoundsLimit
void SetBoundsLimit(std::optional< Rect > bounds_limit, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown)
Set the bounds limit, which is provided by the user when creating a SaveLayer. This is a hint that al...
Definition: entity_pass.cc:64
entity_pass_clip_stack.h
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
impeller::EntityPass::PopClips
void PopClips(size_t num_clips, uint64_t depth)
Definition: entity_pass.cc:123
impeller::EntityPass::PushClip
void PushClip(Entity entity)
Definition: entity_pass.cc:118
impeller::EntityPass::Render
bool Render(ContentContext &renderer, const RenderTarget &render_target) const
Definition: entity_pass.cc:376
impeller::TSize< int64_t >::Infinite
static constexpr TSize Infinite()
Definition: size.h:38
impeller::EntityPass::kCaptureDocumentName
static const std::string kCaptureDocumentName
Definition: entity_pass.h:56
impeller::EntityPass::SetDelegate
void SetDelegate(std::shared_ptr< EntityPassDelegate > delgate)
Definition: entity_pass.cc:57
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:28
impeller::EntityPass::SetEnableOffscreenCheckerboard
void SetEnableOffscreenCheckerboard(bool enabled)
Definition: entity_pass.cc:1217
render_target.h
impeller::ContentBoundsPromise::kContainsContents
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
impeller
Definition: aiks_blur_unittests.cc:20
impeller::ContentContext
Definition: content_context.h:392
impeller::EntityPass::SetRequiredMipCount
void SetRequiredMipCount(int32_t mip_count)
Definition: entity_pass.h:188
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::EntityPass::GetClearColor
std::optional< Color > GetClearColor(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities, if any.
Definition: entity_pass.cc:1187
impeller::EntityPass::GetClearColorOrDefault
Color GetClearColorOrDefault(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities.
Definition: entity_pass.cc:1183
impeller::EntityPass::AddEntity
void AddEntity(Entity entity)
Add an entity to the current entity pass.
Definition: entity_pass.cc:106
inline_pass_context.h