Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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"
40
41namespace impeller {
42
43#if !defined(NDEBUG)
44#define USE_DEPTH_WATCHER true
45#else
46#define USE_DEPTH_WATCHER false
47#endif // !defined(NDEBUG)
48
49#if USE_DEPTH_WATCHER
50
51// Invoke this macro at the top of any DlOpReceiver dispatch function
52// using a number indicating the maximum depth that the operation is
53// expected to consume in the Canvas. Most rendering ops consume 1
54// except for DrawImageNine that currently consumes 1 per section (i.e. 9).
55// Attribute, clip and transform ops do not consume depth but this
56// macro can still be used with an argument of 0 to verify that expectation.
57//
58// The watchdog object allocated here will automatically double-check
59// the depth usage at any exit point to the function, or any other
60// point at which it falls out of scope.
61#define AUTO_DEPTH_WATCHER(d) \
62 DepthWatcher _watcher(__FILE__, __LINE__, GetCanvas(), \
63 paint_.mask_blur_descriptor.has_value(), d)
64
65// While the AUTO_DEPTH_WATCHER macro will check the depth usage at
66// any exit point from the dispatch function, sometimes the dispatch
67// functions are somewhat compounded and result in multiple Canvas
68// calls.
69//
70// Invoke this macro at any key points in the middle of a dispatch
71// function to verify that you still haven't exceeded the maximum
72// allowed depth. This is especially useful if the function does
73// an implicit save/restore where the restore call might assert the
74// depth constraints in a function in Canvas that can't be as easily
75// traced back to a given dispatch function as these macros can.
76#define AUTO_DEPTH_CHECK() _watcher.check(__FILE__, __LINE__)
77
78// Helper class, use the AUTO_DEPTH_WATCHER macros to access it
79struct DepthWatcher {
80 DepthWatcher(const std::string& file,
81 int line,
82 const impeller::Canvas& canvas,
83 bool has_mask_blur,
84 int allowed)
85 : file_(file),
86 line_(line),
87 canvas_(canvas),
88 allowed_(has_mask_blur ? allowed + 1 : allowed),
89 old_depth_(canvas.GetOpDepth()),
90 old_max_(canvas.GetMaxOpDepth()) {}
91
92 ~DepthWatcher() { check(file_, line_); }
93
94 void check(const std::string& file, int line) {
95 FML_CHECK(canvas_.GetOpDepth() <= (old_depth_ + allowed_) &&
96 canvas_.GetOpDepth() <= old_max_)
97 << std::endl
98 << "from " << file << ":" << line << std::endl
99 << "old/allowed/current/max = " << old_depth_ << "/" << allowed_ << "/"
100 << canvas_.GetOpDepth() << "/" << old_max_;
101 }
102
103 private:
104 const std::string file_;
105 const int line_;
106
107 const impeller::Canvas& canvas_;
108 const uint64_t allowed_;
109 const uint64_t old_depth_;
110 const uint64_t old_max_;
112
113#else // USE_DEPTH_WATCHER
115#define AUTO_DEPTH_WATCHER(d)
116#define AUTO_DEPTH_CHECK()
117
118#endif // USE_DEPTH_WATCHER
119
120#define UNIMPLEMENTED \
121 FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
122
124 const flutter::DlFilterMode options) {
126 switch (options) {
129 desc.label = "Nearest Sampler";
130 break;
133 desc.label = "Linear Sampler";
134 break;
135 default:
136 break;
137 }
138 return desc;
139}
140
141static std::optional<const Rect> ToOptRect(const flutter::DlRect* rect) {
142 if (rect == nullptr) {
143 return std::nullopt;
144 }
145 return *rect;
146}
147
148// |flutter::DlOpReceiver|
151
152 paint_.anti_alias = aa;
153}
154
156 switch (style) {
158 return Paint::Style::kFill;
163 break;
164 }
165 return Paint::Style::kFill;
166}
167
168// |flutter::DlOpReceiver|
174
175// |flutter::DlOpReceiver|
181
182// |flutter::DlOpReceiver|
188
189// |flutter::DlOpReceiver|
195
196// |flutter::DlOpReceiver|
199
200 switch (cap) {
203 break;
206 break;
209 break;
210 }
211}
212
213// |flutter::DlOpReceiver|
229
230// |flutter::DlOpReceiver|
236
237// |flutter::DlOpReceiver|
243
244// |flutter::DlOpReceiver|
247
248 paint_.invert_colors = invert;
249}
250
251// |flutter::DlOpReceiver|
257
270
271// |flutter::DlOpReceiver|
274
275 // Needs https://github.com/flutter/flutter/issues/95434
276 if (filter == nullptr) {
277 paint_.mask_blur_descriptor = std::nullopt;
278 return;
279 }
280 switch (filter->type()) {
282 auto blur = filter->asBlur();
283
285 .style = ToBlurStyle(blur->style()),
286 .sigma = Sigma(blur->sigma()),
287 .respect_ctm = blur->respectCTM(),
288 };
289 break;
290 }
291 }
292}
293
294// |flutter::DlOpReceiver|
300
301// |flutter::DlOpReceiver|
302void DlDispatcherBase::save(uint32_t total_content_depth) {
304
305 GetCanvas().Save(total_content_depth);
306}
307
308// |flutter::DlOpReceiver|
310 const flutter::SaveLayerOptions& options,
311 uint32_t total_content_depth,
312 flutter::DlBlendMode max_content_mode,
313 const flutter::DlImageFilter* backdrop,
314 std::optional<int64_t> backdrop_id) {
316
317 auto paint = options.renders_with_attributes() ? paint_ : Paint{};
318 auto promise = options.content_is_clipped()
321 std::optional<Rect> impeller_bounds;
322 // If the content is unbounded but has developer specified bounds, we take
323 // the original bounds so that we clip the content as expected.
324 if (!options.content_is_unbounded() || options.bounds_from_caller()) {
325 impeller_bounds = bounds;
326 }
327
329 paint, impeller_bounds, backdrop, promise, total_content_depth,
330 // Unbounded content can still have user specified bounds that require a
331 // saveLayer to be created to perform the clip.
332 options.can_distribute_opacity() && !options.content_is_unbounded(),
333 backdrop_id //
334 );
335}
336
337// |flutter::DlOpReceiver|
341
342// |flutter::DlOpReceiver|
345
346 GetCanvas().Translate({tx, ty, 0.0});
347}
348
349// |flutter::DlOpReceiver|
352
353 GetCanvas().Scale({sx, sy, 1.0});
354}
355
356// |flutter::DlOpReceiver|
359
360 GetCanvas().Rotate(Degrees{degrees});
361}
362
363// |flutter::DlOpReceiver|
366
367 GetCanvas().Skew(sx, sy);
368}
369
370// clang-format off
371// |flutter::DlOpReceiver|
373 DlScalar mxx, DlScalar mxy, DlScalar mxt,
374 DlScalar myx, DlScalar myy, DlScalar myt) {
376
378 mxx, mxy, 0, mxt,
379 myx, myy, 0, myt,
380 0 , 0, 1, 0,
381 0 , 0, 0, 1
382 );
383}
384// clang-format on
385
386// clang-format off
387// |flutter::DlOpReceiver|
389 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
390 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
391 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
392 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
394
395 // The order of arguments is row-major but Impeller matrices are
396 // column-major.
397 auto transform = Matrix{
398 mxx, myx, mzx, mwx,
399 mxy, myy, mzy, mwy,
400 mxz, myz, mzz, mwz,
401 mxt, myt, mzt, mwt
402 };
404}
405// clang-format on
406
407// |flutter::DlOpReceiver|
414
423
424// |flutter::DlOpReceiver|
426 flutter::DlClipOp clip_op,
427 bool is_aa) {
429
430 FillRectGeometry geom(rect);
431 GetCanvas().ClipGeometry(geom, ToClipOperation(clip_op), /*is_aa=*/is_aa);
432}
433
434// |flutter::DlOpReceiver|
436 flutter::DlClipOp clip_op,
437 bool is_aa) {
439
440 EllipseGeometry geom(bounds);
441 GetCanvas().ClipGeometry(geom, ToClipOperation(clip_op));
442}
443
444// |flutter::DlOpReceiver|
446 flutter::DlClipOp sk_op,
447 bool is_aa) {
449
450 auto clip_op = ToClipOperation(sk_op);
451 if (rrect.IsRect()) {
452 FillRectGeometry geom(rrect.GetBounds());
453 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
454 } else if (rrect.IsOval()) {
455 EllipseGeometry geom(rrect.GetBounds());
456 GetCanvas().ClipGeometry(geom, clip_op);
457 } else if (rrect.GetRadii().AreAllCornersSame()) {
458 RoundRectGeometry geom(rrect.GetBounds(), rrect.GetRadii().top_left);
459 GetCanvas().ClipGeometry(geom, clip_op);
460 } else {
461 FillRoundRectGeometry geom(rrect);
462 GetCanvas().ClipGeometry(geom, clip_op);
463 }
464}
465
466// |flutter::DlOpReceiver|
468 flutter::DlClipOp sk_op,
469 bool is_aa) {
471
472 auto clip_op = ToClipOperation(sk_op);
473 if (rse.IsRect()) {
474 FillRectGeometry geom(rse.GetBounds());
475 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
476 } else if (rse.IsOval()) {
477 EllipseGeometry geom(rse.GetBounds());
478 GetCanvas().ClipGeometry(geom, clip_op);
479 } else {
481 GetCanvas().ClipGeometry(geom, clip_op);
482 }
483}
484
485// |flutter::DlOpReceiver|
487 flutter::DlClipOp sk_op,
488 bool is_aa) {
490
491 auto clip_op = ToClipOperation(sk_op);
492
493 DlRect rect;
494 if (path.IsRect(&rect)) {
495 FillRectGeometry geom(rect);
496 GetCanvas().ClipGeometry(geom, clip_op, /*is_aa=*/is_aa);
497 } else if (path.IsOval(&rect)) {
498 EllipseGeometry geom(rect);
499 GetCanvas().ClipGeometry(geom, clip_op);
500 } else {
501 DlRoundRect rrect;
502 if (path.IsRoundRect(&rrect) && rrect.GetRadii().AreAllCornersSame()) {
503 RoundRectGeometry geom(rrect.GetBounds(), rrect.GetRadii().top_left);
504 GetCanvas().ClipGeometry(geom, clip_op);
505 } else {
506 FillPathGeometry geom(path);
507 GetCanvas().ClipGeometry(geom, clip_op);
508 }
509 }
510}
511
512// |flutter::DlOpReceiver|
514 flutter::DlBlendMode dl_mode) {
516
517 Paint paint;
518 paint.color = skia_conversions::ToColor(color);
519 paint.blend_mode = dl_mode;
520 GetCanvas().DrawPaint(paint);
521}
522
523// |flutter::DlOpReceiver|
529
530// |flutter::DlOpReceiver|
533
534 GetCanvas().DrawLine(p0, p1, paint_);
535}
536
537// |flutter::DlOpReceiver|
539 const DlPoint& p1,
540 DlScalar on_length,
541 DlScalar off_length) {
543
544 GetCanvas().DrawDashedLine(p0, p1, on_length, off_length, paint_);
545}
546
547// |flutter::DlOpReceiver|
550
551 GetCanvas().DrawRect(rect, paint_);
552}
553
554// |flutter::DlOpReceiver|
557
558 GetCanvas().DrawOval(bounds, paint_);
559}
560
561// |flutter::DlOpReceiver|
562void DlDispatcherBase::drawCircle(const DlPoint& center, DlScalar radius) {
564
565 GetCanvas().DrawCircle(center, radius, paint_);
566}
567
568// |flutter::DlOpReceiver|
574
575// |flutter::DlOpReceiver|
577 const DlRoundRect& inner) {
579
580 GetCanvas().DrawDiffRoundRect(outer, inner, paint_);
581}
582
583// |flutter::DlOpReceiver|
589
590// |flutter::DlOpReceiver|
593
594 GetCanvas().DrawPath(path, paint_);
595}
596
598 const DlPath& path,
599 const Paint& paint) {
600 DlRect rect;
601
602 // We can't "optimize" a path into a rectangle if it's open.
603 bool closed;
604 if (path.IsRect(&rect, &closed) && closed) {
605 canvas.DrawRect(rect, paint);
606 return;
607 }
608
609 DlRoundRect rrect;
610 if (path.IsRoundRect(&rrect) && rrect.GetRadii().AreAllCornersSame()) {
611 canvas.DrawRoundRect(rrect, paint);
612 return;
613 }
614
615 if (path.IsOval(&rect)) {
616 canvas.DrawOval(rect, paint);
617 return;
618 }
619
621 DlPoint end;
622 if (path.IsLine(&start, &end)) {
623 canvas.DrawLine(start, end, paint);
624 return;
625 }
626
627 canvas.DrawPath(path, paint);
628}
629
630// |flutter::DlOpReceiver|
631void DlDispatcherBase::drawArc(const DlRect& oval_bounds,
632 DlScalar start_degrees,
633 DlScalar sweep_degrees,
634 bool use_center) {
636
637 GetCanvas().DrawArc(Arc(oval_bounds, Degrees(start_degrees),
638 Degrees(sweep_degrees), use_center),
639 paint_);
640}
641
642// |flutter::DlOpReceiver|
644 uint32_t count,
645 const DlPoint points[]) {
647
648 Paint paint = paint_;
650 switch (mode) {
652 // Cap::kButt is also treated as a square.
653 PointStyle point_style = paint.stroke.cap == Cap::kRound
656 Scalar radius = paint.stroke.width;
657 if (radius > 0) {
658 radius /= 2.0;
659 }
660 GetCanvas().DrawPoints(points, count, radius, paint, point_style);
661 } break;
663 for (uint32_t i = 1; i < count; i += 2) {
664 Point p0 = points[i - 1];
665 Point p1 = points[i];
666 GetCanvas().DrawLine(p0, p1, paint, /*reuse_depth=*/i > 1);
667 }
668 break;
670 if (count > 1) {
671 Point p0 = points[0];
672 for (uint32_t i = 1; i < count; i++) {
673 Point p1 = points[i];
674 GetCanvas().DrawLine(p0, p1, paint, /*reuse_depth=*/i > 1);
675 p0 = p1;
676 }
677 }
678 break;
679 }
680}
681
682std::shared_ptr<Texture> DlDispatcherBase::GetTexture(
683 const sk_sp<flutter::DlImage>& image) {
684 if (!image) {
685 return nullptr;
686 }
687 return image->asImpellerImage()->GetCachedTexture(GetContentContext());
688}
689
691 const std::shared_ptr<flutter::DlVertices>& vertices,
692 flutter::DlBlendMode dl_mode) {}
693
694// |flutter::DlOpReceiver|
695void DlDispatcherBase::drawImage(const sk_sp<flutter::DlImage> image,
696 const DlPoint& point,
698 bool render_with_attributes) {
700
701 if (!image) {
702 return;
703 }
704
705 auto texture = GetTexture(image);
706 if (!texture) {
707 return;
708 }
709
710 const auto size = texture->GetSize();
711 const auto src = DlRect::MakeWH(size.width, size.height);
712 const auto dest = DlRect::MakeXYWH(point.x, point.y, size.width, size.height);
713
714 drawImageRect(image, // image
715 src, // source rect
716 dest, // destination rect
717 sampling, // sampling options
718 render_with_attributes, // render with attributes
720 );
721}
722
723// |flutter::DlOpReceiver|
724void DlDispatcherBase::drawImageRect(const sk_sp<flutter::DlImage> image,
725 const DlRect& src,
726 const DlRect& dst,
728 bool render_with_attributes,
732
734 GetTexture(image), // image
735 src, // source rect
736 dst, // destination rect
737 render_with_attributes ? paint_ : Paint(), // paint
738 skia_conversions::ToSamplerDescriptor(sampling) // sampling
739 );
740}
741
742// |flutter::DlOpReceiver|
743void DlDispatcherBase::drawImageNine(const sk_sp<flutter::DlImage> image,
744 const DlIRect& center,
745 const DlRect& dst,
747 bool render_with_attributes) {
749
750 NinePatchConverter converter = {};
751 converter.DrawNinePatch(GetTexture(image),
752 Rect::MakeLTRB(center.GetLeft(), center.GetTop(),
753 center.GetRight(), center.GetBottom()),
754 dst, ToSamplerDescriptor(filter), &GetCanvas(),
755 &paint_);
756}
757
758// |flutter::DlOpReceiver|
759void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
760 const RSTransform xform[],
761 const DlRect tex[],
762 const flutter::DlColor colors[],
763 int count,
766 const DlRect* cull_rect,
767 bool render_with_attributes) {
769
770 auto geometry =
771 DlAtlasGeometry(GetTexture(atlas), //
772 xform, //
773 tex, //
774 colors, //
775 static_cast<size_t>(count), //
776 mode, //
778 ToOptRect(cull_rect) //
779 );
780 auto atlas_contents = std::make_shared<AtlasContents>();
781 atlas_contents->SetGeometry(&geometry);
782
783 GetCanvas().DrawAtlas(atlas_contents, paint_);
784}
785
786// |flutter::DlOpReceiver|
788 const sk_sp<flutter::DisplayList> display_list,
789 DlScalar opacity) {
790 AUTO_DEPTH_WATCHER(display_list->total_depth());
791
792 // Save all values that must remain untouched after the operation.
793 Paint saved_paint = paint_;
794 Matrix saved_initial_matrix = initial_matrix_;
795
796 // Establish a new baseline for interpreting the new DL.
797 // Matrix and clip are left untouched, the current
798 // transform is saved as the new base matrix, and paint
799 // values are reset to defaults.
801 paint_ = Paint();
802
803 // Handle passed opacity in the most brute-force way by using
804 // a SaveLayer. If the display_list is able to inherit the
805 // opacity, this could also be handled by modulating all of its
806 // attribute settings (for example, color), by the indicated
807 // opacity.
808 int restore_count = GetCanvas().GetSaveCount();
809 if (opacity < SK_Scalar1) {
810 Paint save_paint;
811 save_paint.color = Color(0, 0, 0, opacity);
812 GetCanvas().SaveLayer(save_paint, display_list->GetBounds(), nullptr,
814 display_list->total_depth(),
815 display_list->can_apply_group_opacity());
816 } else {
817 // The display list may alter the clip, which must be restored to the
818 // current clip at the end of playback.
819 GetCanvas().Save(display_list->total_depth());
820 }
821
822 // TODO(131445): Remove this restriction if we can correctly cull with
823 // perspective transforms.
824 if (display_list->has_rtree() && !initial_matrix_.HasPerspective()) {
825 // The canvas remembers the screen-space culling bounds clipped by
826 // the surface and the history of clip calls. DisplayList can cull
827 // the ops based on a rectangle expressed in its "destination bounds"
828 // so we need the canvas to transform those into the current local
829 // coordinate space into which the DisplayList will be rendered.
830 auto global_culling_bounds = GetCanvas().GetLocalCoverageLimit();
831 if (global_culling_bounds.has_value()) {
832 Rect cull_rect = global_culling_bounds->TransformBounds(
833 GetCanvas().GetCurrentTransform().Invert());
834 display_list->Dispatch(*this, cull_rect);
835 } else {
836 // If the culling bounds are empty, this display list can be skipped
837 // entirely.
838 }
839 } else {
840 display_list->Dispatch(*this);
841 }
842
843 // Restore all saved state back to what it was before we interpreted
844 // the display_list
846 GetCanvas().RestoreToCount(restore_count);
847 initial_matrix_ = saved_initial_matrix;
848 paint_ = saved_paint;
849}
850
851// |flutter::DlOpReceiver|
852void DlDispatcherBase::drawText(const std::shared_ptr<flutter::DlText>& text,
853 DlScalar x,
854 DlScalar y) {
856
857 auto text_frame = text->GetTextFrame();
858
859 // When running with Impeller enabled Skia text blobs are converted to
860 // Impeller text frames in paragraph_skia.cc
861 FML_CHECK(text_frame != nullptr);
862 GetCanvas().DrawTextFrame(text_frame, //
863 impeller::Point{x, y}, //
864 paint_ //
865 );
866}
867
868// |flutter::DlOpReceiver|
870 const flutter::DlColor color,
871 const DlScalar elevation,
872 bool transparent_occluder,
873 DlScalar dpr) {
875
876 Color spot_color = skia_conversions::ToColor(color);
877 spot_color.alpha *= 0.25;
878
879 // Compute the spot color -- ported from SkShadowUtils::ComputeTonalColors.
880 {
881 Scalar max =
882 std::max(std::max(spot_color.red, spot_color.green), spot_color.blue);
883 Scalar min =
884 std::min(std::min(spot_color.red, spot_color.green), spot_color.blue);
885 Scalar luminance = (min + max) * 0.5;
886
887 Scalar alpha_adjust =
888 (2.6f + (-2.66667f + 1.06667f * spot_color.alpha) * spot_color.alpha) *
889 spot_color.alpha;
890 Scalar color_alpha =
891 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
892 luminance;
893 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
894
895 Scalar greyscale_alpha =
896 std::clamp(spot_color.alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
897
898 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
899 Scalar tonal_alpha = color_scale + greyscale_alpha;
900 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
901 spot_color = Color(unpremul_scale * spot_color.red,
902 unpremul_scale * spot_color.green,
903 unpremul_scale * spot_color.blue, tonal_alpha);
904 }
905
906 Vector3 light_position(0, -1, 1);
907 Scalar occluder_z = dpr * elevation;
908
909 constexpr Scalar kLightRadius = 800 / 600; // Light radius / light height
910
911 Paint paint;
913 paint.color = spot_color;
916 .sigma = Radius{kLightRadius * occluder_z /
918 };
919
920 GetCanvas().Save(1u);
922 Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y)));
923
924 SimplifyOrDrawPath(GetCanvas(), path, paint);
926
927 GetCanvas().Restore();
928}
929
930/// Subclasses
931
933 const ContentContext& renderer,
934 flutter::DlBlendMode max_root_blend_mode) {
935 return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() &&
936 max_root_blend_mode > Entity::kLastPipelineBlendMode;
937}
938
940 RenderTarget& render_target,
941 bool is_onscreen,
942 bool has_root_backdrop_filter,
943 flutter::DlBlendMode max_root_blend_mode,
944 IRect32 cull_rect)
946 canvas_(renderer,
947 render_target,
948 is_onscreen,
949 has_root_backdrop_filter ||
950 RequiresReadbackForBlends(renderer, max_root_blend_mode),
951 cull_rect),
952 renderer_(renderer) {}
953
954Canvas& CanvasDlDispatcher::GetCanvas() {
955 return canvas_;
956}
957
958const ContentContext& CanvasDlDispatcher::GetContentContext() const {
959 return renderer_;
960}
961
963 const std::shared_ptr<flutter::DlVertices>& vertices,
964 flutter::DlBlendMode dl_mode) {
966
967 GetCanvas().DrawVertices(
968 std::make_shared<DlVerticesGeometry>(vertices, renderer_), dl_mode,
969 paint_);
970}
971
973 std::unordered_map<int64_t, BackdropData> backdrop,
974 size_t backdrop_count) {
975 GetCanvas().SetBackdropData(std::move(backdrop), backdrop_count);
976}
977
978//// Text Frame Dispatcher
979
981 const Matrix& initial_matrix,
982 const Rect cull_rect)
983 : renderer_(renderer), matrix_(initial_matrix) {
984 cull_rect_state_.push_back(cull_rect);
985}
986
988 FML_DCHECK(cull_rect_state_.size() == 1);
989}
990
992 stack_.emplace_back(matrix_);
993 cull_rect_state_.push_back(cull_rect_state_.back());
994}
995
997 const flutter::SaveLayerOptions options,
998 const flutter::DlImageFilter* backdrop,
999 std::optional<int64_t> backdrop_id) {
1000 save();
1001
1002 backdrop_count_ += (backdrop == nullptr ? 0 : 1);
1003 if (backdrop != nullptr && backdrop_id.has_value()) {
1004 std::shared_ptr<flutter::DlImageFilter> shared_backdrop =
1005 backdrop->shared();
1006 std::unordered_map<int64_t, BackdropData>::iterator existing =
1007 backdrop_data_.find(backdrop_id.value());
1008 if (existing == backdrop_data_.end()) {
1009 backdrop_data_[backdrop_id.value()] =
1010 BackdropData{.backdrop_count = 1, .last_backdrop = shared_backdrop};
1011 } else {
1012 BackdropData& data = existing->second;
1013 data.backdrop_count++;
1014 if (data.all_filters_equal) {
1015 data.all_filters_equal = (*data.last_backdrop == *shared_backdrop);
1016 data.last_backdrop = shared_backdrop;
1017 }
1018 }
1019 }
1020
1021 // This dispatcher does not track enough state to accurately compute
1022 // cull rects with image filters.
1023 auto global_cull_rect = cull_rect_state_.back();
1024 if (has_image_filter_ || global_cull_rect.IsMaximum()) {
1025 cull_rect_state_.back() = Rect::MakeMaximum();
1026 } else {
1027 auto global_save_bounds = bounds.TransformBounds(matrix_);
1028 auto new_cull_rect = global_cull_rect.Intersection(global_save_bounds);
1029 if (new_cull_rect.has_value()) {
1030 cull_rect_state_.back() = new_cull_rect.value();
1031 } else {
1032 cull_rect_state_.back() = Rect::MakeLTRB(0, 0, 0, 0);
1033 }
1034 }
1035}
1036
1038 matrix_ = stack_.back();
1039 stack_.pop_back();
1040 cull_rect_state_.pop_back();
1041}
1042
1044 matrix_ = matrix_.Translate({tx, ty});
1045}
1046
1048 matrix_ = matrix_.Scale({sx, sy, 1.0f});
1049}
1050
1052 matrix_ = matrix_ * Matrix::MakeRotationZ(Degrees(degrees));
1053}
1054
1056 matrix_ = matrix_ * Matrix::MakeSkew(sx, sy);
1057}
1058
1059// clang-format off
1060// 2x3 2D affine subset of a 4x4 transform in row major order
1062 DlScalar mxx, DlScalar mxy, DlScalar mxt,
1063 DlScalar myx, DlScalar myy, DlScalar myt) {
1064 matrix_ = matrix_ * Matrix::MakeColumn(
1065 mxx, myx, 0.0f, 0.0f,
1066 mxy, myy, 0.0f, 0.0f,
1067 0.0f, 0.0f, 1.0f, 0.0f,
1068 mxt, myt, 0.0f, 1.0f
1069 );
1070}
1071// clang-format on
1072
1073// clang-format off
1074// full 4x4 transform in row major order
1076 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
1077 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
1078 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
1079 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) {
1080 matrix_ = matrix_ * Matrix::MakeColumn(
1081 mxx, myx, mzx, mwx,
1082 mxy, myy, mzy, mwy,
1083 mxz, myz, mzz, mwz,
1084 mxt, myt, mzt, mwt
1085 );
1086}
1087// clang-format on
1088
1090 matrix_ = Matrix();
1091}
1092
1093void FirstPassDispatcher::drawText(const std::shared_ptr<flutter::DlText>& text,
1094 DlScalar x,
1095 DlScalar y) {
1096 GlyphProperties properties;
1097 auto text_frame = text->GetTextFrame();
1098 if (text_frame == nullptr) {
1099 return;
1100 }
1101
1102 properties.stroke = paint_.GetStroke();
1103
1104 if (text_frame->HasColor()) {
1105 // Alpha is always applied when rendering, remove it here so
1106 // we do not double-apply the alpha.
1107 properties.tone_or_color = paint_.color.WithAlpha(1.0);
1108 } else {
1110 }
1111
1112 renderer_.GetLazyGlyphAtlas()->AddTextFrame(text_frame, //
1113 Point(x, y), //
1114 matrix_, //
1115 properties //
1116 );
1117}
1118
1119const Rect FirstPassDispatcher::GetCurrentLocalCullingBounds() const {
1120 auto cull_rect = cull_rect_state_.back();
1121 if (!cull_rect.IsEmpty() && !cull_rect.IsMaximum()) {
1122 Matrix inverse = matrix_.Invert();
1123 cull_rect = cull_rect.TransformBounds(inverse);
1124 }
1125 return cull_rect;
1126}
1127
1129 const sk_sp<flutter::DisplayList> display_list,
1130 DlScalar opacity) {
1131 [[maybe_unused]] size_t stack_depth = stack_.size();
1132 save();
1133 Paint old_paint = paint_;
1134 paint_ = Paint{};
1135 bool old_has_image_filter = has_image_filter_;
1136 has_image_filter_ = false;
1137
1138 if (matrix_.HasPerspective()) {
1139 display_list->Dispatch(*this);
1140 } else {
1141 Rect local_cull_bounds = GetCurrentLocalCullingBounds();
1142 if (local_cull_bounds.IsMaximum()) {
1143 display_list->Dispatch(*this);
1144 } else if (!local_cull_bounds.IsEmpty()) {
1145 DlIRect cull_rect = DlIRect::RoundOut(local_cull_bounds);
1146 display_list->Dispatch(*this, cull_rect);
1147 }
1148 }
1149
1150 restore();
1151 paint_ = old_paint;
1152 has_image_filter_ = old_has_image_filter;
1153 FML_DCHECK(stack_depth == stack_.size());
1154}
1155
1156// |flutter::DlOpReceiver|
1160
1161// |flutter::DlOpReceiver|
1165
1166// |flutter::DlOpReceiver|
1170
1171// |flutter::DlOpReceiver|
1173 paint_.stroke.miter_limit = limit;
1174}
1175
1176// |flutter::DlOpReceiver|
1178 switch (cap) {
1180 paint_.stroke.cap = Cap::kButt;
1181 break;
1183 paint_.stroke.cap = Cap::kRound;
1184 break;
1186 paint_.stroke.cap = Cap::kSquare;
1187 break;
1188 }
1189}
1190
1191// |flutter::DlOpReceiver|
1193 switch (join) {
1195 paint_.stroke.join = Join::kMiter;
1196 break;
1198 paint_.stroke.join = Join::kRound;
1199 break;
1201 paint_.stroke.join = Join::kBevel;
1202 break;
1203 }
1204}
1205
1206// |flutter::DlOpReceiver|
1208 if (filter == nullptr) {
1209 has_image_filter_ = false;
1210 } else {
1211 has_image_filter_ = true;
1212 }
1213}
1214
1215namespace {
1216bool PixelFormatSupportsMSAA(std::optional<PixelFormat> pixel_format) {
1217 return !pixel_format.has_value();
1218}
1219} // namespace
1220
1221std::pair<std::unordered_map<int64_t, BackdropData>, size_t>
1223 std::unordered_map<int64_t, BackdropData> temp;
1224 std::swap(temp, backdrop_data_);
1225 return std::make_pair(temp, backdrop_count_);
1226}
1227
1228std::shared_ptr<Texture> DisplayListToTexture(
1229 const sk_sp<flutter::DisplayList>& display_list,
1230 ISize size,
1231 AiksContext& context,
1232 bool reset_host_buffer,
1233 bool generate_mips,
1234 std::optional<PixelFormat> target_pixel_format) {
1235 int mip_count = 1;
1236 if (generate_mips) {
1237 mip_count = size.MipCount();
1238 }
1239 // Do not use the render target cache as the lifecycle of this texture
1240 // will outlive a particular frame.
1241 impeller::RenderTargetAllocator render_target_allocator =
1243 context.GetContext()->GetResourceAllocator());
1245 if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA() &&
1246 PixelFormatSupportsMSAA(target_pixel_format)) {
1247 target = render_target_allocator.CreateOffscreenMSAA(
1248 *context.GetContext(), // context
1249 size, // size
1250 /*mip_count=*/mip_count,
1251 "Picture Snapshot MSAA", // label
1253 kDefaultColorAttachmentConfigMSAA, // color_attachment_config
1254 std::nullopt, // stencil_attachment_config
1255 nullptr, // existing_color_msaa_texture
1256 nullptr, // existing_color_resolve_texture
1257 nullptr, // existing_depth_stencil_texture
1258 target_pixel_format // target_format
1259 );
1260 } else {
1261 target = render_target_allocator.CreateOffscreen(
1262 *context.GetContext(), // context
1263 size, // size
1264 /*mip_count=*/mip_count,
1265 "Picture Snapshot", // label
1267 kDefaultColorAttachmentConfig, // color_attachment_config
1268 std::nullopt, // stencil_attachment_config
1269 nullptr, // existing_color_texture
1270 nullptr, // existing_depth_stencil_texture
1271 target_pixel_format // target_format
1272 );
1273 }
1274 if (!target.IsValid()) {
1275 return nullptr;
1276 }
1277
1278 DlIRect cull_rect = DlIRect::MakeWH(size.width, size.height);
1281 display_list->Dispatch(collector, cull_rect);
1282 impeller::CanvasDlDispatcher impeller_dispatcher(
1283 context.GetContentContext(), //
1284 target, //
1285 /*is_onscreen=*/false, //
1286 display_list->root_has_backdrop_filter(), //
1287 display_list->max_root_blend_mode(), //
1289 );
1290 const auto& [data, count] = collector.TakeBackdropData();
1291 impeller_dispatcher.SetBackdropData(data, count);
1293 fml::ScopedCleanupClosure cleanup([&] {
1294 if (reset_host_buffer) {
1295 context.GetContentContext().GetTransientsDataBuffer().Reset();
1296 context.GetContentContext().GetTransientsIndexesBuffer().Reset();
1297 }
1298 context.GetContentContext().GetTextShadowCache().MarkFrameEnd();
1299 context.GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames();
1300 context.GetContext()->DisposeThreadLocalCachedResources();
1301 });
1302
1303 display_list->Dispatch(impeller_dispatcher, cull_rect);
1304 impeller_dispatcher.FinishRecording();
1305
1306 return target.GetRenderTargetTexture();
1307}
1308
1310 RenderTarget render_target,
1311 const sk_sp<flutter::DisplayList>& display_list,
1312 Rect cull_rect,
1313 bool reset_host_buffer,
1314 bool is_onscreen) {
1315 FirstPassDispatcher collector(context, impeller::Matrix(), cull_rect);
1316 display_list->Dispatch(collector, cull_rect);
1317
1318 impeller::CanvasDlDispatcher impeller_dispatcher(
1319 context, //
1320 render_target, //
1321 /*is_onscreen=*/is_onscreen, //
1322 display_list->root_has_backdrop_filter(), //
1323 display_list->max_root_blend_mode(), //
1324 IRect32::RoundOut(cull_rect) //
1325 );
1326 const auto& [data, count] = collector.TakeBackdropData();
1327 impeller_dispatcher.SetBackdropData(data, count);
1329 fml::ScopedCleanupClosure cleanup([&] {
1330 if (reset_host_buffer) {
1331 context.ResetTransientsBuffers();
1332 }
1333 context.GetTextShadowCache().MarkFrameEnd();
1334 });
1335
1336 display_list->Dispatch(impeller_dispatcher, cull_rect);
1337 impeller_dispatcher.FinishRecording();
1338 context.GetLazyGlyphAtlas()->ResetTextFrames();
1339
1340 return true;
1341}
1342
1343} // 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:1120
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:2229
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
Definition canvas.cc:1026
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
Definition canvas.cc:1501
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:1538
const Matrix & GetCurrentTransform() const
Definition canvas.cc:371
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
Definition canvas.cc:1301
void DrawOval(const Rect &rect, const Paint &paint)
Definition canvas.cc:856
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:1234
void RestoreToCount(size_t count)
Definition canvas.cc:418
size_t GetSaveCount() const
Definition canvas.cc:410
void Transform(const Matrix &transform)
Definition canvas.cc:367
uint64_t GetMaxOpDepth() const
Definition canvas.h:257
void DrawDashedLine(const Point &p0, const Point &p1, Scalar on_length, Scalar off_length, const Paint &paint)
Definition canvas.cc:799
void DrawDiffRoundRect(const RoundRect &outer, const RoundRect &inner, const Paint &paint)
Definition canvas.cc:1010
void DrawPath(const flutter::DlPath &path, const Paint &paint)
Definition canvas.cc:426
void PreConcat(const Matrix &transform)
Definition canvas.cc:359
void Rotate(Radians radians)
Definition canvas.cc:391
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
Definition canvas.cc:1202
void ResetTransform()
Definition canvas.cc:363
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
Definition canvas.cc:1960
void DrawPaint(const Paint &paint)
Definition canvas.cc:446
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
Definition canvas.cc:963
void Skew(Scalar sx, Scalar sy)
Definition canvas.cc:387
void Scale(const Vector2 &scale)
Definition canvas.cc:379
uint64_t GetOpDepth() const
Definition canvas.h:255
void Save(uint32_t total_content_depth=kMaxDepth)
Definition canvas.cc:1484
void DrawRect(const Rect &rect, const Paint &paint)
Definition canvas.cc:825
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
Definition canvas.cc:1416
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
Definition canvas.cc:776
void Translate(const Vector3 &offset)
Definition canvas.cc:375
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition canvas.cc:1083
void DrawArc(const Arc &arc, const Paint &paint)
Definition canvas.cc:911
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
std::shared_ptr< Texture > GetTexture(const sk_sp< flutter::DlImage > &image)
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
virtual const ContentContext & GetContentContext() const =0
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, 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)
static constexpr AttachmentConfig kDefaultColorAttachmentConfig
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...
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)
Point Vector2
Definition point.h:430
float Scalar
Definition scalar.h:19
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)
PointStyle
Definition canvas.h:66
@ kRound
Points are drawn as squares.
@ kSquare
Points are drawn as circles.
TPoint< Scalar > Point
Definition point.h:426
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:283
Scalar red
Definition color.h:128
Scalar green
Definition color.h:133
static Tone ComputeTone(const Color &c)
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:426
FilterContents::BlurStyle style
Definition paint.h:55
const flutter::DlColorFilter * color_filter
Definition paint.h:81
const flutter::DlColorSource * color_source
Definition paint.h:80
bool anti_alias
Definition paint.h:88
const flutter::DlImageFilter * image_filter
Definition paint.h:82
Style style
Definition paint.h:85
bool invert_colors
Definition paint.h:87
std::optional< StrokeParameters > GetStroke() const
Return an optional StrokeParameters if this Paint is a stroked Paint, otherwise return a nullopt.
Definition paint.h:95
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition paint.h:90
Color color
Definition paint.h:79
BlendMode blend_mode
Definition paint.h:86
StrokeParameters stroke
Definition paint.h:84
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:506
static constexpr TRect MakeWH(Type width, Type height)
Definition rect.h:140
constexpr std::optional< TRect > Intersection(const TRect &o) const
Definition rect.h:562
constexpr bool IsMaximum() const
Definition rect.h:348
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition rect.h:331
RoundOut(const TRect< U > &r)
Definition rect.h:713
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:212
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