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