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