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"
58 bool IsPipelineBlendOrMatrixFilter(
const flutter::DlColorFilter* filter) {
59 return filter->type() == flutter::DlColorFilterType::kMatrix ||
60 (filter->type() == flutter::DlColorFilterType::kBlend &&
64 static bool UseColorSourceContents(
65 const std::shared_ptr<VerticesGeometry>& vertices,
69 if (vertices->HasVertexColors()) {
72 if (vertices->HasTextureCoordinates() && !paint.color_source) {
75 return !vertices->HasTextureCoordinates();
78 static void SetClipScissor(std::optional<Rect> clip_coverage,
80 Point global_pass_position) {
84 if (clip_coverage.has_value()) {
85 clip_coverage = clip_coverage->Shift(-global_pass_position);
92 pass.SetScissor(scissor);
95 static void ApplyFramebufferBlend(Entity& entity) {
96 auto src_contents = entity.GetContents();
97 auto contents = std::make_shared<FramebufferBlendContents>();
98 contents->SetChildContents(src_contents);
99 contents->SetBlendMode(entity.GetBlendMode());
100 entity.SetContents(std::move(contents));
106 static std::shared_ptr<Contents> CreateContentsForSubpassTarget(
108 const std::shared_ptr<Texture>& target,
109 const Matrix& effect_transform) {
111 contents->SetTexture(target);
112 contents->SetLabel(
"Subpass");
114 contents->SetOpacity(paint.color.alpha);
115 contents->SetDeferApplyingOpacity(
true);
117 return paint.WithFiltersForSubpassTarget(std::move(contents),
121 static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
122 RenderTarget::AttachmentConfig{
128 static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
129 ContentContext& renderer,
131 const Color& clear_color) {
132 const std::shared_ptr<Context>& context = renderer.GetContext();
140 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
141 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
147 RenderTarget::AttachmentConfigMSAA{
152 .clear_color = clear_color},
153 kDefaultStencilConfig);
155 target = renderer.GetRenderTargetCache()->CreateOffscreen(
160 RenderTarget::AttachmentConfig{
164 .clear_color = clear_color,
166 kDefaultStencilConfig
170 return std::make_unique<EntityPassTarget>(
172 renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
173 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
179 std::shared_ptr<SolidRRectLikeBlurContents>
180 Canvas::RRectBlurShape::BuildBlurContent() {
181 return std::make_shared<SolidRRectBlurContents>();
184 Geometry& Canvas::RRectBlurShape::BuildGeometry(
Rect rect,
Scalar radius) {
185 return geom_.emplace(rect,
Size{radius, radius});
188 std::shared_ptr<SolidRRectLikeBlurContents>
189 Canvas::RSuperellipseBlurShape::BuildBlurContent() {
190 return std::make_shared<SolidRSuperellipseBlurContents>();
193 Geometry& Canvas::RSuperellipseBlurShape::BuildGeometry(
Rect rect,
195 return geom_.emplace(rect, radius);
201 bool requires_readback)
202 : renderer_(renderer),
203 render_target_(render_target),
204 is_onscreen_(is_onscreen),
205 requires_readback_(requires_readback),
207 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
208 Initialize(std::nullopt);
215 bool requires_readback,
217 : renderer_(renderer),
218 render_target_(render_target),
219 is_onscreen_(is_onscreen),
220 requires_readback_(requires_readback),
222 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
223 Initialize(cull_rect);
230 bool requires_readback,
232 : renderer_(renderer),
233 render_target_(render_target),
234 is_onscreen_(is_onscreen),
235 requires_readback_(requires_readback),
237 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
243 void Canvas::Initialize(std::optional<Rect> cull_rect) {
244 initial_cull_rect_ = cull_rect;
251 void Canvas::Reset() {
253 transform_stack_ = {};
265 transform_stack_.back().transform = {};
273 return transform_stack_.back().transform;
296 Point Canvas::GetGlobalPassPosition()
const {
297 if (save_layer_state_.empty()) {
300 return save_layer_state_.back().coverage.GetOrigin();
304 size_t Canvas::GetClipHeightFloor()
const {
305 if (transform_stack_.size() > 1) {
306 return transform_stack_[transform_stack_.size() - 2].clip_height;
312 return transform_stack_.size();
315 bool Canvas::IsSkipping()
const {
316 return transform_stack_.back().skipping;
334 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
337 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
347 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
354 bool Canvas::AttemptColorFilterOptimization(
355 const std::shared_ptr<Texture>& image,
369 if (paint.
color_filter->type() == flutter::DlColorFilterType::kBlend) {
370 const flutter::DlBlendColorFilter* blend_filter =
372 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
377 blend_filter->mode(),
379 src_rect_constraint ==
382 auto atlas_contents = std::make_shared<AtlasContents>();
383 atlas_contents->SetGeometry(&geometry);
389 entity.SetContents(atlas_contents);
391 AddRenderEntityToCurrentPass(entity);
399 const flutter::DlMatrixColorFilter* matrix_filter =
402 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
409 src_rect_constraint ==
412 auto atlas_contents = std::make_shared<ColorFilterAtlasContents>();
413 atlas_contents->SetGeometry(&geometry);
416 matrix_filter->get_matrix(color_matrix.
array);
417 atlas_contents->SetMatrix(color_matrix);
422 entity.SetContents(atlas_contents);
424 AddRenderEntityToCurrentPass(entity);
429 bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
431 const Paint& paint) {
432 RRectBlurShape rrect_shape;
433 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint, rrect_shape);
436 bool Canvas::AttemptDrawBlurredRSuperellipse(
const Rect& rect,
438 const Paint& paint) {
439 RSuperellipseBlurShape rsuperellipse_shape;
440 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint,
441 rsuperellipse_shape);
444 bool Canvas::AttemptDrawBlurredRRectLike(
const Rect& rect,
447 RRectLikeBlurShape& shape) {
452 if (paint.color_source) {
456 if (!paint.mask_blur_descriptor.has_value()) {
466 if (fabsf(corner_radii.width - corner_radii.height) >
kEhCloseEnough) {
469 Scalar corner_radius = corner_radii.width;
473 Color rrect_color = paint.color;
474 if (paint.invert_colors) {
477 if (paint.color_filter) {
481 Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor};
502 if ((paint.mask_blur_descriptor->style !=
504 paint.image_filter) ||
507 Rect render_bounds = rect;
508 if (paint.mask_blur_descriptor->style !=
511 render_bounds.
Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
517 .image_filter = paint.image_filter,
518 .blend_mode = paint.blend_mode,
521 rrect_paint.color = rrect_color.WithAlpha(1);
523 rrect_paint.color = rrect_color;
524 rrect_paint.blend_mode = paint.blend_mode;
525 rrect_paint.image_filter = paint.image_filter;
529 auto draw_blurred_rrect = [
this, &rect, corner_radius, &rrect_paint,
531 auto contents = shape.BuildBlurContent();
533 contents->SetColor(rrect_paint.color);
534 contents->SetSigma(rrect_paint.mask_blur_descriptor->sigma);
535 contents->SetShape(rect, corner_radius);
537 Entity blurred_rrect_entity;
539 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
541 rrect_paint.mask_blur_descriptor = std::nullopt;
542 blurred_rrect_entity.SetContents(
543 rrect_paint.WithFilters(std::move(contents)));
544 AddRenderEntityToCurrentPass(blurred_rrect_entity);
547 switch (rrect_paint.mask_blur_descriptor->style) {
549 draw_blurred_rrect();
554 draw_blurred_rrect();
558 entity.SetBlendMode(rrect_paint.blend_mode);
560 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
561 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, rrect_paint,
566 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
568 draw_blurred_rrect();
572 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
574 draw_blurred_rrect();
592 auto geometry = std::make_unique<LineGeometry>(p0, p1, paint.
stroke);
594 if (renderer_.
GetContext()->GetFlags().antialiased_lines &&
599 AddRenderEntityToCurrentPass(entity, reuse_depth);
601 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
610 const Paint& paint) {
620 if (length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
626 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
633 if (AttemptDrawBlurredRRect(rect, {}, paint)) {
643 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
646 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
662 if (AttemptDrawBlurredRRect(rect, rect.
GetSize() * 0.5f, paint)) {
672 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
675 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
686 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
699 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
712 return DrawOval(oval_bounds, paint);
725 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
731 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
736 auto& radii = round_rect.
GetRadii();
737 if (radii.AreAllCornersSame()) {
738 if (AttemptDrawBlurredRRect(rect, radii.top_left, paint)) {
748 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
759 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
762 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
768 const Paint& paint) {
775 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
778 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
783 const Paint& paint) {
784 auto& rect = round_superellipse.
GetBounds();
785 auto& radii = round_superellipse.
GetRadii();
786 if (radii.AreAllCornersSame() &&
787 AttemptDrawBlurredRSuperellipse(rect, radii.top_left, paint)) {
797 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
800 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
806 const Paint& paint) {
807 Size half_size(radius, radius);
808 if (AttemptDrawBlurredRRect(
810 {radius, radius}, paint)) {
820 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
823 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
844 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
845 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
846 uint32_t clip_depth = transform_stack_.back().clip_depth;
848 const Matrix clip_transform =
852 std::optional<Rect> clip_coverage = geometry.
GetCoverage(clip_transform);
853 if (!clip_coverage.has_value()) {
858 clip_coverage.value(),
867 GetGlobalPassPosition(),
869 GetClipHeightFloor(),
876 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
877 GetGlobalPassPosition());
880 ++transform_stack_.back().clip_height;
881 ++transform_stack_.back().num_clips;
898 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
905 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
924 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
951 ISize size = image->GetSize();
956 std::optional<Rect> clipped_source =
958 if (!clipped_source) {
962 if (AttemptColorFilterOptimization(image, source, dest, paint, sampler,
963 src_rect_constraint)) {
967 if (*clipped_source != source) {
977 texture_contents->SetTexture(image);
978 texture_contents->SetSourceRect(*clipped_source);
979 texture_contents->SetStrictSourceRect(src_rect_constraint ==
981 texture_contents->SetSamplerDescriptor(sampler);
982 texture_contents->SetOpacity(paint.
color.
alpha);
983 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
991 AddRenderEntityToCurrentPass(entity);
999 AddRenderEntityToCurrentPass(entity);
1002 size_t Canvas::GetClipHeight()
const {
1003 return transform_stack_.back().clip_height;
1008 const Paint& paint) {
1021 if (UseColorSourceContents(vertices, paint)) {
1022 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1028 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1029 contents->SetBlendMode(blend_mode);
1031 contents->SetGeometry(vertices);
1033 AddRenderEntityToCurrentPass(entity);
1040 paint.
color_source->type() == flutter::DlColorSourceType::kImage) {
1041 const flutter::DlImageColorSource* image_color_source =
1043 FML_DCHECK(image_color_source &&
1044 image_color_source->image()->impeller_texture());
1045 auto texture = image_color_source->image()->impeller_texture();
1047 image_color_source->horizontal_tile_mode());
1050 auto sampler_descriptor =
1052 auto effect_transform = image_color_source->matrix();
1054 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1055 contents->SetBlendMode(blend_mode);
1057 contents->SetGeometry(vertices);
1058 contents->SetEffectTransform(effect_transform);
1059 contents->SetTexture(texture);
1060 contents->SetTileMode(x_tile_mode, y_tile_mode);
1061 contents->SetSamplerDescriptor(sampler_descriptor);
1064 AddRenderEntityToCurrentPass(entity);
1068 auto src_paint = paint;
1071 std::shared_ptr<ColorSourceContents> src_contents =
1072 src_paint.CreateContents();
1073 src_contents->SetGeometry(vertices.get());
1081 auto size = src_contents->GetColorSourceSize();
1082 if (size.has_value()) {
1085 auto cvg = vertices->GetCoverage(
Matrix{});
1086 FML_CHECK(cvg.has_value());
1087 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1088 if (texture_coverage.has_value()) {
1091 texture_coverage->GetSize().Max({1, 1}));
1094 src_coverage = cvg.value();
1097 src_contents = src_paint.CreateContents();
1100 src_contents->SetGeometry(clip_geometry_.back().get());
1102 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1103 contents->SetBlendMode(blend_mode);
1105 contents->SetGeometry(vertices);
1106 contents->SetLazyTextureCoverage(src_coverage);
1107 contents->SetLazyTexture([src_contents,
1113 src_contents->RenderToSnapshot(renderer, {},
Rect::Round(src_coverage));
1114 return snapshot.has_value() ? snapshot->texture :
nullptr;
1117 AddRenderEntityToCurrentPass(entity);
1121 const Paint& paint) {
1129 AddRenderEntityToCurrentPass(entity);
1135 void Canvas::SetupRenderPass() {
1141 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
1146 *renderer_.
GetContext()->GetResourceAllocator(),
1148 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
1149 "ImpellerOnscreen", kDefaultStencilConfig);
1161 if (requires_readback_) {
1162 auto entity_pass_target =
1163 CreateRenderTarget(renderer_,
1166 render_passes_.push_back(
1167 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1169 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1174 render_passes_.push_back(
1175 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1179 void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
1180 auto entry = CanvasStackEntry{};
1181 entry.skipping =
true;
1182 entry.clip_depth = current_depth_ + total_content_depth;
1183 transform_stack_.push_back(entry);
1188 return SkipUntilMatchingRestore(total_content_depth);
1192 entry.
transform = transform_stack_.back().transform;
1193 entry.clip_depth = current_depth_ + total_content_depth;
1194 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1195 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1196 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1197 <<
" after allocating " << total_content_depth;
1198 entry.clip_height = transform_stack_.back().clip_height;
1200 transform_stack_.push_back(entry);
1207 return std::nullopt;
1210 std::optional<Rect> maybe_current_clip_coverage =
1212 if (!maybe_current_clip_coverage.has_value()) {
1213 return std::nullopt;
1216 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1218 FML_CHECK(!render_passes_.empty());
1220 std::shared_ptr<Texture> back_texture =
1222 FML_CHECK(back_texture) <<
"Context is valid:"
1227 std::optional<Rect> maybe_coverage_limit =
1229 Size(back_texture->GetSize()))
1232 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1233 return std::nullopt;
1236 return maybe_coverage_limit->Intersection(
1241 std::optional<Rect> bounds,
1242 const flutter::DlImageFilter* backdrop_filter,
1244 uint32_t total_content_depth,
1245 bool can_distribute_opacity,
1246 std::optional<int64_t> backdrop_id) {
1247 TRACE_EVENT0(
"flutter",
"Canvas::saveLayer");
1249 return SkipUntilMatchingRestore(total_content_depth);
1253 if (!maybe_coverage_limit.has_value()) {
1254 return SkipUntilMatchingRestore(total_content_depth);
1256 auto coverage_limit = maybe_coverage_limit.value();
1258 if (can_distribute_opacity && !backdrop_filter &&
1261 Save(total_content_depth);
1262 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1266 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1267 Rect(), transform_stack_.back().transform,
1272 transform_stack_.back().transform,
1277 !!backdrop_filter ||
1282 if (!maybe_subpass_coverage.has_value()) {
1283 return SkipUntilMatchingRestore(total_content_depth);
1286 auto subpass_coverage = maybe_subpass_coverage.value();
1297 bool did_round_out =
false;
1298 Point coverage_origin_adjustment =
Point{0, 0};
1302 did_round_out =
true;
1306 coverage_origin_adjustment =
1307 Point(subpass_coverage.GetLeftTop().x -
1308 std::floor(subpass_coverage.GetLeftTop().x),
1309 subpass_coverage.GetLeftTop().y -
1310 std::floor(subpass_coverage.GetLeftTop().y));
1313 return SkipUntilMatchingRestore(total_content_depth);
1321 ->GetMaximumRenderPassAttachmentSize());
1324 std::shared_ptr<FilterContents> backdrop_filter_contents;
1326 if (backdrop_filter) {
1327 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1329 [backdrop_filter = backdrop_filter](
1332 auto filter =
WrapInput(backdrop_filter, input);
1333 filter->SetEffectTransform(effect_transform);
1334 filter->SetRenderingMode(rendering_mode);
1338 std::shared_ptr<Texture> input_texture;
1343 bool will_cache_backdrop_texture =
false;
1348 size_t backdrop_count = 1;
1349 if (backdrop_id.has_value()) {
1350 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1351 backdrop_data_.find(backdrop_id.value());
1352 if (backdrop_data_it != backdrop_data_.end()) {
1353 backdrop_data = &backdrop_data_it->second;
1354 will_cache_backdrop_texture =
1356 backdrop_count = backdrop_data_it->second.backdrop_count;
1360 if (!will_cache_backdrop_texture || !backdrop_data->
texture_slot) {
1361 backdrop_count_ -= backdrop_count;
1367 const bool should_use_onscreen =
1369 backdrop_count_ == 0 && render_passes_.size() == 1u;
1370 input_texture = FlipBackdrop(
1371 GetGlobalPassPosition(),
1372 will_cache_backdrop_texture,
1375 if (!input_texture) {
1380 if (will_cache_backdrop_texture) {
1387 backdrop_filter_contents = backdrop_filter_proc(
1389 transform_stack_.back().transform.Basis(),
1392 transform_stack_.back().transform.HasTranslation()
1396 if (will_cache_backdrop_texture) {
1397 FML_DCHECK(backdrop_data);
1404 backdrop_filter_contents->RenderToSnapshot(renderer_, {});
1407 std::optional<Snapshot> maybe_snapshot =
1409 if (maybe_snapshot.has_value()) {
1410 const Snapshot& snapshot = maybe_snapshot.value();
1412 subpass_coverage.Shift(-GetGlobalPassPosition()));
1415 contents->SetTexture(snapshot.
texture);
1416 contents->SetSourceRect(scaled);
1426 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1434 Paint paint_copy = paint;
1435 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1436 transform_stack_.back().distributed_opacity = 1.0;
1438 render_passes_.push_back(
1440 CreateRenderTarget(renderer_,
1445 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1448 entry.
transform = transform_stack_.back().transform;
1449 entry.
clip_depth = current_depth_ + total_content_depth;
1450 FML_DCHECK(entry.
clip_depth <= transform_stack_.back().clip_depth)
1451 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1452 <<
" after allocating " << total_content_depth;
1453 entry.
clip_height = transform_stack_.back().clip_height;
1456 transform_stack_.emplace_back(entry);
1463 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1465 if (!backdrop_filter_contents) {
1471 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1474 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1475 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1479 FML_DCHECK(transform_stack_.size() > 0);
1480 if (transform_stack_.size() == 1) {
1497 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1498 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1499 current_depth_ = transform_stack_.back().clip_depth;
1502 transform_stack_.pop_back();
1506 if (transform_stack_.back().rendering_mode ==
1508 transform_stack_.back().rendering_mode ==
1510 auto lazy_render_pass = std::move(render_passes_.back());
1511 render_passes_.pop_back();
1513 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1516 save_layer_state_.pop_back();
1517 auto global_pass_position = GetGlobalPassPosition();
1519 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1520 save_layer_state.
paint,
1521 lazy_render_pass.GetInlinePassContext()->GetTexture(),
1523 transform_stack_.back().transform
1526 lazy_render_pass.GetInlinePassContext()->EndPass();
1533 Point subpass_texture_position;
1534 if (transform_stack_.back().did_round_out) {
1537 subpass_texture_position =
1542 subpass_texture_position =
1556 ApplyFramebufferBlend(element_entity);
1567 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1568 if (!input_texture) {
1578 contents->SetCoverageHint(element_entity.
GetCoverage());
1586 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1589 transform_stack_.pop_back();
1597 size_t num_clips = transform_stack_.back().num_clips;
1598 transform_stack_.pop_back();
1600 if (num_clips > 0) {
1611 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1612 GetGlobalPassPosition()
1620 bool Canvas::AttemptBlurredTextOptimization(
1621 const std::shared_ptr<TextFrame>& text_frame,
1622 const std::shared_ptr<TextContents>& text_contents,
1624 const Paint& paint) {
1638 std::shared_ptr<FilterContents> filter =
1643 std::optional<Glyph> maybe_glyph = text_frame->AsSingleGlyph();
1644 int64_t identifier = maybe_glyph.has_value()
1645 ? maybe_glyph.value().index
1646 :
reinterpret_cast<int64_t
>(text_frame.get());
1647 TextShadowCache::TextShadowCacheKey cache_key(
1650 maybe_glyph.has_value(),
1651 text_frame->GetFont(),
1655 renderer_, entity, filter, cache_key);
1656 if (result.has_value()) {
1657 AddRenderEntityToCurrentPass(result.value(),
false);
1671 const Paint& paint) {
1673 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1675 fml::StatusOr<flutter::DlPath> path = text_frame->GetPath();
1689 auto text_contents = std::make_shared<TextContents>();
1690 text_contents->SetTextFrame(text_frame);
1692 text_contents->SetScale(max_scale);
1693 text_contents->SetColor(paint.
color);
1694 text_contents->SetOffset(position);
1695 text_contents->SetTextProperties(paint.
color,
1697 ? std::optional(paint.
stroke)
1703 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1709 AddRenderEntityToCurrentPass(entity,
false);
1712 void Canvas::AddRenderEntityWithFiltersToCurrentPass(
Entity& entity,
1716 std::shared_ptr<ColorSourceContents> contents = paint.
CreateContents();
1719 contents->SetGeometry(geometry);
1721 AddRenderEntityToCurrentPass(entity, reuse_depth);
1729 if (needs_color_filter &&
1730 contents->ApplyColorFilter([&](Color color) -> Color {
1731 if (paint.color_filter) {
1732 color = GetCPUColorFilterProc(paint.color_filter)(color);
1735 color = color.ApplyColorMatrix(kColorInversion);
1739 needs_color_filter =
false;
1743 contents->SetGeometry(geometry);
1749 FillRectGeometry out_rect(
Rect{});
1751 contents, needs_color_filter ? paint.
color_filter :
nullptr,
1752 needs_color_filter ? paint.
invert_colors :
false, &out_rect);
1754 AddRenderEntityToCurrentPass(entity, reuse_depth);
1758 std::shared_ptr<Contents> contents_copy = std::move(contents);
1762 if (needs_color_filter &&
1764 paint.
color_source->type() != flutter::DlColorSourceType::kImage)) {
1778 std::shared_ptr<FilterContents> filter =
WrapInput(
1782 AddRenderEntityToCurrentPass(entity, reuse_depth);
1787 AddRenderEntityToCurrentPass(entity, reuse_depth);
1790 void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
1795 entity.SetTransform(
1796 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1797 entity.GetTransform());
1798 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
1799 if (entity.GetBlendMode() == BlendMode::kSrcOver &&
1800 entity.GetContents()->IsOpaque(entity.GetTransform())) {
1801 entity.SetBlendMode(BlendMode::kSrc);
1807 if (render_passes_.back().IsApplyingClearColor()) {
1808 std::optional<Color> maybe_color = entity.AsBackgroundColor(
1809 render_passes_.back().GetInlinePassContext()->GetTexture()->GetSize());
1810 if (maybe_color.has_value()) {
1811 Color color = maybe_color.value();
1812 RenderTarget& render_target = render_passes_.back()
1813 .GetInlinePassContext()
1816 ColorAttachment attachment = render_target.GetColorAttachment(0);
1819 attachment.clear_color = attachment.clear_color.Unpremultiply()
1820 .Blend(color, entity.GetBlendMode())
1822 render_target.SetColorAttachment(attachment, 0u);
1833 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1834 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1835 entity.SetClipDepth(current_depth_);
1837 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1838 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
1839 ApplyFramebufferBlend(entity);
1850 auto input_texture = FlipBackdrop(GetGlobalPassPosition(),
1854 if (!input_texture) {
1862 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
1863 entity.GetContents()->SetCoverageHint(Rect::Intersection(
1864 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
1866 FilterInput::Vector inputs = {
1867 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
1868 FilterInput::Make(entity.GetContents())};
1870 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
1871 entity.SetContents(std::move(contents));
1872 entity.SetBlendMode(BlendMode::kSrc);
1876 const std::shared_ptr<RenderPass>& result =
1877 render_passes_.back().GetInlinePassContext()->GetRenderPass();
1885 entity.Render(renderer_, *result);
1888 RenderPass& Canvas::GetCurrentRenderPass()
const {
1889 return *render_passes_.back().GetInlinePassContext()->GetRenderPass();
1892 void Canvas::SetBackdropData(
1893 std::unordered_map<int64_t, BackdropData> backdrop_data,
1894 size_t backdrop_count) {
1895 backdrop_data_ = std::move(backdrop_data);
1896 backdrop_count_ = backdrop_count;
1899 std::shared_ptr<Texture> Canvas::FlipBackdrop(
Point global_pass_position,
1900 bool should_remove_texture,
1901 bool should_use_onscreen,
1902 bool post_depth_increment) {
1904 render_passes_.pop_back();
1920 <<
"Failed to end the current render pass in order to read from "
1921 "the backdrop texture and apply an advanced blend or backdrop "
1926 render_passes_.emplace_back(std::move(rendering_config));
1930 const std::shared_ptr<Texture>& input_texture =
1933 if (!input_texture) {
1934 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
1935 "apply an advanced blend or backdrop filter.";
1938 render_passes_.emplace_back(std::move(rendering_config));
1942 if (should_use_onscreen) {
1943 ColorAttachment color0 = render_target_.GetColorAttachment(0);
1947 color0.
load_action = color0.resolve_texture !=
nullptr
1948 ? LoadAction::kDontCare
1949 : LoadAction::kLoad;
1950 render_target_.SetColorAttachment(color0, 0);
1952 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1954 renderer_.GetDeviceCapabilities().SupportsReadFromResolve(),
1955 renderer_.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
1957 render_passes_.push_back(
1958 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1959 requires_readback_ =
false;
1961 render_passes_.emplace_back(std::move(rendering_config));
1964 if (should_remove_texture) {
1965 render_passes_.back().GetEntityPassTarget()->RemoveSecondary();
1968 RenderPass& current_render_pass =
1969 *render_passes_.back().GetInlinePassContext()->GetRenderPass();
1978 Rect size_rect = Rect::MakeSize(input_texture->GetSize());
1979 auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
1980 msaa_backdrop_contents->SetStencilEnabled(
false);
1981 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
1982 msaa_backdrop_contents->SetSourceRect(size_rect);
1983 msaa_backdrop_contents->SetTexture(input_texture);
1985 Entity msaa_backdrop_entity;
1986 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
1987 msaa_backdrop_entity.SetBlendMode(BlendMode::kSrc);
1988 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
1989 if (!msaa_backdrop_entity.Render(renderer_, current_render_pass)) {
1996 auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
1997 uint64_t current_depth =
1998 post_depth_increment ? current_depth_ - 1 : current_depth_;
1999 for (
const auto& replay : replay_entities) {
2000 if (replay.clip_depth <= current_depth) {
2004 SetClipScissor(replay.clip_coverage, current_render_pass,
2005 global_pass_position);
2006 if (!replay.clip_contents.Render(renderer_, current_render_pass,
2007 replay.clip_depth)) {
2012 return input_texture;
2015 bool Canvas::SupportsBlitToOnscreen()
const {
2016 return renderer_.GetContext()
2018 ->SupportsTextureToTextureBlits() &&
2019 renderer_.GetContext()->GetBackendType() ==
2020 Context::BackendType::kMetal;
2023 bool Canvas::BlitToOnscreen(
bool is_onscreen) {
2024 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
2025 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
2026 auto offscreen_target = render_passes_.back()
2027 .GetInlinePassContext()
2030 if (SupportsBlitToOnscreen()) {
2031 auto blit_pass = command_buffer->CreateBlitPass();
2032 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
2033 render_target_.GetRenderTargetTexture());
2034 if (!blit_pass->EncodeCommands()) {
2039 auto render_pass = command_buffer->CreateRenderPass(render_target_);
2040 render_pass->SetLabel(
"EntityPass Root Render Pass");
2043 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
2044 auto contents = TextureContents::MakeRect(size_rect);
2045 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
2046 contents->SetSourceRect(size_rect);
2047 contents->SetLabel(
"Root pass blit");
2050 entity.SetContents(contents);
2051 entity.SetBlendMode(BlendMode::kSrc);
2053 if (!entity.Render(renderer_, *render_pass)) {
2059 if (!render_pass->EncodeCommands()) {
2066 return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer));
2068 return renderer_.GetContext()->EnqueueCommandBuffer(
2069 std::move(command_buffer));
2073 bool Canvas::EnsureFinalMipmapGeneration()
const {
2074 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2077 std::shared_ptr<CommandBuffer> cmd_buffer =
2078 renderer_.GetContext()->CreateCommandBuffer();
2082 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2086 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2087 blit_pass->EncodeCommands();
2088 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2091 void Canvas::EndReplay() {
2092 FML_DCHECK(render_passes_.size() == 1u);
2093 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2094 render_passes_.back().GetInlinePassContext()->EndPass(
2095 !requires_readback_ && is_onscreen_);
2096 backdrop_data_.clear();
2101 if (requires_readback_) {
2102 BlitToOnscreen(is_onscreen_);
2104 if (!EnsureFinalMipmapGeneration()) {
2107 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2111 render_passes_.clear();
2112 renderer_.GetRenderTargetCache()->End();
2113 clip_geometry_.clear();
2116 Initialize(initial_cull_rect_);
2119 LazyRenderingConfig::LazyRenderingConfig(
2121 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
2122 : entity_pass_target_(
std::move(p_entity_pass_target)) {
2123 inline_pass_context_ =
2124 std::make_unique<InlinePassContext>(renderer, *entity_pass_target_);
2128 return !inline_pass_context_->IsActive();
2132 return entity_pass_target_.get();
2136 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...
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