122 {
124 switch (options) {
127 desc.
label =
"Nearest Sampler";
128 break;
131 desc.
label =
"Linear Sampler";
132 break;
133 default:
134 break;
135 }
136 return desc;
137}
138
140 if (rect == nullptr) {
141 return std::nullopt;
142 }
143 return *rect;
144}
145
146
147void DlDispatcherBase::setAntiAlias(bool aa) {
149
150
151}
152
154 switch (style) {
156 return Paint::Style::kFill;
158 return Paint::Style::kStroke;
161 break;
162 }
163 return Paint::Style::kFill;
164}
165
166
169
171}
172
173
176
177 paint_.color = skia_conversions::ToColor(color);
178}
179
180
181void DlDispatcherBase::setStrokeWidth(DlScalar
width) {
183
184 paint_.stroke.width =
width;
185}
186
187
188void DlDispatcherBase::setStrokeMiter(DlScalar limit) {
190
191 paint_.stroke.miter_limit = limit;
192}
193
194
197
198 switch (cap) {
200 paint_.stroke.cap = Cap::kButt;
201 break;
203 paint_.stroke.cap = Cap::kRound;
204 break;
206 paint_.stroke.cap = Cap::kSquare;
207 break;
208 }
209}
210
211
214
215 switch (join) {
217 paint_.stroke.join = Join::kMiter;
218 break;
220 paint_.stroke.join = Join::kRound;
221 break;
223 paint_.stroke.join = Join::kBevel;
224 break;
225 }
226}
227
228
231
232 paint_.color_source = source;
233}
234
235
238
239 paint_.color_filter = filter;
240}
241
242
243void DlDispatcherBase::setInvertColors(bool invert) {
245
246 paint_.invert_colors = invert;
247}
248
249
252
253 paint_.blend_mode = dl_mode;
254}
255
257 switch (blur_style) {
259 return FilterContents::BlurStyle::kNormal;
261 return FilterContents::BlurStyle::kSolid;
263 return FilterContents::BlurStyle::kOuter;
265 return FilterContents::BlurStyle::kInner;
266 }
267}
268
269
272
273
274 if (filter == nullptr) {
275 paint_.mask_blur_descriptor = std::nullopt;
276 return;
277 }
278 switch (filter->
type()) {
280 auto blur = filter->
asBlur();
281
282 paint_.mask_blur_descriptor = {
284 .sigma = Sigma(blur->sigma()),
285 .respect_ctm = blur->respectCTM(),
286 };
287 break;
288 }
289 }
290}
291
292
295
296 paint_.image_filter = filter;
297}
298
299
300void DlDispatcherBase::save(uint32_t total_content_depth) {
302
303 GetCanvas().Save(total_content_depth);
304}
305
306
307void DlDispatcherBase::saveLayer(const DlRect& bounds,
309 uint32_t total_content_depth,
312 std::optional<int64_t> backdrop_id) {
314
317 ? ContentBoundsPromise::kMayClipContents
318 : ContentBoundsPromise::kContainsContents;
319 std::optional<Rect> impeller_bounds;
320
321
323 impeller_bounds = bounds;
324 }
325
326 GetCanvas().SaveLayer(
327 paint, impeller_bounds, backdrop, promise, total_content_depth,
328
329
331 backdrop_id
332 );
333}
334
335
336void DlDispatcherBase::restore() {
337 GetCanvas().Restore();
338}
339
340
341void DlDispatcherBase::translate(DlScalar tx, DlScalar ty) {
343
344 GetCanvas().Translate({tx, ty, 0.0});
345}
346
347
348void DlDispatcherBase::scale(DlScalar sx, DlScalar sy) {
350
351 GetCanvas().Scale({sx, sy, 1.0});
352}
353
354
355void DlDispatcherBase::rotate(DlScalar degrees) {
357
358 GetCanvas().Rotate(Degrees{degrees});
359}
360
361
362void DlDispatcherBase::skew(DlScalar sx, DlScalar sy) {
364
365 GetCanvas().Skew(sx, sy);
366}
367
368
369
370void DlDispatcherBase::transform2DAffine(
371 DlScalar mxx, DlScalar mxy, DlScalar mxt,
372 DlScalar myx, DlScalar myy, DlScalar myt) {
374
375 transformFullPerspective(
376 mxx, mxy, 0, mxt,
377 myx, myy, 0, myt,
378 0 , 0, 1, 0,
379 0 , 0, 0, 1
380 );
381}
382
383
384
385
386void DlDispatcherBase::transformFullPerspective(
387 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
388 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
389 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
390 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
392
393
394
396 mxx, myx, mzx, mwx,
397 mxy, myy, mzy, mwy,
398 mxz, myz, mzz, mwz,
399 mxt, myt, mzt, mwt
400 };
402}
403
404
405
406void DlDispatcherBase::transformReset() {
408
409 GetCanvas().ResetTransform();
410 GetCanvas().Transform(initial_matrix_);
411}
412
414 switch (clip_op) {
416 return Entity::ClipOperation::kDifference;
418 return Entity::ClipOperation::kIntersect;
419 }
420}
421
422
423void DlDispatcherBase::clipRect(const DlRect& rect,
425 bool is_aa) {
427
428 FillRectGeometry geom(rect);
430}
431
432
433void DlDispatcherBase::clipOval(const DlRect& bounds,
435 bool is_aa) {
437
438 EllipseGeometry geom(bounds);
440}
441
442
443void DlDispatcherBase::clipRoundRect(const DlRoundRect& rrect,
445 bool is_aa) {
447
449 if (rrect.IsRect()) {
450 FillRectGeometry geom(rrect.GetBounds());
451 GetCanvas().ClipGeometry(geom, clip_op, is_aa);
452 } else if (rrect.IsOval()) {
453 EllipseGeometry geom(rrect.GetBounds());
454 GetCanvas().ClipGeometry(geom, clip_op);
455 } else if (rrect.GetRadii().AreAllCornersSame()) {
456 RoundRectGeometry geom(rrect.GetBounds(), rrect.GetRadii().top_left);
457 GetCanvas().ClipGeometry(geom, clip_op);
458 } else {
459 FillRoundRectGeometry geom(rrect);
460 GetCanvas().ClipGeometry(geom, clip_op);
461 }
462}
463
464
465void DlDispatcherBase::clipRoundSuperellipse(const DlRoundSuperellipse& rse,
467 bool is_aa) {
469
471 if (rse.IsRect()) {
472 FillRectGeometry geom(rse.GetBounds());
473 GetCanvas().ClipGeometry(geom, clip_op, is_aa);
474 } else if (rse.IsOval()) {
475 EllipseGeometry geom(rse.GetBounds());
476 GetCanvas().ClipGeometry(geom, clip_op);
477 } else {
478 RoundSuperellipseGeometry geom(rse.GetBounds(), rse.GetRadii());
479 GetCanvas().ClipGeometry(geom, clip_op);
480 }
481}
482
483
484void DlDispatcherBase::clipPath(const DlPath& path,
486 bool is_aa) {
488
490
492 if (
path.IsRect(&rect)) {
493 FillRectGeometry geom(rect);
494 GetCanvas().ClipGeometry(geom, clip_op, is_aa);
495 }
else if (
path.IsOval(&rect)) {
496 EllipseGeometry geom(rect);
497 GetCanvas().ClipGeometry(geom, clip_op);
498 } else {
500 if (
path.IsRoundRect(&rrect) && rrect.GetRadii().AreAllCornersSame()) {
501 RoundRectGeometry geom(rrect.GetBounds(), rrect.GetRadii().top_left);
502 GetCanvas().ClipGeometry(geom, clip_op);
503 } else {
504 FillPathGeometry geom(path);
505 GetCanvas().ClipGeometry(geom, clip_op);
506 }
507 }
508}
509
510
514
515 Paint paint;
516 paint.color = skia_conversions::ToColor(color);
517 paint.blend_mode = dl_mode;
518 GetCanvas().DrawPaint(paint);
519}
520
521
522void DlDispatcherBase::drawPaint() {
524
525 GetCanvas().DrawPaint(paint_);
526}
527
528
529void DlDispatcherBase::drawLine(const DlPoint& p0, const DlPoint& p1) {
531
532 GetCanvas().DrawLine(p0, p1, paint_);
533}
534
535
536void DlDispatcherBase::drawDashedLine(const DlPoint& p0,
537 const DlPoint& p1,
538 DlScalar on_length,
539 DlScalar off_length) {
541
542 GetCanvas().DrawDashedLine(p0, p1, on_length, off_length, paint_);
543}
544
545
546void DlDispatcherBase::drawRect(const DlRect& rect) {
548
549 GetCanvas().DrawRect(rect, paint_);
550}
551
552
553void DlDispatcherBase::drawOval(const DlRect& bounds) {
555
556 GetCanvas().DrawOval(bounds, paint_);
557}
558
559
560void DlDispatcherBase::drawCircle(const DlPoint& center, DlScalar radius) {
562
563 GetCanvas().DrawCircle(center, radius, paint_);
564}
565
566
567void DlDispatcherBase::drawRoundRect(const DlRoundRect& rrect) {
569
570 GetCanvas().DrawRoundRect(rrect, paint_);
571}
572
573
574void DlDispatcherBase::drawDiffRoundRect(const DlRoundRect& outer,
575 const DlRoundRect& inner) {
577
578 GetCanvas().DrawDiffRoundRect(outer, inner, paint_);
579}
580
581
582void DlDispatcherBase::drawRoundSuperellipse(const DlRoundSuperellipse& rse) {
584
585 GetCanvas().DrawRoundSuperellipse(rse, paint_);
586}
587
588
589void DlDispatcherBase::drawPath(const DlPath& path) {
591
592 SimplifyOrDrawPath(GetCanvas(), path, paint_);
593}
594
595void DlDispatcherBase::SimplifyOrDrawPath(Canvas& canvas,
596 const DlPath& path,
597 const Paint& paint) {
599
600
601 bool closed;
602 if (
path.IsRect(&rect, &closed) && closed) {
603 canvas.DrawRect(rect, paint);
604 return;
605 }
606
608 if (
path.IsRoundRect(&rrect) && rrect.GetRadii().AreAllCornersSame()) {
609 canvas.DrawRoundRect(rrect, paint);
610 return;
611 }
612
613 if (
path.IsOval(&rect)) {
614 canvas.DrawOval(rect, paint);
615 return;
616 }
617
620 if (
path.IsLine(&start, &
end)) {
621 canvas.DrawLine(start,
end, paint);
622 return;
623 }
624
625 canvas.DrawPath(path, paint);
626}
627
628
629void DlDispatcherBase::drawArc(const DlRect& oval_bounds,
630 DlScalar start_degrees,
631 DlScalar sweep_degrees,
634
635 GetCanvas().DrawArc(Arc(oval_bounds, Degrees(start_degrees),
637 paint_);
638}
639
640
642 uint32_t count,
645
646 Paint paint = paint_;
647 paint.style = Paint::Style::kStroke;
648 switch (mode) {
650
651 PointStyle point_style = paint.stroke.cap == Cap::kRound
652 ? PointStyle::kRound
653 : PointStyle::kSquare;
654 Scalar radius = paint.stroke.width;
655 if (radius > 0) {
656 radius /= 2.0;
657 }
658 GetCanvas().DrawPoints(
points, count, radius, paint, point_style);
659 } break;
661 for (uint32_t
i = 1;
i < count;
i += 2) {
664 GetCanvas().DrawLine(p0, p1, paint,
i > 1);
665 }
666 break;
668 if (count > 1) {
670 for (uint32_t
i = 1;
i < count;
i++) {
672 GetCanvas().DrawLine(p0, p1, paint,
i > 1);
673 p0 = p1;
674 }
675 }
676 break;
677 }
678}
679
680void DlDispatcherBase::drawVertices(
681 const std::shared_ptr<flutter::DlVertices>& vertices,
683
684
685void DlDispatcherBase::drawImage(
const sk_sp<flutter::DlImage>
image,
686 const DlPoint& point,
688 bool render_with_attributes) {
690
692 return;
693 }
694
697 return;
698 }
699
701 const auto src = DlRect::MakeWH(
size.width,
size.height);
702 const auto dest = DlRect::MakeXYWH(point.x, point.y,
size.width,
size.height);
703
705 src,
706 dest,
707 sampling,
708 render_with_attributes,
710 );
711}
712
713
714void DlDispatcherBase::drawImageRect(
const sk_sp<flutter::DlImage>
image,
715 const DlRect& src,
716 const DlRect& dst,
718 bool render_with_attributes,
722
723 GetCanvas().DrawImageRect(
724 image->impeller_texture(),
725 src,
726 dst,
727 render_with_attributes ? paint_ : Paint(),
729 );
730}
731
732
733void DlDispatcherBase::drawImageNine(
const sk_sp<flutter::DlImage>
image,
734 const DlIRect& center,
735 const DlRect& dst,
737 bool render_with_attributes) {
739
740 NinePatchConverter converter = {};
741 converter.DrawNinePatch(
image->impeller_texture(),
745 &paint_);
746}
747
748
749void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
750 const RSTransform xform[],
751 const DlRect tex[],
753 int count,
756 const DlRect* cull_rect,
757 bool render_with_attributes) {
759
760 auto geometry =
761 DlAtlasGeometry(atlas->impeller_texture(),
762 xform,
763 tex,
764 colors,
765 static_cast<size_t>(count),
766 mode,
767 skia_conversions::ToSamplerDescriptor(sampling),
769 );
770 auto atlas_contents = std::make_shared<AtlasContents>();
771 atlas_contents->SetGeometry(&geometry);
772
773 GetCanvas().DrawAtlas(atlas_contents, paint_);
774}
775
776
777void DlDispatcherBase::drawDisplayList(
778 const sk_sp<flutter::DisplayList> display_list,
779 DlScalar opacity) {
781
782
783 Paint saved_paint = paint_;
784 Matrix saved_initial_matrix = initial_matrix_;
785
786
787
788
789
790 initial_matrix_ = GetCanvas().GetCurrentTransform();
791 paint_ = Paint();
792
793
794
795
796
797
798 int restore_count = GetCanvas().GetSaveCount();
799 if (opacity < SK_Scalar1) {
800 Paint save_paint;
801 save_paint.color = Color(0, 0, 0, opacity);
802 GetCanvas().SaveLayer(save_paint, display_list->GetBounds(), nullptr,
803 ContentBoundsPromise::kContainsContents,
804 display_list->total_depth(),
805 display_list->can_apply_group_opacity());
806 } else {
807
808
809 GetCanvas().Save(display_list->total_depth());
810 }
811
812
813
814 if (display_list->has_rtree() && !initial_matrix_.HasPerspective()) {
815
816
817
818
819
820 auto global_culling_bounds = GetCanvas().GetLocalCoverageLimit();
821 if (global_culling_bounds.has_value()) {
823 GetCanvas().GetCurrentTransform().Invert());
824 display_list->Dispatch(*this, cull_rect);
825 } else {
826
827
828 }
829 } else {
830 display_list->Dispatch(*this);
831 }
832
833
834
836 GetCanvas().RestoreToCount(restore_count);
837 initial_matrix_ = saved_initial_matrix;
838 paint_ = saved_paint;
839}
840
841
842void DlDispatcherBase::drawText(
const std::shared_ptr<flutter::DlText>&
text,
846
847 auto text_frame =
text->GetTextFrame();
848
849
850
852 GetCanvas().DrawTextFrame(text_frame,
854 paint_
855 );
856}
857
858
859void DlDispatcherBase::drawShadow(const DlPath& path,
861 const DlScalar elevation,
862 bool transparent_occluder,
863 DlScalar dpr) {
865
866 Color spot_color = skia_conversions::ToColor(color);
867 spot_color.alpha *= 0.25;
868
869
870 {
872 std::max(std::max(spot_color.red, spot_color.green), spot_color.blue);
874 std::min(std::min(spot_color.red, spot_color.green), spot_color.blue);
875 Scalar luminance = (min + max) * 0.5;
876
878 (2.6f + (-2.66667f + 1.06667f * spot_color.alpha) * spot_color.alpha) *
879 spot_color.alpha;
881 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
882 luminance;
883 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
884
886 std::clamp(spot_color.alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
887
888 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
889 Scalar tonal_alpha = color_scale + greyscale_alpha;
890 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
891 spot_color = Color(unpremul_scale * spot_color.red,
892 unpremul_scale * spot_color.green,
893 unpremul_scale * spot_color.blue, tonal_alpha);
894 }
895
896 Vector3 light_position(0, -1, 1);
897 Scalar occluder_z = dpr * elevation;
898
899 constexpr Scalar kLightRadius = 800 / 600;
900
901 Paint paint;
902 paint.style = Paint::Style::kFill;
903 paint.color = spot_color;
904 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
905 .style = FilterContents::BlurStyle::kNormal,
906 .sigma = Radius{kLightRadius * occluder_z /
907 GetCanvas().GetCurrentTransform().GetScale().y},
908 };
909
910 GetCanvas().Save(1u);
911 GetCanvas().PreConcat(
912 Matrix::MakeTranslation(
Vector2(0, -occluder_z * light_position.y)));
913
914 SimplifyOrDrawPath(GetCanvas(), path, paint);
916
917 GetCanvas().Restore();
918}
919
920
921
923 const ContentContext& renderer,
925 return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() &&
926 max_root_blend_mode > Entity::kLastPipelineBlendMode;
927}
928
929CanvasDlDispatcher::CanvasDlDispatcher(ContentContext& renderer,
930 RenderTarget& render_target,
931 bool is_onscreen,
932 bool has_root_backdrop_filter,
934 IRect32 cull_rect)
935 : canvas_(renderer,
936 render_target,
937 is_onscreen,
938 has_root_backdrop_filter ||
940 cull_rect),
941 renderer_(renderer) {}
942
943Canvas& CanvasDlDispatcher::GetCanvas() {
944 return canvas_;
945}
946
947void CanvasDlDispatcher::drawVertices(
948 const std::shared_ptr<flutter::DlVertices>& vertices,
951
952 GetCanvas().DrawVertices(
953 std::make_shared<DlVerticesGeometry>(vertices, renderer_), dl_mode,
954 paint_);
955}
956
957void CanvasDlDispatcher::SetBackdropData(
958 std::unordered_map<int64_t, BackdropData> backdrop,
959 size_t backdrop_count) {
960 GetCanvas().SetBackdropData(std::move(backdrop), backdrop_count);
961}
962
963
964
965FirstPassDispatcher::FirstPassDispatcher(const ContentContext& renderer,
966 const Matrix& initial_matrix,
967 const Rect cull_rect)
968 : renderer_(renderer), matrix_(initial_matrix) {
969 cull_rect_state_.push_back(cull_rect);
970}
971
972FirstPassDispatcher::~FirstPassDispatcher() {
974}
975
976void FirstPassDispatcher::save() {
977 stack_.emplace_back(matrix_);
978 cull_rect_state_.push_back(cull_rect_state_.back());
979}
980
981void FirstPassDispatcher::saveLayer(const DlRect& bounds,
984 std::optional<int64_t> backdrop_id) {
985 save();
986
987 backdrop_count_ += (backdrop == nullptr ? 0 : 1);
988 if (backdrop != nullptr && backdrop_id.has_value()) {
989 std::shared_ptr<flutter::DlImageFilter> shared_backdrop =
991 std::unordered_map<int64_t, BackdropData>::iterator existing =
992 backdrop_data_.find(backdrop_id.value());
993 if (existing == backdrop_data_.end()) {
994 backdrop_data_[backdrop_id.value()] =
995 BackdropData{.backdrop_count = 1, .last_backdrop = shared_backdrop};
996 } else {
997 BackdropData&
data = existing->second;
998 data.backdrop_count++;
999 if (
data.all_filters_equal) {
1000 data.all_filters_equal = (*
data.last_backdrop == *shared_backdrop);
1001 data.last_backdrop = shared_backdrop;
1002 }
1003 }
1004 }
1005
1006
1007
1008 auto global_cull_rect = cull_rect_state_.back();
1009 if (has_image_filter_ || global_cull_rect.IsMaximum()) {
1010 cull_rect_state_.back() = Rect::MakeMaximum();
1011 } else {
1012 auto global_save_bounds = bounds.TransformBounds(matrix_);
1013 auto new_cull_rect = global_cull_rect.Intersection(global_save_bounds);
1014 if (new_cull_rect.has_value()) {
1015 cull_rect_state_.back() = new_cull_rect.value();
1016 } else {
1017 cull_rect_state_.back() = Rect::MakeLTRB(0, 0, 0, 0);
1018 }
1019 }
1020}
1021
1022void FirstPassDispatcher::restore() {
1023 matrix_ = stack_.back();
1024 stack_.pop_back();
1025 cull_rect_state_.pop_back();
1026}
1027
1028void FirstPassDispatcher::translate(DlScalar tx, DlScalar ty) {
1029 matrix_ = matrix_.Translate({tx, ty});
1030}
1031
1032void FirstPassDispatcher::scale(DlScalar sx, DlScalar sy) {
1033 matrix_ = matrix_.Scale({sx, sy, 1.0f});
1034}
1035
1036void FirstPassDispatcher::rotate(DlScalar degrees) {
1037 matrix_ = matrix_ * Matrix::MakeRotationZ(Degrees(degrees));
1038}
1039
1040void FirstPassDispatcher::skew(DlScalar sx, DlScalar sy) {
1041 matrix_ = matrix_ * Matrix::MakeSkew(sx, sy);
1042}
1043
1044
1045
1046void FirstPassDispatcher::transform2DAffine(
1047 DlScalar mxx, DlScalar mxy, DlScalar mxt,
1048 DlScalar myx, DlScalar myy, DlScalar myt) {
1049 matrix_ = matrix_ * Matrix::MakeColumn(
1050 mxx, myx, 0.0f, 0.0f,
1051 mxy, myy, 0.0f, 0.0f,
1052 0.0f, 0.0f, 1.0f, 0.0f,
1053 mxt, myt, 0.0f, 1.0f
1054 );
1055}
1056
1057
1058
1059
1060void FirstPassDispatcher::transformFullPerspective(
1061 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
1062 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
1063 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
1064 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
1065 matrix_ = matrix_ * Matrix::MakeColumn(
1066 mxx, myx, mzx, mwx,
1067 mxy, myy, mzy, mwy,
1068 mxz, myz, mzz, mwz,
1069 mxt, myt, mzt, mwt
1070 );
1071}
1072
1073
1074void FirstPassDispatcher::transformReset() {
1075 matrix_ = Matrix();
1076}
1077
1078void FirstPassDispatcher::drawText(
const std::shared_ptr<flutter::DlText>&
text,
1081 GlyphProperties properties;
1082 auto text_frame =
text->GetTextFrame();
1083 if (text_frame == nullptr) {
1084 return;
1085 }
1086
1087 if (paint_.style == Paint::Style::kStroke) {
1088 properties.stroke = paint_.stroke;
1089 }
1090
1091 if (text_frame->HasColor()) {
1092
1093
1094 properties.color = paint_.color.WithAlpha(1.0);
1095 }
1096 auto scale = TextFrame::RoundScaledFontSize(
1097 (matrix_ * Matrix::MakeTranslation(
Point(
x,
y))).GetMaxBasisLengthXY());
1098
1099 renderer_.GetLazyGlyphAtlas()->AddTextFrame(
1100 text_frame,
1101 scale,
1103 matrix_,
1104 (properties.stroke.has_value() || text_frame->HasColor())
1105 ? std::optional<GlyphProperties>(properties)
1107 );
1108}
1109
1110const Rect FirstPassDispatcher::GetCurrentLocalCullingBounds()
const {
1111 auto cull_rect = cull_rect_state_.back();
1112 if (!cull_rect.IsEmpty() && !cull_rect.IsMaximum()) {
1113 Matrix inverse = matrix_.Invert();
1115 }
1116 return cull_rect;
1117}
1118
1119void FirstPassDispatcher::drawDisplayList(
1120 const sk_sp<flutter::DisplayList> display_list,
1121 DlScalar opacity) {
1122 [[maybe_unused]] size_t stack_depth = stack_.size();
1123 save();
1124 Paint old_paint = paint_;
1125 paint_ = Paint{};
1126 bool old_has_image_filter = has_image_filter_;
1127 has_image_filter_ = false;
1128
1129 if (matrix_.HasPerspective()) {
1130 display_list->Dispatch(*this);
1131 } else {
1132 Rect local_cull_bounds = GetCurrentLocalCullingBounds();
1133 if (local_cull_bounds.IsMaximum()) {
1134 display_list->Dispatch(*this);
1135 } else if (!local_cull_bounds.IsEmpty()) {
1136 DlIRect cull_rect = DlIRect::RoundOut(local_cull_bounds);
1137 display_list->Dispatch(*this, cull_rect);
1138 }
1139 }
1140
1141 restore();
1142 paint_ = old_paint;
1143 has_image_filter_ = old_has_image_filter;
1145}
1146
1147
1149 paint_.style =
ToStyle(style);
1150}
1151
1152
1154 paint_.color = skia_conversions::ToColor(color);
1155}
1156
1157
1158void FirstPassDispatcher::setStrokeWidth(DlScalar
width) {
1159 paint_.stroke.width =
width;
1160}
1161
1162
1163void FirstPassDispatcher::setStrokeMiter(DlScalar limit) {
1164 paint_.stroke.miter_limit = limit;
1165}
1166
1167
1169 switch (cap) {
1171 paint_.stroke.cap = Cap::kButt;
1172 break;
1174 paint_.stroke.cap = Cap::kRound;
1175 break;
1177 paint_.stroke.cap = Cap::kSquare;
1178 break;
1179 }
1180}
1181
1182
1184 switch (join) {
1186 paint_.stroke.join = Join::kMiter;
1187 break;
1189 paint_.stroke.join = Join::kRound;
1190 break;
1192 paint_.stroke.join = Join::kBevel;
1193 break;
1194 }
1195}
1196
1197
1199 if (filter == nullptr) {
1200 has_image_filter_ = false;
1201 } else {
1202 has_image_filter_ = true;
1203 }
1204}
1205
1206std::pair<std::unordered_map<int64_t, BackdropData>, size_t>
1207FirstPassDispatcher::TakeBackdropData() {
1208 std::unordered_map<int64_t, BackdropData> temp;
1209 std::swap(temp, backdrop_data_);
1210 return std::make_pair(temp, backdrop_count_);
1211}
1212
1214 const sk_sp<flutter::DisplayList>& display_list,
1215 ISize size,
1216 AiksContext& context,
1217 bool reset_host_buffer,
1218 bool generate_mips) {
1219 int mip_count = 1;
1220 if (generate_mips) {
1221 mip_count =
size.MipCount();
1222 }
1223
1224
1227 context.GetContext()->GetResourceAllocator());
1229 if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
1231 *context.GetContext(),
1232 size,
1233 mip_count,
1234 "Picture Snapshot MSAA",
1236 kDefaultColorAttachmentConfigMSAA
1237 );
1238 } else {
1240 *context.GetContext(),
1241 size,
1242 mip_count,
1243 "Picture Snapshot",
1245 kDefaultColorAttachmentConfig
1246 );
1247 }
1249 return nullptr;
1250 }
1251
1255 display_list->Dispatch(collector, cull_rect);
1257 context.GetContentContext(),
1259 false,
1260 display_list->root_has_backdrop_filter(),
1261 display_list->max_root_blend_mode(),
1263 );
1264 const auto& [
data, count] = collector.TakeBackdropData();
1265 impeller_dispatcher.SetBackdropData(
data, count);
1266 context.GetContentContext().GetTextShadowCache().MarkFrameStart();
1268 if (reset_host_buffer) {
1269 context.GetContentContext().GetTransientsDataBuffer().
Reset();
1270 context.GetContentContext().GetTransientsIndexesBuffer().
Reset();
1271 }
1272 context.GetContentContext().GetTextShadowCache().MarkFrameEnd();
1273 context.GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames();
1274 context.GetContext()->DisposeThreadLocalCachedResources();
1275 });
1276
1277 display_list->Dispatch(impeller_dispatcher, cull_rect);
1278 impeller_dispatcher.FinishRecording();
1279
1280 return target.GetRenderTargetTexture();
1281}
1282
1284 RenderTarget render_target,
1285 const sk_sp<flutter::DisplayList>& display_list,
1286 Rect cull_rect,
1287 bool reset_host_buffer,
1288 bool is_onscreen) {
1290 display_list->Dispatch(collector, cull_rect);
1291
1293 context,
1294 render_target,
1295 is_onscreen,
1296 display_list->root_has_backdrop_filter(),
1297 display_list->max_root_blend_mode(),
1298 IRect32::RoundOut(cull_rect)
1299 );
1300 const auto& [
data, count] = collector.TakeBackdropData();
1301 impeller_dispatcher.SetBackdropData(
data, count);
1302 context.GetTextShadowCache().MarkFrameStart();
1304 if (reset_host_buffer) {
1305 context.ResetTransientsBuffers();
1306 }
1307 context.GetTextShadowCache().MarkFrameEnd();
1308 });
1309
1310 display_list->Dispatch(impeller_dispatcher, cull_rect);
1311 impeller_dispatcher.FinishRecording();
1312 context.GetLazyGlyphAtlas()->ResetTextFrames();
1313
1314 return true;
1315}
1316
1317}
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)
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)
#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
@ kNormal
fuzzy inside and outside
@ kOuter
nothing inside, fuzzy outside
@ kInner
fuzzy inside, nothing outside
@ kSolid
solid inside, fuzzy outside
void Reset(SkPathBuilder *path)
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.
static Paint::Style ToStyle(flutter::DlDrawStyle style)
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
std::shared_ptr< const fml::Mapping > data