Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
21
22namespace impeller {
23
24class 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|.
29 /// @brief The caller makes no claims related to the size of the bounds.
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.
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.
41};
42
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>(
60 const Matrix& effect_transform,
61 Entity::RenderingMode rendering_mode)>;
62
64
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,
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.
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 EntityPass* GetSuperpass() const;
115
116 bool Render(ContentContext& renderer,
117 const RenderTarget& render_target) const;
118
119 /// @brief Iterate all elements (entities and subpasses) in this pass,
120 /// recursively including elements of child passes. The iteration
121 /// order is depth-first. Whenever a subpass elements is encountered,
122 /// it's included in the stream before its children.
123 void IterateAllElements(const std::function<bool(Element&)>& iterator);
124
126 const std::function<bool(const Element&)>& iterator) const;
127
128 //----------------------------------------------------------------------------
129 /// @brief Iterate all entities in this pass, recursively including entities
130 /// of child passes. The iteration order is depth-first.
131 ///
132 void IterateAllEntities(const std::function<bool(Entity&)>& iterator);
133
134 //----------------------------------------------------------------------------
135 /// @brief Iterate all entities in this pass, recursively including entities
136 /// of child passes. The iteration order is depth-first and does not
137 /// allow modification of the entities.
138 ///
140 const std::function<bool(const Entity&)>& iterator) const;
141
142 //----------------------------------------------------------------------------
143 /// @brief Iterate entities in this pass up until the first subpass is found.
144 /// This is useful for limiting look-ahead optimizations.
145 ///
146 /// @return Returns whether a subpass was encountered.
147 ///
148 bool IterateUntilSubpass(const std::function<bool(Entity&)>& iterator);
149
150 //----------------------------------------------------------------------------
151 /// @brief Return the number of elements on this pass.
152 ///
153 size_t GetElementCount() const;
154
156
157 void SetClipHeight(size_t clip_height);
158
159 size_t GetClipHeight() const;
160
161 void SetClipDepth(size_t clip_depth);
162
163 uint32_t GetClipDepth() const;
164
165 void SetBlendMode(BlendMode blend_mode);
166
167 /// @brief Return the premultiplied clear color of the pass entities, if any.
168 std::optional<Color> GetClearColor(ISize size = ISize::Infinite()) const;
169
170 /// @brief Return the premultiplied clear color of the pass entities.
171 ///
172 /// If the entity pass has no clear color, this will return transparent black.
174
176
177 void SetEnableOffscreenCheckerboard(bool enabled);
178
179 int32_t GetRequiredMipCount() const { return required_mip_count_; }
180
181 void SetRequiredMipCount(int32_t mip_count) {
182 required_mip_count_ = mip_count;
183 }
184
185 //----------------------------------------------------------------------------
186 /// @brief Computes the coverage of a given subpass. This is used to
187 /// determine the texture size of a given subpass before it's rendered
188 /// to and passed through the subpass ImageFilter, if any.
189 ///
190 /// @param[in] subpass The EntityPass for which to compute
191 /// pre-filteredcoverage.
192 /// @param[in] coverage_limit Confines coverage to a specified area. This
193 /// hint is used to trim coverage to the root
194 /// framebuffer area. `std::nullopt` means there
195 /// is no limit.
196 ///
197 /// @return The screen space pixel area that the subpass contents will render
198 /// into, prior to being transformed by the subpass ImageFilter, if
199 /// any. `std::nullopt` means rendering the subpass will have no
200 /// effect on the color attachment.
201 ///
202 std::optional<Rect> GetSubpassCoverage(
203 const EntityPass& subpass,
204 std::optional<Rect> coverage_limit) const;
205
206 std::optional<Rect> GetElementsCoverage(
207 std::optional<Rect> coverage_limit) const;
208
209 private:
210 struct EntityResult {
211 enum Status {
212 /// The entity was successfully resolved and can be rendered.
213 kSuccess,
214 /// An unexpected rendering error occurred while resolving the Entity.
215 kFailure,
216 /// The entity should be skipped because rendering it will contribute
217 /// nothing to the frame.
218 kSkip,
219 };
220
221 /// @brief The resulting entity that should be rendered. If `std::nullopt`,
222 /// there is nothing to render.
223 Entity entity;
224 /// @brief This is set to `false` if there was an unexpected rendering
225 /// error while resolving the Entity.
226 Status status = kFailure;
227
228 static EntityResult Success(Entity e) { return {std::move(e), kSuccess}; }
229 static EntityResult Failure() { return {{}, kFailure}; }
230 static EntityResult Skip() { return {{}, kSkip}; }
231 };
232
233 bool RenderElement(Entity& element_entity,
234 size_t clip_height_floor,
235 InlinePassContext& pass_context,
236 int32_t pass_depth,
237 ContentContext& renderer,
238 EntityPassClipStack& clip_coverage_stack,
239 Point global_pass_position) const;
240
241 EntityResult GetEntityForElement(const EntityPass::Element& element,
242 ContentContext& renderer,
243 Capture& capture,
244 InlinePassContext& pass_context,
245 ISize root_pass_size,
246 Point global_pass_position,
247 uint32_t pass_depth,
248 EntityPassClipStack& clip_coverage_stack,
249 size_t clip_height_floor) const;
250
251 //----------------------------------------------------------------------------
252 /// @brief OnRender is the internal command recording routine for
253 /// `EntityPass`. Its job is to walk through each `Element` which
254 /// was appended to the scene (either an `Entity` via `AddEntity()`
255 /// or a child `EntityPass` via `AddSubpass()`) and render them to
256 /// the given `pass_target`.
257 /// @param[in] renderer The Contents context, which manages
258 /// pipeline state.
259 /// @param[in] root_pass_size The size of the texture being
260 /// rendered into at the root of the
261 /// `EntityPass` tree. This is the size
262 /// of the `RenderTarget` color
263 /// attachment passed to the public
264 /// `EntityPass::Render` method.
265 /// @param[out] pass_target Stores the render target that should
266 /// be used for rendering.
267 /// @param[in] global_pass_position The position that this `EntityPass`
268 /// will be drawn to the parent pass
269 /// relative to the root pass origin.
270 /// Used for offsetting drawn `Element`s,
271 /// whose origins are all in root
272 /// pass/screen space,
273 /// @param[in] local_pass_position The position that this `EntityPass`
274 /// will be drawn to the parent pass
275 /// relative to the parent pass origin.
276 /// Used for positioning backdrop
277 /// filters.
278 /// @param[in] pass_depth The tree depth of the `EntityPass` at
279 /// render time. Only used for labeling
280 /// and debugging purposes. This can vary
281 /// depending on whether passes are
282 /// collapsed or not.
283 /// @param[in] clip_coverage_stack A global stack of coverage rectangles
284 /// for the clip buffer at each depth.
285 /// Higher depths are more restrictive.
286 /// Used to cull Elements that we
287 /// know won't result in a visible
288 /// change.
289 /// @param[in] clip_height_floor The clip depth that a value of
290 /// zero corresponds to in the given
291 /// `pass_target` clip buffer.
292 /// When new `pass_target`s are created
293 /// for subpasses, their clip buffers are
294 /// initialized at zero, and so this
295 /// value is used to offset Entity clip
296 /// depths to match the clip buffer.
297 /// @param[in] backdrop_filter_contents Optional. Is supplied, this contents
298 /// is rendered prior to anything else in
299 /// the `EntityPass`, offset by the
300 /// `local_pass_position`.
301 /// @param[in] collapsed_parent_pass Optional. If supplied, this
302 /// `InlinePassContext` state is used to
303 /// begin rendering elements instead of
304 /// creating a new `RenderPass`. This
305 /// "collapses" the Elements into the
306 /// parent pass.
307 ///
308 bool OnRender(ContentContext& renderer,
309 Capture& capture,
310 ISize root_pass_size,
311 EntityPassTarget& pass_target,
312 Point global_pass_position,
313 Point local_pass_position,
314 uint32_t pass_depth,
315 EntityPassClipStack& clip_coverage_stack,
316 size_t clip_height_floor = 0,
317 std::shared_ptr<Contents> backdrop_filter_contents = nullptr,
318 const std::optional<InlinePassContext::RenderPassResult>&
319 collapsed_parent_pass = std::nullopt) const;
320
321 /// The list of renderable items in the scene. Each of these items is
322 /// evaluated and recorded to an `EntityPassTarget` by the `OnRender` method.
323 std::vector<Element> elements_;
324
325 /// The stack of currently active clips (during Aiks recording time). Each
326 /// entry is an index into the `elements_` list. The depth value of a clip is
327 /// the max of all the entities it affects, so assignment of the depth value
328 /// is deferred until clip restore or end of the EntityPass.
329 std::vector<size_t> active_clips_;
330
331 EntityPass* superpass_ = nullptr;
332 Matrix transform_;
333 size_t clip_height_ = 0u;
334 uint32_t clip_depth_ = 1u;
335 BlendMode blend_mode_ = BlendMode::kSourceOver;
336 bool flood_clip_ = false;
337 bool enable_offscreen_debug_checkerboard_ = false;
338 std::optional<Rect> bounds_limit_;
340 int32_t required_mip_count_ = 1;
341
342 /// These values indicate whether something has been added to the EntityPass
343 /// that requires reading from the backdrop texture. Currently, this can
344 /// happen in the following scenarios:
345 /// 1. An entity with an "advanced blend" is added to the pass.
346 /// 2. A subpass with a backdrop filter is added to the pass.
347 /// These are tracked as separate values because we may ignore
348 /// `blend_reads_from_pass_texture_` if the device supports framebuffer based
349 /// advanced blends.
350 bool advanced_blend_reads_from_pass_texture_ = false;
351 bool backdrop_filter_reads_from_pass_texture_ = false;
352
353 bool DoesBackdropGetRead(ContentContext& renderer) const;
354
355 BackdropFilterProc backdrop_filter_proc_ = nullptr;
356
357 std::shared_ptr<EntityPassDelegate> delegate_ =
359
360 EntityPass(const EntityPass&) = delete;
361
362 EntityPass& operator=(const EntityPass&) = delete;
363};
364
365} // namespace impeller
366
367#endif // FLUTTER_IMPELLER_ENTITY_ENTITY_PASS_H_
static std::unique_ptr< EntityPassDelegate > MakeDefault()
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...
void SetElements(std::vector< Element > elements)
void IterateAllElements(const std::function< bool(Element &)> &iterator)
Iterate all elements (entities and subpasses) in this pass, recursively including elements of child p...
std::variant< Entity, std::unique_ptr< EntityPass > > Element
Definition entity_pass.h:54
size_t GetElementCount() const
Return the number of elements on this pass.
void SetRequiredMipCount(int32_t mip_count)
bool GetBoundsLimitMightClipContent() const
Indicates if the bounds limit set using |SetBoundsLimit()| might clip the contents of the pass.
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...
void SetEnableOffscreenCheckerboard(bool enabled)
Color GetClearColorOrDefault(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities.
void SetClipDepth(size_t clip_depth)
void AddEntity(Entity entity)
Add an entity to the current entity pass.
size_t GetClipHeight() const
void SetBackdropFilter(BackdropFilterProc proc)
bool GetBoundsLimitIsSnug() const
Indicates if the bounds limit set using |SetBoundsLimit()| is a reasonably tight estimate of the boun...
static const std::string kCaptureDocumentName
Definition entity_pass.h:56
std::optional< Rect > GetBoundsLimit() const
Get the bounds limit, which is provided by the user when creating a SaveLayer.
EntityPass * GetSuperpass() const
size_t GetSubpassesDepth() const
void PopClips(size_t num_clips, uint64_t depth)
int32_t GetRequiredMipCount() const
void SetClipHeight(size_t clip_height)
std::optional< Color > GetClearColor(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities, if any.
void SetBlendMode(BlendMode blend_mode)
void SetTransform(Matrix transform)
void IterateAllEntities(const std::function< bool(Entity &)> &iterator)
Iterate all entities in this pass, recursively including entities of child passes....
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...
void PopAllClips(uint64_t depth)
EntityPass * AddSubpass(std::unique_ptr< EntityPass > pass)
Appends a given pass as a subpass.
void SetDelegate(std::shared_ptr< EntityPassDelegate > delgate)
bool Render(ContentContext &renderer, const RenderTarget &render_target) const
std::optional< Rect > GetElementsCoverage(std::optional< Rect > coverage_limit) const
void PushClip(Entity entity)
uint32_t GetClipDepth() const
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
Definition entity_pass.h:61
std::shared_ptr< FilterInput > Ref
@ kSuccess
Definition embedder.h:73
@ kFailure
Failed to make the egl context for the surface current.
TPoint< Scalar > Point
Definition point.h:316
TSize< int64_t > ISize
Definition size.h:138
BlendMode
Definition color.h:59
ContentBoundsPromise
Definition entity_pass.h:28
@ kUnknown
The caller makes no claims related to the size of the bounds.
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr TSize Infinite()
Definition size.h:38