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 "flutter/display_list/effects/dl_image_filter.h"
16 #include "flutter/display_list/geometry/dl_path.h"
24 #include "impeller/entity/entity.h"
31 #include "impeller/geometry/arc.h"
38 
39 namespace impeller {
40 
41 struct BackdropData {
42  size_t backdrop_count = 0;
43  bool all_filters_equal = true;
44  std::shared_ptr<Texture> texture_slot;
45  // A single snapshot of the backdrop filter that is used when there are
46  // multiple backdrops that share an identical filter.
47  std::optional<Snapshot> shared_filter_snapshot;
48  std::shared_ptr<flutter::DlImageFilter> last_backdrop;
49 };
50 
53  uint32_t clip_depth = 0u;
54  size_t clip_height = 0u;
55  // The number of clips tracked for this canvas stack entry.
56  size_t num_clips = 0u;
59  // Whether all entities in the current save should be skipped.
60  bool skipping = false;
61  // Whether subpass coverage was rounded out to pixel coverage, or if false
62  // truncated.
63  bool did_round_out = false;
64 };
65 
66 enum class PointStyle {
67  /// @brief Points are drawn as squares.
68  kRound,
69 
70  /// @brief Points are drawn as circles.
71  kSquare,
72 };
73 
74 /// Controls the behavior of the source rectangle given to DrawImageRect.
76  /// @brief Faster, but may sample outside the bounds of the source rectangle.
77  kFast,
78 
79  /// @brief Sample only within the source rectangle. May be slower.
80  kStrict,
81 };
82 
83 /// Specifies how much to trust the bounds rectangle provided for a list
84 /// of contents. Used by both |EntityPass| and |Canvas::SaveLayer|.
86  /// @brief The caller makes no claims related to the size of the bounds.
87  kUnknown,
88 
89  /// @brief The caller claims the bounds are a reasonably tight estimate
90  /// of the coverage of the contents and should contain all of the
91  /// contents.
93 
94  /// @brief The caller claims the bounds are a subset of an estimate of
95  /// the reasonably tight bounds but likely clips off some of the
96  /// contents.
98 };
99 
101  public:
103  std::unique_ptr<EntityPassTarget> p_entity_pass_target);
104 
106 
107  /// Whether or not the clear color texture can still be updated.
108  bool IsApplyingClearColor() const;
109 
111 
113 
114  private:
115  std::unique_ptr<EntityPassTarget> entity_pass_target_;
116  std::unique_ptr<InlinePassContext> inline_pass_context_;
117 };
118 
119 class Canvas {
120  public:
121  static constexpr uint32_t kMaxDepth = 1 << 24;
122 
123  Canvas(ContentContext& renderer,
124  const RenderTarget& render_target,
125  bool is_onscreen,
126  bool requires_readback);
127 
128  explicit Canvas(ContentContext& renderer,
129  const RenderTarget& render_target,
130  bool is_onscreen,
131  bool requires_readback,
132  Rect cull_rect);
133 
134  explicit Canvas(ContentContext& renderer,
135  const RenderTarget& render_target,
136  bool is_onscreen,
137  bool requires_readback,
138  IRect32 cull_rect);
139 
140  ~Canvas() = default;
141 
142  /// @brief Update the backdrop data used to group together backdrop filters
143  /// within the same layer
144  void SetBackdropData(std::unordered_map<int64_t, BackdropData> backdrop_data,
145  size_t backdrop_count);
146 
147  /// @brief Return the culling bounds of the current render target, or nullopt
148  /// if there is no coverage.
149  std::optional<Rect> GetLocalCoverageLimit() const;
150 
151  void Save(uint32_t total_content_depth = kMaxDepth);
152 
153  void SaveLayer(
154  const Paint& paint,
155  std::optional<Rect> bounds = std::nullopt,
156  const flutter::DlImageFilter* backdrop_filter = nullptr,
158  uint32_t total_content_depth = kMaxDepth,
159  bool can_distribute_opacity = false,
160  std::optional<int64_t> backdrop_id = std::nullopt);
161 
162  bool Restore();
163 
164  size_t GetSaveCount() const;
165 
166  void RestoreToCount(size_t count);
167 
168  const Matrix& GetCurrentTransform() const;
169 
170  void ResetTransform();
171 
172  void Transform(const Matrix& transform);
173 
174  void Concat(const Matrix& transform);
175 
176  void PreConcat(const Matrix& transform);
177 
178  void Translate(const Vector3& offset);
179 
180  void Scale(const Vector2& scale);
181 
182  void Scale(const Vector3& scale);
183 
184  void Skew(Scalar sx, Scalar sy);
185 
186  void Rotate(Radians radians);
187 
188  void DrawPath(const flutter::DlPath& path, const Paint& paint);
189 
190  void DrawPaint(const Paint& paint);
191 
192  void DrawLine(const Point& p0,
193  const Point& p1,
194  const Paint& paint,
195  bool reuse_depth = false);
196 
197  void DrawDashedLine(const Point& p0,
198  const Point& p1,
199  Scalar on_length,
200  Scalar off_length,
201  const Paint& paint);
202 
203  void DrawRect(const Rect& rect, const Paint& paint);
204 
205  void DrawOval(const Rect& rect, const Paint& paint);
206 
207  void DrawArc(const Arc& arc, const Paint& paint);
208 
209  void DrawRoundRect(const RoundRect& rect, const Paint& paint);
210 
211  void DrawDiffRoundRect(const RoundRect& outer,
212  const RoundRect& inner,
213  const Paint& paint);
214 
215  void DrawRoundSuperellipse(const RoundSuperellipse& rse, const Paint& paint);
216 
217  void DrawCircle(const Point& center, Scalar radius, const Paint& paint);
218 
219  void DrawPoints(const Point points[],
220  uint32_t count,
221  Scalar radius,
222  const Paint& paint,
223  PointStyle point_style);
224 
225  void DrawImage(const std::shared_ptr<Texture>& image,
226  Point offset,
227  const Paint& paint,
228  const SamplerDescriptor& sampler = {});
229 
230  void DrawImageRect(
231  const std::shared_ptr<Texture>& image,
232  Rect source,
233  Rect dest,
234  const Paint& paint,
235  const SamplerDescriptor& sampler = {},
236  SourceRectConstraint src_rect_constraint = SourceRectConstraint::kFast);
237 
238  void DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
239  Point position,
240  const Paint& paint);
241 
242  void DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
243  BlendMode blend_mode,
244  const Paint& paint);
245 
246  void DrawAtlas(const std::shared_ptr<AtlasContents>& atlas_contents,
247  const Paint& paint);
248 
249  void ClipGeometry(const Geometry& geometry,
250  Entity::ClipOperation clip_op,
251  bool is_aa = true);
252 
253  void EndReplay();
254 
255  uint64_t GetOpDepth() const { return current_depth_; }
256 
257  uint64_t GetMaxOpDepth() const { return transform_stack_.back().clip_depth; }
258 
259  struct SaveLayerState {
262  };
263 
264  // Visible for testing.
265  bool RequiresReadback() const { return requires_readback_; }
266 
267  // Whether the current device has the capabilities to blit an offscreen
268  // texture into the onscreen.
269  //
270  // This requires the availibility of the blit framebuffer command, but is
271  // disabled for GLES. A simple glBlitFramebuffer does not support resolving
272  // different sample counts which may be present in GLES when using MSAA.
273  //
274  // Visible for testing.
275  bool SupportsBlitToOnscreen() const;
276 
277  /// For picture snapshots we need addition steps to verify that final mipmaps
278  /// are generated.
279  bool EnsureFinalMipmapGeneration() const;
280 
281  /// Returns true if the paint is compatible with SDF rendering.
282  ///
283  /// Visible for testing.
284  static bool IsCompatibleWithSDFRendering(const Paint& paint);
285 
286  private:
287  class BlurShape {
288  public:
289  virtual ~BlurShape() = default;
290  virtual Rect GetBounds() const = 0;
291  virtual std::shared_ptr<SolidBlurContents> BuildBlurContent(
292  Sigma sigma) = 0;
293  virtual const Geometry& BuildDrawGeometry() = 0;
294  };
295  class RRectBlurShape;
296  class RSuperellipseBlurShape;
297  class PathBlurShape;
298 
299  ContentContext& renderer_;
300  RenderTarget render_target_;
301  const bool is_onscreen_;
302  bool requires_readback_;
303  EntityPassClipStack clip_coverage_stack_;
304 
305  std::deque<CanvasStackEntry> transform_stack_;
306  std::optional<Rect> initial_cull_rect_;
307  std::vector<LazyRenderingConfig> render_passes_;
308  std::vector<SaveLayerState> save_layer_state_;
309 
310  /// Backdrop layers identified by an optional backdrop id.
311  ///
312  /// This is not the same as the [backdrop_count_] below as not
313  /// all backdrop filters will have an identified backdrop id. The
314  /// backdrop_count_ is also mutated during rendering.
315  std::unordered_map<int64_t, BackdropData> backdrop_data_;
316 
317  /// The remaining number of backdrop filters.
318  ///
319  /// This value is decremented while rendering. When it reaches 0, then
320  /// the FlipBackdrop can use the onscreen render target instead of
321  /// another offscreen.
322  ///
323  /// This optimization is disabled on devices that do not support framebuffer
324  /// fetch (iOS Simulator and certain OpenGLES devices).
325  size_t backdrop_count_ = 0u;
326 
327  // All geometry objects created for regular draws can be stack allocated,
328  // but clip geometries must be cached for record/replay for backdrop filters
329  // and so must be kept alive longer.
330  std::vector<std::unique_ptr<Geometry>> clip_geometry_;
331 
332  uint64_t current_depth_ = 0u;
333 
334  Point GetGlobalPassPosition() const;
335 
336  // clip depth of the previous save or 0.
337  size_t GetClipHeightFloor() const;
338 
339  /// @brief Whether all entites should be skipped until a corresponding
340  /// restore.
341  bool IsSkipping() const;
342 
343  /// @brief Skip all rendering/clipping entities until next restore.
344  void SkipUntilMatchingRestore(size_t total_content_depth);
345 
346  void SetupRenderPass();
347 
348  /// @brief Ends the current render pass, saving the result as a texture, and
349  /// thenrestart it with the backdrop cleared to the previous contents.
350  ///
351  /// The returned texture is used as the input for backdrop filters and
352  /// emulated advanced blends. Returns nullptr if there was a validation
353  /// failure.
354  ///
355  /// [should_remove_texture] defaults to false. If true, the render target
356  /// texture is removed from the entity pass target. This allows the texture to
357  /// be cached by the canvas dispatcher for usage in the backdrop filter reuse
358  /// mechanism.
359  ///
360  /// [should_use_onscreen] defaults to false. If true, the results are flipped
361  /// to the onscreen render target. This will set requires_readback_ to false.
362  /// This action is only safe to perform when there are no more backdrop
363  /// filters or advanced blends, or no more backdrop filters and the device
364  /// supports framebuffer fetch.
365  std::shared_ptr<Texture> FlipBackdrop(Point global_pass_position,
366  bool should_remove_texture = false,
367  bool should_use_onscreen = false,
368  bool post_depth_increment = false);
369 
370  bool BlitToOnscreen(bool is_onscreen = false);
371 
372  size_t GetClipHeight() const;
373 
374  void Initialize(std::optional<Rect> cull_rect);
375 
376  void Reset();
377 
378  void AddRenderEntityWithFiltersToCurrentPass(
379  Entity& entity,
380  const Geometry* geometry,
381  const Paint& paint,
382  bool reuse_depth = false,
383  std::shared_ptr<Contents> override_contents = nullptr);
384 
385  /// @brief Adds a rendering entity using the UberSDF pipeline
386  /// to the current render pass.
387  ///
388  /// @param paint The paint style to apply.
389  /// @param params The SDF parameters for the shape.
390  /// @param reuse_depth Whether to reuse the current depth value or
391  /// allocate a new depth layer.
392  /// @param shape_transform An optional transform applied to the shape
393  /// relative to the current canvas transform.
394  void AddRenderSDFEntityToCurrentPass(
395  const Paint& paint,
396  UberSDFParameters params,
397  bool reuse_depth = false,
398  const std::optional<Matrix>& shape_transform = std::nullopt);
399 
400  void AddRenderEntityToCurrentPass(Entity& entity, bool reuse_depth = false);
401 
402  /// Returns true if this operation is consistent with a DrawShadow-like
403  /// operation.
404  static bool IsShadowBlurDrawOperation(const Paint& paint);
405 
406  bool AttemptDrawLineSDF(const Point& p0,
407  const Point& p1,
408  const Paint& paint,
409  bool reuse_depth);
410 
411  bool AttemptDrawAntialiasedCircle(const Point& center,
412  Scalar radius,
413  const Paint& paint);
414 
415  /// Returns the radius common to both width and height of all corners,
416  /// or -1 if the radii are not uniform.
417  static Scalar GetCommonRRectLikeRadius(const RoundingRadii& radii);
418 
419  bool AttemptDrawBlurredPathSource(const PathSource& source,
420  const Paint& paint);
421 
422  bool AttemptDrawBlurredRRect(const RoundRect& round_rect, const Paint& paint);
423 
424  bool AttemptDrawBlurredRSuperellipse(const RoundSuperellipse& rse,
425  const Paint& paint);
426 
427  bool AttemptDrawBlur(BlurShape& shape, const Paint& paint);
428 
429  /// For simple DrawImageRect calls, optimize any draws with a color filter
430  /// into the corresponding atlas draw.
431  ///
432  /// Returns whether not the optimization was applied.
433  bool AttemptColorFilterOptimization(const std::shared_ptr<Texture>& image,
434  Rect source,
435  Rect dest,
436  const Paint& paint,
437  const SamplerDescriptor& sampler,
438  SourceRectConstraint src_rect_constraint);
439 
440  bool AttemptBlurredTextOptimization(
441  const std::shared_ptr<TextFrame>& text_frame,
442  const std::shared_ptr<TextContents>& text_contents,
443  Entity& entity,
444  const Paint& paint);
445 
446  RenderPass& GetCurrentRenderPass() const;
447 
448  Canvas(const Canvas&) = delete;
449 
450  Canvas& operator=(const Canvas&) = delete;
451 };
452 
453 } // namespace impeller
454 
455 #endif // FLUTTER_IMPELLER_DISPLAY_LIST_CANVAS_H_
void ClipGeometry(const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
Definition: canvas.cc:1292
static constexpr uint32_t kMaxDepth
Definition: canvas.h:121
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:2408
Canvas(ContentContext &renderer, const RenderTarget &render_target, bool is_onscreen, bool requires_readback)
Definition: canvas.cc:330
bool RequiresReadback() const
Definition: canvas.h:265
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
Definition: canvas.cc:1186
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition: canvas.cc:1673
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:1710
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:404
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition: canvas.cc:1473
void DrawOval(const Rect &rect, const Paint &paint)
Definition: canvas.cc:994
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:1406
void RestoreToCount(size_t count)
Definition: canvas.cc:451
static bool IsCompatibleWithSDFRendering(const Paint &paint)
Definition: canvas.cc:2635
bool Restore()
Definition: canvas.cc:1940
size_t GetSaveCount() const
Definition: canvas.cc:443
void Concat(const Matrix &transform)
Definition: canvas.cc:388
void Transform(const Matrix &transform)
Definition: canvas.cc:400
uint64_t GetMaxOpDepth() const
Definition: canvas.h:257
void DrawDashedLine(const Point &p0, const Point &p1, Scalar on_length, Scalar off_length, const Paint &paint)
Definition: canvas.cc:915
void DrawDiffRoundRect(const RoundRect &outer, const RoundRect &inner, const Paint &paint)
Definition: canvas.cc:1170
void DrawPath(const flutter::DlPath &path, const Paint &paint)
Definition: canvas.cc:459
void PreConcat(const Matrix &transform)
Definition: canvas.cc:392
void Rotate(Radians radians)
Definition: canvas.cc:424
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
Definition: canvas.cc:1374
void ResetTransform()
Definition: canvas.cc:396
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition: canvas.cc:2132
void DrawImage(const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, const SamplerDescriptor &sampler={})
Definition: canvas.cc:1392
void DrawPaint(const Paint &paint)
Definition: canvas.cc:479
void EndReplay()
Definition: canvas.cc:2607
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
Definition: canvas.cc:1101
void Skew(Scalar sx, Scalar sy)
Definition: canvas.cc:420
~Canvas()=default
void Scale(const Vector2 &scale)
Definition: canvas.cc:412
uint64_t GetOpDepth() const
Definition: canvas.h:255
void Save(uint32_t total_content_depth=kMaxDepth)
Definition: canvas.cc:1656
bool SupportsBlitToOnscreen() const
Definition: canvas.cc:2531
void DrawRect(const Rect &rect, const Paint &paint)
Definition: canvas.cc:941
bool EnsureFinalMipmapGeneration() const
Definition: canvas.cc:2589
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
Definition: canvas.cc:1588
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition: canvas.cc:897
void Translate(const Vector3 &offset)
Definition: canvas.cc:408
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:1255
void DrawArc(const Arc &arc, const Paint &paint)
Definition: canvas.cc:1049
LazyRenderingConfig(ContentContext &renderer, std::unique_ptr< EntityPassTarget > p_entity_pass_target)
Definition: canvas.cc:2679
bool IsApplyingClearColor() const
Whether or not the clear color texture can still be updated.
Definition: canvas.cc:2687
EntityPassTarget * GetEntityPassTarget() const
Definition: canvas.cc:2691
LazyRenderingConfig(LazyRenderingConfig &&)=default
InlinePassContext * GetInlinePassContext() const
Definition: canvas.cc:2695
float Scalar
Definition: scalar.h:19
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
Definition: canvas.h:75
@ kStrict
Sample only within the source rectangle. May be slower.
@ kFast
Faster, but may sample outside the bounds of the source rectangle.
TRect< Scalar > Rect
Definition: rect.h:857
PointStyle
Definition: canvas.h:66
@ kRound
Points are drawn as squares.
@ kSquare
Points are drawn as circles.
TPoint< Scalar > Point
Definition: point.h:426
flutter::DlPath DlPath
Definition: dl_dispatcher.h:34
BlendMode
Definition: color.h:58
ContentBoundsPromise
Definition: canvas.h:85
@ 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...
std::shared_ptr< Texture > texture_slot
Definition: canvas.h:44
std::shared_ptr< flutter::DlImageFilter > last_backdrop
Definition: canvas.h:48
size_t backdrop_count
Definition: canvas.h:42
std::optional< Snapshot > shared_filter_snapshot
Definition: canvas.h:47
Definition: canvas.h:51
size_t clip_height
Definition: canvas.h:54
bool did_round_out
Definition: canvas.h:63
Entity::RenderingMode rendering_mode
Definition: canvas.h:58
Scalar distributed_opacity
Definition: canvas.h:57
bool skipping
Definition: canvas.h:60
size_t num_clips
Definition: canvas.h:56
Matrix transform
Definition: canvas.h:52
uint32_t clip_depth
Definition: canvas.h:53
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
std::vector< Point > points