123 {
125 switch (options) {
128 desc.
label =
"Nearest Sampler";
129 break;
132 desc.
label =
"Linear Sampler";
133 break;
134 default:
135 break;
136 }
137 return desc;
138}
139
141 if (rect == nullptr) {
142 return std::nullopt;
143 }
144 return *rect;
145}
146
147
148void DlDispatcherBase::setAntiAlias(bool aa) {
150
151 paint_.anti_alias = aa;
152}
153
155 switch (style) {
157 return Paint::Style::kFill;
159 return Paint::Style::kStroke;
162 break;
163 }
164 return Paint::Style::kFill;
165}
166
167
170
172}
173
174
177
178 paint_.color = skia_conversions::ToColor(color);
179}
180
181
182void DlDispatcherBase::setStrokeWidth(DlScalar
width) {
184
185 paint_.stroke.width =
width;
186}
187
188
189void DlDispatcherBase::setStrokeMiter(DlScalar limit) {
191
192 paint_.stroke.miter_limit = limit;
193}
194
195
198
199 switch (cap) {
201 paint_.stroke.cap = Cap::kButt;
202 break;
204 paint_.stroke.cap = Cap::kRound;
205 break;
207 paint_.stroke.cap = Cap::kSquare;
208 break;
209 }
210}
211
212
215
216 switch (join) {
218 paint_.stroke.join = Join::kMiter;
219 break;
221 paint_.stroke.join = Join::kRound;
222 break;
224 paint_.stroke.join = Join::kBevel;
225 break;
226 }
227}
228
229
232
233 paint_.color_source = source;
234}
235
236
239
240 paint_.color_filter = filter;
241}
242
243
244void DlDispatcherBase::setInvertColors(bool invert) {
246
247 paint_.invert_colors = invert;
248}
249
250
253
254 paint_.blend_mode = dl_mode;
255}
256
258 switch (blur_style) {
260 return FilterContents::BlurStyle::kNormal;
262 return FilterContents::BlurStyle::kSolid;
264 return FilterContents::BlurStyle::kOuter;
266 return FilterContents::BlurStyle::kInner;
267 }
268}
269
270
273
274
275 if (filter == nullptr) {
276 paint_.mask_blur_descriptor = std::nullopt;
277 return;
278 }
279 switch (filter->
type()) {
281 auto blur = filter->
asBlur();
282
283 paint_.mask_blur_descriptor = {
285 .sigma = Sigma(blur->sigma()),
286 .respect_ctm = blur->respectCTM(),
287 };
288 break;
289 }
290 }
291}
292
293
296
297 paint_.image_filter = filter;
298}
299
300
301void DlDispatcherBase::save(uint32_t total_content_depth) {
303
304 GetCanvas().Save(total_content_depth);
305}
306
307
308void DlDispatcherBase::saveLayer(const DlRect& bounds,
310 uint32_t total_content_depth,
313 std::optional<int64_t> backdrop_id) {
315
318 ? ContentBoundsPromise::kMayClipContents
319 : ContentBoundsPromise::kContainsContents;
320 std::optional<Rect> impeller_bounds;
321
322
324 impeller_bounds = bounds;
325 }
326
327 GetCanvas().SaveLayer(
328 paint, impeller_bounds, backdrop, promise, total_content_depth,
329
330
332 backdrop_id
333 );
334}
335
336
337void DlDispatcherBase::restore() {
338 GetCanvas().Restore();
339}
340
341
342void DlDispatcherBase::translate(DlScalar tx, DlScalar ty) {
344
345 GetCanvas().Translate({tx, ty, 0.0});
346}
347
348
349void DlDispatcherBase::scale(DlScalar sx, DlScalar sy) {
351
352 GetCanvas().Scale({sx, sy, 1.0});
353}
354
355
356void DlDispatcherBase::rotate(DlScalar degrees) {
358
359 GetCanvas().Rotate(Degrees{degrees});
360}
361
362
363void DlDispatcherBase::skew(DlScalar sx, DlScalar sy) {
365
366 GetCanvas().Skew(sx, sy);
367}
368
369
370
371void DlDispatcherBase::transform2DAffine(
372 DlScalar mxx, DlScalar mxy, DlScalar mxt,
373 DlScalar myx, DlScalar myy, DlScalar myt) {
375
376 transformFullPerspective(
377 mxx, mxy, 0, mxt,
378 myx, myy, 0, myt,
379 0 , 0, 1, 0,
380 0 , 0, 0, 1
381 );
382}
383
384
385
386
387void DlDispatcherBase::transformFullPerspective(
388 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
389 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
390 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
391 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
393
394
395
397 mxx, myx, mzx, mwx,
398 mxy, myy, mzy, mwy,
399 mxz, myz, mzz, mwz,
400 mxt, myt, mzt, mwt
401 };
403}
404
405
406
407void DlDispatcherBase::transformReset() {
409
410 GetCanvas().ResetTransform();
411 GetCanvas().Transform(initial_matrix_);
412}
413
415 switch (clip_op) {
417 return Entity::ClipOperation::kDifference;
419 return Entity::ClipOperation::kIntersect;
420 }
421}
422
423
424void DlDispatcherBase::clipRect(const DlRect& rect,
426 bool is_aa) {
428
429 FillRectGeometry geom(rect);
431}
432
433
434void DlDispatcherBase::clipOval(const DlRect& bounds,
436 bool is_aa) {
438
439 EllipseGeometry geom(bounds);
441}
442
443
444void DlDispatcherBase::clipRoundRect(const DlRoundRect& rrect,
446 bool is_aa) {
448
450 if (rrect.IsRect()) {
451 FillRectGeometry geom(rrect.GetBounds());
452 GetCanvas().ClipGeometry(geom, clip_op, is_aa);
453 } else if (rrect.IsOval()) {
454 EllipseGeometry geom(rrect.GetBounds());
455 GetCanvas().ClipGeometry(geom, clip_op);
456 } else if (rrect.GetRadii().AreAllCornersSame()) {
457 RoundRectGeometry geom(rrect.GetBounds(), rrect.GetRadii().top_left);
458 GetCanvas().ClipGeometry(geom, clip_op);
459 } else {
460 FillRoundRectGeometry geom(rrect);
461 GetCanvas().ClipGeometry(geom, clip_op);
462 }
463}
464
465
466void DlDispatcherBase::clipRoundSuperellipse(const DlRoundSuperellipse& rse,
468 bool is_aa) {
470
472 if (rse.IsRect()) {
473 FillRectGeometry geom(rse.GetBounds());
474 GetCanvas().ClipGeometry(geom, clip_op, is_aa);
475 } else if (rse.IsOval()) {
476 EllipseGeometry geom(rse.GetBounds());
477 GetCanvas().ClipGeometry(geom, clip_op);
478 } else {
479 RoundSuperellipseGeometry geom(rse.GetBounds(), rse.GetRadii());
480 GetCanvas().ClipGeometry(geom, clip_op);
481 }
482}
483
484
485void DlDispatcherBase::clipPath(const DlPath& path,
487 bool is_aa) {
489
491
493 if (
path.IsRect(&rect)) {
494 FillRectGeometry geom(rect);
495 GetCanvas().ClipGeometry(geom, clip_op, is_aa);
496 }
else if (
path.IsOval(&rect)) {
497 EllipseGeometry geom(rect);
498 GetCanvas().ClipGeometry(geom, clip_op);
499 } else {
501 if (
path.IsRoundRect(&rrect) && rrect.GetRadii().AreAllCornersSame()) {
502 RoundRectGeometry geom(rrect.GetBounds(), rrect.GetRadii().top_left);
503 GetCanvas().ClipGeometry(geom, clip_op);
504 } else {
505 FillPathGeometry geom(path);
506 GetCanvas().ClipGeometry(geom, clip_op);
507 }
508 }
509}
510
511
515
516 Paint paint;
517 paint.color = skia_conversions::ToColor(color);
518 paint.blend_mode = dl_mode;
519 GetCanvas().DrawPaint(paint);
520}
521
522
523void DlDispatcherBase::drawPaint() {
525
526 GetCanvas().DrawPaint(paint_);
527}
528
529
530void DlDispatcherBase::drawLine(
const DlPoint& p0,
const DlPoint&
p1) {
532
533 GetCanvas().DrawLine(p0,
p1, paint_);
534}
535
536
537void DlDispatcherBase::drawDashedLine(const DlPoint& p0,
539 DlScalar on_length,
540 DlScalar off_length) {
542
543 GetCanvas().DrawDashedLine(p0,
p1, on_length, off_length, paint_);
544}
545
546
547void DlDispatcherBase::drawRect(const DlRect& rect) {
549
550 GetCanvas().DrawRect(rect, paint_);
551}
552
553
554void DlDispatcherBase::drawOval(const DlRect& bounds) {
556
557 GetCanvas().DrawOval(bounds, paint_);
558}
559
560
561void DlDispatcherBase::drawCircle(const DlPoint& center, DlScalar radius) {
563
564 GetCanvas().DrawCircle(center, radius, paint_);
565}
566
567
568void DlDispatcherBase::drawRoundRect(const DlRoundRect& rrect) {
570
571 GetCanvas().DrawRoundRect(rrect, paint_);
572}
573
574
575void DlDispatcherBase::drawDiffRoundRect(const DlRoundRect& outer,
576 const DlRoundRect& inner) {
578
579 GetCanvas().DrawDiffRoundRect(outer, inner, paint_);
580}
581
582
583void DlDispatcherBase::drawRoundSuperellipse(const DlRoundSuperellipse& rse) {
585
586 GetCanvas().DrawRoundSuperellipse(rse, paint_);
587}
588
589
590void DlDispatcherBase::drawPath(const DlPath& path) {
592
593 GetCanvas().DrawPath(path, paint_);
594}
595
596void DlDispatcherBase::SimplifyOrDrawPath(Canvas& canvas,
597 const DlPath& path,
598 const Paint& paint) {
600
601
602 bool closed;
603 if (
path.IsRect(&rect, &closed) && closed) {
604 canvas.DrawRect(rect, paint);
605 return;
606 }
607
609 if (
path.IsRoundRect(&rrect) && rrect.GetRadii().AreAllCornersSame()) {
610 canvas.DrawRoundRect(rrect, paint);
611 return;
612 }
613
614 if (
path.IsOval(&rect)) {
615 canvas.DrawOval(rect, paint);
616 return;
617 }
618
621 if (
path.IsLine(&start, &
end)) {
622 canvas.DrawLine(start,
end, paint);
623 return;
624 }
625
626 canvas.DrawPath(path, paint);
627}
628
629
630void DlDispatcherBase::drawArc(const DlRect& oval_bounds,
631 DlScalar start_degrees,
632 DlScalar sweep_degrees,
635
636 GetCanvas().DrawArc(Arc(oval_bounds, Degrees(start_degrees),
638 paint_);
639}
640
641
643 uint32_t count,
646
647 Paint paint = paint_;
648 paint.style = Paint::Style::kStroke;
649 switch (mode) {
651
652 PointStyle point_style = paint.stroke.cap == Cap::kRound
653 ? PointStyle::kRound
654 : PointStyle::kSquare;
655 Scalar radius = paint.stroke.width;
656 if (radius > 0) {
657 radius /= 2.0;
658 }
659 GetCanvas().DrawPoints(
points, count, radius, paint, point_style);
660 } break;
662 for (uint32_t
i = 1;
i < count;
i += 2) {
665 GetCanvas().DrawLine(p0,
p1, paint,
i > 1);
666 }
667 break;
669 if (count > 1) {
671 for (uint32_t
i = 1;
i < count;
i++) {
673 GetCanvas().DrawLine(p0,
p1, paint,
i > 1);
675 }
676 }
677 break;
678 }
679}
680
681std::shared_ptr<Texture> DlDispatcherBase::GetTexture(
682 const sk_sp<flutter::DlImage>&
image) {
684 return nullptr;
685 }
686 return image->asImpellerImage()->GetCachedTexture(GetContentContext());
687}
688
689void DlDispatcherBase::drawVertices(
690 const std::shared_ptr<flutter::DlVertices>& vertices,
692
693
694void DlDispatcherBase::drawImage(
const sk_sp<flutter::DlImage>
image,
695 const DlPoint& point,
697 bool render_with_attributes) {
699
701 return;
702 }
703
706 return;
707 }
708
710 const auto src = DlRect::MakeWH(
size.width,
size.height);
711 const auto dest = DlRect::MakeXYWH(point.x, point.y,
size.width,
size.height);
712
714 src,
715 dest,
716 sampling,
717 render_with_attributes,
719 );
720}
721
722
723void DlDispatcherBase::drawImageRect(
const sk_sp<flutter::DlImage>
image,
724 const DlRect& src,
725 const DlRect& dst,
727 bool render_with_attributes,
731
732 GetCanvas().DrawImageRect(
734 src,
735 dst,
736 render_with_attributes ? paint_ : Paint(),
738 );
739}
740
741
742void DlDispatcherBase::drawImageNine(
const sk_sp<flutter::DlImage>
image,
743 const DlIRect& center,
744 const DlRect& dst,
746 bool render_with_attributes) {
748
749 NinePatchConverter converter = {};
750 converter.DrawNinePatch(GetTexture(
image),
754 &paint_);
755}
756
757
758void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
759 const RSTransform xform[],
760 const DlRect tex[],
762 int count,
765 const DlRect* cull_rect,
766 bool render_with_attributes) {
768
769 auto geometry =
770 DlAtlasGeometry(GetTexture(atlas),
771 xform,
772 tex,
773 colors,
774 static_cast<size_t>(count),
775 mode,
776 skia_conversions::ToSamplerDescriptor(sampling),
778 );
779 auto atlas_contents = std::make_shared<AtlasContents>();
780 atlas_contents->SetGeometry(&geometry);
781
782 GetCanvas().DrawAtlas(atlas_contents, paint_);
783}
784
785
786void DlDispatcherBase::drawDisplayList(
787 const sk_sp<flutter::DisplayList> display_list,
788 DlScalar opacity) {
790
791
792 Paint saved_paint = paint_;
793 Matrix saved_initial_matrix = initial_matrix_;
794
795
796
797
798
799 initial_matrix_ = GetCanvas().GetCurrentTransform();
800 paint_ = Paint();
801
802
803
804
805
806
807 int restore_count = GetCanvas().GetSaveCount();
808 if (opacity < SK_Scalar1) {
809 Paint save_paint;
810 save_paint.color = Color(0, 0, 0, opacity);
811 GetCanvas().SaveLayer(save_paint, display_list->GetBounds(), nullptr,
812 ContentBoundsPromise::kContainsContents,
813 display_list->total_depth(),
814 display_list->can_apply_group_opacity());
815 } else {
816
817
818 GetCanvas().Save(display_list->total_depth());
819 }
820
821
822
823 if (display_list->has_rtree() && !initial_matrix_.HasPerspective()) {
824
825
826
827
828
829 auto global_culling_bounds = GetCanvas().GetLocalCoverageLimit();
830 if (global_culling_bounds.has_value()) {
832 GetCanvas().GetCurrentTransform().Invert());
833 display_list->Dispatch(*this, cull_rect);
834 } else {
835
836
837 }
838 } else {
839 display_list->Dispatch(*this);
840 }
841
842
843
845 GetCanvas().RestoreToCount(restore_count);
846 initial_matrix_ = saved_initial_matrix;
847 paint_ = saved_paint;
848}
849
850
851void DlDispatcherBase::drawText(
const std::shared_ptr<flutter::DlText>&
text,
855
856 auto text_frame =
text->GetTextFrame();
857
858
859
861 GetCanvas().DrawTextFrame(text_frame,
863 paint_
864 );
865}
866
867
868void DlDispatcherBase::drawShadow(const DlPath& path,
870 const DlScalar elevation,
871 bool transparent_occluder,
872 DlScalar dpr) {
874
875 Color spot_color = skia_conversions::ToColor(color);
876 spot_color.alpha *= 0.25;
877
878
879 {
881 std::max(std::max(spot_color.red, spot_color.green), spot_color.blue);
883 std::min(std::min(spot_color.red, spot_color.green), spot_color.blue);
884 Scalar luminance = (min + max) * 0.5;
885
887 (2.6f + (-2.66667f + 1.06667f * spot_color.alpha) * spot_color.alpha) *
888 spot_color.alpha;
890 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
891 luminance;
892 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
893
895 std::clamp(spot_color.alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
896
897 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
898 Scalar tonal_alpha = color_scale + greyscale_alpha;
899 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
900 spot_color = Color(unpremul_scale * spot_color.red,
901 unpremul_scale * spot_color.green,
902 unpremul_scale * spot_color.blue, tonal_alpha);
903 }
904
905 Vector3 light_position(0, -1, 1);
906 Scalar occluder_z = dpr * elevation;
907
908 constexpr Scalar kLightRadius = 800 / 600;
909
910 Paint paint;
911 paint.style = Paint::Style::kFill;
912 paint.color = spot_color;
913 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
914 .style = FilterContents::BlurStyle::kNormal,
915 .sigma = Radius{kLightRadius * occluder_z /
916 GetCanvas().GetCurrentTransform().GetScale().y},
917 };
918
919 GetCanvas().Save(1u);
920 GetCanvas().PreConcat(
921 Matrix::MakeTranslation(
Vector2(0, -occluder_z * light_position.y)));
922
923 SimplifyOrDrawPath(GetCanvas(), path, paint);
925
926 GetCanvas().Restore();
927}
928
929
930
932 const ContentContext& renderer,
934 return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() &&
935 max_root_blend_mode > Entity::kLastPipelineBlendMode;
936}
937
938CanvasDlDispatcher::CanvasDlDispatcher(ContentContext& renderer,
939 RenderTarget& render_target,
940 bool is_onscreen,
941 bool has_root_backdrop_filter,
943 IRect32 cull_rect)
944 : DlDispatcherBase(),
945 canvas_(renderer,
946 render_target,
947 is_onscreen,
948 has_root_backdrop_filter ||
950 cull_rect),
951 renderer_(renderer) {}
952
953Canvas& CanvasDlDispatcher::GetCanvas() {
954 return canvas_;
955}
956
957const ContentContext& CanvasDlDispatcher::GetContentContext() const {
958 return renderer_;
959}
960
961void CanvasDlDispatcher::drawVertices(
962 const std::shared_ptr<flutter::DlVertices>& vertices,
965
966 GetCanvas().DrawVertices(
967 std::make_shared<DlVerticesGeometry>(vertices, renderer_), dl_mode,
968 paint_);
969}
970
971void CanvasDlDispatcher::SetBackdropData(
972 std::unordered_map<int64_t, BackdropData> backdrop,
973 size_t backdrop_count) {
974 GetCanvas().SetBackdropData(std::move(backdrop), backdrop_count);
975}
976
977
978
979FirstPassDispatcher::FirstPassDispatcher(const ContentContext& renderer,
980 const Matrix& initial_matrix,
981 const Rect cull_rect)
982 : renderer_(renderer), matrix_(initial_matrix) {
983 cull_rect_state_.push_back(cull_rect);
984}
985
986FirstPassDispatcher::~FirstPassDispatcher() {
988}
989
990void FirstPassDispatcher::save() {
991 stack_.emplace_back(matrix_);
992 cull_rect_state_.push_back(cull_rect_state_.back());
993}
994
995void FirstPassDispatcher::saveLayer(const DlRect& bounds,
998 std::optional<int64_t> backdrop_id) {
999 save();
1000
1001 backdrop_count_ += (backdrop == nullptr ? 0 : 1);
1002 if (backdrop != nullptr && backdrop_id.has_value()) {
1003 std::shared_ptr<flutter::DlImageFilter> shared_backdrop =
1005 std::unordered_map<int64_t, BackdropData>::iterator existing =
1006 backdrop_data_.find(backdrop_id.value());
1007 if (existing == backdrop_data_.end()) {
1008 backdrop_data_[backdrop_id.value()] =
1009 BackdropData{.backdrop_count = 1, .last_backdrop = shared_backdrop};
1010 } else {
1011 BackdropData&
data = existing->second;
1012 data.backdrop_count++;
1013 if (
data.all_filters_equal) {
1014 data.all_filters_equal = (*
data.last_backdrop == *shared_backdrop);
1015 data.last_backdrop = shared_backdrop;
1016 }
1017 }
1018 }
1019
1020
1021
1022 auto global_cull_rect = cull_rect_state_.back();
1023 if (has_image_filter_ || global_cull_rect.IsMaximum()) {
1024 cull_rect_state_.back() = Rect::MakeMaximum();
1025 } else {
1026 auto global_save_bounds = bounds.TransformBounds(matrix_);
1027 auto new_cull_rect = global_cull_rect.Intersection(global_save_bounds);
1028 if (new_cull_rect.has_value()) {
1029 cull_rect_state_.back() = new_cull_rect.value();
1030 } else {
1031 cull_rect_state_.back() = Rect::MakeLTRB(0, 0, 0, 0);
1032 }
1033 }
1034}
1035
1036void FirstPassDispatcher::restore() {
1037 matrix_ = stack_.back();
1038 stack_.pop_back();
1039 cull_rect_state_.pop_back();
1040}
1041
1042void FirstPassDispatcher::translate(DlScalar tx, DlScalar ty) {
1043 matrix_ = matrix_.Translate({tx, ty});
1044}
1045
1046void FirstPassDispatcher::scale(DlScalar sx, DlScalar sy) {
1047 matrix_ = matrix_.Scale({sx, sy, 1.0f});
1048}
1049
1050void FirstPassDispatcher::rotate(DlScalar degrees) {
1051 matrix_ = matrix_ * Matrix::MakeRotationZ(Degrees(degrees));
1052}
1053
1054void FirstPassDispatcher::skew(DlScalar sx, DlScalar sy) {
1055 matrix_ = matrix_ * Matrix::MakeSkew(sx, sy);
1056}
1057
1058
1059
1060void FirstPassDispatcher::transform2DAffine(
1061 DlScalar mxx, DlScalar mxy, DlScalar mxt,
1062 DlScalar myx, DlScalar myy, DlScalar myt) {
1063 matrix_ = matrix_ * Matrix::MakeColumn(
1064 mxx, myx, 0.0f, 0.0f,
1065 mxy, myy, 0.0f, 0.0f,
1066 0.0f, 0.0f, 1.0f, 0.0f,
1067 mxt, myt, 0.0f, 1.0f
1068 );
1069}
1070
1071
1072
1073
1074void FirstPassDispatcher::transformFullPerspective(
1075 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
1076 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
1077 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
1078 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
1079 matrix_ = matrix_ * Matrix::MakeColumn(
1080 mxx, myx, mzx, mwx,
1081 mxy, myy, mzy, mwy,
1082 mxz, myz, mzz, mwz,
1083 mxt, myt, mzt, mwt
1084 );
1085}
1086
1087
1088void FirstPassDispatcher::transformReset() {
1089 matrix_ = Matrix();
1090}
1091
1092void FirstPassDispatcher::drawText(
const std::shared_ptr<flutter::DlText>&
text,
1095 GlyphProperties properties;
1096 auto text_frame =
text->GetTextFrame();
1097 if (text_frame == nullptr) {
1098 return;
1099 }
1100
1101 properties.stroke = paint_.GetStroke();
1102
1103 if (text_frame->HasColor()) {
1104
1105
1106 properties.tone_or_color = paint_.color.WithAlpha(1.0);
1107 } else {
1108 properties.tone_or_color = GlyphProperties::ComputeTone(paint_.color);
1109 }
1110
1111 renderer_.GetLazyGlyphAtlas()->AddTextFrame(text_frame,
1113 matrix_,
1114 properties
1115 );
1116}
1117
1118const Rect FirstPassDispatcher::GetCurrentLocalCullingBounds()
const {
1119 auto cull_rect = cull_rect_state_.back();
1120 if (!cull_rect.IsEmpty() && !cull_rect.IsMaximum()) {
1121 Matrix inverse = matrix_.Invert();
1123 }
1124 return cull_rect;
1125}
1126
1127void FirstPassDispatcher::drawDisplayList(
1128 const sk_sp<flutter::DisplayList> display_list,
1129 DlScalar opacity) {
1130 [[maybe_unused]] size_t stack_depth = stack_.size();
1131 save();
1132 Paint old_paint = paint_;
1133 paint_ = Paint{};
1134 bool old_has_image_filter = has_image_filter_;
1135 has_image_filter_ = false;
1136
1137 if (matrix_.HasPerspective()) {
1138 display_list->Dispatch(*this);
1139 } else {
1140 Rect local_cull_bounds = GetCurrentLocalCullingBounds();
1141 if (local_cull_bounds.IsMaximum()) {
1142 display_list->Dispatch(*this);
1143 } else if (!local_cull_bounds.IsEmpty()) {
1144 DlIRect cull_rect = DlIRect::RoundOut(local_cull_bounds);
1145 display_list->Dispatch(*this, cull_rect);
1146 }
1147 }
1148
1149 restore();
1150 paint_ = old_paint;
1151 has_image_filter_ = old_has_image_filter;
1153}
1154
1155
1157 paint_.style =
ToStyle(style);
1158}
1159
1160
1162 paint_.color = skia_conversions::ToColor(color);
1163}
1164
1165
1166void FirstPassDispatcher::setStrokeWidth(DlScalar
width) {
1167 paint_.stroke.width =
width;
1168}
1169
1170
1171void FirstPassDispatcher::setStrokeMiter(DlScalar limit) {
1172 paint_.stroke.miter_limit = limit;
1173}
1174
1175
1177 switch (cap) {
1179 paint_.stroke.cap = Cap::kButt;
1180 break;
1182 paint_.stroke.cap = Cap::kRound;
1183 break;
1185 paint_.stroke.cap = Cap::kSquare;
1186 break;
1187 }
1188}
1189
1190
1192 switch (join) {
1194 paint_.stroke.join = Join::kMiter;
1195 break;
1197 paint_.stroke.join = Join::kRound;
1198 break;
1200 paint_.stroke.join = Join::kBevel;
1201 break;
1202 }
1203}
1204
1205
1207 if (filter == nullptr) {
1208 has_image_filter_ = false;
1209 } else {
1210 has_image_filter_ = true;
1211 }
1212}
1213
1214namespace {
1215bool PixelFormatSupportsMSAA(std::optional<PixelFormat> pixel_format) {
1216 return !pixel_format.has_value();
1217}
1218}
1219
1220std::pair<std::unordered_map<int64_t, BackdropData>, size_t>
1221FirstPassDispatcher::TakeBackdropData() {
1222 std::unordered_map<int64_t, BackdropData> temp;
1223 std::swap(temp, backdrop_data_);
1224 return std::make_pair(temp, backdrop_count_);
1225}
1226
1228 const sk_sp<flutter::DisplayList>& display_list,
1229 ISize size,
1230 AiksContext& context,
1231 bool reset_host_buffer,
1232 bool generate_mips,
1233 std::optional<PixelFormat> target_pixel_format) {
1234 int mip_count = 1;
1235 if (generate_mips) {
1236 mip_count =
size.MipCount();
1237 }
1238
1239
1242 context.GetContext()->GetResourceAllocator());
1244 if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA() &&
1245 PixelFormatSupportsMSAA(target_pixel_format)) {
1247 *context.GetContext(),
1248 size,
1249 mip_count,
1250 "Picture Snapshot MSAA",
1252 kDefaultColorAttachmentConfigMSAA,
1254 nullptr,
1255 nullptr,
1256 nullptr,
1257 target_pixel_format
1258 );
1259 } else {
1261 *context.GetContext(),
1262 size,
1263 mip_count,
1264 "Picture Snapshot",
1266 kDefaultColorAttachmentConfig,
1268 nullptr,
1269 nullptr,
1270 target_pixel_format
1271 );
1272 }
1274 return nullptr;
1275 }
1276
1280 display_list->Dispatch(collector, cull_rect);
1282 context.GetContentContext(),
1284 false,
1285 display_list->root_has_backdrop_filter(),
1286 display_list->max_root_blend_mode(),
1288 );
1289 const auto& [
data, count] = collector.TakeBackdropData();
1290 impeller_dispatcher.SetBackdropData(data, count);
1291 context.GetContentContext().GetTextShadowCache().MarkFrameStart();
1293 if (reset_host_buffer) {
1294 context.GetContentContext().GetTransientsDataBuffer().
Reset();
1295 context.GetContentContext().GetTransientsIndexesBuffer().
Reset();
1296 }
1297 context.GetContentContext().GetTextShadowCache().MarkFrameEnd();
1298 context.GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames();
1299 context.GetContext()->DisposeThreadLocalCachedResources();
1300 });
1301
1302 display_list->Dispatch(impeller_dispatcher, cull_rect);
1303 impeller_dispatcher.FinishRecording();
1304
1305 return target.GetRenderTargetTexture();
1306}
1307
1309 RenderTarget render_target,
1310 const sk_sp<flutter::DisplayList>& display_list,
1311 Rect cull_rect,
1312 bool reset_host_buffer,
1313 bool is_onscreen) {
1315 display_list->Dispatch(collector, cull_rect);
1316
1318 context,
1319 render_target,
1320 is_onscreen,
1321 display_list->root_has_backdrop_filter(),
1322 display_list->max_root_blend_mode(),
1323 IRect32::RoundOut(cull_rect)
1324 );
1325 const auto& [
data, count] = collector.TakeBackdropData();
1326 impeller_dispatcher.SetBackdropData(data, count);
1327 context.GetTextShadowCache().MarkFrameStart();
1329 if (reset_host_buffer) {
1330 context.ResetTransientsBuffers();
1331 }
1332 context.GetTextShadowCache().MarkFrameEnd();
1333 });
1334
1335 display_list->Dispatch(impeller_dispatcher, cull_rect);
1336 impeller_dispatcher.FinishRecording();
1337 context.GetLazyGlyphAtlas()->ResetTextFrames();
1338
1339 return true;
1340}
1341
1342}
virtual T type() const =0
virtual std::shared_ptr< D > shared() const =0
DlBlurStyle style() const
virtual const DlBlurMaskFilter * asBlur() const
bool content_is_clipped() const
bool renders_with_attributes() const
bool bounds_from_caller() const
bool content_is_unbounded() const
bool can_distribute_opacity() const
Wraps a closure that is invoked in the destructor unless released by the caller.
a wrapper around the impeller [Allocator] instance that can be used to provide caching of allocated r...
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, std::optional< PixelFormat > target_pixel_format=std::nullopt)
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, std::optional< PixelFormat > target_pixel_format=std::nullopt)
#define AUTO_DEPTH_WATCHER(d)
#define AUTO_DEPTH_CHECK()
FlutterVulkanImage * image
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
@ kMiter
extends to miter limit
@ kBevel
connects outside edges
impeller::RoundRect DlRoundRect
@ kButt
no stroke extension
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
@ kLines
draw each separate pair of points as a line segment
@ kPolygon
draw each pair of overlapping points as a line segment
@ kPoints
draw each point separately
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
@ kStrokeAndFill
both strokes and fills shapes
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
impeller::IRect32 DlIRect
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
@ kNormal
fuzzy inside and outside
@ kOuter
nothing inside, fuzzy outside
@ kInner
fuzzy inside, nothing outside
@ kSolid
solid inside, fuzzy outside
void Reset(SkPathBuilder *path)
static Paint::Style ToStyle(flutter::DlDrawStyle style)
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips, std::optional< PixelFormat > target_pixel_format)
Render the provided display list to a texture with the given size.
static std::optional< const Rect > ToOptRect(const flutter::DlRect *rect)
static Entity::ClipOperation ToClipOperation(flutter::DlClipOp clip_op)
static bool RequiresReadbackForBlends(const ContentContext &renderer, flutter::DlBlendMode max_root_blend_mode)
Subclasses.
static impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlFilterMode options)
bool RenderToTarget(ContentContext &context, RenderTarget render_target, const sk_sp< flutter::DisplayList > &display_list, Rect cull_rect, bool reset_host_buffer, bool is_onscreen)
Render the provided display list to the render target.
@ kNearest
Select nearest to the sample point. Most widely supported.
static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style)
A 4x4 matrix using column-major storage.
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
static constexpr TRect MakeSize(const TSize< U > &size)
std::vector< Point > points