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"
20 
21 namespace impeller {
22 
23 class ContentContext;
24 class EntityPassClipRecorder;
25 
26 class EntityPass {
27  public:
28  /// Elements are renderable items in the `EntityPass`. Each can either be an
29  /// `Entity` or a child `EntityPass`.
30  ///
31  /// When the element is a child `EntityPass`, it may be rendered to an
32  /// offscreen texture and converted into an `Entity` that draws the texture
33  /// into the current pass, or its children may be collapsed into the current
34  ///
35  /// `EntityPass`. Elements are converted to Entities in
36  /// `GetEntityForElement()`.
37  using Element = std::variant<Entity, std::unique_ptr<EntityPass>>;
38 
39  static const std::string kCaptureDocumentName;
40 
41  using BackdropFilterProc = std::function<std::shared_ptr<FilterContents>(
43  const Matrix& effect_transform,
44  Entity::RenderingMode rendering_mode)>;
45 
47  std::optional<Rect> coverage;
48  size_t clip_depth;
49  };
50 
51  using ClipCoverageStack = std::vector<ClipCoverageLayer>;
52 
53  EntityPass();
54 
55  ~EntityPass();
56 
57  void SetDelegate(std::shared_ptr<EntityPassDelegate> delgate);
58 
59  /// @brief Set the bounds limit, which is provided by the user when creating
60  /// a SaveLayer. This is a hint that allows the user to communicate
61  /// that it's OK to not render content outside of the bounds.
62  ///
63  /// For consistency with Skia, we effectively treat this like a
64  /// rectangle clip by forcing the subpass texture size to never exceed
65  /// it.
66  void SetBoundsLimit(std::optional<Rect> bounds_limit);
67 
68  /// @brief Get the bounds limit, which is provided by the user when creating
69  /// a SaveLayer.
70  std::optional<Rect> GetBoundsLimit() const;
71 
72  size_t GetSubpassesDepth() const;
73 
74  std::unique_ptr<EntityPass> Clone() const;
75 
76  /// @brief Add an entity to the current entity pass.
77  void AddEntity(Entity entity);
78 
79  void SetElements(std::vector<Element> elements);
80 
81  //----------------------------------------------------------------------------
82  /// @brief Appends a given pass as a subpass.
83  ///
84  EntityPass* AddSubpass(std::unique_ptr<EntityPass> pass);
85 
86  //----------------------------------------------------------------------------
87  /// @brief Merges a given pass into this pass. Useful for drawing
88  /// pre-recorded pictures that don't require rendering into a separate
89  /// subpass.
90  ///
91  void AddSubpassInline(std::unique_ptr<EntityPass> pass);
92 
93  EntityPass* GetSuperpass() const;
94 
95  bool Render(ContentContext& renderer,
96  const RenderTarget& render_target) const;
97 
98  /// @brief Iterate all elements (entities and subpasses) in this pass,
99  /// recursively including elements of child passes. The iteration
100  /// order is depth-first. Whenever a subpass elements is encountered,
101  /// it's included in the stream before its children.
102  void IterateAllElements(const std::function<bool(Element&)>& iterator);
103 
104  //----------------------------------------------------------------------------
105  /// @brief Iterate all entities in this pass, recursively including entities
106  /// of child passes. The iteration order is depth-first.
107  ///
108  void IterateAllEntities(const std::function<bool(Entity&)>& iterator);
109 
110  //----------------------------------------------------------------------------
111  /// @brief Iterate all entities in this pass, recursively including entities
112  /// of child passes. The iteration order is depth-first and does not
113  /// allow modification of the entities.
114  ///
115  void IterateAllEntities(
116  const std::function<bool(const Entity&)>& iterator) const;
117 
118  //----------------------------------------------------------------------------
119  /// @brief Iterate entities in this pass up until the first subpass is found.
120  /// This is useful for limiting look-ahead optimizations.
121  ///
122  /// @return Returns whether a subpass was encountered.
123  ///
124  bool IterateUntilSubpass(const std::function<bool(Entity&)>& iterator);
125 
126  //----------------------------------------------------------------------------
127  /// @brief Return the number of elements on this pass.
128  ///
129  size_t GetElementCount() const;
130 
131  void SetTransform(Matrix transform);
132 
133  void SetClipDepth(size_t clip_depth);
134 
135  size_t GetClipDepth();
136 
137  void SetBlendMode(BlendMode blend_mode);
138 
139  /// @brief Return the premultiplied clear color of the pass entities, if any.
140  std::optional<Color> GetClearColor(ISize size = ISize::Infinite()) const;
141 
142  /// @brief Return the premultiplied clear color of the pass entities.
143  ///
144  /// If the entity pass has no clear color, this will return transparent black.
146 
148 
149  void SetEnableOffscreenCheckerboard(bool enabled);
150 
151  //----------------------------------------------------------------------------
152  /// @brief Computes the coverage of a given subpass. This is used to
153  /// determine the texture size of a given subpass before it's rendered
154  /// to and passed through the subpass ImageFilter, if any.
155  ///
156  /// @param[in] subpass The EntityPass for which to compute
157  /// pre-filteredcoverage.
158  /// @param[in] coverage_limit Confines coverage to a specified area. This
159  /// hint is used to trim coverage to the root
160  /// framebuffer area. `std::nullopt` means there
161  /// is no limit.
162  ///
163  /// @return The screen space pixel area that the subpass contents will render
164  /// into, prior to being transformed by the subpass ImageFilter, if
165  /// any. `std::nullopt` means rendering the subpass will have no
166  /// effect on the color attachment.
167  ///
168  std::optional<Rect> GetSubpassCoverage(
169  const EntityPass& subpass,
170  std::optional<Rect> coverage_limit) const;
171 
172  std::optional<Rect> GetElementsCoverage(
173  std::optional<Rect> coverage_limit) const;
174 
175  private:
176  struct EntityResult {
177  enum Status {
178  /// The entity was successfully resolved and can be rendered.
179  kSuccess,
180  /// An unexpected rendering error occurred while resolving the Entity.
181  kFailure,
182  /// The entity should be skipped because rendering it will contribute
183  /// nothing to the frame.
184  kSkip,
185  };
186 
187  /// @brief The resulting entity that should be rendered. If `std::nullopt`,
188  /// there is nothing to render.
189  Entity entity;
190  /// @brief This is set to `false` if there was an unexpected rendering
191  /// error while resolving the Entity.
192  Status status = kFailure;
193 
194  static EntityResult Success(Entity e) { return {std::move(e), kSuccess}; }
195  static EntityResult Failure() { return {{}, kFailure}; }
196  static EntityResult Skip() { return {{}, kSkip}; }
197  };
198 
199  bool RenderElement(Entity& element_entity,
200  size_t clip_depth_floor,
201  InlinePassContext& pass_context,
202  int32_t pass_depth,
203  ContentContext& renderer,
204  ClipCoverageStack& clip_coverage_stack,
205  Point global_pass_position) const;
206 
207  EntityResult GetEntityForElement(const EntityPass::Element& element,
208  ContentContext& renderer,
209  Capture& capture,
210  InlinePassContext& pass_context,
211  ISize root_pass_size,
212  Point global_pass_position,
213  uint32_t pass_depth,
214  ClipCoverageStack& clip_coverage_stack,
215  size_t clip_depth_floor) const;
216 
217  //----------------------------------------------------------------------------
218  /// @brief OnRender is the internal command recording routine for
219  /// `EntityPass`. Its job is to walk through each `Element` which
220  /// was appended to the scene (either an `Entity` via `AddEntity()`
221  /// or a child `EntityPass` via `AddSubpass()`) and render them to
222  /// the given `pass_target`.
223  /// @param[in] renderer The Contents context, which manages
224  /// pipeline state.
225  /// @param[in] root_pass_size The size of the texture being
226  /// rendered into at the root of the
227  /// `EntityPass` tree. This is the size
228  /// of the `RenderTarget` color
229  /// attachment passed to the public
230  /// `EntityPass::Render` method.
231  /// @param[out] pass_target Stores the render target that should
232  /// be used for rendering.
233  /// @param[in] global_pass_position The position that this `EntityPass`
234  /// will be drawn to the parent pass
235  /// relative to the root pass origin.
236  /// Used for offsetting drawn `Element`s,
237  /// whose origins are all in root
238  /// pass/screen space,
239  /// @param[in] local_pass_position The position that this `EntityPass`
240  /// will be drawn to the parent pass
241  /// relative to the parent pass origin.
242  /// Used for positioning backdrop
243  /// filters.
244  /// @param[in] pass_depth The tree depth of the `EntityPass` at
245  /// render time. Only used for labeling
246  /// and debugging purposes. This can vary
247  /// depending on whether passes are
248  /// collapsed or not.
249  /// @param[in] clip_coverage_stack A global stack of coverage rectangles
250  /// for the clip buffer at each depth.
251  /// Higher depths are more restrictive.
252  /// Used to cull Elements that we
253  /// know won't result in a visible
254  /// change.
255  /// @param[in] clip_depth_floor The clip depth that a value of
256  /// zero corresponds to in the given
257  /// `pass_target` clip buffer.
258  /// When new `pass_target`s are created
259  /// for subpasses, their clip buffers are
260  /// initialized at zero, and so this
261  /// value is used to offset Entity clip
262  /// depths to match the clip buffer.
263  /// @param[in] backdrop_filter_contents Optional. Is supplied, this contents
264  /// is rendered prior to anything else in
265  /// the `EntityPass`, offset by the
266  /// `local_pass_position`.
267  /// @param[in] collapsed_parent_pass Optional. If supplied, this
268  /// `InlinePassContext` state is used to
269  /// begin rendering elements instead of
270  /// creating a new `RenderPass`. This
271  /// "collapses" the Elements into the
272  /// parent pass.
273  ///
274  bool OnRender(ContentContext& renderer,
275  Capture& capture,
276  ISize root_pass_size,
277  EntityPassTarget& pass_target,
278  Point global_pass_position,
279  Point local_pass_position,
280  uint32_t pass_depth,
281  ClipCoverageStack& clip_coverage_stack,
282  size_t clip_depth_floor = 0,
283  std::shared_ptr<Contents> backdrop_filter_contents = nullptr,
284  const std::optional<InlinePassContext::RenderPassResult>&
285  collapsed_parent_pass = std::nullopt) const;
286 
287  /// The list of renderable items in the scene. Each of these items is
288  /// evaluated and recorded to an `EntityPassTarget` by the `OnRender` method.
289  std::vector<Element> elements_;
290 
291  EntityPass* superpass_ = nullptr;
292  Matrix transform_;
293  size_t clip_depth_ = 0u;
294  BlendMode blend_mode_ = BlendMode::kSourceOver;
295  bool flood_clip_ = false;
296  bool enable_offscreen_debug_checkerboard_ = false;
297  std::optional<Rect> bounds_limit_;
298  std::unique_ptr<EntityPassClipRecorder> clip_replay_ =
299  std::make_unique<EntityPassClipRecorder>();
300 
301  /// These values are incremented whenever something is added to the pass that
302  /// requires reading from the backdrop texture. Currently, this can happen in
303  /// the following scenarios:
304  /// 1. An entity with an "advanced blend" is added to the pass.
305  /// 2. A subpass with a backdrop filter is added to the pass.
306  /// These are tracked as separate values because we may ignore
307  /// blend_reads_from_pass_texture_ if the device supports framebuffer based
308  /// advanced blends.
309  uint32_t advanced_blend_reads_from_pass_texture_ = 0;
310  uint32_t backdrop_filter_reads_from_pass_texture_ = 0;
311 
312  uint32_t GetTotalPassReads(ContentContext& renderer) const;
313 
314  BackdropFilterProc backdrop_filter_proc_ = nullptr;
315 
316  std::shared_ptr<EntityPassDelegate> delegate_ =
318 
319  EntityPass(const EntityPass&) = delete;
320 
321  EntityPass& operator=(const EntityPass&) = delete;
322 };
323 
324 /// @brief A class that tracks all clips that have been recorded in the current
325 /// entity pass stencil.
326 ///
327 /// These clips are replayed when restoring the backdrop so that the
328 /// stencil buffer is left in an identical state.
330  public:
332 
333  ~EntityPassClipRecorder() = default;
334 
335  /// @brief Record the entity based on the provided coverage [type].
336  void RecordEntity(const Entity& entity, Contents::ClipCoverage::Type type);
337 
338  const std::vector<Entity>& GetReplayEntities() const;
339 
340  private:
341  std::vector<Entity> rendered_clip_entities_;
342 };
343 
344 } // namespace impeller
345 
346 #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:224
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:1019
impeller::EntityPass::GetClipDepth
size_t GetClipDepth()
Definition: entity_pass.cc:1123
impeller::EntityPassClipRecorder::RecordEntity
void RecordEntity(const Entity &entity, Contents::ClipCoverage::Type type)
Record the entity based on the provided coverage [type].
Definition: entity_pass.cc:1172
impeller::EntityPass::SetBackdropFilter
void SetBackdropFilter(BackdropFilterProc proc)
Definition: entity_pass.cc:1157
contents.h
impeller::EntityPassClipRecorder::GetReplayEntities
const std::vector< Entity > & GetReplayEntities() const
Definition: entity_pass.cc:1186
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:44
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:173
impeller::Contents::ClipCoverage::Type
Type
Definition: contents.h:41
entity.h
impeller::EntityPass::GetSubpassesDepth
size_t GetSubpassesDepth() const
Definition: entity_pass.cc:86
impeller::EntityPass::SetBoundsLimit
void SetBoundsLimit(std::optional< Rect > bounds_limit)
Set the bounds limit, which is provided by the user when creating a SaveLayer. This is a hint that al...
Definition: entity_pass.cc:62
impeller::BlendMode
BlendMode
Definition: color.h:59
impeller::Color
Definition: color.h:124
impeller::EntityPass::EntityPass
EntityPass()
impeller::EntityPass::ClipCoverageLayer::clip_depth
size_t clip_depth
Definition: entity_pass.h:48
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:205
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:1062
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:1003
impeller::EntityPass::ClipCoverageStack
std::vector< ClipCoverageLayer > ClipCoverageStack
Definition: entity_pass.h:51
impeller::EntityPass::GetElementsCoverage
std::optional< Rect > GetElementsCoverage(std::optional< Rect > coverage_limit) const
Definition: entity_pass.cc:97
impeller::EntityPass::~EntityPass
~EntityPass()
impeller::EntityPass::SetClipDepth
void SetClipDepth(size_t clip_depth)
Definition: entity_pass.cc:1119
impeller::EntityPass::SetBlendMode
void SetBlendMode(BlendMode blend_mode)
Definition: entity_pass.cc:1127
impeller::Entity
Definition: entity.h:21
impeller::TSize< int64_t >
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
impeller::EntityPass::SetElements
void SetElements(std::vector< Element > elements)
Definition: entity_pass.cc:82
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:66
impeller::EntityPass::GetSuperpass
EntityPass * GetSuperpass() const
Definition: entity_pass.cc:201
impeller::EntityPassClipRecorder::~EntityPassClipRecorder
~EntityPassClipRecorder()=default
impeller::EntityPass
Definition: entity_pass.h:26
impeller::EntityPass::ClipCoverageLayer::coverage
std::optional< Rect > coverage
Definition: entity_pass.h:47
impeller::EntityPass::Element
std::variant< Entity, std::unique_ptr< EntityPass > > Element
Definition: entity_pass.h:37
impeller::EntityPass::GetElementCount
size_t GetElementCount() const
Return the number of elements on this pass.
Definition: entity_pass.cc:1080
impeller::RenderTarget
Definition: render_target.h:49
impeller::EntityPass::ClipCoverageLayer
Definition: entity_pass.h:46
impeller::EntityPass::SetTransform
void SetTransform(Matrix transform)
Definition: entity_pass.cc:1115
impeller::EntityPassClipRecorder
A class that tracks all clips that have been recorded in the current entity pass stencil.
Definition: entity_pass.h:329
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
impeller::EntityPass::Render
bool Render(ContentContext &renderer, const RenderTarget &render_target) const
Definition: entity_pass.cc:301
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:39
impeller::EntityPass::SetDelegate
void SetDelegate(std::shared_ptr< EntityPassDelegate > delgate)
Definition: entity_pass.cc:55
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:26
impeller::EntityPass::SetEnableOffscreenCheckerboard
void SetEnableOffscreenCheckerboard(bool enabled)
Definition: entity_pass.cc:1166
render_target.h
impeller::EntityPassClipRecorder::EntityPassClipRecorder
EntityPassClipRecorder()
Definition: entity_pass.cc:1170
impeller
Definition: aiks_context.cc:10
impeller::ContentContext
Definition: content_context.h:332
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:1136
impeller::EntityPass::GetClearColorOrDefault
Color GetClearColorOrDefault(ISize size=ISize::Infinite()) const
Return the premultiplied clear color of the pass entities.
Definition: entity_pass.cc:1132
impeller::EntityPass::AddEntity
void AddEntity(Entity entity)
Add an entity to the current entity pass.
Definition: entity_pass.cc:70
inline_pass_context.h
impeller::EntityPass::Clone
std::unique_ptr< EntityPass > Clone() const
Definition: entity_pass.cc:1084