| Flutter Impeller |

dl_dispatcher.cc
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 #include "impeller/display_list/dl_dispatcher.h"
6
7 #include <algorithm>
8 #include <cstring>
9 #include <memory>
10 #include <optional>
11 #include <vector>
12
13 #include "display_list/dl_sampling_options.h"
14 #include "display_list/effects/dl_image_filter.h"
15 #include "flutter/fml/logging.h"
16 #include "fml/closure.h"
17 #include "impeller/core/formats.h"
18 #include "impeller/display_list/aiks_context.h"
19 #include "impeller/display_list/canvas.h"
20 #include "impeller/display_list/dl_atlas_geometry.h"
21 #include "impeller/display_list/dl_vertices_geometry.h"
22 #include "impeller/display_list/nine_patch_converter.h"
23 #include "impeller/display_list/skia_conversions.h"
24 #include "impeller/entity/contents/atlas_contents.h"
25 #include "impeller/entity/contents/content_context.h"
26 #include "impeller/entity/contents/filters/filter_contents.h"
27 #include "impeller/entity/contents/filters/inputs/filter_input.h"
28 #include "impeller/entity/entity.h"
29 #include "impeller/entity/geometry/ellipse_geometry.h"
30 #include "impeller/entity/geometry/fill_path_geometry.h"
31 #include "impeller/entity/geometry/rect_geometry.h"
32 #include "impeller/entity/geometry/round_rect_geometry.h"
33 #include "impeller/entity/geometry/round_superellipse_geometry.h"
34 #include "impeller/geometry/color.h"
35 #include "impeller/geometry/path.h"
36 #include "impeller/geometry/path_builder.h"
37 #include "impeller/geometry/scalar.h"
38 #include "impeller/geometry/sigma.h"
39 #include "impeller/typographer/font_glyph_pair.h"
40
41 namespace impeller {
42
43 #if !defined(NDEBUG)
44 #define USE_DEPTH_WATCHER true
45 #else
46 #define USE_DEPTH_WATCHER false
47 #endif // !defined(NDEBUG)
48
49 #if USE_DEPTH_WATCHER
50
51 // Invoke this macro at the top of any DlOpReceiver dispatch function
52 // using a number indicating the maximum depth that the operation is
53 // expected to consume in the Canvas. Most rendering ops consume 1
54 // except for DrawImageNine that currently consumes 1 per section (i.e. 9).
55 // Attribute, clip and transform ops do not consume depth but this
56 // macro can still be used with an argument of 0 to verify that expectation.
57 //
58 // The watchdog object allocated here will automatically double-check
59 // the depth usage at any exit point to the function, or any other
60 // point at which it falls out of scope.
61 #define AUTO_DEPTH_WATCHER(d) \
62 DepthWatcher _watcher(__FILE__, __LINE__, GetCanvas(), \
63 paint_.mask_blur_descriptor.has_value(), d)
64
65 // While the AUTO_DEPTH_WATCHER macro will check the depth usage at
66 // any exit point from the dispatch function, sometimes the dispatch
67 // functions are somewhat compounded and result in multiple Canvas
68 // calls.
69 //
70 // Invoke this macro at any key points in the middle of a dispatch
71 // function to verify that you still haven't exceeded the maximum
72 // allowed depth. This is especially useful if the function does
73 // an implicit save/restore where the restore call might assert the
74 // depth constraints in a function in Canvas that can't be as easily
75 // traced back to a given dispatch function as these macros can.
76 #define AUTO_DEPTH_CHECK() _watcher.check(__FILE__, __LINE__)
77
78 // Helper class, use the AUTO_DEPTH_WATCHER macros to access it
79 struct DepthWatcher {
80 DepthWatcher(const std::string& file,
81 int line,
82 const impeller::Canvas& canvas,
83 bool has_mask_blur,
84 int allowed)
85 : file_(file),
86 line_(line),
87 canvas_(canvas),
88 allowed_(has_mask_blur ? allowed + 1 : allowed),
89 old_depth_(canvas.GetOpDepth()),
90 old_max_(canvas.GetMaxOpDepth()) {}
91
92 ~DepthWatcher() { check(file_, line_); }
93
94 void check(const std::string& file, int line) {
95 FML_CHECK(canvas_.GetOpDepth() <= (old_depth_ + allowed_) &&
96 canvas_.GetOpDepth() <= old_max_)
97 << std::endl
98 << "from " << file << ":" << line << std::endl
99 << "old/allowed/current/max = " << old_depth_ << "/" << allowed_ << "/"
100 << canvas_.GetOpDepth() << "/" << old_max_;
101 }
102
103 private:
104 const std::string file_;
105 const int line_;
106
107 const impeller::Canvas& canvas_;
108 const uint64_t allowed_;
109 const uint64_t old_depth_;
110 const uint64_t old_max_;
111 };
112
113 #else // USE_DEPTH_WATCHER
114
115 #define AUTO_DEPTH_WATCHER(d)
116 #define AUTO_DEPTH_CHECK()
117
118 #endif // USE_DEPTH_WATCHER
119
120 #define UNIMPLEMENTED \
121 FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
122
123 static impeller::SamplerDescriptor ToSamplerDescriptor(
124 const flutter::DlFilterMode options) {
125 impeller::SamplerDescriptor desc;
126 switch (options) {
127 case flutter::DlFilterMode::kNearest:
128 desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
129 desc.label = "Nearest Sampler";
130 break;
131 case flutter::DlFilterMode::kLinear:
132 desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
133 desc.label = "Linear Sampler";
134 break;
135 default:
136 break;
137 }
138 return desc;
139 }
140
141 static std::optional<const Rect> ToOptRect(const flutter::DlRect* rect) {
142 if (rect == nullptr) {
143 return std::nullopt;
144 }
145 return *rect;
146 }
147
148 // |flutter::DlOpReceiver|
149 void DlDispatcherBase::setAntiAlias(bool aa) {
150 AUTO_DEPTH_WATCHER(0u);
151
152 // Nothing to do because AA is implicit.
153 }
154
155 static Paint::Style ToStyle(flutter::DlDrawStyle style) {
156 switch (style) {
157 case flutter::DlDrawStyle::kFill:
158 return Paint::Style::kFill;
159 case flutter::DlDrawStyle::kStroke:
160 return Paint::Style::kStroke;
161 case flutter::DlDrawStyle::kStrokeAndFill:
162 UNIMPLEMENTED;
163 break;
164 }
165 return Paint::Style::kFill;
166 }
167
168 // |flutter::DlOpReceiver|
169 void DlDispatcherBase::setDrawStyle(flutter::DlDrawStyle style) {
170 AUTO_DEPTH_WATCHER(0u);
171
172 paint_.style = ToStyle(style);
173 }
174
175 // |flutter::DlOpReceiver|
176 void DlDispatcherBase::setColor(flutter::DlColor color) {
177 AUTO_DEPTH_WATCHER(0u);
178
179 paint_.color = skia_conversions::ToColor(color);
180 }
181
182 // |flutter::DlOpReceiver|
183 void DlDispatcherBase::setStrokeWidth(DlScalar width) {
184 AUTO_DEPTH_WATCHER(0u);
185
186 paint_.stroke_width = width;
187 }
188
189 // |flutter::DlOpReceiver|
190 void DlDispatcherBase::setStrokeMiter(DlScalar limit) {
191 AUTO_DEPTH_WATCHER(0u);
192
193 paint_.stroke_miter = limit;
194 }
195
196 // |flutter::DlOpReceiver|
197 void DlDispatcherBase::setStrokeCap(flutter::DlStrokeCap cap) {
198 AUTO_DEPTH_WATCHER(0u);
199
200 switch (cap) {
201 case flutter::DlStrokeCap::kButt:
202 paint_.stroke_cap = Cap::kButt;
203 break;
204 case flutter::DlStrokeCap::kRound:
205 paint_.stroke_cap = Cap::kRound;
206 break;
207 case flutter::DlStrokeCap::kSquare:
208 paint_.stroke_cap = Cap::kSquare;
209 break;
210 }
211 }
212
213 // |flutter::DlOpReceiver|
214 void DlDispatcherBase::setStrokeJoin(flutter::DlStrokeJoin join) {
215 AUTO_DEPTH_WATCHER(0u);
216
217 switch (join) {
218 case flutter::DlStrokeJoin::kMiter:
219 paint_.stroke_join = Join::kMiter;
220 break;
221 case flutter::DlStrokeJoin::kRound:
222 paint_.stroke_join = Join::kRound;
223 break;
224 case flutter::DlStrokeJoin::kBevel:
225 paint_.stroke_join = Join::kBevel;
226 break;
227 }
228 }
229
230 // |flutter::DlOpReceiver|
231 void DlDispatcherBase::setColorSource(const flutter::DlColorSource* source) {
232 AUTO_DEPTH_WATCHER(0u);
233
234 paint_.color_source = source;
235 }
236
237 // |flutter::DlOpReceiver|
238 void DlDispatcherBase::setColorFilter(const flutter::DlColorFilter* filter) {
239 AUTO_DEPTH_WATCHER(0u);
240
241 paint_.color_filter = filter;
242 }
243
244 // |flutter::DlOpReceiver|
245 void DlDispatcherBase::setInvertColors(bool invert) {
246 AUTO_DEPTH_WATCHER(0u);
247
248 paint_.invert_colors = invert;
249 }
250
251 // |flutter::DlOpReceiver|
252 void DlDispatcherBase::setBlendMode(flutter::DlBlendMode dl_mode) {
253 AUTO_DEPTH_WATCHER(0u);
254
255 paint_.blend_mode = dl_mode;
256 }
257
258 static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style) {
259 switch (blur_style) {
260 case flutter::DlBlurStyle::kNormal:
261 return FilterContents::BlurStyle::kNormal;
262 case flutter::DlBlurStyle::kSolid:
263 return FilterContents::BlurStyle::kSolid;
264 case flutter::DlBlurStyle::kOuter:
265 return FilterContents::BlurStyle::kOuter;
266 case flutter::DlBlurStyle::kInner:
267 return FilterContents::BlurStyle::kInner;
268 }
269 }
270
271 // |flutter::DlOpReceiver|
272 void DlDispatcherBase::setMaskFilter(const flutter::DlMaskFilter* filter) {
273 AUTO_DEPTH_WATCHER(0u);
274
275 // Needs https://github.com/flutter/flutter/issues/95434
276 if (filter == nullptr) {
277 paint_.mask_blur_descriptor = std::nullopt;
278 return;
279 }
280 switch (filter->type()) {
281 case flutter::DlMaskFilterType::kBlur: {
282 auto blur = filter->asBlur();
283
284 paint_.mask_blur_descriptor = {
285 .style = ToBlurStyle(blur->style()),
286 .sigma = Sigma(blur->sigma()),
287 .respect_ctm = blur->respectCTM(),
288 };
289 break;
290 }
291 }
292 }
293
294 // |flutter::DlOpReceiver|
295 void DlDispatcherBase::setImageFilter(const flutter::DlImageFilter* filter) {
296 AUTO_DEPTH_WATCHER(0u);
297
298 paint_.image_filter = filter;
299 }
300
301 // |flutter::DlOpReceiver|
302 void DlDispatcherBase::save(uint32_t total_content_depth) {
303 AUTO_DEPTH_WATCHER(1u);
304
305 GetCanvas().Save(total_content_depth);
306 }
307
308 // |flutter::DlOpReceiver|
309 void DlDispatcherBase::saveLayer(const DlRect& bounds,
310 const flutter::SaveLayerOptions& options,
311 uint32_t total_content_depth,
312 flutter::DlBlendMode max_content_mode,
313 const flutter::DlImageFilter* backdrop,
314 std::optional<int64_t> backdrop_id) {
315 AUTO_DEPTH_WATCHER(1u);
316
317 auto paint = options.renders_with_attributes() ? paint_ : Paint{};
318 auto promise = options.content_is_clipped()
319 ? ContentBoundsPromise::kMayClipContents
320 : ContentBoundsPromise::kContainsContents;
321 std::optional<Rect> impeller_bounds;
322 // If the content is unbounded but has developer specified bounds, we take
323 // the original bounds so that we clip the content as expected.
324 if (!options.content_is_unbounded() || options.bounds_from_caller()) {
325 impeller_bounds = bounds;
326 }
327
328 GetCanvas().SaveLayer(
329 paint, impeller_bounds, backdrop, promise, total_content_depth,
330 // Unbounded content can still have user specified bounds that require a
331 // saveLayer to be created to perform the clip.
332 options.can_distribute_opacity() && !options.content_is_unbounded(),
333 backdrop_id //
334 );
335 }
336
337 // |flutter::DlOpReceiver|
338 void DlDispatcherBase::restore() {
339 GetCanvas().Restore();
340 }
341
342 // |flutter::DlOpReceiver|
343 void DlDispatcherBase::translate(DlScalar tx, DlScalar ty) {
344 AUTO_DEPTH_WATCHER(0u);
345
346 GetCanvas().Translate({tx, ty, 0.0});
347 }
348
349 // |flutter::DlOpReceiver|
350 void DlDispatcherBase::scale(DlScalar sx, DlScalar sy) {
351 AUTO_DEPTH_WATCHER(0u);
352
353 GetCanvas().Scale({sx, sy, 1.0});
354 }
355
356 // |flutter::DlOpReceiver|
357 void DlDispatcherBase::rotate(DlScalar degrees) {
358 AUTO_DEPTH_WATCHER(0u);
359
360 GetCanvas().Rotate(Degrees{degrees});
361 }
362
363 // |flutter::DlOpReceiver|
364 void DlDispatcherBase::skew(DlScalar sx, DlScalar sy) {
365 AUTO_DEPTH_WATCHER(0u);
366
367 GetCanvas().Skew(sx, sy);
368 }
369
370 // |flutter::DlOpReceiver|
371 void DlDispatcherBase::transform2DAffine(DlScalar mxx,
372 DlScalar mxy,
373 DlScalar mxt,
374 DlScalar myx,
375 DlScalar myy,
376 DlScalar myt) {
377 AUTO_DEPTH_WATCHER(0u);
378
379 // clang-format off
380 transformFullPerspective(
381 mxx, mxy, 0, mxt,
382 myx, myy, 0, myt,
383 0 , 0, 1, 0,
384 0 , 0, 0, 1
385 );
386 // clang-format on
387 }
388
389 // |flutter::DlOpReceiver|
390 void DlDispatcherBase::transformFullPerspective(DlScalar mxx,
391 DlScalar mxy,
392 DlScalar mxz,
393 DlScalar mxt,
394 DlScalar myx,
395 DlScalar myy,
396 DlScalar myz,
397 DlScalar myt,
398 DlScalar mzx,
399 DlScalar mzy,
400 DlScalar mzz,
401 DlScalar mzt,
402 DlScalar mwx,
403 DlScalar mwy,
404 DlScalar mwz,
405 DlScalar mwt) {
406 AUTO_DEPTH_WATCHER(0u);
407
408 // The order of arguments is row-major but Impeller matrices are
409 // column-major.
410 // clang-format off
411 auto transform = Matrix{
412 mxx, myx, mzx, mwx,
413 mxy, myy, mzy, mwy,
414 mxz, myz, mzz, mwz,
415 mxt, myt, mzt, mwt
416 };
417 // clang-format on
418 GetCanvas().Transform(transform);
419 }
420
421 // |flutter::DlOpReceiver|
422 void DlDispatcherBase::transformReset() {
423 AUTO_DEPTH_WATCHER(0u);
424
425 GetCanvas().ResetTransform();
426 GetCanvas().Transform(initial_matrix_);
427 }
428
429 static Entity::ClipOperation ToClipOperation(flutter::DlClipOp clip_op) {
430 switch (clip_op) {
431 case flutter::DlClipOp::kDifference:
432 return Entity::ClipOperation::kDifference;
433 case flutter::DlClipOp::kIntersect:
434 return Entity::ClipOperation::kIntersect;
435 }
436 }
437
438 // |flutter::DlOpReceiver|
439 void DlDispatcherBase::clipRect(const DlRect& rect,
440 flutter::DlClipOp clip_op,
441 bool is_aa) {
442 AUTO_DEPTH_WATCHER(0u);
443
444 RectGeometry geom(rect);
445 GetCanvas().ClipGeometry(geom, ToClipOperation(clip_op), /*is_aa=*/is_aa);
446 }
447
448 // |flutter::DlOpReceiver|
449 void DlDispatcherBase::clipOval(const DlRect& bounds,
450 flutter::DlClipOp clip_op,
451 bool is_aa) {
452 AUTO_DEPTH_WATCHER(0u);
453
454 EllipseGeometry geom(bounds);
455 GetCanvas().ClipGeometry(geom, ToClipOperation(clip_op));
456 }
457
458 // |flutter::DlOpReceiver|
459 void DlDispatcherBase::clipRoundRect(const DlRoundRect& rrect,
460 flutter::DlClipOp sk_op,
461 bool is_aa) {
462 AUTO_DEPTH_WATCHER(0u);
463
464 auto clip_op = ToClipOperation(sk_op);
465 if (rrect.IsRect()) {
466 RectGeometry geom(rrect.GetBounds());
467 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
468 } else if (rrect.IsOval()) {
469 EllipseGeometry geom(rrect.GetBounds());
470 GetCanvas().ClipGeometry(geom, clip_op);
471 } else if (rrect.GetRadii().AreAllCornersSame()) {
472 RoundRectGeometry geom(rrect.GetBounds(), rrect.GetRadii().top_left);
473 GetCanvas().ClipGeometry(geom, clip_op);
474 } else {
475 FillPathGeometry geom(PathBuilder{}.AddRoundRect(rrect).TakePath());
476 GetCanvas().ClipGeometry(geom, clip_op);
477 }
478 }
479
480 // |flutter::DlOpReceiver|
481 void DlDispatcherBase::clipRoundSuperellipse(const DlRoundSuperellipse& rse,
482 flutter::DlClipOp sk_op,
483 bool is_aa) {
484 AUTO_DEPTH_WATCHER(0u);
485
486 auto clip_op = ToClipOperation(sk_op);
487 if (rse.IsRect()) {
488 RectGeometry geom(rse.GetBounds());
489 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
490 } else if (rse.IsOval()) {
491 EllipseGeometry geom(rse.GetBounds());
492 GetCanvas().ClipGeometry(geom, clip_op);
493 } else {
494 RoundSuperellipseGeometry geom(rse.GetBounds(), rse.GetRadii());
495 GetCanvas().ClipGeometry(geom, clip_op);
496 }
497 }
498
499 // |flutter::DlOpReceiver|
500 void DlDispatcherBase::clipPath(const DlPath& path,
501 flutter::DlClipOp sk_op,
502 bool is_aa) {
503 AUTO_DEPTH_WATCHER(0u);
504
505 auto clip_op = ToClipOperation(sk_op);
506
507 DlRect rect;
508 if (path.IsRect(&rect)) {
509 RectGeometry geom(rect);
510 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
511 } else if (path.IsOval(&rect)) {
512 EllipseGeometry geom(rect);
513 GetCanvas().ClipGeometry(geom, clip_op);
514 } else {
515 SkRRect rrect;
516 if (path.IsSkRRect(&rrect) && rrect.isSimple()) {
517 RoundRectGeometry geom(flutter::ToDlRect(rrect.rect()),
518 flutter::ToDlSize(rrect.getSimpleRadii()));
519 GetCanvas().ClipGeometry(geom, clip_op);
520 } else {
521 FillPathGeometry geom(path.GetPath());
522 GetCanvas().ClipGeometry(geom, clip_op);
523 }
524 }
525 }
526
527 // |flutter::DlOpReceiver|
528 void DlDispatcherBase::drawColor(flutter::DlColor color,
529 flutter::DlBlendMode dl_mode) {
530 AUTO_DEPTH_WATCHER(1u);
531
532 Paint paint;
533 paint.color = skia_conversions::ToColor(color);
534 paint.blend_mode = dl_mode;
535 GetCanvas().DrawPaint(paint);
536 }
537
538 // |flutter::DlOpReceiver|
539 void DlDispatcherBase::drawPaint() {
540 AUTO_DEPTH_WATCHER(1u);
541
542 GetCanvas().DrawPaint(paint_);
543 }
544
545 // |flutter::DlOpReceiver|
546 void DlDispatcherBase::drawLine(const DlPoint& p0, const DlPoint& p1) {
547 AUTO_DEPTH_WATCHER(1u);
548
549 GetCanvas().DrawLine(p0, p1, paint_);
550 }
551
552 void DlDispatcherBase::drawDashedLine(const DlPoint& p0,
553 const DlPoint& p1,
554 DlScalar on_length,
555 DlScalar off_length) {
556 AUTO_DEPTH_WATCHER(1u);
557
558 Scalar length = p0.GetDistance(p1);
559 // Reasons to defer to regular DrawLine:
560 // length is non-positive - drawLine will draw appropriate "dot"
561 // off_length is non-positive - no gaps, drawLine will draw it solid
562 // on_length is negative - invalid dashing
563 // Note that a 0 length "on" dash will draw "dot"s every "off" distance
564 // apart
565 if (length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
566 Point delta = (p1 - p0) / length; // length > 0 already tested
567 PathBuilder builder;
568
569 Scalar consumed = 0.0f;
570 while (consumed < length) {
571 builder.MoveTo(p0 + delta * consumed);
572
573 Scalar dash_end = consumed + on_length;
574 if (dash_end < length) {
575 builder.LineTo(p0 + delta * dash_end);
576 } else {
577 builder.LineTo(p1);
578 // Should happen anyway due to the math, but let's make it explicit
579 // in case of bit errors. We're done with this line.
580 break;
581 }
582
583 consumed = dash_end + off_length;
584 }
585
586 Paint stroke_paint = paint_;
587 stroke_paint.style = Paint::Style::kStroke;
588 GetCanvas().DrawPath(builder.TakePath(), stroke_paint);
589 } else {
590 drawLine(p0, p1);
591 }
592 }
593
594 // |flutter::DlOpReceiver|
595 void DlDispatcherBase::drawRect(const DlRect& rect) {
596 AUTO_DEPTH_WATCHER(1u);
597
598 GetCanvas().DrawRect(rect, paint_);
599 }
600
601 // |flutter::DlOpReceiver|
602 void DlDispatcherBase::drawOval(const DlRect& bounds) {
603 AUTO_DEPTH_WATCHER(1u);
604
605 GetCanvas().DrawOval(bounds, paint_);
606 }
607
608 // |flutter::DlOpReceiver|
609 void DlDispatcherBase::drawCircle(const DlPoint& center, DlScalar radius) {
610 AUTO_DEPTH_WATCHER(1u);
611
612 GetCanvas().DrawCircle(center, radius, paint_);
613 }
614
615 // |flutter::DlOpReceiver|
616 void DlDispatcherBase::drawRoundRect(const DlRoundRect& rrect) {
617 AUTO_DEPTH_WATCHER(1u);
618
619 GetCanvas().DrawRoundRect(rrect, paint_);
620 }
621
622 // |flutter::DlOpReceiver|
623 void DlDispatcherBase::drawDiffRoundRect(const DlRoundRect& outer,
624 const DlRoundRect& inner) {
625 AUTO_DEPTH_WATCHER(1u);
626
627 PathBuilder builder;
628 builder.AddRoundRect(outer);
629 builder.AddRoundRect(inner);
630 builder.SetBounds(outer.GetBounds().Union(inner.GetBounds()));
631 GetCanvas().DrawPath(builder.TakePath(FillType::kOdd), paint_);
632 }
633
634 // |flutter::DlOpReceiver|
635 void DlDispatcherBase::drawRoundSuperellipse(const DlRoundSuperellipse& rse) {
636 AUTO_DEPTH_WATCHER(1u);
637
638 GetCanvas().DrawRoundSuperellipse(rse, paint_);
639 }
640
641 // |flutter::DlOpReceiver|
642 void DlDispatcherBase::drawPath(const DlPath& path) {
643 AUTO_DEPTH_WATCHER(1u);
644
645 SimplifyOrDrawPath(GetCanvas(), path, paint_);
646 }
647
648 void DlDispatcherBase::SimplifyOrDrawPath(Canvas& canvas,
649 const DlPath& path,
650 const Paint& paint) {
651 DlRect rect;
652
653 // We can't "optimize" a path into a rectangle if it's open.
654 bool closed;
655 if (path.IsRect(&rect, &closed) && closed) {
656 canvas.DrawRect(rect, paint);
657 return;
658 }
659
660 SkRRect rrect;
661 if (path.IsSkRRect(&rrect) && rrect.isSimple()) {
662 canvas.DrawRoundRect(flutter::ToDlRoundRect(rrect), paint);
663 return;
664 }
665
666 if (path.IsOval(&rect)) {
667 canvas.DrawOval(rect, paint);
668 return;
669 }
670
671 DlPoint start;
672 DlPoint end;
673 if (path.IsLine(&start, &end)) {
674 canvas.DrawLine(start, end, paint);
675 return;
676 }
677
678 canvas.DrawPath(path.GetPath(), paint);
679 }
680
681 // |flutter::DlOpReceiver|
682 void DlDispatcherBase::drawArc(const DlRect& oval_bounds,
683 DlScalar start_degrees,
684 DlScalar sweep_degrees,
685 bool use_center) {
686 AUTO_DEPTH_WATCHER(1u);
687
688 if (paint_.stroke_width >
689 std::max(oval_bounds.GetWidth(), oval_bounds.GetHeight())) {
690 // This is a special case for rendering arcs whose stroke width is so large
691 // you are effectively drawing a sector of a circle.
692 // https://github.com/flutter/flutter/issues/158567
693 DlRect expanded_rect = oval_bounds.Expand(Size(paint_.stroke_width / 2));
694 PathBuilder builder;
695 Paint fill_paint = paint_;
696 fill_paint.style = Paint::Style::kFill;
697 fill_paint.stroke_width = 1;
698 builder.AddArc(expanded_rect, Degrees(start_degrees),
699 Degrees(sweep_degrees),
700 /*use_center=*/true);
701 GetCanvas().DrawPath(builder.TakePath(), fill_paint);
702 } else {
703 PathBuilder builder;
704 builder.AddArc(oval_bounds, Degrees(start_degrees), Degrees(sweep_degrees),
705 use_center);
706 GetCanvas().DrawPath(builder.TakePath(), paint_);
707 }
708 }
709
710 // |flutter::DlOpReceiver|
711 void DlDispatcherBase::drawPoints(flutter::DlPointMode mode,
712 uint32_t count,
713 const DlPoint points[]) {
714 AUTO_DEPTH_WATCHER(1u);
715
716 Paint paint = paint_;
717 paint.style = Paint::Style::kStroke;
718 switch (mode) {
719 case flutter::DlPointMode::kPoints: {
720 // Cap::kButt is also treated as a square.
721 PointStyle point_style = paint.stroke_cap == Cap::kRound
722 ? PointStyle::kRound
723 : PointStyle::kSquare;
724 Scalar radius = paint.stroke_width;
725 if (radius > 0) {
726 radius /= 2.0;
727 }
728 GetCanvas().DrawPoints(points, count, radius, paint, point_style);
729 } break;
730 case flutter::DlPointMode::kLines:
731 for (uint32_t i = 1; i < count; i += 2) {
732 Point p0 = points[i - 1];
733 Point p1 = points[i];
734 GetCanvas().DrawLine(p0, p1, paint, /*reuse_depth=*/i > 1);
735 }
736 break;
737 case flutter::DlPointMode::kPolygon:
738 if (count > 1) {
739 Point p0 = points[0];
740 for (uint32_t i = 1; i < count; i++) {
741 Point p1 = points[i];
742 GetCanvas().DrawLine(p0, p1, paint, /*reuse_depth=*/i > 1);
743 p0 = p1;
744 }
745 }
746 break;
747 }
748 }
749
750 void DlDispatcherBase::drawVertices(
751 const std::shared_ptr<flutter::DlVertices>& vertices,
752 flutter::DlBlendMode dl_mode) {}
753
754 // |flutter::DlOpReceiver|
755 void DlDispatcherBase::drawImage(const sk_sp<flutter::DlImage> image,
756 const DlPoint& point,
757 flutter::DlImageSampling sampling,
758 bool render_with_attributes) {
759 AUTO_DEPTH_WATCHER(1u);
760
761 if (!image) {
762 return;
763 }
764
765 auto texture = image->impeller_texture();
766 if (!texture) {
767 return;
768 }
769
770 const auto size = texture->GetSize();
771 const auto src = DlRect::MakeWH(size.width, size.height);
772 const auto dest = DlRect::MakeXYWH(point.x, point.y, size.width, size.height);
773
774 drawImageRect(image, // image
775 src, // source rect
776 dest, // destination rect
777 sampling, // sampling options
778 render_with_attributes, // render with attributes
779 flutter::DlSrcRectConstraint::kStrict // constraint
780 );
781 }
782
783 // |flutter::DlOpReceiver|
784 void DlDispatcherBase::drawImageRect(const sk_sp<flutter::DlImage> image,
785 const DlRect& src,
786 const DlRect& dst,
787 flutter::DlImageSampling sampling,
788 bool render_with_attributes,
789 flutter::DlSrcRectConstraint constraint =
790 flutter::DlSrcRectConstraint::kFast) {
791 AUTO_DEPTH_WATCHER(1u);
792
793 GetCanvas().DrawImageRect(
794 image->impeller_texture(), // image
795 src, // source rect
796 dst, // destination rect
797 render_with_attributes ? paint_ : Paint(), // paint
798 skia_conversions::ToSamplerDescriptor(sampling) // sampling
799 );
800 }
801
802 // |flutter::DlOpReceiver|
803 void DlDispatcherBase::drawImageNine(const sk_sp<flutter::DlImage> image,
804 const DlIRect& center,
805 const DlRect& dst,
806 flutter::DlFilterMode filter,
807 bool render_with_attributes) {
808 AUTO_DEPTH_WATCHER(9u);
809
810 NinePatchConverter converter = {};
811 converter.DrawNinePatch(image->impeller_texture(),
812 Rect::MakeLTRB(center.GetLeft(), center.GetTop(),
813 center.GetRight(), center.GetBottom()),
814 dst, ToSamplerDescriptor(filter), &GetCanvas(),
815 &paint_);
816 }
817
818 // |flutter::DlOpReceiver|
819 void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
820 const RSTransform xform[],
821 const DlRect tex[],
822 const flutter::DlColor colors[],
823 int count,
824 flutter::DlBlendMode mode,
825 flutter::DlImageSampling sampling,
826 const DlRect* cull_rect,
827 bool render_with_attributes) {
828 AUTO_DEPTH_WATCHER(1u);
829
830 auto geometry =
831 DlAtlasGeometry(atlas->impeller_texture(), //
832 xform, //
833 tex, //
834 colors, //
835 static_cast<size_t>(count), //
836 mode, //
837 skia_conversions::ToSamplerDescriptor(sampling), //
838 ToOptRect(cull_rect) //
839 );
840 auto atlas_contents = std::make_shared<AtlasContents>();
841 atlas_contents->SetGeometry(&geometry);
842
843 GetCanvas().DrawAtlas(atlas_contents, paint_);
844 }
845
846 // |flutter::DlOpReceiver|
847 void DlDispatcherBase::drawDisplayList(
848 const sk_sp<flutter::DisplayList> display_list,
849 DlScalar opacity) {
850 AUTO_DEPTH_WATCHER(display_list->total_depth());
851
852 // Save all values that must remain untouched after the operation.
853 Paint saved_paint = paint_;
854 Matrix saved_initial_matrix = initial_matrix_;
855
856 // Establish a new baseline for interpreting the new DL.
857 // Matrix and clip are left untouched, the current
858 // transform is saved as the new base matrix, and paint
859 // values are reset to defaults.
860 initial_matrix_ = GetCanvas().GetCurrentTransform();
861 paint_ = Paint();
862
863 // Handle passed opacity in the most brute-force way by using
864 // a SaveLayer. If the display_list is able to inherit the
865 // opacity, this could also be handled by modulating all of its
866 // attribute settings (for example, color), by the indicated
867 // opacity.
868 int restore_count = GetCanvas().GetSaveCount();
869 if (opacity < SK_Scalar1) {
870 Paint save_paint;
871 save_paint.color = Color(0, 0, 0, opacity);
872 GetCanvas().SaveLayer(save_paint, display_list->GetBounds(), nullptr,
873 ContentBoundsPromise::kContainsContents,
874 display_list->total_depth(),
875 display_list->can_apply_group_opacity());
876 } else {
877 // The display list may alter the clip, which must be restored to the
878 // current clip at the end of playback.
879 GetCanvas().Save(display_list->total_depth());
880 }
881
882 // TODO(131445): Remove this restriction if we can correctly cull with
883 // perspective transforms.
884 if (display_list->has_rtree() && !initial_matrix_.HasPerspective()) {
885 // The canvas remembers the screen-space culling bounds clipped by
886 // the surface and the history of clip calls. DisplayList can cull
887 // the ops based on a rectangle expressed in its "destination bounds"
888 // so we need the canvas to transform those into the current local
889 // coordinate space into which the DisplayList will be rendered.
890 auto global_culling_bounds = GetCanvas().GetLocalCoverageLimit();
891 if (global_culling_bounds.has_value()) {
892 Rect cull_rect = global_culling_bounds->TransformBounds(
893 GetCanvas().GetCurrentTransform().Invert());
894 display_list->Dispatch(
895 *this, SkRect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
896 cull_rect.GetRight(), cull_rect.GetBottom()));
897 } else {
898 // If the culling bounds are empty, this display list can be skipped
899 // entirely.
900 }
901 } else {
902 display_list->Dispatch(*this);
903 }
904
905 // Restore all saved state back to what it was before we interpreted
906 // the display_list
907 AUTO_DEPTH_CHECK();
908 GetCanvas().RestoreToCount(restore_count);
909 initial_matrix_ = saved_initial_matrix;
910 paint_ = saved_paint;
911 }
912
913 // |flutter::DlOpReceiver|
914 void DlDispatcherBase::drawTextBlob(const sk_sp<SkTextBlob> blob,
915 DlScalar x,
916 DlScalar y) {
917 // When running with Impeller enabled Skia text blobs are converted to
918 // Impeller text frames in paragraph_skia.cc
919 UNIMPLEMENTED;
920 }
921
922 // |flutter::DlOpReceiver|
923 void DlDispatcherBase::drawTextFrame(
924 const std::shared_ptr<TextFrame>& text_frame,
925 DlScalar x,
926 DlScalar y) {
927 AUTO_DEPTH_WATCHER(1u);
928
929 GetCanvas().DrawTextFrame(text_frame, //
930 impeller::Point{x, y}, //
931 paint_ //
932 );
933 }
934
935 // |flutter::DlOpReceiver|
936 void DlDispatcherBase::drawShadow(const DlPath& path,
937 const flutter::DlColor color,
938 const DlScalar elevation,
939 bool transparent_occluder,
940 DlScalar dpr) {
941 AUTO_DEPTH_WATCHER(1u);
942
943 Color spot_color = skia_conversions::ToColor(color);
944 spot_color.alpha *= 0.25;
945
946 // Compute the spot color -- ported from SkShadowUtils::ComputeTonalColors.
947 {
948 Scalar max =
949 std::max(std::max(spot_color.red, spot_color.green), spot_color.blue);
950 Scalar min =
951 std::min(std::min(spot_color.red, spot_color.green), spot_color.blue);
952 Scalar luminance = (min + max) * 0.5;
953
954 Scalar alpha_adjust =
955 (2.6f + (-2.66667f + 1.06667f * spot_color.alpha) * spot_color.alpha) *
956 spot_color.alpha;
957 Scalar color_alpha =
958 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
959 luminance;
960 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
961
962 Scalar greyscale_alpha =
963 std::clamp(spot_color.alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
964
965 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
966 Scalar tonal_alpha = color_scale + greyscale_alpha;
967 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
968 spot_color = Color(unpremul_scale * spot_color.red,
969 unpremul_scale * spot_color.green,
970 unpremul_scale * spot_color.blue, tonal_alpha);
971 }
972
973 Vector3 light_position(0, -1, 1);
974 Scalar occluder_z = dpr * elevation;
975
976 constexpr Scalar kLightRadius = 800 / 600; // Light radius / light height
977
978 Paint paint;
979 paint.style = Paint::Style::kFill;
980 paint.color = spot_color;
981 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
982 .style = FilterContents::BlurStyle::kNormal,
983 .sigma = Radius{kLightRadius * occluder_z /
984 GetCanvas().GetCurrentTransform().GetScale().y},
985 };
986
987 GetCanvas().Save(1u);
988 GetCanvas().PreConcat(
989 Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y)));
990
991 SimplifyOrDrawPath(GetCanvas(), path, paint);
992 AUTO_DEPTH_CHECK();
993
994 GetCanvas().Restore();
995 }
996
997 /// Subclasses
998
999 static bool RequiresReadbackForBlends(
1000 const ContentContext& renderer,
1001 flutter::DlBlendMode max_root_blend_mode) {
1002 return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() &&
1003 max_root_blend_mode > Entity::kLastPipelineBlendMode;
1004 }
1005
1006 CanvasDlDispatcher::CanvasDlDispatcher(ContentContext& renderer,
1007 RenderTarget& render_target,
1008 bool is_onscreen,
1009 bool has_root_backdrop_filter,
1010 flutter::DlBlendMode max_root_blend_mode,
1011 IRect cull_rect)
1012 : canvas_(renderer,
1013 render_target,
1014 is_onscreen,
1015 has_root_backdrop_filter ||
1016 RequiresReadbackForBlends(renderer, max_root_blend_mode),
1017 cull_rect),
1018 renderer_(renderer) {}
1019
1020 Canvas& CanvasDlDispatcher::GetCanvas() {
1021 return canvas_;
1022 }
1023
1024 void CanvasDlDispatcher::drawVertices(
1025 const std::shared_ptr<flutter::DlVertices>& vertices,
1026 flutter::DlBlendMode dl_mode) {
1027 AUTO_DEPTH_WATCHER(1u);
1028
1029 GetCanvas().DrawVertices(
1030 std::make_shared<DlVerticesGeometry>(vertices, renderer_), dl_mode,
1031 paint_);
1032 }
1033
1034 void CanvasDlDispatcher::SetBackdropData(
1035 std::unordered_map<int64_t, BackdropData> backdrop,
1036 size_t backdrop_count) {
1037 GetCanvas().SetBackdropData(std::move(backdrop), backdrop_count);
1038 }
1039
1040 //// Text Frame Dispatcher
1041
1042 FirstPassDispatcher::FirstPassDispatcher(const ContentContext& renderer,
1043 const Matrix& initial_matrix,
1044 const Rect cull_rect)
1045 : renderer_(renderer), matrix_(initial_matrix) {
1046 cull_rect_state_.push_back(cull_rect);
1047 }
1048
1049 FirstPassDispatcher::~FirstPassDispatcher() {
1050 FML_DCHECK(cull_rect_state_.size() == 1);
1051 }
1052
1053 void FirstPassDispatcher::save() {
1054 stack_.emplace_back(matrix_);
1055 cull_rect_state_.push_back(cull_rect_state_.back());
1056 }
1057
1058 void FirstPassDispatcher::saveLayer(const DlRect& bounds,
1059 const flutter::SaveLayerOptions options,
1060 const flutter::DlImageFilter* backdrop,
1061 std::optional<int64_t> backdrop_id) {
1062 save();
1063
1064 backdrop_count_ += (backdrop == nullptr ? 0 : 1);
1065 if (backdrop != nullptr && backdrop_id.has_value()) {
1066 std::shared_ptr<flutter::DlImageFilter> shared_backdrop =
1067 backdrop->shared();
1068 std::unordered_map<int64_t, BackdropData>::iterator existing =
1069 backdrop_data_.find(backdrop_id.value());
1070 if (existing == backdrop_data_.end()) {
1071 backdrop_data_[backdrop_id.value()] =
1072 BackdropData{.backdrop_count = 1, .last_backdrop = shared_backdrop};
1073 } else {
1074 BackdropData& data = existing->second;
1075 data.backdrop_count++;
1076 if (data.all_filters_equal) {
1077 data.all_filters_equal = (*data.last_backdrop == *shared_backdrop);
1078 data.last_backdrop = shared_backdrop;
1079 }
1080 }
1081 }
1082
1083 // This dispatcher does not track enough state to accurately compute
1084 // cull rects with image filters.
1085 auto global_cull_rect = cull_rect_state_.back();
1086 if (has_image_filter_ || global_cull_rect.IsMaximum()) {
1087 cull_rect_state_.back() = Rect::MakeMaximum();
1088 } else {
1089 auto global_save_bounds = bounds.TransformBounds(matrix_);
1090 auto new_cull_rect = global_cull_rect.Intersection(global_save_bounds);
1091 if (new_cull_rect.has_value()) {
1092 cull_rect_state_.back() = new_cull_rect.value();
1093 } else {
1094 cull_rect_state_.back() = Rect::MakeLTRB(0, 0, 0, 0);
1095 }
1096 }
1097 }
1098
1099 void FirstPassDispatcher::restore() {
1100 matrix_ = stack_.back();
1101 stack_.pop_back();
1102 cull_rect_state_.pop_back();
1103 }
1104
1105 void FirstPassDispatcher::translate(DlScalar tx, DlScalar ty) {
1106 matrix_ = matrix_.Translate({tx, ty});
1107 }
1108
1109 void FirstPassDispatcher::scale(DlScalar sx, DlScalar sy) {
1110 matrix_ = matrix_.Scale({sx, sy, 1.0f});
1111 }
1112
1113 void FirstPassDispatcher::rotate(DlScalar degrees) {
1114 matrix_ = matrix_ * Matrix::MakeRotationZ(Degrees(degrees));
1115 }
1116
1117 void FirstPassDispatcher::skew(DlScalar sx, DlScalar sy) {
1118 matrix_ = matrix_ * Matrix::MakeSkew(sx, sy);
1119 }
1120
1121 // clang-format off
1122 // 2x3 2D affine subset of a 4x4 transform in row major order
1123 void FirstPassDispatcher::transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt,
1124 DlScalar myx, DlScalar myy, DlScalar myt) {
1125 matrix_ = matrix_ * Matrix::MakeColumn(
1126 mxx, myx, 0.0f, 0.0f,
1127 mxy, myy, 0.0f, 0.0f,
1128 0.0f, 0.0f, 1.0f, 0.0f,
1129 mxt, myt, 0.0f, 1.0f
1130 );
1131 }
1132
1133 // full 4x4 transform in row major order
1134 void FirstPassDispatcher::transformFullPerspective(
1135 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
1136 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
1137 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
1138 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
1139 matrix_ = matrix_ * Matrix::MakeColumn(
1140 mxx, myx, mzx, mwx,
1141 mxy, myy, mzy, mwy,
1142 mxz, myz, mzz, mwz,
1143 mxt, myt, mzt, mwt
1144 );
1145 }
1146 // clang-format on
1147
1148 void FirstPassDispatcher::transformReset() {
1149 matrix_ = Matrix();
1150 }
1151
1152 void FirstPassDispatcher::drawTextFrame(
1153 const std::shared_ptr<impeller::TextFrame>& text_frame,
1154 DlScalar x,
1155 DlScalar y) {
1156 GlyphProperties properties;
1157 if (paint_.style == Paint::Style::kStroke) {
1158 properties.stroke = true;
1159 properties.stroke_cap = paint_.stroke_cap;
1160 properties.stroke_join = paint_.stroke_join;
1161 properties.stroke_miter = paint_.stroke_miter;
1162 properties.stroke_width = paint_.stroke_width;
1163 }
1164 if (text_frame->HasColor()) {
1165 // Alpha is always applied when rendering, remove it here so
1166 // we do not double-apply the alpha.
1167 properties.color = paint_.color.WithAlpha(1.0);
1168 }
1169 auto scale = TextFrame::RoundScaledFontSize(
1170 (matrix_ * Matrix::MakeTranslation(Point(x, y))).GetMaxBasisLengthXY());
1171
1172 renderer_.GetLazyGlyphAtlas()->AddTextFrame(
1173 text_frame, //
1174 scale, //
1175 Point(x, y), //
1176 matrix_,
1177 (properties.stroke || text_frame->HasColor()) //
1178 ? std::optional<GlyphProperties>(properties) //
1179 : std::nullopt //
1180 );
1181 }
1182
1183 const Rect FirstPassDispatcher::GetCurrentLocalCullingBounds() const {
1184 auto cull_rect = cull_rect_state_.back();
1185 if (!cull_rect.IsEmpty() && !cull_rect.IsMaximum()) {
1186 Matrix inverse = matrix_.Invert();
1187 cull_rect = cull_rect.TransformBounds(inverse);
1188 }
1189 return cull_rect;
1190 }
1191
1192 void FirstPassDispatcher::drawDisplayList(
1193 const sk_sp<flutter::DisplayList> display_list,
1194 DlScalar opacity) {
1195 [[maybe_unused]] size_t stack_depth = stack_.size();
1196 save();
1197 Paint old_paint = paint_;
1198 paint_ = Paint{};
1199 bool old_has_image_filter = has_image_filter_;
1200 has_image_filter_ = false;
1201
1202 if (matrix_.HasPerspective()) {
1203 display_list->Dispatch(*this);
1204 } else {
1205 Rect local_cull_bounds = GetCurrentLocalCullingBounds();
1206 if (local_cull_bounds.IsMaximum()) {
1207 display_list->Dispatch(*this);
1208 } else if (!local_cull_bounds.IsEmpty()) {
1209 IRect cull_rect = IRect::RoundOut(local_cull_bounds);
1210 display_list->Dispatch(*this,
1211 SkIRect::MakeLTRB(cull_rect.GetLeft(), //
1212 cull_rect.GetTop(), //
1213 cull_rect.GetRight(), //
1214 cull_rect.GetBottom() //
1215 ));
1216 }
1217 }
1218
1219 restore();
1220 paint_ = old_paint;
1221 has_image_filter_ = old_has_image_filter;
1222 FML_DCHECK(stack_depth == stack_.size());
1223 }
1224
1225 // |flutter::DlOpReceiver|
1226 void FirstPassDispatcher::setDrawStyle(flutter::DlDrawStyle style) {
1227 paint_.style = ToStyle(style);
1228 }
1229
1230 // |flutter::DlOpReceiver|
1231 void FirstPassDispatcher::setColor(flutter::DlColor color) {
1232 paint_.color = skia_conversions::ToColor(color);
1233 }
1234
1235 // |flutter::DlOpReceiver|
1236 void FirstPassDispatcher::setStrokeWidth(DlScalar width) {
1237 paint_.stroke_width = width;
1238 }
1239
1240 // |flutter::DlOpReceiver|
1241 void FirstPassDispatcher::setStrokeMiter(DlScalar limit) {
1242 paint_.stroke_miter = limit;
1243 }
1244
1245 // |flutter::DlOpReceiver|
1246 void FirstPassDispatcher::setStrokeCap(flutter::DlStrokeCap cap) {
1247 switch (cap) {
1248 case flutter::DlStrokeCap::kButt:
1249 paint_.stroke_cap = Cap::kButt;
1250 break;
1251 case flutter::DlStrokeCap::kRound:
1252 paint_.stroke_cap = Cap::kRound;
1253 break;
1254 case flutter::DlStrokeCap::kSquare:
1255 paint_.stroke_cap = Cap::kSquare;
1256 break;
1257 }
1258 }
1259
1260 // |flutter::DlOpReceiver|
1261 void FirstPassDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) {
1262 switch (join) {
1263 case flutter::DlStrokeJoin::kMiter:
1264 paint_.stroke_join = Join::kMiter;
1265 break;
1266 case flutter::DlStrokeJoin::kRound:
1267 paint_.stroke_join = Join::kRound;
1268 break;
1269 case flutter::DlStrokeJoin::kBevel:
1270 paint_.stroke_join = Join::kBevel;
1271 break;
1272 }
1273 }
1274
1275 // |flutter::DlOpReceiver|
1276 void FirstPassDispatcher::setImageFilter(const flutter::DlImageFilter* filter) {
1277 if (filter == nullptr) {
1278 has_image_filter_ = false;
1279 } else {
1280 has_image_filter_ = true;
1281 }
1282 }
1283
1284 std::pair<std::unordered_map<int64_t, BackdropData>, size_t>
1285 FirstPassDispatcher::TakeBackdropData() {
1286 std::unordered_map<int64_t, BackdropData> temp;
1287 std::swap(temp, backdrop_data_);
1288 return std::make_pair(temp, backdrop_count_);
1289 }
1290
1291 std::shared_ptr<Texture> DisplayListToTexture(
1292 const sk_sp<flutter::DisplayList>& display_list,
1293 ISize size,
1294 AiksContext& context,
1295 bool reset_host_buffer,
1296 bool generate_mips) {
1297 int mip_count = 1;
1298 if (generate_mips) {
1299 mip_count = size.MipCount();
1300 }
1301 // Do not use the render target cache as the lifecycle of this texture
1302 // will outlive a particular frame.
1303 impeller::RenderTargetAllocator render_target_allocator =
1304 impeller::RenderTargetAllocator(
1305 context.GetContext()->GetResourceAllocator());
1306 impeller::RenderTarget target;
1307 if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
1308 target = render_target_allocator.CreateOffscreenMSAA(
1309 *context.GetContext(), // context
1310 size, // size
1311 /*mip_count=*/mip_count,
1312 "Picture Snapshot MSAA", // label
1313 impeller::RenderTarget::
1314 kDefaultColorAttachmentConfigMSAA // color_attachment_config
1315 );
1316 } else {
1317 target = render_target_allocator.CreateOffscreen(
1318 *context.GetContext(), // context
1319 size, // size
1320 /*mip_count=*/mip_count,
1321 "Picture Snapshot", // label
1322 impeller::RenderTarget::
1323 kDefaultColorAttachmentConfig // color_attachment_config
1324 );
1325 }
1326 if (!target.IsValid()) {
1327 return nullptr;
1328 }
1329
1330 SkIRect sk_cull_rect = SkIRect::MakeWH(size.width, size.height);
1331 impeller::FirstPassDispatcher collector(
1332 context.GetContentContext(), impeller::Matrix(), Rect::MakeSize(size));
1333 display_list->Dispatch(collector, sk_cull_rect);
1334 impeller::CanvasDlDispatcher impeller_dispatcher(
1335 context.GetContentContext(), //
1336 target, //
1337 /*is_onscreen=*/false, //
1338 display_list->root_has_backdrop_filter(), //
1339 display_list->max_root_blend_mode(), //
1340 impeller::IRect::MakeSize(size) //
1341 );
1342 const auto& [data, count] = collector.TakeBackdropData();
1343 impeller_dispatcher.SetBackdropData(data, count);
1344 context.GetContentContext().GetTextShadowCache().MarkFrameStart();
1345 fml::ScopedCleanupClosure cleanup([&] {
1346 if (reset_host_buffer) {
1347 context.GetContentContext().GetTransientsBuffer().Reset();
1348 }
1349 context.GetContentContext().GetTextShadowCache().MarkFrameEnd();
1350 context.GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames();
1351 context.GetContext()->DisposeThreadLocalCachedResources();
1352 });
1353
1354 display_list->Dispatch(impeller_dispatcher, sk_cull_rect);
1355 impeller_dispatcher.FinishRecording();
1356
1357 return target.GetRenderTargetTexture();
1358 }
1359
1360 bool RenderToTarget(ContentContext& context,
1361 RenderTarget render_target,
1362 const sk_sp<flutter::DisplayList>& display_list,
1363 SkIRect cull_rect,
1364 bool reset_host_buffer,
1365 bool is_onscreen) {
1366 Rect ip_cull_rect = Rect::MakeLTRB(cull_rect.left(), cull_rect.top(),
1367 cull_rect.right(), cull_rect.bottom());
1368 FirstPassDispatcher collector(context, impeller::Matrix(), ip_cull_rect);
1369 display_list->Dispatch(collector, cull_rect);
1370
1371 impeller::CanvasDlDispatcher impeller_dispatcher(
1372 context, //
1373 render_target, //
1374 /*is_onscreen=*/is_onscreen, //
1375 display_list->root_has_backdrop_filter(), //
1376 display_list->max_root_blend_mode(), //
1377 IRect::RoundOut(ip_cull_rect) //
1378 );
1379 const auto& [data, count] = collector.TakeBackdropData();
1380 impeller_dispatcher.SetBackdropData(data, count);
1381 context.GetTextShadowCache().MarkFrameStart();
1382 fml::ScopedCleanupClosure cleanup([&] {
1383 if (reset_host_buffer) {
1384 context.GetTransientsBuffer().Reset();
1385 }
1386 context.GetTextShadowCache().MarkFrameEnd();
1387 });
1388
1389 display_list->Dispatch(impeller_dispatcher, cull_rect);
1390 impeller_dispatcher.FinishRecording();
1391 context.GetLazyGlyphAtlas()->ResetTextFrames();
1392
1393 return true;
1394 }
1395
1396 } // namespace impeller
aiks_context.h
atlas_contents.h
canvas.h
impeller::AiksContext
Definition: aiks_context.h:19
impeller::AiksContext::GetContentContext
ContentContext & GetContentContext() const
Definition: aiks_context.cc:42
impeller::AiksContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: aiks_context.cc:38
impeller::CanvasDlDispatcher
Definition: dl_dispatcher.h:268
impeller::CanvasDlDispatcher::FinishRecording
void FinishRecording()
Definition: dl_dispatcher.h:301
impeller::CanvasDlDispatcher::CanvasDlDispatcher
CanvasDlDispatcher(ContentContext &renderer, RenderTarget &render_target, bool is_onscreen, bool has_root_backdrop_filter, flutter::DlBlendMode max_root_blend_mode, IRect cull_rect)
Definition: dl_dispatcher.cc:1006
impeller::CanvasDlDispatcher::drawVertices
void drawVertices(const std::shared_ptr< flutter::DlVertices > &vertices, flutter::DlBlendMode dl_mode) override
Definition: dl_dispatcher.cc:1024
impeller::CanvasDlDispatcher::SetBackdropData
void SetBackdropData(std::unordered_map< int64_t, BackdropData > backdrop, size_t backdrop_count)
Definition: dl_dispatcher.cc:1034
impeller::Canvas
Definition: canvas.h:116
impeller::Canvas::ClipGeometry
void ClipGeometry(const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
Definition: canvas.cc:686
impeller::Canvas::SetBackdropData
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
impeller::Canvas::DrawRoundSuperellipse
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
Definition: canvas.cc:640
impeller::Canvas::GetLocalCoverageLimit
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
impeller::Canvas::SaveLayer
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
impeller::Canvas::GetCurrentTransform
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:254
impeller::Canvas::DrawVertices
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition: canvas.cc:864
impeller::Canvas::DrawOval
void DrawOval(const Rect &rect, const Paint &paint)
Definition: canvas.cc:583
impeller::Canvas::DrawImageRect
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
impeller::Canvas::RestoreToCount
void RestoreToCount(size_t count)
Definition: canvas.cc:301
impeller::Canvas::Restore
bool Restore()
Definition: canvas.cc:1329
impeller::Canvas::GetSaveCount
size_t GetSaveCount() const
Definition: canvas.cc:293
impeller::Canvas::Transform
void Transform(const Matrix &transform)
Definition: canvas.cc:250
impeller::Canvas::GetMaxOpDepth
uint64_t GetMaxOpDepth() const
Definition: canvas.h:247
impeller::Canvas::PreConcat
void PreConcat(const Matrix &transform)
Definition: canvas.cc:242
impeller::Canvas::Rotate
void Rotate(Radians radians)
Definition: canvas.cc:274
impeller::Canvas::DrawPoints
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
Definition: canvas.cc:767
impeller::Canvas::ResetTransform
void ResetTransform()
Definition: canvas.cc:246
impeller::Canvas::DrawTextFrame
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition: canvas.cc:1520
impeller::Canvas::DrawPaint
void DrawPaint(const Paint &paint)
Definition: canvas.cc:324
impeller::Canvas::DrawRoundRect
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
Definition: canvas.cc:613
impeller::Canvas::Skew
void Skew(Scalar sx, Scalar sy)
Definition: canvas.cc:270
impeller::Canvas::Scale
void Scale(const Vector2 &scale)
Definition: canvas.cc:262
impeller::Canvas::GetOpDepth
uint64_t GetOpDepth() const
Definition: canvas.h:245
impeller::Canvas::DrawPath
void DrawPath(const Path &path, const Paint &paint)
Definition: canvas.cc:309
impeller::Canvas::Save
void Save(uint32_t total_content_depth=kMaxDepth)
Definition: canvas.cc:1043
impeller::Canvas::DrawRect
void DrawRect(const Rect &rect, const Paint &paint)
Definition: canvas.cc:565
impeller::Canvas::DrawAtlas
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
Definition: canvas.cc:977
impeller::Canvas::DrawLine
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition: canvas.cc:542
impeller::Canvas::Translate
void Translate(const Vector3 &offset)
Definition: canvas.cc:258
impeller::Canvas::DrawCircle
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:663
impeller::Capabilities::SupportsFramebufferFetch
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
impeller::ContentContext
Definition: content_context.h:138
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:296
impeller::ContentContext::GetLazyGlyphAtlas
const std::shared_ptr< LazyGlyphAtlas > & GetLazyGlyphAtlas() const
Definition: content_context.h:264
impeller::ContentContext::GetDeviceCapabilities
const Capabilities & GetDeviceCapabilities() const
Definition: content_context.cc:917
impeller::ContentContext::GetTextShadowCache
TextShadowCache & GetTextShadowCache() const
Definition: content_context.h:298
impeller::DlAtlasGeometry
A wrapper around data provided by a drawAtlas call.
Definition: dl_atlas_geometry.h:17
impeller::DlDispatcherBase::drawLine
void drawLine(const DlPoint &p0, const DlPoint &p1) override
Definition: dl_dispatcher.cc:546
impeller::DlDispatcherBase::drawAtlas
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
Definition: dl_dispatcher.cc:819
impeller::DlDispatcherBase::drawPoints
void drawPoints(flutter::DlPointMode mode, uint32_t count, const DlPoint points[]) override
Definition: dl_dispatcher.cc:711
impeller::DlDispatcherBase::GetCanvas
virtual Canvas & GetCanvas()=0
impeller::DlDispatcherBase::drawDashedLine
void drawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length) override
Definition: dl_dispatcher.cc:552
impeller::DlDispatcherBase::drawOval
void drawOval(const DlRect &bounds) override
Definition: dl_dispatcher.cc:602
impeller::DlDispatcherBase::setImageFilter
void setImageFilter(const flutter::DlImageFilter *filter) override
Definition: dl_dispatcher.cc:295
impeller::DlDispatcherBase::drawPath
void drawPath(const DlPath &path) override
Definition: dl_dispatcher.cc:642
impeller::DlDispatcherBase::setStrokeCap
void setStrokeCap(flutter::DlStrokeCap cap) override
Definition: dl_dispatcher.cc:197
impeller::DlDispatcherBase::clipOval
void clipOval(const DlRect &bounds, flutter::DlClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:449
impeller::DlDispatcherBase::drawRoundSuperellipse
void drawRoundSuperellipse(const DlRoundSuperellipse &rse) override
Definition: dl_dispatcher.cc:635
impeller::DlDispatcherBase::clipRoundRect
void clipRoundRect(const DlRoundRect &rrect, flutter::DlClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:459
impeller::DlDispatcherBase::initial_matrix_
Matrix initial_matrix_
Definition: dl_dispatcher.h:261
impeller::DlDispatcherBase::skew
void skew(DlScalar sx, DlScalar sy) override
Definition: dl_dispatcher.cc:364
impeller::DlDispatcherBase::clipRect
void clipRect(const DlRect &rect, flutter::DlClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:439
impeller::DlDispatcherBase::setAntiAlias
void setAntiAlias(bool aa) override
Definition: dl_dispatcher.cc:149
impeller::DlDispatcherBase::transformFullPerspective
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
Definition: dl_dispatcher.cc:390
impeller::DlDispatcherBase::setStrokeWidth
void setStrokeWidth(DlScalar width) override
Definition: dl_dispatcher.cc:183
impeller::DlDispatcherBase::paint_
Paint paint_
Definition: dl_dispatcher.h:260
impeller::DlDispatcherBase::drawDiffRoundRect
void drawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner) override
Definition: dl_dispatcher.cc:623
impeller::DlDispatcherBase::drawRoundRect
void drawRoundRect(const DlRoundRect &rrect) override
Definition: dl_dispatcher.cc:616
impeller::DlDispatcherBase::drawPaint
void drawPaint() override
Definition: dl_dispatcher.cc:539
impeller::DlDispatcherBase::setStrokeJoin
void setStrokeJoin(flutter::DlStrokeJoin join) override
Definition: dl_dispatcher.cc:214
impeller::DlDispatcherBase::drawTextBlob
void drawTextBlob(const sk_sp< SkTextBlob > blob, DlScalar x, DlScalar y) override
Definition: dl_dispatcher.cc:914
impeller::DlDispatcherBase::rotate
void rotate(DlScalar degrees) override
Definition: dl_dispatcher.cc:357
impeller::DlDispatcherBase::setColorFilter
void setColorFilter(const flutter::DlColorFilter *filter) override
Definition: dl_dispatcher.cc:238
impeller::DlDispatcherBase::scale
void scale(DlScalar sx, DlScalar sy) override
Definition: dl_dispatcher.cc:350
impeller::DlDispatcherBase::setDrawStyle
void setDrawStyle(flutter::DlDrawStyle style) override
Definition: dl_dispatcher.cc:169
impeller::DlDispatcherBase::drawShadow
void drawShadow(const DlPath &path, const flutter::DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr) override
Definition: dl_dispatcher.cc:936
impeller::DlDispatcherBase::drawImage
void drawImage(const sk_sp< flutter::DlImage > image, const DlPoint &point, flutter::DlImageSampling sampling, bool render_with_attributes) override
Definition: dl_dispatcher.cc:755
impeller::DlDispatcherBase::clipPath
void clipPath(const DlPath &path, flutter::DlClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:500
impeller::DlDispatcherBase::drawImageRect
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
Definition: dl_dispatcher.cc:784
impeller::DlDispatcherBase::clipRoundSuperellipse
void clipRoundSuperellipse(const DlRoundSuperellipse &rse, flutter::DlClipOp clip_op, bool is_aa) override
Definition: dl_dispatcher.cc:481
impeller::DlDispatcherBase::drawArc
void drawArc(const DlRect &oval_bounds, DlScalar start_degrees, DlScalar sweep_degrees, bool use_center) override
Definition: dl_dispatcher.cc:682
impeller::DlDispatcherBase::saveLayer
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
Definition: dl_dispatcher.cc:309
impeller::DlDispatcherBase::drawDisplayList
void drawDisplayList(const sk_sp< flutter::DisplayList > display_list, DlScalar opacity) override
Definition: dl_dispatcher.cc:847
impeller::DlDispatcherBase::transform2DAffine
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
Definition: dl_dispatcher.cc:371
impeller::DlDispatcherBase::setInvertColors
void setInvertColors(bool invert) override
Definition: dl_dispatcher.cc:245
impeller::DlDispatcherBase::setColor
void setColor(flutter::DlColor color) override
Definition: dl_dispatcher.cc:176
impeller::DlDispatcherBase::save
void save(uint32_t total_content_depth) override
Definition: dl_dispatcher.cc:302
impeller::DlDispatcherBase::setStrokeMiter
void setStrokeMiter(DlScalar limit) override
Definition: dl_dispatcher.cc:190
impeller::DlDispatcherBase::translate
void translate(DlScalar tx, DlScalar ty) override
Definition: dl_dispatcher.cc:343
impeller::DlDispatcherBase::drawVertices
void drawVertices(const std::shared_ptr< flutter::DlVertices > &vertices, flutter::DlBlendMode dl_mode) override
Definition: dl_dispatcher.cc:750
impeller::DlDispatcherBase::drawCircle
void drawCircle(const DlPoint &center, DlScalar radius) override
Definition: dl_dispatcher.cc:609
impeller::DlDispatcherBase::drawTextFrame
void drawTextFrame(const std::shared_ptr< impeller::TextFrame > &text_frame, DlScalar x, DlScalar y) override
Definition: dl_dispatcher.cc:923
impeller::DlDispatcherBase::setMaskFilter
void setMaskFilter(const flutter::DlMaskFilter *filter) override
Definition: dl_dispatcher.cc:272
impeller::DlDispatcherBase::restore
void restore() override
Definition: dl_dispatcher.cc:338
impeller::DlDispatcherBase::setColorSource
void setColorSource(const flutter::DlColorSource *source) override
Definition: dl_dispatcher.cc:231
impeller::DlDispatcherBase::drawImageNine
void drawImageNine(const sk_sp< flutter::DlImage > image, const DlIRect &center, const DlRect &dst, flutter::DlFilterMode filter, bool render_with_attributes) override
Definition: dl_dispatcher.cc:803
impeller::DlDispatcherBase::transformReset
void transformReset() override
Definition: dl_dispatcher.cc:422
impeller::DlDispatcherBase::setBlendMode
void setBlendMode(flutter::DlBlendMode mode) override
Definition: dl_dispatcher.cc:252
impeller::DlDispatcherBase::drawColor
void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override
Definition: dl_dispatcher.cc:528
impeller::DlDispatcherBase::drawRect
void drawRect(const DlRect &rect) override
Definition: dl_dispatcher.cc:595
impeller::DlDispatcherBase::SimplifyOrDrawPath
static void SimplifyOrDrawPath(Canvas &canvas, const DlPath &cache, const Paint &paint)
Definition: dl_dispatcher.cc:648
impeller::EllipseGeometry
Definition: ellipse_geometry.h:16
impeller::Entity::kLastPipelineBlendMode
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:22
impeller::Entity::ClipOperation
ClipOperation
Definition: entity.h:61
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::FillPathGeometry
A geometry that is created from a filled path object.
Definition: fill_path_geometry.h:16
impeller::FilterContents::BlurStyle
BlurStyle
Definition: filter_contents.h:28
impeller::FilterContents::BlurStyle::kNormal
@ kNormal
Blurred inside and outside.
impeller::FilterContents::BlurStyle::kOuter
@ kOuter
Nothing inside, blurred outside.
impeller::FilterContents::BlurStyle::kInner
@ kInner
Blurred inside, nothing outside.
impeller::FilterContents::BlurStyle::kSolid
@ kSolid
Solid inside, blurred outside.
impeller::FirstPassDispatcher
Definition: dl_dispatcher.h:318
impeller::FirstPassDispatcher::setColor
void setColor(flutter::DlColor color) override
Definition: dl_dispatcher.cc:1231
impeller::FirstPassDispatcher::setStrokeCap
void setStrokeCap(flutter::DlStrokeCap cap) override
Definition: dl_dispatcher.cc:1246
impeller::FirstPassDispatcher::saveLayer
void saveLayer(const DlRect &bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
Definition: dl_dispatcher.cc:1058
impeller::FirstPassDispatcher::setDrawStyle
void setDrawStyle(flutter::DlDrawStyle style) override
Definition: dl_dispatcher.cc:1226
impeller::FirstPassDispatcher::save
void save() override
Definition: dl_dispatcher.cc:1053
impeller::FirstPassDispatcher::restore
void restore() override
Definition: dl_dispatcher.cc:1099
impeller::FirstPassDispatcher::TakeBackdropData
std::pair< std::unordered_map< int64_t, BackdropData >, size_t > TakeBackdropData()
Definition: dl_dispatcher.cc:1285
impeller::FirstPassDispatcher::rotate
void rotate(DlScalar degrees) override
Definition: dl_dispatcher.cc:1113
impeller::FirstPassDispatcher::drawTextFrame
void drawTextFrame(const std::shared_ptr< impeller::TextFrame > &text_frame, DlScalar x, DlScalar y) override
Definition: dl_dispatcher.cc:1152
impeller::FirstPassDispatcher::setImageFilter
void setImageFilter(const flutter::DlImageFilter *filter) override
Definition: dl_dispatcher.cc:1276
impeller::FirstPassDispatcher::setStrokeMiter
void setStrokeMiter(DlScalar limit) override
Definition: dl_dispatcher.cc:1241
impeller::FirstPassDispatcher::transformFullPerspective
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
Definition: dl_dispatcher.cc:1134
impeller::FirstPassDispatcher::scale
void scale(DlScalar sx, DlScalar sy) override
Definition: dl_dispatcher.cc:1109
impeller::FirstPassDispatcher::translate
void translate(DlScalar tx, DlScalar ty) override
Definition: dl_dispatcher.cc:1105
impeller::FirstPassDispatcher::skew
void skew(DlScalar sx, DlScalar sy) override
Definition: dl_dispatcher.cc:1117
impeller::FirstPassDispatcher::FirstPassDispatcher
FirstPassDispatcher(const ContentContext &renderer, const Matrix &initial_matrix, const Rect cull_rect)
Definition: dl_dispatcher.cc:1042
impeller::FirstPassDispatcher::drawDisplayList
void drawDisplayList(const sk_sp< flutter::DisplayList > display_list, DlScalar opacity) override
Definition: dl_dispatcher.cc:1192
impeller::FirstPassDispatcher::setStrokeWidth
void setStrokeWidth(DlScalar width) override
Definition: dl_dispatcher.cc:1236
impeller::FirstPassDispatcher::setStrokeJoin
void setStrokeJoin(flutter::DlStrokeJoin join) override
Definition: dl_dispatcher.cc:1261
impeller::FirstPassDispatcher::~FirstPassDispatcher
~FirstPassDispatcher()
Definition: dl_dispatcher.cc:1049
impeller::FirstPassDispatcher::transformReset
void transformReset() override
Definition: dl_dispatcher.cc:1148
impeller::FirstPassDispatcher::transform2DAffine
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
Definition: dl_dispatcher.cc:1123
impeller::NinePatchConverter
Definition: nine_patch_converter.h:17
impeller::NinePatchConverter::DrawNinePatch
void DrawNinePatch(const std::shared_ptr< Texture > &image, Rect center, Rect dst, const SamplerDescriptor &sampler, Canvas *canvas, Paint *paint)
Definition: nine_patch_converter.cc:60
impeller::PathBuilder
Definition: path_builder.h:16
impeller::PathBuilder::TakePath
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:30
impeller::PathBuilder::AddArc
PathBuilder & AddArc(const Rect &oval_bounds, Radians start, Radians sweep, bool use_center=false)
Definition: path_builder.cc:397
impeller::PathBuilder::AddRoundRect
PathBuilder & AddRoundRect(RoundRect rect)
Definition: path_builder.cc:175
impeller::PathBuilder::LineTo
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
Definition: path_builder.cc:66
impeller::PathBuilder::MoveTo
PathBuilder & MoveTo(Point point, bool relative=false)
Definition: path_builder.cc:47
impeller::PathBuilder::SetBounds
PathBuilder & SetBounds(Rect bounds)
Set the bounding box that will be used by Path.GetBoundingBox in place of performing the computation.
Definition: path_builder.cc:576
impeller::RectGeometry
Definition: rect_geometry.h:12
impeller::RenderTargetAllocator
a wrapper around the impeller [Allocator] instance that can be used to provide caching of allocated r...
Definition: render_target.h:149
impeller::RenderTargetAllocator::CreateOffscreenMSAA
virtual RenderTarget CreateOffscreenMSAA(const Context &context, ISize size, int mip_count, std::string_view label="Offscreen MSAA", RenderTarget::AttachmentConfigMSAA color_attachment_config=RenderTarget::kDefaultColorAttachmentConfigMSAA, std::optional< RenderTarget::AttachmentConfig > stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &existing_color_msaa_texture=nullptr, const std::shared_ptr< Texture > &existing_color_resolve_texture=nullptr, const std::shared_ptr< Texture > &existing_depth_stencil_texture=nullptr)
Definition: render_target.cc:376
impeller::RenderTargetAllocator::CreateOffscreen
virtual RenderTarget CreateOffscreen(const Context &context, ISize size, int mip_count, std::string_view label="Offscreen", RenderTarget::AttachmentConfig color_attachment_config=RenderTarget::kDefaultColorAttachmentConfig, std::optional< RenderTarget::AttachmentConfig > stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &existing_color_texture=nullptr, const std::shared_ptr< Texture > &existing_depth_stencil_texture=nullptr)
Definition: render_target.cc:322
impeller::RenderTarget
Definition: render_target.h:38
impeller::RenderTarget::GetRenderTargetTexture
std::shared_ptr< Texture > GetRenderTargetTexture() const
Definition: render_target.cc:176
impeller::RenderTarget::IsValid
bool IsValid() const
Definition: render_target.cc:23
impeller::RoundRectGeometry
Definition: round_rect_geometry.h:16
impeller::RoundSuperellipseGeometry
Definition: round_superellipse_geometry.h:25
impeller::TextFrame::RoundScaledFontSize
static Rational RoundScaledFontSize(Scalar scale)
Definition: text_frame.cc:55
impeller::TextShadowCache::MarkFrameStart
void MarkFrameStart()
Mark all glyph textures as unused this frame.
Definition: text_shadow_cache.cc:30
color.h
content_context.h
formats.h
dl_atlas_geometry.h
AUTO_DEPTH_WATCHER
#define AUTO_DEPTH_WATCHER(d)
Definition: dl_dispatcher.cc:115
UNIMPLEMENTED
#define UNIMPLEMENTED
Definition: dl_dispatcher.cc:120
AUTO_DEPTH_CHECK
#define AUTO_DEPTH_CHECK()
Definition: dl_dispatcher.cc:116
dl_dispatcher.h
x
int32_t x
Definition: dl_golden_unittests.cc:458
dl_vertices_geometry.h
ellipse_geometry.h
entity.h
fill_path_geometry.h
filter_contents.h
filter_input.h
font_glyph_pair.h
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
path.h
path_builder.h
impeller::skia_conversions::ToSamplerDescriptor
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Definition: skia_conversions.cc:24
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:13
impeller
Definition: allocation.cc:12
impeller::DisplayListToTexture
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips)
Render the provided display list to a texture with the given size.
Definition: dl_dispatcher.cc:1291
impeller::Join::kRound
@ kRound
impeller::Join::kMiter
@ kMiter
impeller::Join::kBevel
@ kBevel
impeller::Vector2
Point Vector2
Definition: point.h:331
impeller::DlRect
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::DlIRect
flutter::DlIRect DlIRect
Definition: dl_dispatcher.h:26
impeller::ToStyle
static Paint::Style ToStyle(flutter::DlDrawStyle style)
Definition: dl_dispatcher.cc:155
impeller::FillType::kOdd
@ kOdd
impeller::DlRoundRect
flutter::DlRoundRect DlRoundRect
Definition: dl_dispatcher.h:27
impeller::ToOptRect
static std::optional< const Rect > ToOptRect(const flutter::DlRect *rect)
Definition: dl_dispatcher.cc:141
impeller::PointStyle
PointStyle
Definition: canvas.h:61
impeller::PointStyle::kRound
@ kRound
Points are drawn as squares.
impeller::PointStyle::kSquare
@ kSquare
Points are drawn as circles.
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::ToClipOperation
static Entity::ClipOperation ToClipOperation(flutter::DlClipOp clip_op)
Definition: dl_dispatcher.cc:429
impeller::RenderToTarget
bool RenderToTarget(ContentContext &context, RenderTarget render_target, const sk_sp< flutter::DisplayList > &display_list, SkIRect cull_rect, bool reset_host_buffer, bool is_onscreen)
Render the provided display list to the render target.
Definition: dl_dispatcher.cc:1360
impeller::Cap::kRound
@ kRound
impeller::Cap::kButt
@ kButt
impeller::Cap::kSquare
@ kSquare
impeller::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
impeller::DlRoundSuperellipse
flutter::DlRoundSuperellipse DlRoundSuperellipse
Definition: dl_dispatcher.h:28
impeller::RequiresReadbackForBlends
static bool RequiresReadbackForBlends(const ContentContext &renderer, flutter::DlBlendMode max_root_blend_mode)
Subclasses.
Definition: dl_dispatcher.cc:999
impeller::ToSamplerDescriptor
static impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlFilterMode options)
Definition: dl_dispatcher.cc:123
impeller::DlPath
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
impeller::ContentBoundsPromise::kMayClipContents
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
impeller::ContentBoundsPromise::kContainsContents
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
impeller::Size
TSize< Scalar > Size
Definition: size.h:159
impeller::MinMagFilter::kLinear
@ kLinear
impeller::MinMagFilter::kNearest
@ kNearest
Select nearest to the sample point. Most widely supported.
impeller::DlScalar
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23
impeller::ToBlurStyle
static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style)
Definition: dl_dispatcher.cc:258
nine_patch_converter.h
rect_geometry.h
round_rect_geometry.h
round_superellipse_geometry.h
scalar.h
sigma.h
skia_conversions.h
impeller::BackdropData
Definition: canvas.h:36
impeller::BackdropData::backdrop_count
size_t backdrop_count
Definition: canvas.h:37
impeller::Color
Definition: color.h:124
impeller::Color::blue
Scalar blue
Definition: color.h:138
impeller::Color::alpha
Scalar alpha
Definition: color.h:143
impeller::Color::WithAlpha
constexpr Color WithAlpha(Scalar new_alpha) const
Definition: color.h:278
impeller::Color::red
Scalar red
Definition: color.h:128
impeller::Color::green
Scalar green
Definition: color.h:133
impeller::Degrees
Definition: scalar.h:51
impeller::GlyphProperties
Definition: font_glyph_pair.h:17
impeller::GlyphProperties::color
Color color
Definition: font_glyph_pair.h:18
impeller::GlyphProperties::stroke_cap
Cap stroke_cap
Definition: font_glyph_pair.h:20
impeller::GlyphProperties::stroke_width
Scalar stroke_width
Definition: font_glyph_pair.h:19
impeller::GlyphProperties::stroke_join
Join stroke_join
Definition: font_glyph_pair.h:21
impeller::GlyphProperties::stroke_miter
Scalar stroke_miter
Definition: font_glyph_pair.h:22
impeller::GlyphProperties::stroke
bool stroke
Definition: font_glyph_pair.h:23
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::Matrix::Translate
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:263
impeller::Matrix::GetScale
constexpr Vector3 GetScale() const
Definition: matrix.h:341
impeller::Matrix::Invert
Matrix Invert() const
Definition: matrix.cc:97
impeller::Matrix::MakeColumn
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition: matrix.h:69
impeller::Matrix::MakeSkew
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
Definition: matrix.h:127
impeller::Matrix::Scale
constexpr Matrix Scale(const Vector3 &s) const
Definition: matrix.h:275
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:223
impeller::Matrix::HasPerspective
constexpr bool HasPerspective() const
Definition: matrix.h:365
impeller::Paint::MaskBlurDescriptor
Definition: paint.h:51
impeller::Paint::MaskBlurDescriptor::style
FilterContents::BlurStyle style
Definition: paint.h:52
impeller::Paint
Definition: paint.h:26
impeller::Paint::color_filter
const flutter::DlColorFilter * color_filter
Definition: paint.h:76
impeller::Paint::color_source
const flutter::DlColorSource * color_source
Definition: paint.h:75
impeller::Paint::Style
Style
Definition: paint.h:46
impeller::Paint::Style::kStroke
@ kStroke
impeller::Paint::Style::kFill
@ kFill
impeller::Paint::image_filter
const flutter::DlImageFilter * image_filter
Definition: paint.h:77
impeller::Paint::stroke_cap
Cap stroke_cap
Definition: paint.h:80
impeller::Paint::stroke_join
Join stroke_join
Definition: paint.h:81
impeller::Paint::stroke_miter
Scalar stroke_miter
Definition: paint.h:82
impeller::Paint::style
Style style
Definition: paint.h:83
impeller::Paint::invert_colors
bool invert_colors
Definition: paint.h:85
impeller::Paint::mask_blur_descriptor
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition: paint.h:87
impeller::Paint::color
Color color
Definition: paint.h:74
impeller::Paint::blend_mode
BlendMode blend_mode
Definition: paint.h:84
impeller::Paint::stroke_width
Scalar stroke_width
Definition: paint.h:79
impeller::RSTransform
Definition: rstransform.h:20
impeller::Radius
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition: sigma.h:48
impeller::SamplerDescriptor
Definition: sampler_descriptor.h:14
impeller::SamplerDescriptor::mag_filter
MinMagFilter mag_filter
Definition: sampler_descriptor.h:16
impeller::SamplerDescriptor::label
std::string_view label
Definition: sampler_descriptor.h:23
impeller::SamplerDescriptor::min_filter
MinMagFilter min_filter
Definition: sampler_descriptor.h:15
impeller::Sigma
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
impeller::TPoint< Scalar >
impeller::TRect< Scalar >
impeller::TRect::GetBottom
constexpr auto GetBottom() const
Definition: rect.h:361
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:476
impeller::TRect::GetTop
constexpr auto GetTop() const
Definition: rect.h:357
impeller::TRect::IsMaximum
constexpr bool IsMaximum() const
Definition: rect.h:318
impeller::TRect::IsEmpty
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: rect.h:301
impeller::TRect::GetLeft
constexpr auto GetLeft() const
Definition: rect.h:355
impeller::TRect::RoundOut
RoundOut(const TRect< U > &r)
Definition: rect.h:683
impeller::TRect::GetRight
constexpr auto GetRight() const
Definition: rect.h:359
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::TRect< Scalar >::MakeMaximum
constexpr static TRect MakeMaximum()
Definition: rect.h:188
impeller::TSize
Definition: size.h:25
impeller::TSize::height
Type height
Definition: size.h:29
impeller::TSize::width
Type width
Definition: size.h:28
impeller::TSize::MipCount
constexpr size_t MipCount() const
Return the mip count of the texture.
Definition: size.h:137
impeller::Vector3
Definition: vector.h:20
impeller::Vector3::y
Scalar y
Definition: vector.h:24
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67