Flutter Impeller
canvas.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_DISPLAY_LIST_CANVAS_H_
6 #define FLUTTER_IMPELLER_DISPLAY_LIST_CANVAS_H_
7 
8 #include <deque>
9 #include <functional>
10 #include <memory>
11 #include <optional>
12 #include <utility>
13 #include <vector>
14 
15 #include "display_list/effects/dl_image_filter.h"
21 #include "impeller/entity/entity.h"
27 #include "impeller/geometry/path.h"
33 
34 namespace impeller {
35 
36 struct BackdropData {
37  size_t backdrop_count = 0;
38  bool all_filters_equal = true;
39  std::shared_ptr<Texture> texture_slot;
40  // A single snapshot of the backdrop filter that is used when there are
41  // multiple backdrops that share an identical filter.
42  std::optional<Snapshot> shared_filter_snapshot;
43  std::shared_ptr<flutter::DlImageFilter> last_backdrop;
44 };
45 
48  uint32_t clip_depth = 0u;
49  size_t clip_height = 0u;
50  // The number of clips tracked for this canvas stack entry.
51  size_t num_clips = 0u;
54  // Whether all entities in the current save should be skipped.
55  bool skipping = false;
56  // Whether subpass coverage was rounded out to pixel coverage, or if false
57  // truncated.
58  bool did_round_out = false;
59 };
60 
61 enum class PointStyle {
62  /// @brief Points are drawn as squares.
63  kRound,
64 
65  /// @brief Points are drawn as circles.
66  kSquare,
67 };
68 
69 /// Controls the behavior of the source rectangle given to DrawImageRect.
71  /// @brief Faster, but may sample outside the bounds of the source rectangle.
72  kFast,
73 
74  /// @brief Sample only within the source rectangle. May be slower.
75  kStrict,
76 };
77 
78 /// Specifies how much to trust the bounds rectangle provided for a list
79 /// of contents. Used by both |EntityPass| and |Canvas::SaveLayer|.
81  /// @brief The caller makes no claims related to the size of the bounds.
82  kUnknown,
83 
84  /// @brief The caller claims the bounds are a reasonably tight estimate
85  /// of the coverage of the contents and should contain all of the
86  /// contents.
88 
89  /// @brief The caller claims the bounds are a subset of an estimate of
90  /// the reasonably tight bounds but likely clips off some of the
91  /// contents.
93 };
94 
96  std::unique_ptr<EntityPassTarget> entity_pass_target;
97  std::unique_ptr<InlinePassContext> inline_pass_context;
98 
99  /// Whether or not the clear color texture can still be updated.
100  bool IsApplyingClearColor() const { return !inline_pass_context->IsActive(); }
101 
103  std::unique_ptr<EntityPassTarget> p_entity_pass_target)
104  : entity_pass_target(std::move(p_entity_pass_target)) {
106  std::make_unique<InlinePassContext>(renderer, *entity_pass_target);
107  }
108 
110  std::unique_ptr<EntityPassTarget> entity_pass_target,
111  std::unique_ptr<InlinePassContext> inline_pass_context)
114 };
115 
116 class Canvas {
117  public:
118  static constexpr uint32_t kMaxDepth = 1 << 24;
119 
120  using BackdropFilterProc = std::function<std::shared_ptr<FilterContents>(
122  const Matrix& effect_transform,
123  Entity::RenderingMode rendering_mode)>;
124 
125  Canvas(ContentContext& renderer,
126  const RenderTarget& render_target,
127  bool is_onscreen,
128  bool requires_readback);
129 
130  explicit Canvas(ContentContext& renderer,
131  const RenderTarget& render_target,
132  bool is_onscreen,
133  bool requires_readback,
134  Rect cull_rect);
135 
136  explicit Canvas(ContentContext& renderer,
137  const RenderTarget& render_target,
138  bool is_onscreen,
139  bool requires_readback,
140  IRect cull_rect);
141 
142  ~Canvas() = default;
143 
144  /// @brief Update the backdrop data used to group together backdrop filters
145  /// within the same layer
146  void SetBackdropData(std::unordered_map<int64_t, BackdropData> backdrop_data,
147  size_t backdrop_count);
148 
149  /// @brief Return the culling bounds of the current render target, or nullopt
150  /// if there is no coverage.
151  std::optional<Rect> GetLocalCoverageLimit() const;
152 
153  void Save(uint32_t total_content_depth = kMaxDepth);
154 
155  void SaveLayer(
156  const Paint& paint,
157  std::optional<Rect> bounds = std::nullopt,
158  const flutter::DlImageFilter* backdrop_filter = nullptr,
160  uint32_t total_content_depth = kMaxDepth,
161  bool can_distribute_opacity = false,
162  std::optional<int64_t> backdrop_id = std::nullopt);
163 
164  bool Restore();
165 
166  size_t GetSaveCount() const;
167 
168  void RestoreToCount(size_t count);
169 
170  const Matrix& GetCurrentTransform() const;
171 
172  void ResetTransform();
173 
174  void Transform(const Matrix& transform);
175 
176  void Concat(const Matrix& transform);
177 
178  void PreConcat(const Matrix& transform);
179 
180  void Translate(const Vector3& offset);
181 
182  void Scale(const Vector2& scale);
183 
184  void Scale(const Vector3& scale);
185 
186  void Skew(Scalar sx, Scalar sy);
187 
188  void Rotate(Radians radians);
189 
190  void DrawPath(const Path& path, const Paint& paint);
191 
192  void DrawPaint(const Paint& paint);
193 
194  void DrawLine(const Point& p0,
195  const Point& p1,
196  const Paint& paint,
197  bool reuse_depth = false);
198 
199  void DrawRect(const Rect& rect, const Paint& paint);
200 
201  void DrawOval(const Rect& rect, const Paint& paint);
202 
203  void DrawRoundRect(const RoundRect& rect, const Paint& paint);
204 
205  void DrawRoundSuperellipse(const RoundSuperellipse& rse, const Paint& paint);
206 
207  void DrawCircle(const Point& center, Scalar radius, const Paint& paint);
208 
209  void DrawPoints(const Point points[],
210  uint32_t count,
211  Scalar radius,
212  const Paint& paint,
213  PointStyle point_style);
214 
215  void DrawImage(const std::shared_ptr<Texture>& image,
216  Point offset,
217  const Paint& paint,
218  const SamplerDescriptor& sampler = {});
219 
220  void DrawImageRect(
221  const std::shared_ptr<Texture>& image,
222  Rect source,
223  Rect dest,
224  const Paint& paint,
225  const SamplerDescriptor& sampler = {},
226  SourceRectConstraint src_rect_constraint = SourceRectConstraint::kFast);
227 
228  void DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
229  Point position,
230  const Paint& paint);
231 
232  void DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
233  BlendMode blend_mode,
234  const Paint& paint);
235 
236  void DrawAtlas(const std::shared_ptr<AtlasContents>& atlas_contents,
237  const Paint& paint);
238 
239  void ClipGeometry(const Geometry& geometry,
240  Entity::ClipOperation clip_op,
241  bool is_aa = true);
242 
243  void EndReplay();
244 
245  uint64_t GetOpDepth() const { return current_depth_; }
246 
247  uint64_t GetMaxOpDepth() const { return transform_stack_.back().clip_depth; }
248 
249  struct SaveLayerState {
252  };
253 
254  // Visible for testing.
255  bool RequiresReadback() const { return requires_readback_; }
256 
257  // Whether the current device has the capabilities to blit an offscreen
258  // texture into the onscreen.
259  //
260  // This requires the availibility of the blit framebuffer command, but is
261  // disabled for GLES. A simple glBlitFramebuffer does not support resolving
262  // different sample counts which may be present in GLES when using MSAA.
263  //
264  // Visible for testing.
265  bool SupportsBlitToOnscreen() const;
266 
267  /// For picture snapshots we need addition steps to verify that final mipmaps
268  /// are generated.
269  bool EnsureFinalMipmapGeneration() const;
270 
271  private:
272  ContentContext& renderer_;
273  RenderTarget render_target_;
274  const bool is_onscreen_;
275  bool requires_readback_;
276  EntityPassClipStack clip_coverage_stack_;
277 
278  std::deque<CanvasStackEntry> transform_stack_;
279  std::optional<Rect> initial_cull_rect_;
280  std::vector<LazyRenderingConfig> render_passes_;
281  std::vector<SaveLayerState> save_layer_state_;
282 
283  /// Backdrop layers identified by an optional backdrop id.
284  ///
285  /// This is not the same as the [backdrop_count_] below as not
286  /// all backdrop filters will have an identified backdrop id. The
287  /// backdrop_count_ is also mutated during rendering.
288  std::unordered_map<int64_t, BackdropData> backdrop_data_;
289 
290  /// The remaining number of backdrop filters.
291  ///
292  /// This value is decremented while rendering. When it reaches 0, then
293  /// the FlipBackdrop can use the onscreen render target instead of
294  /// another offscreen.
295  ///
296  /// This optimization is disabled on devices that do not support framebuffer
297  /// fetch (iOS Simulator and certain OpenGLES devices).
298  size_t backdrop_count_ = 0u;
299 
300  // All geometry objects created for regular draws can be stack allocated,
301  // but clip geometries must be cached for record/replay for backdrop filters
302  // and so must be kept alive longer.
303  std::vector<std::unique_ptr<Geometry>> clip_geometry_;
304 
305  uint64_t current_depth_ = 0u;
306 
307  Point GetGlobalPassPosition() const;
308 
309  // clip depth of the previous save or 0.
310  size_t GetClipHeightFloor() const;
311 
312  /// @brief Whether all entites should be skipped until a corresponding
313  /// restore.
314  bool IsSkipping() const;
315 
316  /// @brief Skip all rendering/clipping entities until next restore.
317  void SkipUntilMatchingRestore(size_t total_content_depth);
318 
319  void SetupRenderPass();
320 
321  /// @brief Ends the current render pass, saving the result as a texture, and
322  /// thenrestart it with the backdrop cleared to the previous contents.
323  ///
324  /// The returned texture is used as the input for backdrop filters and
325  /// emulated advanced blends. Returns nullptr if there was a validation
326  /// failure.
327  ///
328  /// [should_remove_texture] defaults to false. If true, the render target
329  /// texture is removed from the entity pass target. This allows the texture to
330  /// be cached by the canvas dispatcher for usage in the backdrop filter reuse
331  /// mechanism.
332  ///
333  /// [should_use_onscreen] defaults to false. If true, the results are flipped
334  /// to the onscreen render target. This will set requires_readback_ to false.
335  /// This action is only safe to perform when there are no more backdrop
336  /// filters or advanced blends, or no more backdrop filters and the device
337  /// supports framebuffer fetch.
338  std::shared_ptr<Texture> FlipBackdrop(Point global_pass_position,
339  bool should_remove_texture = false,
340  bool should_use_onscreen = false);
341 
342  bool BlitToOnscreen(bool is_onscreen = false);
343 
344  size_t GetClipHeight() const;
345 
346  void Initialize(std::optional<Rect> cull_rect);
347 
348  void Reset();
349 
350  void AddRenderEntityWithFiltersToCurrentPass(Entity& entity,
351  const Geometry* geometry,
352  const Paint& paint,
353  bool reuse_depth = false);
354 
355  void AddRenderEntityToCurrentPass(Entity& entity, bool reuse_depth = false);
356 
357  bool AttemptDrawBlurredRRect(const Rect& rect,
358  Size corner_radii,
359  const Paint& paint);
360 
361  /// For simple DrawImageRect calls, optimize any draws with a color filter
362  /// into the corresponding atlas draw.
363  ///
364  /// Returns whether not the optimization was applied.
365  bool AttemptColorFilterOptimization(const std::shared_ptr<Texture>& image,
366  Rect source,
367  Rect dest,
368  const Paint& paint,
369  const SamplerDescriptor& sampler,
370  SourceRectConstraint src_rect_constraint);
371 
372  bool AttemptBlurredTextOptimization(
373  const std::shared_ptr<TextFrame>& text_frame,
374  const std::shared_ptr<TextContents>& text_contents,
375  Entity& entity,
376  const Paint& paint);
377 
378  RenderPass& GetCurrentRenderPass() const;
379 
380  Canvas(const Canvas&) = delete;
381 
382  Canvas& operator=(const Canvas&) = delete;
383 };
384 
385 } // namespace impeller
386 
387 #endif // FLUTTER_IMPELLER_DISPLAY_LIST_CANVAS_H_
void ClipGeometry(const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
Definition: canvas.cc:686
static constexpr uint32_t kMaxDepth
Definition: canvas.h:118
void SetBackdropData(std::unordered_map< int64_t, BackdropData > backdrop_data, size_t backdrop_count)
Update the backdrop data used to group together backdrop filters within the same layer.
Definition: canvas.cc:1742
Canvas(ContentContext &renderer, const RenderTarget &render_target, bool is_onscreen, bool requires_readback)
Definition: canvas.cc:180
bool RequiresReadback() const
Definition: canvas.h:255
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
Definition: canvas.cc:640
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition: canvas.cc:1060
void SaveLayer(const Paint &paint, std::optional< Rect > bounds=std::nullopt, const flutter::DlImageFilter *backdrop_filter=nullptr, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, uint32_t total_content_depth=kMaxDepth, bool can_distribute_opacity=false, std::optional< int64_t > backdrop_id=std::nullopt)
Definition: canvas.cc:1091
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:254
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition: canvas.cc:864
void DrawOval(const Rect &rect, const Paint &paint)
Definition: canvas.cc:583
void DrawImageRect(const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, const SamplerDescriptor &sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
Definition: canvas.cc:799
void RestoreToCount(size_t count)
Definition: canvas.cc:301
bool Restore()
Definition: canvas.cc:1329
size_t GetSaveCount() const
Definition: canvas.cc:293
void Concat(const Matrix &transform)
Definition: canvas.cc:238
void Transform(const Matrix &transform)
Definition: canvas.cc:250
uint64_t GetMaxOpDepth() const
Definition: canvas.h:247
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
Definition: canvas.h:123
void PreConcat(const Matrix &transform)
Definition: canvas.cc:242
void Rotate(Radians radians)
Definition: canvas.cc:274
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
Definition: canvas.cc:767
void ResetTransform()
Definition: canvas.cc:246
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition: canvas.cc:1520
void DrawImage(const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, const SamplerDescriptor &sampler={})
Definition: canvas.cc:785
void DrawPaint(const Paint &paint)
Definition: canvas.cc:324
void EndReplay()
Definition: canvas.cc:1943
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
Definition: canvas.cc:613
void Skew(Scalar sx, Scalar sy)
Definition: canvas.cc:270
~Canvas()=default
void Scale(const Vector2 &scale)
Definition: canvas.cc:262
uint64_t GetOpDepth() const
Definition: canvas.h:245
void DrawPath(const Path &path, const Paint &paint)
Definition: canvas.cc:309
void Save(uint32_t total_content_depth=kMaxDepth)
Definition: canvas.cc:1043
bool SupportsBlitToOnscreen() const
Definition: canvas.cc:1868
void DrawRect(const Rect &rect, const Paint &paint)
Definition: canvas.cc:565
bool EnsureFinalMipmapGeneration() const
Definition: canvas.cc:1925
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
Definition: canvas.cc:977
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition: canvas.cc:542
void Translate(const Vector3 &offset)
Definition: canvas.cc:258
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:663
A class that tracks all clips that have been recorded in the current entity pass stencil.
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:54
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
float Scalar
Definition: scalar.h:18
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
Definition: canvas.h:70
@ kStrict
Sample only within the source rectangle. May be slower.
@ kFast
Faster, but may sample outside the bounds of the source rectangle.
PointStyle
Definition: canvas.h:61
@ kRound
Points are drawn as squares.
@ kSquare
Points are drawn as circles.
TPoint< Scalar > Point
Definition: point.h:327
BlendMode
Definition: color.h:58
ContentBoundsPromise
Definition: canvas.h:80
@ 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...
Definition: comparable.h:95
const Scalar scale
SeparatedVector2 offset
std::shared_ptr< Texture > texture_slot
Definition: canvas.h:39
std::shared_ptr< flutter::DlImageFilter > last_backdrop
Definition: canvas.h:43
size_t backdrop_count
Definition: canvas.h:37
std::optional< Snapshot > shared_filter_snapshot
Definition: canvas.h:42
Definition: canvas.h:46
size_t clip_height
Definition: canvas.h:49
bool did_round_out
Definition: canvas.h:58
Entity::RenderingMode rendering_mode
Definition: canvas.h:53
Scalar distributed_opacity
Definition: canvas.h:52
bool skipping
Definition: canvas.h:55
size_t num_clips
Definition: canvas.h:51
Matrix transform
Definition: canvas.h:47
uint32_t clip_depth
Definition: canvas.h:48
LazyRenderingConfig(ContentContext &renderer, std::unique_ptr< EntityPassTarget > p_entity_pass_target)
Definition: canvas.h:102
bool IsApplyingClearColor() const
Whether or not the clear color texture can still be updated.
Definition: canvas.h:100
std::unique_ptr< InlinePassContext > inline_pass_context
Definition: canvas.h:97
std::unique_ptr< EntityPassTarget > entity_pass_target
Definition: canvas.h:96
LazyRenderingConfig(ContentContext &renderer, std::unique_ptr< EntityPassTarget > entity_pass_target, std::unique_ptr< InlinePassContext > inline_pass_context)
Definition: canvas.h:109
A 4x4 matrix using column-major storage.
Definition: matrix.h:37