Flutter Impeller
dl_dispatcher.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_DL_DISPATCHER_H_
6 #define FLUTTER_IMPELLER_DISPLAY_LIST_DL_DISPATCHER_H_
7 
8 #include <memory>
9 
10 #include "flutter/display_list/dl_op_receiver.h"
11 #include "flutter/display_list/geometry/dl_geometry_types.h"
12 #include "flutter/display_list/geometry/dl_path.h"
13 #include "flutter/display_list/utils/dl_receiver_utils.h"
14 #include "fml/logging.h"
19 #include "impeller/geometry/rect.h"
20 
21 namespace impeller {
22 
30 
31 //////////////////////////////////////////////////////////////////////////
32 /// Important implementation note.
33 ///
34 /// The Impeller DisplayList Dispatcher implementation is divided into
35 /// two parts and conducted in two passes.
36 ///
37 /// The first pass is conducted using the FirstPassDispatcher which
38 /// examines the rendering ops for important conditions needed by the
39 /// rendering pass and computes some needed information for them.
40 ///
41 /// The second pass is conducted using CanvasDlDispatcher to perform the
42 /// actual rendering using a Canvas and data provided by the first pass.
43 ///
44 /// @important It is important to note that the 2 passes perform slightly
45 /// different DisplayList culling and may process different subsets of the
46 /// frame's operations.
47 /// See https://github.com/flutter/flutter/issues/182639
48 ///
49 /// Given the above issue any data precomputed by the first pass should
50 /// be presented in a way that doesn't assume a 1:1 correlation of the
51 /// rendering operations in both passes (perhaps provide it in a map
52 /// instead of a vector). While we have not yet observed and cases where
53 /// an operation is missed during the first pass but still processed in
54 /// the rendering pass, it would be wise to include a backup plan in
55 /// the canvas dispatcher for when the data was not forwarded.
56 //////////////////////////////////////////////////////////////////////////
57 
58 /// Base (virtual) dispatcher utility class to implement most DlOpReceiver
59 /// operations for other specific classes.
60 class DlDispatcherBase : public flutter::DlOpReceiver {
61  public:
62  // |flutter::DlOpReceiver|
63  void setAntiAlias(bool aa) override;
64 
65  // |flutter::DlOpReceiver|
66  void setDrawStyle(flutter::DlDrawStyle style) override;
67 
68  // |flutter::DlOpReceiver|
69  void setColor(flutter::DlColor color) override;
70 
71  // |flutter::DlOpReceiver|
72  void setStrokeWidth(DlScalar width) override;
73 
74  // |flutter::DlOpReceiver|
75  void setStrokeMiter(DlScalar limit) override;
76 
77  // |flutter::DlOpReceiver|
78  void setStrokeCap(flutter::DlStrokeCap cap) override;
79 
80  // |flutter::DlOpReceiver|
81  void setStrokeJoin(flutter::DlStrokeJoin join) override;
82 
83  // |flutter::DlOpReceiver|
84  void setColorSource(const flutter::DlColorSource* source) override;
85 
86  // |flutter::DlOpReceiver|
87  void setColorFilter(const flutter::DlColorFilter* filter) override;
88 
89  // |flutter::DlOpReceiver|
90  void setInvertColors(bool invert) override;
91 
92  // |flutter::DlOpReceiver|
93  void setBlendMode(flutter::DlBlendMode mode) override;
94 
95  // |flutter::DlOpReceiver|
96  void setMaskFilter(const flutter::DlMaskFilter* filter) override;
97 
98  // |flutter::DlOpReceiver|
99  void setImageFilter(const flutter::DlImageFilter* filter) override;
100 
101  // |flutter::DlOpReceiver|
102  void save(uint32_t total_content_depth) override;
103 
104  // |flutter::DlOpReceiver|
105  void saveLayer(const DlRect& bounds,
106  const flutter::SaveLayerOptions& options,
107  uint32_t total_content_depth,
108  flutter::DlBlendMode max_content_mode,
109  const flutter::DlImageFilter* backdrop,
110  std::optional<int64_t> backdrop_id) override;
111 
112  // |flutter::DlOpReceiver|
113  void restore() override;
114 
115  // |flutter::DlOpReceiver|
116  void translate(DlScalar tx, DlScalar ty) override;
117 
118  // |flutter::DlOpReceiver|
119  void scale(DlScalar sx, DlScalar sy) override;
120 
121  // |flutter::DlOpReceiver|
122  void rotate(DlScalar degrees) override;
123 
124  // |flutter::DlOpReceiver|
125  void skew(DlScalar sx, DlScalar sy) override;
126 
127  // |flutter::DlOpReceiver|
128  void transform2DAffine(DlScalar mxx,
129  DlScalar mxy,
130  DlScalar mxt,
131  DlScalar myx,
132  DlScalar myy,
133  DlScalar myt) override;
134 
135  // |flutter::DlOpReceiver|
137  DlScalar mxy,
138  DlScalar mxz,
139  DlScalar mxt,
140  DlScalar myx,
141  DlScalar myy,
142  DlScalar myz,
143  DlScalar myt,
144  DlScalar mzx,
145  DlScalar mzy,
146  DlScalar mzz,
147  DlScalar mzt,
148  DlScalar mwx,
149  DlScalar mwy,
150  DlScalar mwz,
151  DlScalar mwt) override;
152 
153  // |flutter::DlOpReceiver|
154  void transformReset() override;
155 
156  // |flutter::DlOpReceiver|
157  void clipRect(const DlRect& rect,
158  flutter::DlClipOp clip_op,
159  bool is_aa) override;
160 
161  // |flutter::DlOpReceiver|
162  void clipOval(const DlRect& bounds,
163  flutter::DlClipOp clip_op,
164  bool is_aa) override;
165 
166  // |flutter::DlOpReceiver|
167  void clipRoundRect(const DlRoundRect& rrect,
168  flutter::DlClipOp clip_op,
169  bool is_aa) override;
170 
171  // |flutter::DlOpReceiver|
173  flutter::DlClipOp clip_op,
174  bool is_aa) override;
175 
176  // |flutter::DlOpReceiver|
177  void clipPath(const DlPath& path,
178  flutter::DlClipOp clip_op,
179  bool is_aa) override;
180 
181  // |flutter::DlOpReceiver|
182  void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override;
183 
184  // |flutter::DlOpReceiver|
185  void drawPaint() override;
186 
187  // |flutter::DlOpReceiver|
188  void drawLine(const DlPoint& p0, const DlPoint& p1) override;
189 
190  // |flutter::DlOpReceiver|
191  void drawDashedLine(const DlPoint& p0,
192  const DlPoint& p1,
193  DlScalar on_length,
194  DlScalar off_length) override;
195 
196  // |flutter::DlOpReceiver|
197  void drawRect(const DlRect& rect) override;
198 
199  // |flutter::DlOpReceiver|
200  void drawOval(const DlRect& bounds) override;
201 
202  // |flutter::DlOpReceiver|
203  void drawCircle(const DlPoint& center, DlScalar radius) override;
204 
205  // |flutter::DlOpReceiver|
206  void drawRoundRect(const DlRoundRect& rrect) override;
207 
208  // |flutter::DlOpReceiver|
209  void drawDiffRoundRect(const DlRoundRect& outer,
210  const DlRoundRect& inner) override;
211 
212  // |flutter::DlOpReceiver|
213  void drawRoundSuperellipse(const DlRoundSuperellipse& rse) override;
214 
215  // |flutter::DlOpReceiver|
216  void drawPath(const DlPath& path) override;
217 
218  // |flutter::DlOpReceiver|
219  void drawArc(const DlRect& oval_bounds,
220  DlScalar start_degrees,
221  DlScalar sweep_degrees,
222  bool use_center) override;
223 
224  // |flutter::DlOpReceiver|
225  void drawPoints(flutter::DlPointMode mode,
226  uint32_t count,
227  const DlPoint points[]) override;
228 
229  // |flutter::DlOpReceiver|
230  void drawVertices(const std::shared_ptr<flutter::DlVertices>& vertices,
231  flutter::DlBlendMode dl_mode) override;
232 
233  // |flutter::DlOpReceiver|
234  void drawImage(const sk_sp<flutter::DlImage> image,
235  const DlPoint& point,
236  flutter::DlImageSampling sampling,
237  bool render_with_attributes) override;
238 
239  // |flutter::DlOpReceiver|
240  void drawImageRect(const sk_sp<flutter::DlImage> image,
241  const DlRect& src,
242  const DlRect& dst,
243  flutter::DlImageSampling sampling,
244  bool render_with_attributes,
245  flutter::DlSrcRectConstraint constraint) override;
246 
247  // |flutter::DlOpReceiver|
248  void drawImageNine(const sk_sp<flutter::DlImage> image,
249  const DlIRect& center,
250  const DlRect& dst,
251  flutter::DlFilterMode filter,
252  bool render_with_attributes) override;
253 
254  // |flutter::DlOpReceiver|
255  void drawAtlas(const sk_sp<flutter::DlImage> atlas,
256  const RSTransform xform[],
257  const DlRect tex[],
258  const flutter::DlColor colors[],
259  int count,
260  flutter::DlBlendMode mode,
261  flutter::DlImageSampling sampling,
262  const DlRect* cull_rect,
263  bool render_with_attributes) override;
264 
265  // |flutter::DlOpReceiver|
266  void drawDisplayList(const sk_sp<flutter::DisplayList> display_list,
267  DlScalar opacity) override;
268 
269  // |flutter::DlOpReceiver|
270  void drawText(const std::shared_ptr<flutter::DlText>& text,
271  DlScalar x,
272  DlScalar y) override;
273 
274  // |flutter::DlOpReceiver|
275  void drawShadow(const DlPath& path,
276  const flutter::DlColor color,
277  const DlScalar elevation,
278  bool transparent_occluder,
279  DlScalar dpr) override;
280 
281  virtual Canvas& GetCanvas() = 0;
282 
283  protected:
286 
287  static void SimplifyOrDrawPath(Canvas& canvas,
288  const DlPath& cache,
289  const Paint& paint);
290 };
291 
292 /// Specific non-virtual dispatcher utility class that uses DlDispatcherBase
293 /// to implement most operations but provides additional implementation of
294 /// operations that are specific to the rendering pass of the Impeller
295 /// 2-pass rendering procedure.
297  public:
299  RenderTarget& render_target,
300  bool is_onscreen,
301  bool has_root_backdrop_filter,
302  flutter::DlBlendMode max_root_blend_mode,
303  IRect32 cull_rect);
304 
305  ~CanvasDlDispatcher() = default;
306 
307  void SetBackdropData(std::unordered_map<int64_t, BackdropData> backdrop,
308  size_t backdrop_count);
309 
310  // |flutter::DlOpReceiver|
311  void save() override {
312  // This dispatcher should never be used with the save() variant
313  // that does not include the content_depth parameter.
314  FML_UNREACHABLE();
315  }
317 
318  // |flutter::DlOpReceiver|
319  void saveLayer(const DlRect& bounds,
320  const flutter::SaveLayerOptions options,
321  const flutter::DlImageFilter* backdrop,
322  std::optional<int64_t> backdrop_id) override {
323  // This dispatcher should never be used with the saveLayer() variant
324  // that does not include the content_depth parameter.
325  FML_UNREACHABLE();
326  }
328 
329  void FinishRecording() { canvas_.EndReplay(); }
330 
331  // |flutter::DlOpReceiver|
332  void drawVertices(const std::shared_ptr<flutter::DlVertices>& vertices,
333  flutter::DlBlendMode dl_mode) override;
334 
335  private:
336  Canvas canvas_;
337  const ContentContext& renderer_;
338 
339  Canvas& GetCanvas() override;
340 };
341 
342 /// Performs a first pass over the display list to collect information
343 /// that will be useful in a second pass by the CanvasDlDispatcher.
344 /// This class collects things like text frames and backdrop filters.
345 class FirstPassDispatcher : public flutter::IgnoreAttributeDispatchHelper,
346  public flutter::IgnoreClipDispatchHelper,
347  public flutter::IgnoreDrawDispatchHelper {
348  public:
349  FirstPassDispatcher(const ContentContext& renderer,
350  const Matrix& initial_matrix,
351  const Rect cull_rect);
352 
354 
355  void save() override;
356 
357  void saveLayer(const DlRect& bounds,
358  const flutter::SaveLayerOptions options,
359  const flutter::DlImageFilter* backdrop,
360  std::optional<int64_t> backdrop_id) override;
361 
362  void restore() override;
363 
364  void translate(DlScalar tx, DlScalar ty) override;
365 
366  void scale(DlScalar sx, DlScalar sy) override;
367 
368  void rotate(DlScalar degrees) override;
369 
370  void skew(DlScalar sx, DlScalar sy) override;
371 
372  // clang-format off
373  // 2x3 2D affine subset of a 4x4 transform in row major order
374  void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt,
375  DlScalar myx, DlScalar myy, DlScalar myt) override;
376  // clang-format on
377 
378  // clang-format off
379  // full 4x4 transform in row major order
381  DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
382  DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
383  DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
384  DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override;
385  // clang-format on
386 
387  void transformReset() override;
388 
389  void drawText(const std::shared_ptr<flutter::DlText>& text,
390  DlScalar x,
391  DlScalar y) override;
392 
393  void drawDisplayList(const sk_sp<flutter::DisplayList> display_list,
394  DlScalar opacity) override;
395 
396  // |flutter::DlOpReceiver|
397  void setDrawStyle(flutter::DlDrawStyle style) override;
398 
399  // |flutter::DlOpReceiver|
400  void setColor(flutter::DlColor color) override;
401 
402  // |flutter::DlOpReceiver|
403  void setStrokeWidth(DlScalar width) override;
404 
405  // |flutter::DlOpReceiver|
406  void setStrokeMiter(DlScalar limit) override;
407 
408  // |flutter::DlOpReceiver|
409  void setStrokeCap(flutter::DlStrokeCap cap) override;
410 
411  // |flutter::DlOpReceiver|
412  void setStrokeJoin(flutter::DlStrokeJoin join) override;
413 
414  // |flutter::DlOpReceiver|
415  void setImageFilter(const flutter::DlImageFilter* filter) override;
416 
417  std::pair<std::unordered_map<int64_t, BackdropData>, size_t>
419 
420  private:
421  const Rect GetCurrentLocalCullingBounds() const;
422 
423  const ContentContext& renderer_;
424  Matrix matrix_;
425  std::vector<Matrix> stack_;
426  std::unordered_map<int64_t, BackdropData> backdrop_data_;
427  // note: cull rects are always in the global coordinate space.
428  std::vector<Rect> cull_rect_state_;
429  bool has_image_filter_ = false;
430  size_t backdrop_count_ = 0;
431  Paint paint_;
432 };
433 
434 /// Render the provided display list to a texture with the given size.
435 std::shared_ptr<Texture> DisplayListToTexture(
436  const sk_sp<flutter::DisplayList>& display_list,
437  ISize size,
438  AiksContext& context,
439  bool reset_host_buffer = true,
440  bool generate_mips = false,
441  std::optional<PixelFormat> target_pixel_format = std::nullopt);
442 
443 /// @brief Render the provided display list to the render target.
444 ///
445 /// If [is_onscreen] is true, then the onscreen command buffer will be
446 /// submitted via Context::SubmitOnscreen.
447 bool RenderToTarget(ContentContext& context,
448  RenderTarget render_target,
449  const sk_sp<flutter::DisplayList>& display_list,
450  Rect cull_rect,
451  bool reset_host_buffer,
452  bool is_onscreen = true);
453 
454 } // namespace impeller
455 
456 #endif // FLUTTER_IMPELLER_DISPLAY_LIST_DL_DISPATCHER_H_
bool use_center
void saveLayer(const DlRect &bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
CanvasDlDispatcher(ContentContext &renderer, RenderTarget &render_target, bool is_onscreen, bool has_root_backdrop_filter, flutter::DlBlendMode max_root_blend_mode, IRect32 cull_rect)
void drawVertices(const std::shared_ptr< flutter::DlVertices > &vertices, flutter::DlBlendMode dl_mode) override
void SetBackdropData(std::unordered_map< int64_t, BackdropData > backdrop, size_t backdrop_count)
void EndReplay()
Definition: canvas.cc:2377
void drawLine(const DlPoint &p0, const DlPoint &p1) override
void drawText(const std::shared_ptr< flutter::DlText > &text, DlScalar x, DlScalar y) override
void drawAtlas(const sk_sp< flutter::DlImage > atlas, const RSTransform xform[], const DlRect tex[], const flutter::DlColor colors[], int count, flutter::DlBlendMode mode, flutter::DlImageSampling sampling, const DlRect *cull_rect, bool render_with_attributes) override
void drawPoints(flutter::DlPointMode mode, uint32_t count, const DlPoint points[]) override
virtual Canvas & GetCanvas()=0
void drawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length) override
void drawOval(const DlRect &bounds) override
void setImageFilter(const flutter::DlImageFilter *filter) override
void drawPath(const DlPath &path) override
void setStrokeCap(flutter::DlStrokeCap cap) override
void clipOval(const DlRect &bounds, flutter::DlClipOp clip_op, bool is_aa) override
void drawRoundSuperellipse(const DlRoundSuperellipse &rse) override
void clipRoundRect(const DlRoundRect &rrect, flutter::DlClipOp clip_op, bool is_aa) override
void skew(DlScalar sx, DlScalar sy) override
void clipRect(const DlRect &rect, flutter::DlClipOp clip_op, bool is_aa) override
void setAntiAlias(bool aa) override
void transformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void setStrokeWidth(DlScalar width) override
void drawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner) override
void drawRoundRect(const DlRoundRect &rrect) override
void setStrokeJoin(flutter::DlStrokeJoin join) override
void rotate(DlScalar degrees) override
void setColorFilter(const flutter::DlColorFilter *filter) override
void scale(DlScalar sx, DlScalar sy) override
void setDrawStyle(flutter::DlDrawStyle style) override
void drawShadow(const DlPath &path, const flutter::DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr) override
void drawImage(const sk_sp< flutter::DlImage > image, const DlPoint &point, flutter::DlImageSampling sampling, bool render_with_attributes) override
void clipPath(const DlPath &path, flutter::DlClipOp clip_op, bool is_aa) override
void drawImageRect(const sk_sp< flutter::DlImage > image, const DlRect &src, const DlRect &dst, flutter::DlImageSampling sampling, bool render_with_attributes, flutter::DlSrcRectConstraint constraint) override
void clipRoundSuperellipse(const DlRoundSuperellipse &rse, flutter::DlClipOp clip_op, bool is_aa) override
void drawArc(const DlRect &oval_bounds, DlScalar start_degrees, DlScalar sweep_degrees, bool use_center) override
void saveLayer(const DlRect &bounds, const flutter::SaveLayerOptions &options, uint32_t total_content_depth, flutter::DlBlendMode max_content_mode, const flutter::DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void drawDisplayList(const sk_sp< flutter::DisplayList > display_list, DlScalar opacity) override
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
void setInvertColors(bool invert) override
void setColor(flutter::DlColor color) override
void save(uint32_t total_content_depth) override
void setStrokeMiter(DlScalar limit) override
void translate(DlScalar tx, DlScalar ty) override
void drawVertices(const std::shared_ptr< flutter::DlVertices > &vertices, flutter::DlBlendMode dl_mode) override
void drawCircle(const DlPoint &center, DlScalar radius) override
void setMaskFilter(const flutter::DlMaskFilter *filter) override
void setColorSource(const flutter::DlColorSource *source) override
void drawImageNine(const sk_sp< flutter::DlImage > image, const DlIRect &center, const DlRect &dst, flutter::DlFilterMode filter, bool render_with_attributes) override
void transformReset() override
void setBlendMode(flutter::DlBlendMode mode) override
void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override
void drawRect(const DlRect &rect) override
static void SimplifyOrDrawPath(Canvas &canvas, const DlPath &cache, const Paint &paint)
void setColor(flutter::DlColor color) override
void setStrokeCap(flutter::DlStrokeCap cap) override
void saveLayer(const DlRect &bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void setDrawStyle(flutter::DlDrawStyle style) override
std::pair< std::unordered_map< int64_t, BackdropData >, size_t > TakeBackdropData()
void rotate(DlScalar degrees) override
void setImageFilter(const flutter::DlImageFilter *filter) override
void setStrokeMiter(DlScalar limit) override
void transformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void drawText(const std::shared_ptr< flutter::DlText > &text, DlScalar x, DlScalar y) override
void scale(DlScalar sx, DlScalar sy) override
void translate(DlScalar tx, DlScalar ty) override
void skew(DlScalar sx, DlScalar sy) override
FirstPassDispatcher(const ContentContext &renderer, const Matrix &initial_matrix, const Rect cull_rect)
void drawDisplayList(const sk_sp< flutter::DisplayList > display_list, DlScalar opacity) override
void setStrokeWidth(DlScalar width) override
void setStrokeJoin(flutter::DlStrokeJoin join) override
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
int32_t x
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
flutter::DlIRect DlIRect
Definition: dl_dispatcher.h:26
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips, std::optional< PixelFormat > target_pixel_format)
Render the provided display list to a texture with the given size.
flutter::DlRoundRect DlRoundRect
Definition: dl_dispatcher.h:27
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
flutter::DlRoundSuperellipse DlRoundSuperellipse
Definition: dl_dispatcher.h:28
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
bool RenderToTarget(ContentContext &context, RenderTarget render_target, const sk_sp< flutter::DisplayList > &display_list, Rect cull_rect, bool reset_host_buffer, bool is_onscreen)
Render the provided display list to the render target.
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
std::vector< Point > points