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