9 #include <unordered_map>
12 #include "display_list/effects/color_filters/dl_blend_color_filter.h"
13 #include "display_list/effects/color_filters/dl_matrix_color_filter.h"
14 #include "display_list/effects/dl_color_filter.h"
15 #include "display_list/effects/dl_color_source.h"
16 #include "display_list/effects/dl_image_filter.h"
17 #include "display_list/image/dl_image.h"
18 #include "flutter/fml/logging.h"
19 #include "flutter/fml/trace_event.h"
59 bool IsPipelineBlendOrMatrixFilter(
const flutter::DlColorFilter* filter) {
60 return filter->type() == flutter::DlColorFilterType::kMatrix ||
61 (filter->type() == flutter::DlColorFilterType::kBlend &&
65 static bool UseColorSourceContents(
66 const std::shared_ptr<VerticesGeometry>& vertices,
70 if (vertices->HasVertexColors()) {
73 if (vertices->HasTextureCoordinates() && !paint.color_source) {
76 return !vertices->HasTextureCoordinates();
79 static void SetClipScissor(std::optional<Rect> clip_coverage,
81 Point global_pass_position) {
85 if (clip_coverage.has_value()) {
86 clip_coverage = clip_coverage->Shift(-global_pass_position);
93 pass.SetScissor(scissor);
96 static void ApplyFramebufferBlend(Entity& entity) {
97 auto src_contents = entity.GetContents();
98 auto contents = std::make_shared<FramebufferBlendContents>();
99 contents->SetChildContents(src_contents);
100 contents->SetBlendMode(entity.GetBlendMode());
101 entity.SetContents(std::move(contents));
107 static std::shared_ptr<Contents> CreateContentsForSubpassTarget(
109 const std::shared_ptr<Texture>& target,
110 const Matrix& effect_transform) {
112 contents->SetTexture(target);
113 contents->SetLabel(
"Subpass");
115 contents->SetOpacity(paint.color.alpha);
116 contents->SetDeferApplyingOpacity(
true);
118 return paint.WithFiltersForSubpassTarget(std::move(contents),
122 static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
123 RenderTarget::AttachmentConfig{
129 static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
130 ContentContext& renderer,
132 const Color& clear_color) {
133 const std::shared_ptr<Context>& context = renderer.GetContext();
141 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
142 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
148 RenderTarget::AttachmentConfigMSAA{
153 .clear_color = clear_color},
154 kDefaultStencilConfig);
156 target = renderer.GetRenderTargetCache()->CreateOffscreen(
161 RenderTarget::AttachmentConfig{
165 .clear_color = clear_color,
167 kDefaultStencilConfig
171 return std::make_unique<EntityPassTarget>(
173 renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
174 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
180 std::shared_ptr<SolidRRectLikeBlurContents>
181 Canvas::RRectBlurShape::BuildBlurContent() {
182 return std::make_shared<SolidRRectBlurContents>();
185 Geometry& Canvas::RRectBlurShape::BuildGeometry(
Rect rect,
Scalar radius) {
186 return geom_.emplace(rect,
Size{radius, radius});
189 std::shared_ptr<SolidRRectLikeBlurContents>
190 Canvas::RSuperellipseBlurShape::BuildBlurContent() {
191 return std::make_shared<SolidRSuperellipseBlurContents>();
194 Geometry& Canvas::RSuperellipseBlurShape::BuildGeometry(
Rect rect,
196 return geom_.emplace(rect, radius);
202 bool requires_readback)
203 : renderer_(renderer),
204 render_target_(render_target),
205 is_onscreen_(is_onscreen),
206 requires_readback_(requires_readback),
208 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
209 Initialize(std::nullopt);
216 bool requires_readback,
218 : renderer_(renderer),
219 render_target_(render_target),
220 is_onscreen_(is_onscreen),
221 requires_readback_(requires_readback),
223 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
224 Initialize(cull_rect);
231 bool requires_readback,
233 : renderer_(renderer),
234 render_target_(render_target),
235 is_onscreen_(is_onscreen),
236 requires_readback_(requires_readback),
238 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
244 void Canvas::Initialize(std::optional<Rect> cull_rect) {
245 initial_cull_rect_ = cull_rect;
252 void Canvas::Reset() {
254 transform_stack_ = {};
266 transform_stack_.back().transform = {};
274 return transform_stack_.back().transform;
297 Point Canvas::GetGlobalPassPosition()
const {
298 if (save_layer_state_.empty()) {
301 return save_layer_state_.back().coverage.GetOrigin();
305 size_t Canvas::GetClipHeightFloor()
const {
306 if (transform_stack_.size() > 1) {
307 return transform_stack_[transform_stack_.size() - 2].clip_height;
313 return transform_stack_.size();
316 bool Canvas::IsSkipping()
const {
317 return transform_stack_.back().skipping;
335 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
338 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
348 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
355 bool Canvas::AttemptColorFilterOptimization(
356 const std::shared_ptr<Texture>& image,
370 if (paint.
color_filter->type() == flutter::DlColorFilterType::kBlend) {
371 const flutter::DlBlendColorFilter* blend_filter =
373 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
378 blend_filter->mode(),
380 src_rect_constraint ==
383 auto atlas_contents = std::make_shared<AtlasContents>();
384 atlas_contents->SetGeometry(&geometry);
390 entity.SetContents(atlas_contents);
392 AddRenderEntityToCurrentPass(entity);
400 const flutter::DlMatrixColorFilter* matrix_filter =
403 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
410 src_rect_constraint ==
413 auto atlas_contents = std::make_shared<ColorFilterAtlasContents>();
414 atlas_contents->SetGeometry(&geometry);
417 matrix_filter->get_matrix(color_matrix.
array);
418 atlas_contents->SetMatrix(color_matrix);
423 entity.SetContents(atlas_contents);
425 AddRenderEntityToCurrentPass(entity);
430 bool Canvas::AttemptDrawAntialiasedCircle(
const Point& center,
432 const Paint& paint) {
433 if (paint.HasColorFilter() || paint.image_filter || paint.invert_colors ||
434 paint.color_source || paint.mask_blur_descriptor.has_value()) {
440 entity.SetBlendMode(paint.blend_mode);
443 std::unique_ptr<CircleGeometry> geom;
445 geom = std::make_unique<CircleGeometry>(center, radius, paint.stroke.width);
447 geom = std::make_unique<CircleGeometry>(center, radius);
453 entity.SetContents(std::move(contents));
454 AddRenderEntityToCurrentPass(entity);
459 bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
461 const Paint& paint) {
462 RRectBlurShape rrect_shape;
463 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint, rrect_shape);
466 bool Canvas::AttemptDrawBlurredRSuperellipse(
const Rect& rect,
468 const Paint& paint) {
469 RSuperellipseBlurShape rsuperellipse_shape;
470 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint,
471 rsuperellipse_shape);
474 bool Canvas::AttemptDrawBlurredRRectLike(
const Rect& rect,
477 RRectLikeBlurShape& shape) {
482 if (paint.color_source) {
486 if (!paint.mask_blur_descriptor.has_value()) {
496 if (fabsf(corner_radii.width - corner_radii.height) >
kEhCloseEnough) {
499 Scalar corner_radius = corner_radii.width;
503 Color rrect_color = paint.color;
504 if (paint.invert_colors) {
507 if (paint.color_filter) {
511 Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor};
532 if ((paint.mask_blur_descriptor->style !=
534 paint.image_filter) ||
537 Rect render_bounds = rect;
538 if (paint.mask_blur_descriptor->style !=
541 render_bounds.
Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
547 .image_filter = paint.image_filter,
548 .blend_mode = paint.blend_mode,
551 rrect_paint.color = rrect_color.WithAlpha(1);
553 rrect_paint.color = rrect_color;
554 rrect_paint.blend_mode = paint.blend_mode;
555 rrect_paint.image_filter = paint.image_filter;
559 auto draw_blurred_rrect = [
this, &rect, corner_radius, &rrect_paint,
561 auto contents = shape.BuildBlurContent();
563 contents->SetColor(rrect_paint.color);
564 contents->SetSigma(rrect_paint.mask_blur_descriptor->sigma);
565 contents->SetShape(rect, corner_radius);
567 Entity blurred_rrect_entity;
569 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
571 rrect_paint.mask_blur_descriptor = std::nullopt;
572 blurred_rrect_entity.SetContents(
573 rrect_paint.WithFilters(std::move(contents)));
574 AddRenderEntityToCurrentPass(blurred_rrect_entity);
577 switch (rrect_paint.mask_blur_descriptor->style) {
579 draw_blurred_rrect();
584 draw_blurred_rrect();
588 entity.SetBlendMode(rrect_paint.blend_mode);
590 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
591 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, rrect_paint,
596 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
598 draw_blurred_rrect();
602 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
604 draw_blurred_rrect();
622 auto geometry = std::make_unique<LineGeometry>(p0, p1, paint.
stroke);
624 if (renderer_.
GetContext()->GetFlags().antialiased_lines &&
629 AddRenderEntityToCurrentPass(entity, reuse_depth);
631 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
640 const Paint& paint) {
650 if (length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
656 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
663 if (AttemptDrawBlurredRRect(rect, {}, paint)) {
673 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
676 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
692 if (AttemptDrawBlurredRRect(rect, rect.
GetSize() * 0.5f, paint)) {
702 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
705 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
716 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
729 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
742 return DrawOval(oval_bounds, paint);
752 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
758 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
763 auto& radii = round_rect.
GetRadii();
764 if (radii.AreAllCornersSame()) {
765 if (AttemptDrawBlurredRRect(rect, radii.top_left, paint)) {
775 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
786 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
789 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
795 const Paint& paint) {
802 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
805 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
810 const Paint& paint) {
811 auto& rect = round_superellipse.
GetBounds();
812 auto& radii = round_superellipse.
GetRadii();
813 if (radii.AreAllCornersSame() &&
814 AttemptDrawBlurredRSuperellipse(rect, radii.top_left, paint)) {
824 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
827 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
833 const Paint& paint) {
834 Size half_size(radius, radius);
835 if (AttemptDrawBlurredRRect(
837 {radius, radius}, paint)) {
841 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
851 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
854 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
875 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
876 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
877 uint32_t clip_depth = transform_stack_.back().clip_depth;
879 const Matrix clip_transform =
883 std::optional<Rect> clip_coverage = geometry.
GetCoverage(clip_transform);
884 if (!clip_coverage.has_value()) {
889 clip_coverage.value(),
898 GetGlobalPassPosition(),
900 GetClipHeightFloor(),
907 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
908 GetGlobalPassPosition());
911 ++transform_stack_.back().clip_height;
912 ++transform_stack_.back().num_clips;
929 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
936 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
955 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
982 ISize size = image->GetSize();
987 std::optional<Rect> clipped_source =
989 if (!clipped_source) {
993 if (AttemptColorFilterOptimization(image, source, dest, paint, sampler,
994 src_rect_constraint)) {
998 if (*clipped_source != source) {
1008 texture_contents->SetTexture(image);
1009 texture_contents->SetSourceRect(*clipped_source);
1010 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1012 texture_contents->SetSamplerDescriptor(sampler);
1013 texture_contents->SetOpacity(paint.
color.
alpha);
1014 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
1022 AddRenderEntityToCurrentPass(entity);
1030 AddRenderEntityToCurrentPass(entity);
1033 size_t Canvas::GetClipHeight()
const {
1034 return transform_stack_.back().clip_height;
1039 const Paint& paint) {
1052 if (UseColorSourceContents(vertices, paint)) {
1053 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1059 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1060 contents->SetBlendMode(blend_mode);
1062 contents->SetGeometry(vertices);
1064 AddRenderEntityToCurrentPass(entity);
1071 paint.
color_source->type() == flutter::DlColorSourceType::kImage) {
1072 const flutter::DlImageColorSource* image_color_source =
1074 FML_DCHECK(image_color_source &&
1075 image_color_source->image()->impeller_texture());
1076 auto texture = image_color_source->image()->impeller_texture();
1078 image_color_source->horizontal_tile_mode());
1081 auto sampler_descriptor =
1083 auto effect_transform = image_color_source->matrix();
1085 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1086 contents->SetBlendMode(blend_mode);
1088 contents->SetGeometry(vertices);
1089 contents->SetEffectTransform(effect_transform);
1090 contents->SetTexture(texture);
1091 contents->SetTileMode(x_tile_mode, y_tile_mode);
1092 contents->SetSamplerDescriptor(sampler_descriptor);
1095 AddRenderEntityToCurrentPass(entity);
1099 auto src_paint = paint;
1102 std::shared_ptr<ColorSourceContents> src_contents =
1103 src_paint.CreateContents();
1104 src_contents->SetGeometry(vertices.get());
1112 auto size = src_contents->GetColorSourceSize();
1113 if (size.has_value()) {
1116 auto cvg = vertices->GetCoverage(
Matrix{});
1117 FML_CHECK(cvg.has_value());
1118 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1119 if (texture_coverage.has_value()) {
1122 texture_coverage->GetSize().Max({1, 1}));
1125 src_coverage = cvg.value();
1128 src_contents = src_paint.CreateContents();
1131 src_contents->SetGeometry(clip_geometry_.back().get());
1133 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1134 contents->SetBlendMode(blend_mode);
1136 contents->SetGeometry(vertices);
1137 contents->SetLazyTextureCoverage(src_coverage);
1138 contents->SetLazyTexture(
1143 auto snapshot = src_contents->RenderToSnapshot(
1144 renderer, {}, {.coverage_limit =
Rect::Round(src_coverage)});
1145 return snapshot.has_value() ? snapshot->texture :
nullptr;
1148 AddRenderEntityToCurrentPass(entity);
1152 const Paint& paint) {
1160 AddRenderEntityToCurrentPass(entity);
1166 void Canvas::SetupRenderPass() {
1172 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
1177 *renderer_.
GetContext()->GetResourceAllocator(),
1179 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA() &&
1180 color0.
texture->GetTextureDescriptor().sample_count >
1182 "ImpellerOnscreen", kDefaultStencilConfig);
1194 if (requires_readback_) {
1195 auto entity_pass_target =
1196 CreateRenderTarget(renderer_,
1199 render_passes_.push_back(
1200 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1202 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1207 render_passes_.push_back(
1208 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1212 void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
1213 auto entry = CanvasStackEntry{};
1214 entry.skipping =
true;
1215 entry.clip_depth = current_depth_ + total_content_depth;
1216 transform_stack_.push_back(entry);
1221 return SkipUntilMatchingRestore(total_content_depth);
1225 entry.
transform = transform_stack_.back().transform;
1226 entry.clip_depth = current_depth_ + total_content_depth;
1227 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1228 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1229 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1230 <<
" after allocating " << total_content_depth;
1231 entry.clip_height = transform_stack_.back().clip_height;
1233 transform_stack_.push_back(entry);
1240 return std::nullopt;
1243 std::optional<Rect> maybe_current_clip_coverage =
1245 if (!maybe_current_clip_coverage.has_value()) {
1246 return std::nullopt;
1249 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1251 FML_CHECK(!render_passes_.empty());
1253 std::shared_ptr<Texture> back_texture =
1255 FML_CHECK(back_texture) <<
"Context is valid:"
1260 std::optional<Rect> maybe_coverage_limit =
1262 Size(back_texture->GetSize()))
1265 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1266 return std::nullopt;
1269 return maybe_coverage_limit->Intersection(
1274 std::optional<Rect> bounds,
1275 const flutter::DlImageFilter* backdrop_filter,
1277 uint32_t total_content_depth,
1278 bool can_distribute_opacity,
1279 std::optional<int64_t> backdrop_id) {
1280 TRACE_EVENT0(
"flutter",
"Canvas::saveLayer");
1282 return SkipUntilMatchingRestore(total_content_depth);
1286 if (!maybe_coverage_limit.has_value()) {
1287 return SkipUntilMatchingRestore(total_content_depth);
1289 auto coverage_limit = maybe_coverage_limit.value();
1291 if (can_distribute_opacity && !backdrop_filter &&
1294 Save(total_content_depth);
1295 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1299 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1300 Rect(), transform_stack_.back().transform,
1305 transform_stack_.back().transform,
1310 !!backdrop_filter ||
1315 if (!maybe_subpass_coverage.has_value()) {
1316 return SkipUntilMatchingRestore(total_content_depth);
1319 auto subpass_coverage = maybe_subpass_coverage.value();
1330 bool did_round_out =
false;
1331 Point coverage_origin_adjustment =
Point{0, 0};
1335 did_round_out =
true;
1339 coverage_origin_adjustment =
1340 Point(subpass_coverage.GetLeftTop().x -
1341 std::floor(subpass_coverage.GetLeftTop().x),
1342 subpass_coverage.GetLeftTop().y -
1343 std::floor(subpass_coverage.GetLeftTop().y));
1346 return SkipUntilMatchingRestore(total_content_depth);
1354 ->GetMaximumRenderPassAttachmentSize());
1357 std::shared_ptr<FilterContents> backdrop_filter_contents;
1359 if (backdrop_filter) {
1360 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1362 [backdrop_filter = backdrop_filter](
1365 auto filter =
WrapInput(backdrop_filter, input);
1366 filter->SetEffectTransform(effect_transform);
1367 filter->SetRenderingMode(rendering_mode);
1371 std::shared_ptr<Texture> input_texture;
1376 bool will_cache_backdrop_texture =
false;
1381 size_t backdrop_count = 1;
1382 if (backdrop_id.has_value()) {
1383 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1384 backdrop_data_.find(backdrop_id.value());
1385 if (backdrop_data_it != backdrop_data_.end()) {
1386 backdrop_data = &backdrop_data_it->second;
1387 will_cache_backdrop_texture =
1389 backdrop_count = backdrop_data_it->second.backdrop_count;
1393 if (!will_cache_backdrop_texture || !backdrop_data->
texture_slot) {
1394 backdrop_count_ -= backdrop_count;
1400 const bool should_use_onscreen =
1402 backdrop_count_ == 0 && render_passes_.size() == 1u;
1403 input_texture = FlipBackdrop(
1404 GetGlobalPassPosition(),
1405 will_cache_backdrop_texture,
1408 if (!input_texture) {
1413 if (will_cache_backdrop_texture) {
1420 backdrop_filter_contents = backdrop_filter_proc(
1422 transform_stack_.back().transform.Basis(),
1425 transform_stack_.back().transform.HasTranslation()
1429 if (will_cache_backdrop_texture) {
1430 FML_DCHECK(backdrop_data);
1437 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1440 std::optional<Snapshot> maybe_snapshot =
1442 if (maybe_snapshot.has_value()) {
1443 const Snapshot& snapshot = maybe_snapshot.value();
1445 subpass_coverage.Shift(-GetGlobalPassPosition()));
1448 contents->SetTexture(snapshot.
texture);
1449 contents->SetSourceRect(scaled);
1459 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1467 Paint paint_copy = paint;
1468 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1469 transform_stack_.back().distributed_opacity = 1.0;
1471 render_passes_.push_back(
1473 CreateRenderTarget(renderer_,
1478 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1481 entry.
transform = transform_stack_.back().transform;
1482 entry.
clip_depth = current_depth_ + total_content_depth;
1483 FML_DCHECK(entry.
clip_depth <= transform_stack_.back().clip_depth)
1484 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1485 <<
" after allocating " << total_content_depth;
1486 entry.
clip_height = transform_stack_.back().clip_height;
1489 transform_stack_.emplace_back(entry);
1496 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1498 if (!backdrop_filter_contents) {
1504 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1507 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1508 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1512 FML_DCHECK(transform_stack_.size() > 0);
1513 if (transform_stack_.size() == 1) {
1530 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1531 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1532 current_depth_ = transform_stack_.back().clip_depth;
1535 transform_stack_.pop_back();
1539 if (transform_stack_.back().rendering_mode ==
1541 transform_stack_.back().rendering_mode ==
1543 auto lazy_render_pass = std::move(render_passes_.back());
1544 render_passes_.pop_back();
1546 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1549 save_layer_state_.pop_back();
1550 auto global_pass_position = GetGlobalPassPosition();
1552 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1553 save_layer_state.
paint,
1554 lazy_render_pass.GetInlinePassContext()->GetTexture(),
1556 transform_stack_.back().transform
1559 lazy_render_pass.GetInlinePassContext()->EndPass();
1566 Point subpass_texture_position;
1567 if (transform_stack_.back().did_round_out) {
1570 subpass_texture_position =
1575 subpass_texture_position =
1589 ApplyFramebufferBlend(element_entity);
1600 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1601 if (!input_texture) {
1611 contents->SetCoverageHint(element_entity.
GetCoverage());
1619 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1622 transform_stack_.pop_back();
1630 size_t num_clips = transform_stack_.back().num_clips;
1631 transform_stack_.pop_back();
1633 if (num_clips > 0) {
1644 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1645 GetGlobalPassPosition()
1653 bool Canvas::AttemptBlurredTextOptimization(
1654 const std::shared_ptr<TextFrame>& text_frame,
1655 const std::shared_ptr<TextContents>& text_contents,
1657 const Paint& paint) {
1671 std::shared_ptr<FilterContents> filter =
1676 std::optional<Glyph> maybe_glyph = text_frame->AsSingleGlyph();
1677 int64_t identifier = maybe_glyph.has_value()
1678 ? maybe_glyph.value().index
1679 :
reinterpret_cast<int64_t
>(text_frame.get());
1680 TextShadowCache::TextShadowCacheKey cache_key(
1683 maybe_glyph.has_value(),
1684 text_frame->GetFont(),
1689 renderer_, entity, filter, cache_key);
1690 if (result.has_value()) {
1691 AddRenderEntityToCurrentPass(result.value(),
false);
1705 const Paint& paint) {
1707 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1709 fml::StatusOr<flutter::DlPath> path = text_frame->GetPath();
1723 auto text_contents = std::make_shared<TextContents>();
1724 text_contents->SetTextFrame(text_frame);
1726 text_contents->SetScale(max_scale);
1727 text_contents->SetColor(paint.
color);
1728 text_contents->SetOffset(position);
1729 text_contents->SetTextProperties(paint.
color,
1731 ? std::optional(paint.
stroke)
1737 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1743 AddRenderEntityToCurrentPass(entity,
false);
1746 void Canvas::AddRenderEntityWithFiltersToCurrentPass(
Entity& entity,
1750 std::shared_ptr<ColorSourceContents> contents = paint.
CreateContents();
1753 contents->SetGeometry(geometry);
1755 AddRenderEntityToCurrentPass(entity, reuse_depth);
1763 if (needs_color_filter &&
1764 contents->ApplyColorFilter([&](Color color) -> Color {
1765 if (paint.color_filter) {
1766 color = GetCPUColorFilterProc(paint.color_filter)(color);
1769 color = color.ApplyColorMatrix(kColorInversion);
1773 needs_color_filter =
false;
1777 contents->SetGeometry(geometry);
1783 FillRectGeometry out_rect(
Rect{});
1785 contents, needs_color_filter ? paint.
color_filter :
nullptr,
1786 needs_color_filter ? paint.
invert_colors :
false, &out_rect);
1788 AddRenderEntityToCurrentPass(entity, reuse_depth);
1792 std::shared_ptr<Contents> contents_copy = std::move(contents);
1796 if (needs_color_filter &&
1798 paint.
color_source->type() != flutter::DlColorSourceType::kImage)) {
1812 std::shared_ptr<FilterContents> filter =
WrapInput(
1816 AddRenderEntityToCurrentPass(entity, reuse_depth);
1821 AddRenderEntityToCurrentPass(entity, reuse_depth);
1824 void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
1829 entity.SetTransform(
1830 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1831 entity.GetTransform());
1832 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
1833 if (entity.GetBlendMode() == BlendMode::kSrcOver &&
1834 entity.GetContents()->IsOpaque(entity.GetTransform())) {
1835 entity.SetBlendMode(BlendMode::kSrc);
1841 if (render_passes_.back().IsApplyingClearColor()) {
1842 std::optional<Color> maybe_color = entity.AsBackgroundColor(
1843 render_passes_.back().GetInlinePassContext()->GetTexture()->GetSize());
1844 if (maybe_color.has_value()) {
1845 Color color = maybe_color.value();
1846 RenderTarget& render_target = render_passes_.back()
1847 .GetInlinePassContext()
1850 ColorAttachment attachment = render_target.GetColorAttachment(0);
1853 attachment.clear_color = attachment.clear_color.Unpremultiply()
1854 .Blend(color, entity.GetBlendMode())
1856 render_target.SetColorAttachment(attachment, 0u);
1867 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1868 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1869 entity.SetClipDepth(current_depth_);
1871 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1872 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
1873 ApplyFramebufferBlend(entity);
1884 auto input_texture = FlipBackdrop(GetGlobalPassPosition(),
1888 if (!input_texture) {
1896 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
1897 entity.GetContents()->SetCoverageHint(Rect::Intersection(
1898 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
1900 FilterInput::Vector inputs = {
1901 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
1902 FilterInput::Make(entity.GetContents())};
1904 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
1905 entity.SetContents(std::move(contents));
1906 entity.SetBlendMode(BlendMode::kSrc);
1910 const std::shared_ptr<RenderPass>& result =
1911 render_passes_.back().GetInlinePassContext()->GetRenderPass();
1919 entity.Render(renderer_, *result);
1922 RenderPass& Canvas::GetCurrentRenderPass()
const {
1923 return *render_passes_.back().GetInlinePassContext()->GetRenderPass();
1926 void Canvas::SetBackdropData(
1927 std::unordered_map<int64_t, BackdropData> backdrop_data,
1928 size_t backdrop_count) {
1929 backdrop_data_ = std::move(backdrop_data);
1930 backdrop_count_ = backdrop_count;
1933 std::shared_ptr<Texture> Canvas::FlipBackdrop(
Point global_pass_position,
1934 bool should_remove_texture,
1935 bool should_use_onscreen,
1936 bool post_depth_increment) {
1938 render_passes_.pop_back();
1954 <<
"Failed to end the current render pass in order to read from "
1955 "the backdrop texture and apply an advanced blend or backdrop "
1960 render_passes_.emplace_back(std::move(rendering_config));
1964 const std::shared_ptr<Texture>& input_texture =
1967 if (!input_texture) {
1968 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
1969 "apply an advanced blend or backdrop filter.";
1972 render_passes_.emplace_back(std::move(rendering_config));
1976 if (should_use_onscreen) {
1977 ColorAttachment color0 = render_target_.GetColorAttachment(0);
1981 color0.
load_action = color0.resolve_texture !=
nullptr
1982 ? LoadAction::kDontCare
1983 : LoadAction::kLoad;
1984 render_target_.SetColorAttachment(color0, 0);
1986 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1988 renderer_.GetDeviceCapabilities().SupportsReadFromResolve(),
1989 renderer_.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
1991 render_passes_.push_back(
1992 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1993 requires_readback_ =
false;
1995 render_passes_.emplace_back(std::move(rendering_config));
1998 if (should_remove_texture) {
1999 render_passes_.back().GetEntityPassTarget()->RemoveSecondary();
2002 RenderPass& current_render_pass =
2003 *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2012 Rect size_rect = Rect::MakeSize(input_texture->GetSize());
2013 auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
2014 msaa_backdrop_contents->SetStencilEnabled(
false);
2015 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
2016 msaa_backdrop_contents->SetSourceRect(size_rect);
2017 msaa_backdrop_contents->SetTexture(input_texture);
2019 Entity msaa_backdrop_entity;
2020 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
2021 msaa_backdrop_entity.SetBlendMode(BlendMode::kSrc);
2022 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
2023 if (!msaa_backdrop_entity.Render(renderer_, current_render_pass)) {
2030 auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
2031 uint64_t current_depth =
2032 post_depth_increment ? current_depth_ - 1 : current_depth_;
2033 for (
const auto& replay : replay_entities) {
2034 if (replay.clip_depth <= current_depth) {
2038 SetClipScissor(replay.clip_coverage, current_render_pass,
2039 global_pass_position);
2040 if (!replay.clip_contents.Render(renderer_, current_render_pass,
2041 replay.clip_depth)) {
2046 return input_texture;
2049 bool Canvas::SupportsBlitToOnscreen()
const {
2050 return renderer_.GetContext()
2052 ->SupportsTextureToTextureBlits() &&
2053 renderer_.GetContext()->GetBackendType() ==
2054 Context::BackendType::kMetal;
2057 bool Canvas::BlitToOnscreen(
bool is_onscreen) {
2058 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
2059 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
2060 auto offscreen_target = render_passes_.back()
2061 .GetInlinePassContext()
2064 if (SupportsBlitToOnscreen()) {
2065 auto blit_pass = command_buffer->CreateBlitPass();
2066 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
2067 render_target_.GetRenderTargetTexture());
2068 if (!blit_pass->EncodeCommands()) {
2073 auto render_pass = command_buffer->CreateRenderPass(render_target_);
2074 render_pass->SetLabel(
"EntityPass Root Render Pass");
2077 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
2078 auto contents = TextureContents::MakeRect(size_rect);
2079 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
2080 contents->SetSourceRect(size_rect);
2081 contents->SetLabel(
"Root pass blit");
2084 entity.SetContents(contents);
2085 entity.SetBlendMode(BlendMode::kSrc);
2087 if (!entity.Render(renderer_, *render_pass)) {
2093 if (!render_pass->EncodeCommands()) {
2100 return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer));
2102 return renderer_.GetContext()->EnqueueCommandBuffer(
2103 std::move(command_buffer));
2107 bool Canvas::EnsureFinalMipmapGeneration()
const {
2108 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2111 std::shared_ptr<CommandBuffer> cmd_buffer =
2112 renderer_.GetContext()->CreateCommandBuffer();
2116 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2120 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2121 blit_pass->EncodeCommands();
2122 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2125 void Canvas::EndReplay() {
2126 FML_DCHECK(render_passes_.size() == 1u);
2127 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2128 render_passes_.back().GetInlinePassContext()->EndPass(
2129 !requires_readback_ && is_onscreen_);
2130 backdrop_data_.clear();
2135 if (requires_readback_) {
2136 BlitToOnscreen(is_onscreen_);
2138 if (!EnsureFinalMipmapGeneration()) {
2141 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2145 render_passes_.clear();
2146 renderer_.GetRenderTargetCache()->End();
2147 clip_geometry_.clear();
2150 Initialize(initial_cull_rect_);
2153 LazyRenderingConfig::LazyRenderingConfig(
2155 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
2156 : entity_pass_target_(
std::move(p_entity_pass_target)) {
2157 inline_pass_context_ =
2158 std::make_unique<InlinePassContext>(renderer, *entity_pass_target_);
2162 return !inline_pass_context_->IsActive();
2166 return entity_pass_target_.get();
2170 return inline_pass_context_.get();
A Geometry that produces fillable vertices representing the stroked outline of an |Arc| object using ...
void ClipGeometry(const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
static constexpr uint32_t kMaxDepth
Canvas(ContentContext &renderer, const RenderTarget &render_target, bool is_onscreen, bool requires_readback)
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
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)
const Matrix & GetCurrentTransform() const
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
void DrawOval(const Rect &rect, const Paint &paint)
void DrawImageRect(const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, const SamplerDescriptor &sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
void RestoreToCount(size_t count)
size_t GetSaveCount() const
void Concat(const Matrix &transform)
void Transform(const Matrix &transform)
void DrawDashedLine(const Point &p0, const Point &p1, Scalar on_length, Scalar off_length, const Paint &paint)
void DrawDiffRoundRect(const RoundRect &outer, const RoundRect &inner, const Paint &paint)
void DrawPath(const flutter::DlPath &path, const Paint &paint)
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
void PreConcat(const Matrix &transform)
void Rotate(Radians radians)
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
void DrawImage(const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, const SamplerDescriptor &sampler={})
void DrawPaint(const Paint &paint)
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
void Skew(Scalar sx, Scalar sy)
void Scale(const Vector2 &scale)
void Save(uint32_t total_content_depth=kMaxDepth)
void DrawRect(const Rect &rect, const Paint &paint)
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
void Translate(const Vector3 &offset)
void DrawCircle(const Point ¢er, Scalar radius, const Paint &paint)
void DrawArc(const Arc &arc, const Paint &paint)
virtual bool SupportsImplicitResolvingMSAA() const =0
Whether the context backend supports multisampled rendering to the on-screen surface without requirin...
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
virtual bool SupportsReadFromResolve() const =0
Whether the context backend supports binding the current RenderPass attachments. This is supported if...
static std::unique_ptr< CircleContents > Make(std::unique_ptr< CircleGeometry > geometry, Color color, bool stroked)
void SetGeometry(GeometryResult geometry)
Set the pre-tessellated clip geometry.
void SetClipOperation(Entity::ClipOperation clip_op)
bool Render(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth) const
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
const Capabilities & GetDeviceCapabilities() const
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
TextShadowCache & GetTextShadowCache() const
std::shared_ptr< Context > GetContext() const
A geometry that implements "drawPaint" like behavior by covering the entire render pass area.
A Geometry class that can directly generate vertices (with or without texture coordinates) for filled...
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
std::optional< Rect > GetCoverage() const
@ kSubpassPrependSnapshotTransform
@ kSubpassAppendSnapshotTransform
const std::shared_ptr< Contents > & GetContents() const
void SetClipDepth(uint32_t clip_depth)
BlendMode GetBlendMode() const
void SetContents(std::shared_ptr< Contents > contents)
void SetBlendMode(BlendMode blend_mode)
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
static constexpr BlendMode kLastPipelineBlendMode
static bool IsBlendModeDestructive(BlendMode blend_mode)
Returns true if the blend mode is "destructive", meaning that even fully transparent source colors wo...
A class that tracks all clips that have been recorded in the current entity pass stencil.
std::optional< Rect > CurrentClipCoverage() const
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_height)
ReplayResult & GetLastReplayResult()
ClipStateResult RecordClip(const ClipContents &clip_contents, Matrix transform, Point global_pass_position, uint32_t clip_depth, size_t clip_height_floor, bool is_aa)
ClipStateResult RecordRestore(Point global_pass_position, size_t restore_height)
A Geometry that produces fillable vertices for the gap between a pair of |RoundRect| objects using th...
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.
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
virtual GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const =0
virtual bool CanApplyMaskFilter() const
virtual std::optional< Rect > GetCoverage(const Matrix &transform) const =0
virtual bool IsAxisAlignedRect() const
bool EndPass(bool is_onscreen=false)
std::shared_ptr< Texture > GetTexture()
const std::shared_ptr< RenderPass > & GetRenderPass()
bool IsApplyingClearColor() const
Whether or not the clear color texture can still be updated.
EntityPassTarget * GetEntityPassTarget() const
InlinePassContext * GetInlinePassContext() const
static std::unique_ptr< LineContents > Make(std::unique_ptr< LineGeometry > geometry, Color color)
A geometry class specialized for Canvas::DrawPoints.
ColorAttachment GetColorAttachment(size_t index) const
Get the color attachment at [index].
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
ISize GetRenderTargetSize() const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
void SetupDepthStencilAttachments(const Context &context, Allocator &allocator, ISize size, bool msaa, std::string_view label="Offscreen", RenderTarget::AttachmentConfig stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &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...
A Geometry that produces fillable vertices representing the stroked outline of a |DlPath| object usin...
A Geometry that produces fillable vertices representing the stroked outline of a pair of nested |Roun...
A Geometry class that produces fillable vertices representing the stroked outline of an ellipse with ...
A Geometry that produces fillable vertices representing the stroked outline of a |DlPath| object usin...
A Geometry class that produces fillable vertices representing the stroked outline of any |Roundrect| ...
A Geometry class that produces fillable vertices representing the stroked outline of any |RoundSupere...
std::optional< Entity > Lookup(const ContentContext &renderer, const Entity &entity, const std::shared_ptr< FilterContents > &contents, const TextShadowCacheKey &)
Lookup the entity in the cache with the given filter/text contents, returning the new entity to rende...
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
ISize subpass_size
The output size of the down-sampling pass.
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Color ToColor(const flutter::DlColor &color)
static constexpr Scalar kMaxTextScale
std::shared_ptr< ColorFilterContents > WrapWithGPUColorFilter(const flutter::DlColorFilter *filter, const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
@ kStrict
Sample only within the source rectangle. May be slower.
std::shared_ptr< FilterContents > WrapInput(const flutter::DlImageFilter *filter, const FilterInput::Ref &input)
Generate a new FilterContents using this filter's configuration.
constexpr float kEhCloseEnough
std::shared_ptr< ColorFilterContents > WrapWithInvertColors(const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
@ kRound
Points are drawn as squares.
ColorFilterProc GetCPUColorFilterProc(const flutter::DlColorFilter *filter)
@ 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...
static constexpr const ColorMatrix kColorInversion
A color matrix which inverts colors.
std::optional< Rect > ComputeSaveLayerCoverage(const Rect &content_coverage, const Matrix &effect_transform, const Rect &coverage_limit, const std::shared_ptr< FilterContents > &image_filter, bool flood_output_coverage, bool flood_input_coverage)
Compute the coverage of a subpass in the global coordinate space.
constexpr bool IncludeCenter() const
constexpr bool IsFullCircle() const
const Rect & GetOvalBounds() const
Return the bounds of the oval in which this arc is inscribed.
constexpr Degrees GetSweep() const
constexpr Degrees GetStart() const
std::shared_ptr< Texture > texture
std::shared_ptr< Texture > texture_slot
std::optional< Snapshot > shared_filter_snapshot
Entity::RenderingMode rendering_mode
static constexpr Color BlackTransparent()
static constexpr Color Khaki()
static constexpr Color White()
constexpr Color WithAlpha(Scalar new_alpha) const
ClipContents clip_contents
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...
std::shared_ptr< Contents > WithFilters(std::shared_ptr< Contents > input) const
Wrap this paint's configured filters to the given contents.
const flutter::DlColorFilter * color_filter
const flutter::DlColorSource * color_source
const flutter::DlImageFilter * image_filter
static bool CanApplyOpacityPeephole(const Paint &paint)
Whether or not a save layer with the provided paint can perform the opacity peephole optimization.
std::optional< MaskBlurDescriptor > mask_blur_descriptor
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
std::shared_ptr< ColorSourceContents > CreateContents() const
bool HasColorFilter() const
Whether this paint has a color filter that can apply opacity.
constexpr const RoundingRadii & GetRadii() const
constexpr const Rect & GetBounds() const
constexpr const RoundingRadii & GetRadii() const
constexpr const Rect & GetBounds() const
Represents a texture and its intended draw transform/sampler configuration.
Matrix transform
The transform that should be applied to this texture for rendering.
std::shared_ptr< Texture > texture
SamplerDescriptor sampler_descriptor
constexpr Type GetDistance(const TPoint &p) const
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
constexpr auto GetBottom() const
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
constexpr auto GetTop() const
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
constexpr std::optional< TRect > Intersection(const TRect &o) const
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr auto GetLeft() const
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Round(const TRect< U > &r)
RoundOut(const TRect< U > &r)
constexpr auto GetRight() const
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
constexpr static TRect MakeSize(const TSize< U > &size)
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
constexpr static TRect MakeMaximum()
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
std::vector< Point > points