Flutter Engine
 
Loading...
Searching...
No Matches
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
6
7#include <algorithm>
8#include <cstring>
9#include <memory>
10#include <optional>
11#include <vector>
12
15#include "flutter/fml/logging.h"
16#include "fml/closure.h"
39
40namespace impeller {
41
42#if !defined(NDEBUG)
43#define USE_DEPTH_WATCHER true
44#else
45#define USE_DEPTH_WATCHER false
46#endif // !defined(NDEBUG)
47
48#if USE_DEPTH_WATCHER
49
50// Invoke this macro at the top of any DlOpReceiver dispatch function
51// using a number indicating the maximum depth that the operation is
52// expected to consume in the Canvas. Most rendering ops consume 1
53// except for DrawImageNine that currently consumes 1 per section (i.e. 9).
54// Attribute, clip and transform ops do not consume depth but this
55// macro can still be used with an argument of 0 to verify that expectation.
56//
57// The watchdog object allocated here will automatically double-check
58// the depth usage at any exit point to the function, or any other
59// point at which it falls out of scope.
60#define AUTO_DEPTH_WATCHER(d) \
61 DepthWatcher _watcher(__FILE__, __LINE__, GetCanvas(), \
62 paint_.mask_blur_descriptor.has_value(), d)
63
64// While the AUTO_DEPTH_WATCHER macro will check the depth usage at
65// any exit point from the dispatch function, sometimes the dispatch
66// functions are somewhat compounded and result in multiple Canvas
67// calls.
68//
69// Invoke this macro at any key points in the middle of a dispatch
70// function to verify that you still haven't exceeded the maximum
71// allowed depth. This is especially useful if the function does
72// an implicit save/restore where the restore call might assert the
73// depth constraints in a function in Canvas that can't be as easily
74// traced back to a given dispatch function as these macros can.
75#define AUTO_DEPTH_CHECK() _watcher.check(__FILE__, __LINE__)
77// Helper class, use the AUTO_DEPTH_WATCHER macros to access it
78struct DepthWatcher {
79 DepthWatcher(const std::string& file,
80 int line,
81 const impeller::Canvas& canvas,
82 bool has_mask_blur,
83 int allowed)
84 : file_(file),
85 line_(line),
86 canvas_(canvas),
87 allowed_(has_mask_blur ? allowed + 1 : allowed),
88 old_depth_(canvas.GetOpDepth()),
89 old_max_(canvas.GetMaxOpDepth()) {}
90
91 ~DepthWatcher() { check(file_, line_); }
92
93 void check(const std::string& file, int line) {
94 FML_CHECK(canvas_.GetOpDepth() <= (old_depth_ + allowed_) &&
95 canvas_.GetOpDepth() <= old_max_)
96 << std::endl
97 << "from " << file << ":" << line << std::endl
98 << "old/allowed/current/max = " << old_depth_ << "/" << allowed_ << "/"
99 << canvas_.GetOpDepth() << "/" << old_max_;
100 }
101
102 private:
103 const std::string file_;
104 const int line_;
105
106 const impeller::Canvas& canvas_;
107 const uint64_t allowed_;
108 const uint64_t old_depth_;
109 const uint64_t old_max_;
110};
111
112#else // USE_DEPTH_WATCHER
113
114#define AUTO_DEPTH_WATCHER(d)
115#define AUTO_DEPTH_CHECK()
116
117#endif // USE_DEPTH_WATCHER
118
119#define UNIMPLEMENTED \
120 FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
121
123 const flutter::DlFilterMode options) {
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
140static std::optional<const Rect> ToOptRect(const flutter::DlRect* rect) {
141 if (rect == nullptr) {
142 return std::nullopt;
143 }
144 return *rect;
145}
146
147// |flutter::DlOpReceiver|
150
151 // Nothing to do because AA is implicit.
152}
153
155 switch (style) {
157 return Paint::Style::kFill;
162 break;
163 }
164 return Paint::Style::kFill;
165}
166
167// |flutter::DlOpReceiver|
173
174// |flutter::DlOpReceiver|
180
181// |flutter::DlOpReceiver|
187
188// |flutter::DlOpReceiver|
194
195// |flutter::DlOpReceiver|
198
199 switch (cap) {
202 break;
205 break;
208 break;
209 }
210}
211
212// |flutter::DlOpReceiver|
228
229// |flutter::DlOpReceiver|
235
236// |flutter::DlOpReceiver|
242
243// |flutter::DlOpReceiver|
246
247 paint_.invert_colors = invert;
248}
249
250// |flutter::DlOpReceiver|
256
269
270// |flutter::DlOpReceiver|
273
274 // Needs https://github.com/flutter/flutter/issues/95434
275 if (filter == nullptr) {
276 paint_.mask_blur_descriptor = std::nullopt;
277 return;
278 }
279 switch (filter->type()) {
281 auto blur = filter->asBlur();
282
284 .style = ToBlurStyle(blur->style()),
285 .sigma = Sigma(blur->sigma()),
286 .respect_ctm = blur->respectCTM(),
287 };
288 break;
289 }
290 }
291}
292
293// |flutter::DlOpReceiver|
299
300// |flutter::DlOpReceiver|
301void DlDispatcherBase::save(uint32_t total_content_depth) {
303
304 GetCanvas().Save(total_content_depth);
305}
306
307// |flutter::DlOpReceiver|
309 const flutter::SaveLayerOptions& options,
310 uint32_t total_content_depth,
311 flutter::DlBlendMode max_content_mode,
312 const flutter::DlImageFilter* backdrop,
313 std::optional<int64_t> backdrop_id) {
315
316 auto paint = options.renders_with_attributes() ? paint_ : Paint{};
317 auto promise = options.content_is_clipped()
320 std::optional<Rect> impeller_bounds;
321 // If the content is unbounded but has developer specified bounds, we take
322 // the original bounds so that we clip the content as expected.
323 if (!options.content_is_unbounded() || options.bounds_from_caller()) {
324 impeller_bounds = bounds;
325 }
326
328 paint, impeller_bounds, backdrop, promise, total_content_depth,
329 // Unbounded content can still have user specified bounds that require a
330 // saveLayer to be created to perform the clip.
331 options.can_distribute_opacity() && !options.content_is_unbounded(),
332 backdrop_id //
333 );
334}
335
336// |flutter::DlOpReceiver|
340
341// |flutter::DlOpReceiver|
344
345 GetCanvas().Translate({tx, ty, 0.0});
346}
347
348// |flutter::DlOpReceiver|
351
352 GetCanvas().Scale({sx, sy, 1.0});
353}
354
355// |flutter::DlOpReceiver|
358
359 GetCanvas().Rotate(Degrees{degrees});
360}
361
362// |flutter::DlOpReceiver|
365
366 GetCanvas().Skew(sx, sy);
367}
368
369// clang-format off
370// |flutter::DlOpReceiver|
372 DlScalar mxx, DlScalar mxy, DlScalar mxt,
373 DlScalar myx, DlScalar myy, DlScalar myt) {
375
377 mxx, mxy, 0, mxt,
378 myx, myy, 0, myt,
379 0 , 0, 1, 0,
380 0 , 0, 0, 1
381 );
382}
383// clang-format on
384
385// clang-format off
386// |flutter::DlOpReceiver|
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 // The order of arguments is row-major but Impeller matrices are
395 // column-major.
396 auto transform = Matrix{
397 mxx, myx, mzx, mwx,
398 mxy, myy, mzy, mwy,
399 mxz, myz, mzz, mwz,
400 mxt, myt, mzt, mwt
401 };
403}
404// clang-format on
405
406// |flutter::DlOpReceiver|
413
422
423// |flutter::DlOpReceiver|
425 flutter::DlClipOp clip_op,
426 bool is_aa) {
428
429 FillRectGeometry geom(rect);
430 GetCanvas().ClipGeometry(geom, ToClipOperation(clip_op), /*is_aa=*/is_aa);
431}
432
433// |flutter::DlOpReceiver|
435 flutter::DlClipOp clip_op,
436 bool is_aa) {
438
439 EllipseGeometry geom(bounds);
440 GetCanvas().ClipGeometry(geom, ToClipOperation(clip_op));
441}
442
443// |flutter::DlOpReceiver|
445 flutter::DlClipOp sk_op,
446 bool is_aa) {
448
449 auto clip_op = ToClipOperation(sk_op);
450 if (rrect.IsRect()) {
451 FillRectGeometry geom(rrect.GetBounds());
452 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/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// |flutter::DlOpReceiver|
467 flutter::DlClipOp sk_op,
468 bool is_aa) {
470
471 auto clip_op = ToClipOperation(sk_op);
472 if (rse.IsRect()) {
473 FillRectGeometry geom(rse.GetBounds());
474 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
475 } else if (rse.IsOval()) {
476 EllipseGeometry geom(rse.GetBounds());
477 GetCanvas().ClipGeometry(geom, clip_op);
478 } else {
480 GetCanvas().ClipGeometry(geom, clip_op);
481 }
482}
483
484// |flutter::DlOpReceiver|
486 flutter::DlClipOp sk_op,
487 bool is_aa) {
489
490 auto clip_op = ToClipOperation(sk_op);
491
492 DlRect rect;
493 if (path.IsRect(&rect)) {
494 FillRectGeometry geom(rect);
495 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
496 } else if (path.IsOval(&rect)) {
497 EllipseGeometry geom(rect);
498 GetCanvas().ClipGeometry(geom, clip_op);
499 } else {
500 DlRoundRect rrect;
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// |flutter::DlOpReceiver|
513 flutter::DlBlendMode dl_mode) {
515
516 Paint paint;
517 paint.color = skia_conversions::ToColor(color);
518 paint.blend_mode = dl_mode;
519 GetCanvas().DrawPaint(paint);
520}
521
522// |flutter::DlOpReceiver|
528
529// |flutter::DlOpReceiver|
530void DlDispatcherBase::drawLine(const DlPoint& p0, const DlPoint& p1) {
532
533 GetCanvas().DrawLine(p0, p1, paint_);
534}
535
536// |flutter::DlOpReceiver|
538 const DlPoint& p1,
539 DlScalar on_length,
540 DlScalar off_length) {
542
543 GetCanvas().DrawDashedLine(p0, p1, on_length, off_length, paint_);
544}
545
546// |flutter::DlOpReceiver|
549
550 GetCanvas().DrawRect(rect, paint_);
551}
552
553// |flutter::DlOpReceiver|
556
557 GetCanvas().DrawOval(bounds, paint_);
558}
559
560// |flutter::DlOpReceiver|
561void DlDispatcherBase::drawCircle(const DlPoint& center, DlScalar radius) {
563
564 GetCanvas().DrawCircle(center, radius, paint_);
565}
566
567// |flutter::DlOpReceiver|
573
574// |flutter::DlOpReceiver|
576 const DlRoundRect& inner) {
578
579 GetCanvas().DrawDiffRoundRect(outer, inner, paint_);
580}
581
582// |flutter::DlOpReceiver|
588
589// |flutter::DlOpReceiver|
592
594}
595
597 const DlPath& path,
598 const Paint& paint) {
599 DlRect rect;
600
601 // We can't "optimize" a path into a rectangle if it's open.
602 bool closed;
603 if (path.IsRect(&rect, &closed) && closed) {
604 canvas.DrawRect(rect, paint);
605 return;
606 }
607
608 DlRoundRect rrect;
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
620 DlPoint end;
621 if (path.IsLine(&start, &end)) {
622 canvas.DrawLine(start, end, paint);
623 return;
624 }
625
626 canvas.DrawPath(path, paint);
627}
628
629// |flutter::DlOpReceiver|
630void DlDispatcherBase::drawArc(const DlRect& oval_bounds,
631 DlScalar start_degrees,
632 DlScalar sweep_degrees,
633 bool use_center) {
635
636 GetCanvas().DrawArc(Arc(oval_bounds, Degrees(start_degrees),
637 Degrees(sweep_degrees), use_center),
638 paint_);
639}
640
641// |flutter::DlOpReceiver|
643 uint32_t count,
644 const DlPoint points[]) {
646
647 Paint paint = paint_;
649 switch (mode) {
651 // Cap::kButt is also treated as a square.
652 PointStyle point_style = paint.stroke.cap == Cap::kRound
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) {
663 Point p0 = points[i - 1];
664 Point p1 = points[i];
665 GetCanvas().DrawLine(p0, p1, paint, /*reuse_depth=*/i > 1);
666 }
667 break;
669 if (count > 1) {
670 Point p0 = points[0];
671 for (uint32_t i = 1; i < count; i++) {
672 Point p1 = points[i];
673 GetCanvas().DrawLine(p0, p1, paint, /*reuse_depth=*/i > 1);
674 p0 = p1;
675 }
676 }
677 break;
678 }
679}
680
682 const std::shared_ptr<flutter::DlVertices>& vertices,
683 flutter::DlBlendMode dl_mode) {}
684
685// |flutter::DlOpReceiver|
686void DlDispatcherBase::drawImage(const sk_sp<flutter::DlImage> image,
687 const DlPoint& point,
689 bool render_with_attributes) {
691
692 if (!image) {
693 return;
694 }
695
696 auto texture = image->impeller_texture();
697 if (!texture) {
698 return;
699 }
700
701 const auto size = texture->GetSize();
702 const auto src = DlRect::MakeWH(size.width, size.height);
703 const auto dest = DlRect::MakeXYWH(point.x, point.y, size.width, size.height);
704
705 drawImageRect(image, // image
706 src, // source rect
707 dest, // destination rect
708 sampling, // sampling options
709 render_with_attributes, // render with attributes
711 );
712}
713
714// |flutter::DlOpReceiver|
715void DlDispatcherBase::drawImageRect(const sk_sp<flutter::DlImage> image,
716 const DlRect& src,
717 const DlRect& dst,
719 bool render_with_attributes,
723
725 image->impeller_texture(), // image
726 src, // source rect
727 dst, // destination rect
728 render_with_attributes ? paint_ : Paint(), // paint
729 skia_conversions::ToSamplerDescriptor(sampling) // sampling
730 );
731}
732
733// |flutter::DlOpReceiver|
734void DlDispatcherBase::drawImageNine(const sk_sp<flutter::DlImage> image,
735 const DlIRect& center,
736 const DlRect& dst,
738 bool render_with_attributes) {
740
741 NinePatchConverter converter = {};
742 converter.DrawNinePatch(image->impeller_texture(),
743 Rect::MakeLTRB(center.GetLeft(), center.GetTop(),
744 center.GetRight(), center.GetBottom()),
745 dst, ToSamplerDescriptor(filter), &GetCanvas(),
746 &paint_);
747}
748
749// |flutter::DlOpReceiver|
750void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
751 const RSTransform xform[],
752 const DlRect tex[],
753 const flutter::DlColor colors[],
754 int count,
757 const DlRect* cull_rect,
758 bool render_with_attributes) {
760
761 auto geometry =
762 DlAtlasGeometry(atlas->impeller_texture(), //
763 xform, //
764 tex, //
765 colors, //
766 static_cast<size_t>(count), //
767 mode, //
769 ToOptRect(cull_rect) //
770 );
771 auto atlas_contents = std::make_shared<AtlasContents>();
772 atlas_contents->SetGeometry(&geometry);
773
774 GetCanvas().DrawAtlas(atlas_contents, paint_);
775}
776
777// |flutter::DlOpReceiver|
779 const sk_sp<flutter::DisplayList> display_list,
780 DlScalar opacity) {
781 AUTO_DEPTH_WATCHER(display_list->total_depth());
782
783 // Save all values that must remain untouched after the operation.
784 Paint saved_paint = paint_;
785 Matrix saved_initial_matrix = initial_matrix_;
786
787 // Establish a new baseline for interpreting the new DL.
788 // Matrix and clip are left untouched, the current
789 // transform is saved as the new base matrix, and paint
790 // values are reset to defaults.
792 paint_ = Paint();
793
794 // Handle passed opacity in the most brute-force way by using
795 // a SaveLayer. If the display_list is able to inherit the
796 // opacity, this could also be handled by modulating all of its
797 // attribute settings (for example, color), by the indicated
798 // opacity.
799 int restore_count = GetCanvas().GetSaveCount();
800 if (opacity < SK_Scalar1) {
801 Paint save_paint;
802 save_paint.color = Color(0, 0, 0, opacity);
803 GetCanvas().SaveLayer(save_paint, display_list->GetBounds(), nullptr,
805 display_list->total_depth(),
806 display_list->can_apply_group_opacity());
807 } else {
808 // The display list may alter the clip, which must be restored to the
809 // current clip at the end of playback.
810 GetCanvas().Save(display_list->total_depth());
811 }
812
813 // TODO(131445): Remove this restriction if we can correctly cull with
814 // perspective transforms.
815 if (display_list->has_rtree() && !initial_matrix_.HasPerspective()) {
816 // The canvas remembers the screen-space culling bounds clipped by
817 // the surface and the history of clip calls. DisplayList can cull
818 // the ops based on a rectangle expressed in its "destination bounds"
819 // so we need the canvas to transform those into the current local
820 // coordinate space into which the DisplayList will be rendered.
821 auto global_culling_bounds = GetCanvas().GetLocalCoverageLimit();
822 if (global_culling_bounds.has_value()) {
823 Rect cull_rect = global_culling_bounds->TransformBounds(
824 GetCanvas().GetCurrentTransform().Invert());
825 display_list->Dispatch(*this, cull_rect);
826 } else {
827 // If the culling bounds are empty, this display list can be skipped
828 // entirely.
829 }
830 } else {
831 display_list->Dispatch(*this);
832 }
833
834 // Restore all saved state back to what it was before we interpreted
835 // the display_list
837 GetCanvas().RestoreToCount(restore_count);
838 initial_matrix_ = saved_initial_matrix;
839 paint_ = saved_paint;
840}
841
842// |flutter::DlOpReceiver|
843void DlDispatcherBase::drawText(const std::shared_ptr<flutter::DlText>& text,
844 DlScalar x,
845 DlScalar y) {
847
848 auto text_frame = text->GetTextFrame();
849
850 // When running with Impeller enabled Skia text blobs are converted to
851 // Impeller text frames in paragraph_skia.cc
852 FML_CHECK(text_frame != nullptr);
853 GetCanvas().DrawTextFrame(text_frame, //
854 impeller::Point{x, y}, //
855 paint_ //
856 );
857}
858
859// |flutter::DlOpReceiver|
861 const flutter::DlColor color,
862 const DlScalar elevation,
863 bool transparent_occluder,
864 DlScalar dpr) {
866
867 Color spot_color = skia_conversions::ToColor(color);
868 spot_color.alpha *= 0.25;
869
870 // Compute the spot color -- ported from SkShadowUtils::ComputeTonalColors.
871 {
872 Scalar max =
873 std::max(std::max(spot_color.red, spot_color.green), spot_color.blue);
874 Scalar min =
875 std::min(std::min(spot_color.red, spot_color.green), spot_color.blue);
876 Scalar luminance = (min + max) * 0.5;
877
878 Scalar alpha_adjust =
879 (2.6f + (-2.66667f + 1.06667f * spot_color.alpha) * spot_color.alpha) *
880 spot_color.alpha;
881 Scalar color_alpha =
882 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
883 luminance;
884 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
885
886 Scalar greyscale_alpha =
887 std::clamp(spot_color.alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
888
889 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
890 Scalar tonal_alpha = color_scale + greyscale_alpha;
891 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
892 spot_color = Color(unpremul_scale * spot_color.red,
893 unpremul_scale * spot_color.green,
894 unpremul_scale * spot_color.blue, tonal_alpha);
895 }
896
897 Vector3 light_position(0, -1, 1);
898 Scalar occluder_z = dpr * elevation;
899
900 constexpr Scalar kLightRadius = 800 / 600; // Light radius / light height
901
902 Paint paint;
904 paint.color = spot_color;
907 .sigma = Radius{kLightRadius * occluder_z /
909 };
910
911 GetCanvas().Save(1u);
913 Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y)));
914
915 SimplifyOrDrawPath(GetCanvas(), path, paint);
917
918 GetCanvas().Restore();
919}
920
921/// Subclasses
922
924 const ContentContext& renderer,
925 flutter::DlBlendMode max_root_blend_mode) {
926 return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() &&
927 max_root_blend_mode > Entity::kLastPipelineBlendMode;
928}
929
931 RenderTarget& render_target,
932 bool is_onscreen,
933 bool has_root_backdrop_filter,
934 flutter::DlBlendMode max_root_blend_mode,
935 IRect32 cull_rect)
936 : canvas_(renderer,
937 render_target,
938 is_onscreen,
939 has_root_backdrop_filter ||
940 RequiresReadbackForBlends(renderer, max_root_blend_mode),
941 cull_rect),
942 renderer_(renderer) {}
943
944Canvas& CanvasDlDispatcher::GetCanvas() {
945 return canvas_;
946}
947
949 const std::shared_ptr<flutter::DlVertices>& vertices,
950 flutter::DlBlendMode dl_mode) {
952
953 GetCanvas().DrawVertices(
954 std::make_shared<DlVerticesGeometry>(vertices, renderer_), dl_mode,
955 paint_);
956}
957
959 std::unordered_map<int64_t, BackdropData> backdrop,
960 size_t backdrop_count) {
961 GetCanvas().SetBackdropData(std::move(backdrop), backdrop_count);
962}
963
964//// Text Frame Dispatcher
965
967 const Matrix& initial_matrix,
968 const Rect cull_rect)
969 : renderer_(renderer), matrix_(initial_matrix) {
970 cull_rect_state_.push_back(cull_rect);
971}
972
974 FML_DCHECK(cull_rect_state_.size() == 1);
975}
976
978 stack_.emplace_back(matrix_);
979 cull_rect_state_.push_back(cull_rect_state_.back());
980}
981
983 const flutter::SaveLayerOptions options,
984 const flutter::DlImageFilter* backdrop,
985 std::optional<int64_t> backdrop_id) {
986 save();
987
988 backdrop_count_ += (backdrop == nullptr ? 0 : 1);
989 if (backdrop != nullptr && backdrop_id.has_value()) {
990 std::shared_ptr<flutter::DlImageFilter> shared_backdrop =
991 backdrop->shared();
992 std::unordered_map<int64_t, BackdropData>::iterator existing =
993 backdrop_data_.find(backdrop_id.value());
994 if (existing == backdrop_data_.end()) {
995 backdrop_data_[backdrop_id.value()] =
996 BackdropData{.backdrop_count = 1, .last_backdrop = shared_backdrop};
997 } else {
998 BackdropData& data = existing->second;
1000 if (data.all_filters_equal) {
1001 data.all_filters_equal = (*data.last_backdrop == *shared_backdrop);
1002 data.last_backdrop = shared_backdrop;
1003 }
1004 }
1005 }
1006
1007 // This dispatcher does not track enough state to accurately compute
1008 // cull rects with image filters.
1009 auto global_cull_rect = cull_rect_state_.back();
1010 if (has_image_filter_ || global_cull_rect.IsMaximum()) {
1011 cull_rect_state_.back() = Rect::MakeMaximum();
1012 } else {
1013 auto global_save_bounds = bounds.TransformBounds(matrix_);
1014 auto new_cull_rect = global_cull_rect.Intersection(global_save_bounds);
1015 if (new_cull_rect.has_value()) {
1016 cull_rect_state_.back() = new_cull_rect.value();
1017 } else {
1018 cull_rect_state_.back() = Rect::MakeLTRB(0, 0, 0, 0);
1019 }
1020 }
1021}
1022
1024 matrix_ = stack_.back();
1025 stack_.pop_back();
1026 cull_rect_state_.pop_back();
1027}
1028
1030 matrix_ = matrix_.Translate({tx, ty});
1031}
1032
1034 matrix_ = matrix_.Scale({sx, sy, 1.0f});
1035}
1036
1038 matrix_ = matrix_ * Matrix::MakeRotationZ(Degrees(degrees));
1039}
1040
1042 matrix_ = matrix_ * Matrix::MakeSkew(sx, sy);
1043}
1044
1045// clang-format off
1046// 2x3 2D affine subset of a 4x4 transform in row major order
1048 DlScalar mxx, DlScalar mxy, DlScalar mxt,
1049 DlScalar myx, DlScalar myy, DlScalar myt) {
1050 matrix_ = matrix_ * Matrix::MakeColumn(
1051 mxx, myx, 0.0f, 0.0f,
1052 mxy, myy, 0.0f, 0.0f,
1053 0.0f, 0.0f, 1.0f, 0.0f,
1054 mxt, myt, 0.0f, 1.0f
1055 );
1056}
1057// clang-format on
1058
1059// clang-format off
1060// full 4x4 transform in row major order
1062 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
1063 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
1064 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
1065 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
1066 matrix_ = matrix_ * Matrix::MakeColumn(
1067 mxx, myx, mzx, mwx,
1068 mxy, myy, mzy, mwy,
1069 mxz, myz, mzz, mwz,
1070 mxt, myt, mzt, mwt
1071 );
1072}
1073// clang-format on
1074
1076 matrix_ = Matrix();
1077}
1078
1079void FirstPassDispatcher::drawText(const std::shared_ptr<flutter::DlText>& text,
1080 DlScalar x,
1081 DlScalar y) {
1082 GlyphProperties properties;
1083 auto text_frame = text->GetTextFrame();
1084 if (text_frame == nullptr) {
1085 return;
1086 }
1087
1088 if (paint_.style == Paint::Style::kStroke) {
1089 properties.stroke = paint_.stroke;
1090 }
1091
1092 if (text_frame->HasColor()) {
1093 // Alpha is always applied when rendering, remove it here so
1094 // we do not double-apply the alpha.
1095 properties.color = paint_.color.WithAlpha(1.0);
1096 }
1098 (matrix_ * Matrix::MakeTranslation(Point(x, y))).GetMaxBasisLengthXY());
1099
1100 renderer_.GetLazyGlyphAtlas()->AddTextFrame(
1101 text_frame, //
1102 scale, //
1103 Point(x, y), //
1104 matrix_,
1105 (properties.stroke.has_value() || text_frame->HasColor()) //
1106 ? std::optional<GlyphProperties>(properties) //
1107 : std::nullopt //
1108 );
1109}
1110
1111const Rect FirstPassDispatcher::GetCurrentLocalCullingBounds() const {
1112 auto cull_rect = cull_rect_state_.back();
1113 if (!cull_rect.IsEmpty() && !cull_rect.IsMaximum()) {
1114 Matrix inverse = matrix_.Invert();
1115 cull_rect = cull_rect.TransformBounds(inverse);
1116 }
1117 return cull_rect;
1118}
1119
1121 const sk_sp<flutter::DisplayList> display_list,
1122 DlScalar opacity) {
1123 [[maybe_unused]] size_t stack_depth = stack_.size();
1124 save();
1125 Paint old_paint = paint_;
1126 paint_ = Paint{};
1127 bool old_has_image_filter = has_image_filter_;
1128 has_image_filter_ = false;
1129
1130 if (matrix_.HasPerspective()) {
1131 display_list->Dispatch(*this);
1132 } else {
1133 Rect local_cull_bounds = GetCurrentLocalCullingBounds();
1134 if (local_cull_bounds.IsMaximum()) {
1135 display_list->Dispatch(*this);
1136 } else if (!local_cull_bounds.IsEmpty()) {
1137 DlIRect cull_rect = DlIRect::RoundOut(local_cull_bounds);
1138 display_list->Dispatch(*this, cull_rect);
1139 }
1140 }
1141
1142 restore();
1143 paint_ = old_paint;
1144 has_image_filter_ = old_has_image_filter;
1145 FML_DCHECK(stack_depth == stack_.size());
1146}
1147
1148// |flutter::DlOpReceiver|
1152
1153// |flutter::DlOpReceiver|
1157
1158// |flutter::DlOpReceiver|
1162
1163// |flutter::DlOpReceiver|
1165 paint_.stroke.miter_limit = limit;
1166}
1167
1168// |flutter::DlOpReceiver|
1170 switch (cap) {
1172 paint_.stroke.cap = Cap::kButt;
1173 break;
1175 paint_.stroke.cap = Cap::kRound;
1176 break;
1178 paint_.stroke.cap = Cap::kSquare;
1179 break;
1180 }
1181}
1182
1183// |flutter::DlOpReceiver|
1185 switch (join) {
1187 paint_.stroke.join = Join::kMiter;
1188 break;
1190 paint_.stroke.join = Join::kRound;
1191 break;
1193 paint_.stroke.join = Join::kBevel;
1194 break;
1195 }
1196}
1197
1198// |flutter::DlOpReceiver|
1200 if (filter == nullptr) {
1201 has_image_filter_ = false;
1202 } else {
1203 has_image_filter_ = true;
1204 }
1205}
1206
1207std::pair<std::unordered_map<int64_t, BackdropData>, size_t>
1209 std::unordered_map<int64_t, BackdropData> temp;
1210 std::swap(temp, backdrop_data_);
1211 return std::make_pair(temp, backdrop_count_);
1212}
1213
1214std::shared_ptr<Texture> DisplayListToTexture(
1215 const sk_sp<flutter::DisplayList>& display_list,
1216 ISize size,
1217 AiksContext& context,
1218 bool reset_host_buffer,
1219 bool generate_mips) {
1220 int mip_count = 1;
1221 if (generate_mips) {
1222 mip_count = size.MipCount();
1223 }
1224 // Do not use the render target cache as the lifecycle of this texture
1225 // will outlive a particular frame.
1226 impeller::RenderTargetAllocator render_target_allocator =
1228 context.GetContext()->GetResourceAllocator());
1230 if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
1231 target = render_target_allocator.CreateOffscreenMSAA(
1232 *context.GetContext(), // context
1233 size, // size
1234 /*mip_count=*/mip_count,
1235 "Picture Snapshot MSAA", // label
1237 kDefaultColorAttachmentConfigMSAA // color_attachment_config
1238 );
1239 } else {
1240 target = render_target_allocator.CreateOffscreen(
1241 *context.GetContext(), // context
1242 size, // size
1243 /*mip_count=*/mip_count,
1244 "Picture Snapshot", // label
1245 impeller::RenderTarget::
1246 kDefaultColorAttachmentConfig // color_attachment_config
1247 );
1248 }
1249 if (!target.IsValid()) {
1250 return nullptr;
1251 }
1252
1253 DlIRect cull_rect = DlIRect::MakeWH(size.width, size.height);
1256 display_list->Dispatch(collector, cull_rect);
1257 impeller::CanvasDlDispatcher impeller_dispatcher(
1258 context.GetContentContext(), //
1259 target, //
1260 /*is_onscreen=*/false, //
1261 display_list->root_has_backdrop_filter(), //
1262 display_list->max_root_blend_mode(), //
1264 );
1265 const auto& [data, count] = collector.TakeBackdropData();
1266 impeller_dispatcher.SetBackdropData(data, count);
1268 fml::ScopedCleanupClosure cleanup([&] {
1269 if (reset_host_buffer) {
1270 context.GetContentContext().GetTransientsDataBuffer().Reset();
1271 context.GetContentContext().GetTransientsIndexesBuffer().Reset();
1272 }
1273 context.GetContentContext().GetTextShadowCache().MarkFrameEnd();
1274 context.GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames();
1275 context.GetContext()->DisposeThreadLocalCachedResources();
1276 });
1277
1278 display_list->Dispatch(impeller_dispatcher, cull_rect);
1279 impeller_dispatcher.FinishRecording();
1280
1281 return target.GetRenderTargetTexture();
1282}
1283
1285 RenderTarget render_target,
1286 const sk_sp<flutter::DisplayList>& display_list,
1287 Rect cull_rect,
1288 bool reset_host_buffer,
1289 bool is_onscreen) {
1290 FirstPassDispatcher collector(context, impeller::Matrix(), cull_rect);
1291 display_list->Dispatch(collector, cull_rect);
1292
1293 impeller::CanvasDlDispatcher impeller_dispatcher(
1294 context, //
1295 render_target, //
1296 /*is_onscreen=*/is_onscreen, //
1297 display_list->root_has_backdrop_filter(), //
1298 display_list->max_root_blend_mode(), //
1299 IRect32::RoundOut(cull_rect) //
1300 );
1301 const auto& [data, count] = collector.TakeBackdropData();
1302 impeller_dispatcher.SetBackdropData(data, count);
1304 fml::ScopedCleanupClosure cleanup([&] {
1305 if (reset_host_buffer) {
1306 context.ResetTransientsBuffers();
1307 }
1308 context.GetTextShadowCache().MarkFrameEnd();
1309 });
1310
1311 display_list->Dispatch(impeller_dispatcher, cull_rect);
1312 impeller_dispatcher.FinishRecording();
1313 context.GetLazyGlyphAtlas()->ResetTextFrames();
1314
1315 return true;
1316}
1317
1318} // namespace impeller
virtual T type() const =0
virtual std::shared_ptr< D > shared() const =0
virtual const DlBlurMaskFilter * asBlur() const
virtual void save()=0
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.
Definition closure.h:32
ContentContext & GetContentContext() const
std::shared_ptr< Context > GetContext() const
CanvasDlDispatcher(ContentContext &renderer, RenderTarget &render_target, bool is_onscreen, bool has_root_backdrop_filter, flutter::DlBlendMode max_root_blend_mode, IRect32 cull_rect)
void drawVertices(const std::shared_ptr< flutter::DlVertices > &vertices, flutter::DlBlendMode dl_mode) override
void SetBackdropData(std::unordered_map< int64_t, BackdropData > backdrop, size_t backdrop_count)
void ClipGeometry(const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
Definition canvas.cc:861
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:1927
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
Definition canvas.cc:812
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition canvas.cc:1237
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:1274
const Matrix & GetCurrentTransform() const
Definition canvas.cc:273
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition canvas.cc:1040
void DrawOval(const Rect &rect, const Paint &paint)
Definition canvas.cc:680
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:975
void RestoreToCount(size_t count)
Definition canvas.cc:320
size_t GetSaveCount() const
Definition canvas.cc:312
void Transform(const Matrix &transform)
Definition canvas.cc:269
uint64_t GetMaxOpDepth() const
Definition canvas.h:261
void DrawDashedLine(const Point &p0, const Point &p1, Scalar on_length, Scalar off_length, const Paint &paint)
Definition canvas.cc:636
void DrawDiffRoundRect(const RoundRect &outer, const RoundRect &inner, const Paint &paint)
Definition canvas.cc:796
void DrawPath(const flutter::DlPath &path, const Paint &paint)
Definition canvas.cc:328
void PreConcat(const Matrix &transform)
Definition canvas.cc:261
void Rotate(Radians radians)
Definition canvas.cc:293
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
Definition canvas.cc:943
void ResetTransform()
Definition canvas.cc:265
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition canvas.cc:1704
void DrawPaint(const Paint &paint)
Definition canvas.cc:342
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
Definition canvas.cc:764
void Skew(Scalar sx, Scalar sy)
Definition canvas.cc:289
void Scale(const Vector2 &scale)
Definition canvas.cc:281
uint64_t GetOpDepth() const
Definition canvas.h:259
void Save(uint32_t total_content_depth=kMaxDepth)
Definition canvas.cc:1220
void DrawRect(const Rect &rect, const Paint &paint)
Definition canvas.cc:662
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
Definition canvas.cc:1154
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition canvas.cc:614
void Translate(const Vector3 &offset)
Definition canvas.cc:277
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition canvas.cc:834
void DrawArc(const Arc &arc, const Paint &paint)
Definition canvas.cc:709
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
void ResetTransientsBuffers()
Resets the transients buffers held onto by the content context.
const std::shared_ptr< LazyGlyphAtlas > & GetLazyGlyphAtlas() const
const Capabilities & GetDeviceCapabilities() const
TextShadowCache & GetTextShadowCache() const
A wrapper around data provided by a drawAtlas call.
void drawLine(const DlPoint &p0, const DlPoint &p1) override
void drawText(const std::shared_ptr< flutter::DlText > &text, DlScalar x, DlScalar y) override
void drawAtlas(const sk_sp< flutter::DlImage > atlas, const RSTransform xform[], const DlRect tex[], const flutter::DlColor colors[], int count, flutter::DlBlendMode mode, flutter::DlImageSampling sampling, const DlRect *cull_rect, bool render_with_attributes) override
void drawPoints(flutter::DlPointMode mode, uint32_t count, const DlPoint points[]) override
void drawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length) override
void drawOval(const DlRect &bounds) override
void setImageFilter(const flutter::DlImageFilter *filter) override
void drawPath(const DlPath &path) override
void setStrokeCap(flutter::DlStrokeCap cap) override
void clipOval(const DlRect &bounds, flutter::DlClipOp clip_op, bool is_aa) override
void drawRoundSuperellipse(const DlRoundSuperellipse &rse) override
void clipRoundRect(const DlRoundRect &rrect, flutter::DlClipOp clip_op, bool is_aa) override
void skew(DlScalar sx, DlScalar sy) override
void clipRect(const DlRect &rect, flutter::DlClipOp clip_op, bool is_aa) override
void setAntiAlias(bool aa) override
void transformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void setStrokeWidth(DlScalar width) override
void drawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner) override
void drawRoundRect(const DlRoundRect &rrect) override
void setStrokeJoin(flutter::DlStrokeJoin join) override
void rotate(DlScalar degrees) override
void setColorFilter(const flutter::DlColorFilter *filter) override
void scale(DlScalar sx, DlScalar sy) override
void setDrawStyle(flutter::DlDrawStyle style) override
void drawShadow(const DlPath &path, const flutter::DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr) override
void drawImage(const sk_sp< flutter::DlImage > image, const DlPoint &point, flutter::DlImageSampling sampling, bool render_with_attributes) override
void clipPath(const DlPath &path, flutter::DlClipOp clip_op, bool is_aa) override
void drawImageRect(const sk_sp< flutter::DlImage > image, const DlRect &src, const DlRect &dst, flutter::DlImageSampling sampling, bool render_with_attributes, flutter::DlSrcRectConstraint constraint) override
void clipRoundSuperellipse(const DlRoundSuperellipse &rse, flutter::DlClipOp clip_op, bool is_aa) override
void drawArc(const DlRect &oval_bounds, DlScalar start_degrees, DlScalar sweep_degrees, bool use_center) override
void saveLayer(const DlRect &bounds, const flutter::SaveLayerOptions &options, uint32_t total_content_depth, flutter::DlBlendMode max_content_mode, const flutter::DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void drawDisplayList(const sk_sp< flutter::DisplayList > display_list, DlScalar opacity) override
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
void setInvertColors(bool invert) override
void setColor(flutter::DlColor color) override
void setStrokeMiter(DlScalar limit) override
void translate(DlScalar tx, DlScalar ty) override
void drawVertices(const std::shared_ptr< flutter::DlVertices > &vertices, flutter::DlBlendMode dl_mode) override
void drawCircle(const DlPoint &center, DlScalar radius) override
void setMaskFilter(const flutter::DlMaskFilter *filter) override
virtual Canvas & GetCanvas()=0
void setColorSource(const flutter::DlColorSource *source) override
void drawImageNine(const sk_sp< flutter::DlImage > image, const DlIRect &center, const DlRect &dst, flutter::DlFilterMode filter, bool render_with_attributes) override
void setBlendMode(flutter::DlBlendMode mode) override
void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override
void drawRect(const DlRect &rect) override
static void SimplifyOrDrawPath(Canvas &canvas, const DlPath &cache, const Paint &paint)
A Geometry class that can directly generate vertices (with or without texture coordinates) for filled...
static constexpr BlendMode kLastPipelineBlendMode
Definition entity.h:28
A Geometry that produces fillable vertices from a |DlPath| object using the |FillPathSourceGeometry| ...
A Geometry class that produces fillable vertices from any |RoundRect| object regardless of radii unif...
@ kNormal
Blurred inside and outside.
@ kOuter
Nothing inside, blurred outside.
@ kInner
Blurred inside, nothing outside.
@ kSolid
Solid inside, blurred outside.
void setColor(flutter::DlColor color) override
void setStrokeCap(flutter::DlStrokeCap cap) override
void saveLayer(const DlRect &bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void setDrawStyle(flutter::DlDrawStyle style) override
std::pair< std::unordered_map< int64_t, BackdropData >, size_t > TakeBackdropData()
void rotate(DlScalar degrees) override
void setImageFilter(const flutter::DlImageFilter *filter) override
void setStrokeMiter(DlScalar limit) override
void transformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void drawText(const std::shared_ptr< flutter::DlText > &text, DlScalar x, DlScalar y) override
void scale(DlScalar sx, DlScalar sy) override
void translate(DlScalar tx, DlScalar ty) override
void skew(DlScalar sx, DlScalar sy) override
FirstPassDispatcher(const ContentContext &renderer, const Matrix &initial_matrix, const Rect cull_rect)
void drawDisplayList(const sk_sp< flutter::DisplayList > display_list, DlScalar opacity) override
void setStrokeWidth(DlScalar width) override
void setStrokeJoin(flutter::DlStrokeJoin join) override
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
void DrawNinePatch(const std::shared_ptr< Texture > &image, Rect center, Rect dst, const SamplerDescriptor &sampler, Canvas *canvas, Paint *paint)
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)
A Geometry class that generates fillable vertices (with or without texture coordinates) directly from...
A Geometry class that generates fillable vertices (with or without texture coordinates) directly from...
static Rational RoundScaledFontSize(Scalar scale)
Definition text_frame.cc:55
void MarkFrameStart()
Mark all glyph textures as unused this frame.
#define AUTO_DEPTH_WATCHER(d)
#define UNIMPLEMENTED
#define AUTO_DEPTH_CHECK()
int32_t x
FlutterVulkanImage * image
uint32_t * target
#define FML_CHECK(condition)
Definition logging.h:104
#define FML_DCHECK(condition)
Definition logging.h:122
std::u16string text
FlTexture * texture
double y
DlStrokeJoin
Definition dl_paint.h:37
@ kMiter
extends to miter limit
@ kBevel
connects outside edges
DlStrokeCap
Definition dl_paint.h:28
@ kRound
adds circle
@ kButt
no stroke extension
@ kSquare
adds square
DlPointMode
Definition dl_types.h:15
@ 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
DlDrawStyle
Definition dl_paint.h:19
@ kStrokeAndFill
both strokes and fills shapes
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
@ kNormal
fuzzy inside and outside
@ kOuter
nothing inside, fuzzy outside
@ kInner
fuzzy inside, nothing outside
@ kSolid
solid inside, fuzzy outside
DlSrcRectConstraint
Definition dl_types.h:21
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Color ToColor(const flutter::DlColor &color)
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.
Point Vector2
Definition point.h:331
float Scalar
Definition scalar.h:19
static Paint::Style ToStyle(flutter::DlDrawStyle style)
static std::optional< const Rect > ToOptRect(const flutter::DlRect *rect)
PointStyle
Definition canvas.h:65
@ kRound
Points are drawn as squares.
@ kSquare
Points are drawn as circles.
TPoint< Scalar > Point
Definition point.h:327
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)
BlendMode
Definition color.h:58
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
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.
flutter::DlScalar DlScalar
static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style)
int32_t width
Scalar blue
Definition color.h:138
Scalar alpha
Definition color.h:143
constexpr Color WithAlpha(Scalar new_alpha) const
Definition color.h:278
Scalar red
Definition color.h:128
Scalar green
Definition color.h:133
std::optional< StrokeParameters > stroke
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
constexpr Matrix Translate(const Vector3 &t) const
Definition matrix.h:263
Matrix Invert() const
Definition matrix.cc:99
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
Vector3 GetScale() const
Definition matrix.h:394
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
Definition matrix.h:127
constexpr Matrix Scale(const Vector3 &s) const
Definition matrix.h:275
static Matrix MakeRotationZ(Radians r)
Definition matrix.h:223
constexpr bool HasPerspective() const
Definition matrix.h:418
FilterContents::BlurStyle style
Definition paint.h:53
const flutter::DlColorFilter * color_filter
Definition paint.h:77
const flutter::DlColorSource * color_source
Definition paint.h:76
const flutter::DlImageFilter * image_filter
Definition paint.h:78
Style style
Definition paint.h:81
bool invert_colors
Definition paint.h:83
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition paint.h:85
Color color
Definition paint.h:75
BlendMode blend_mode
Definition paint.h:82
StrokeParameters stroke
Definition paint.h:80
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition sigma.h:48
constexpr bool IsRect() const
Definition round_rect.h:67
constexpr const RoundingRadii & GetRadii() const
Definition round_rect.h:55
constexpr const Rect & GetBounds() const
Definition round_rect.h:53
constexpr bool IsOval() const
Definition round_rect.h:71
constexpr const Rect & GetBounds() const
constexpr bool IsOval() const
constexpr bool IsRect() const
constexpr const RoundingRadii & GetRadii() const
constexpr bool AreAllCornersSame(Scalar tolerance=kEhCloseEnough) const
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition sigma.h:32
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition rect.h:472
static constexpr TRect MakeWH(Type width, Type height)
Definition rect.h:140
constexpr std::optional< TRect > Intersection(const TRect &o) const
Definition rect.h:528
constexpr bool IsMaximum() const
Definition rect.h:314
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition rect.h:297
RoundOut(const TRect< U > &r)
Definition rect.h:679
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
static constexpr TRect MakeMaximum()
Definition rect.h:188
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129
const size_t start
const size_t end
std::vector< Point > points
std::shared_ptr< const fml::Mapping > data