9#include <unordered_map>
65static bool UseColorSourceContents(
66 const std::shared_ptr<VerticesGeometry>& vertices,
70 if (vertices->HasVertexColors()) {
73 if (vertices->HasTextureCoordinates() && !paint.color_source) {
76 return !vertices->HasTextureCoordinates();
79static 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);
96static 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));
107static 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),
122static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
123 RenderTarget::AttachmentConfig{
129static 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()
180std::shared_ptr<SolidRRectLikeBlurContents>
181Canvas::RRectBlurShape::BuildBlurContent() {
182 return std::make_shared<SolidRRectBlurContents>();
185Geometry& Canvas::RRectBlurShape::BuildGeometry(
Rect rect,
Scalar radius) {
186 return geom_.emplace(rect,
Size{radius, radius});
189std::shared_ptr<SolidRRectLikeBlurContents>
190Canvas::RSuperellipseBlurShape::BuildBlurContent() {
191 return std::make_shared<SolidRSuperellipseBlurContents>();
194Geometry& 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()))) {
244void Canvas::Initialize(std::optional<Rect> cull_rect) {
245 initial_cull_rect_ = cull_rect;
252void Canvas::Reset() {
254 transform_stack_ = {};
266 transform_stack_.back().transform = {};
274 return transform_stack_.back().transform;
297Point Canvas::GetGlobalPassPosition()
const {
298 if (save_layer_state_.empty()) {
301 return save_layer_state_.back().coverage.GetOrigin();
305size_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();
316bool Canvas::IsSkipping()
const {
317 return transform_stack_.back().skipping;
335 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
338 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
348 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
355bool Canvas::AttemptColorFilterOptimization(
356 const std::shared_ptr<Texture>&
image,
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);
403 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
410 src_rect_constraint ==
413 auto atlas_contents = std::make_shared<ColorFilterAtlasContents>();
414 atlas_contents->SetGeometry(&geometry);
418 atlas_contents->SetMatrix(color_matrix);
423 entity.SetContents(atlas_contents);
425 AddRenderEntityToCurrentPass(entity);
430bool 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);
459bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
461 const Paint& paint) {
462 RRectBlurShape rrect_shape;
463 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint, rrect_shape);
466bool Canvas::AttemptDrawBlurredRSuperellipse(
const Rect& rect,
468 const Paint& paint) {
469 RSuperellipseBlurShape rsuperellipse_shape;
470 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint,
471 rsuperellipse_shape);
474bool 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);
983 if (size.IsEmpty()) {
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);
1033size_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);
1075 image_color_source->
image()->impeller_texture());
1076 auto texture = image_color_source->
image()->impeller_texture();
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{});
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);
1166void Canvas::SetupRenderPass() {
1172 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
1177 *renderer_.
GetContext()->GetResourceAllocator(),
1179 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
1180 "ImpellerOnscreen", kDefaultStencilConfig);
1192 if (requires_readback_) {
1193 auto entity_pass_target =
1194 CreateRenderTarget(renderer_,
1197 render_passes_.push_back(
1198 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1200 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1205 render_passes_.push_back(
1206 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1210void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
1211 auto entry = CanvasStackEntry{};
1212 entry.skipping =
true;
1213 entry.clip_depth = current_depth_ + total_content_depth;
1214 transform_stack_.push_back(entry);
1219 return SkipUntilMatchingRestore(total_content_depth);
1223 entry.
transform = transform_stack_.back().transform;
1224 entry.clip_depth = current_depth_ + total_content_depth;
1225 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1226 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1227 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1228 <<
" after allocating " << total_content_depth;
1229 entry.clip_height = transform_stack_.back().clip_height;
1231 transform_stack_.push_back(entry);
1238 return std::nullopt;
1241 std::optional<Rect> maybe_current_clip_coverage =
1243 if (!maybe_current_clip_coverage.has_value()) {
1244 return std::nullopt;
1247 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1251 std::shared_ptr<Texture> back_texture =
1253 FML_CHECK(back_texture) <<
"Context is valid:"
1258 std::optional<Rect> maybe_coverage_limit =
1260 Size(back_texture->GetSize()))
1263 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1264 return std::nullopt;
1267 return maybe_coverage_limit->Intersection(
1272 std::optional<Rect> bounds,
1275 uint32_t total_content_depth,
1276 bool can_distribute_opacity,
1277 std::optional<int64_t> backdrop_id) {
1280 return SkipUntilMatchingRestore(total_content_depth);
1284 if (!maybe_coverage_limit.has_value()) {
1285 return SkipUntilMatchingRestore(total_content_depth);
1287 auto coverage_limit = maybe_coverage_limit.value();
1289 if (can_distribute_opacity && !backdrop_filter &&
1292 Save(total_content_depth);
1293 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1297 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1298 Rect(), transform_stack_.back().transform,
1303 transform_stack_.back().transform,
1308 !!backdrop_filter ||
1313 if (!maybe_subpass_coverage.has_value()) {
1314 return SkipUntilMatchingRestore(total_content_depth);
1317 auto subpass_coverage = maybe_subpass_coverage.value();
1328 bool did_round_out =
false;
1329 Point coverage_origin_adjustment =
Point{0, 0};
1333 did_round_out =
true;
1337 coverage_origin_adjustment =
1338 Point(subpass_coverage.GetLeftTop().x -
1339 std::floor(subpass_coverage.GetLeftTop().x),
1340 subpass_coverage.GetLeftTop().y -
1341 std::floor(subpass_coverage.GetLeftTop().y));
1344 return SkipUntilMatchingRestore(total_content_depth);
1352 ->GetMaximumRenderPassAttachmentSize());
1355 std::shared_ptr<FilterContents> backdrop_filter_contents;
1357 if (backdrop_filter) {
1358 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1360 [backdrop_filter = backdrop_filter](
1364 filter->SetEffectTransform(effect_transform);
1365 filter->SetRenderingMode(rendering_mode);
1369 std::shared_ptr<Texture> input_texture;
1374 bool will_cache_backdrop_texture =
false;
1379 size_t backdrop_count = 1;
1380 if (backdrop_id.has_value()) {
1381 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1382 backdrop_data_.find(backdrop_id.value());
1383 if (backdrop_data_it != backdrop_data_.end()) {
1384 backdrop_data = &backdrop_data_it->second;
1385 will_cache_backdrop_texture =
1387 backdrop_count = backdrop_data_it->second.backdrop_count;
1391 if (!will_cache_backdrop_texture || !backdrop_data->
texture_slot) {
1392 backdrop_count_ -= backdrop_count;
1398 const bool should_use_onscreen =
1400 backdrop_count_ == 0 && render_passes_.size() == 1u;
1401 input_texture = FlipBackdrop(
1402 GetGlobalPassPosition(),
1403 will_cache_backdrop_texture,
1406 if (!input_texture) {
1411 if (will_cache_backdrop_texture) {
1418 backdrop_filter_contents = backdrop_filter_proc(
1420 transform_stack_.back().transform.Basis(),
1423 transform_stack_.back().transform.HasTranslation()
1427 if (will_cache_backdrop_texture) {
1435 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1438 std::optional<Snapshot> maybe_snapshot =
1440 if (maybe_snapshot.has_value()) {
1441 const Snapshot& snapshot = maybe_snapshot.value();
1443 subpass_coverage.Shift(-GetGlobalPassPosition()));
1446 contents->SetTexture(snapshot.
texture);
1447 contents->SetSourceRect(scaled);
1457 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1465 Paint paint_copy = paint;
1466 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1467 transform_stack_.back().distributed_opacity = 1.0;
1469 render_passes_.push_back(
1471 CreateRenderTarget(renderer_,
1476 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1479 entry.
transform = transform_stack_.back().transform;
1480 entry.
clip_depth = current_depth_ + total_content_depth;
1482 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1483 <<
" after allocating " << total_content_depth;
1484 entry.
clip_height = transform_stack_.back().clip_height;
1487 transform_stack_.emplace_back(entry);
1494 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1496 if (!backdrop_filter_contents) {
1502 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1505 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1506 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1511 if (transform_stack_.size() == 1) {
1528 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1529 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1530 current_depth_ = transform_stack_.back().clip_depth;
1533 transform_stack_.pop_back();
1537 if (transform_stack_.back().rendering_mode ==
1539 transform_stack_.back().rendering_mode ==
1541 auto lazy_render_pass = std::move(render_passes_.back());
1542 render_passes_.pop_back();
1544 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1547 save_layer_state_.pop_back();
1548 auto global_pass_position = GetGlobalPassPosition();
1550 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1551 save_layer_state.
paint,
1552 lazy_render_pass.GetInlinePassContext()->GetTexture(),
1554 transform_stack_.back().transform
1557 lazy_render_pass.GetInlinePassContext()->EndPass();
1564 Point subpass_texture_position;
1565 if (transform_stack_.back().did_round_out) {
1568 subpass_texture_position =
1573 subpass_texture_position =
1587 ApplyFramebufferBlend(element_entity);
1598 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1599 if (!input_texture) {
1609 contents->SetCoverageHint(element_entity.
GetCoverage());
1617 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1620 transform_stack_.pop_back();
1628 size_t num_clips = transform_stack_.back().num_clips;
1629 transform_stack_.pop_back();
1631 if (num_clips > 0) {
1642 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1643 GetGlobalPassPosition()
1651bool Canvas::AttemptBlurredTextOptimization(
1652 const std::shared_ptr<TextFrame>& text_frame,
1653 const std::shared_ptr<TextContents>& text_contents,
1655 const Paint& paint) {
1669 std::shared_ptr<FilterContents> filter =
1674 std::optional<Glyph> maybe_glyph = text_frame->AsSingleGlyph();
1675 int64_t identifier = maybe_glyph.has_value()
1676 ? maybe_glyph.value().index
1677 :
reinterpret_cast<int64_t
>(text_frame.get());
1678 TextShadowCache::TextShadowCacheKey cache_key(
1681 maybe_glyph.has_value(),
1682 text_frame->GetFont(),
1687 renderer_, entity, filter, cache_key);
1688 if (result.has_value()) {
1689 AddRenderEntityToCurrentPass(result.value(),
false);
1703 const Paint& paint) {
1705 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1721 auto text_contents = std::make_shared<TextContents>();
1722 text_contents->SetTextFrame(text_frame);
1724 text_contents->SetScale(max_scale);
1725 text_contents->SetColor(paint.
color);
1726 text_contents->SetOffset(position);
1727 text_contents->SetTextProperties(paint.
color,
1729 ? std::optional(paint.
stroke)
1735 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1741 AddRenderEntityToCurrentPass(entity,
false);
1744void Canvas::AddRenderEntityWithFiltersToCurrentPass(
Entity& entity,
1748 std::shared_ptr<ColorSourceContents> contents = paint.
CreateContents();
1751 contents->SetGeometry(geometry);
1753 AddRenderEntityToCurrentPass(entity, reuse_depth);
1761 if (needs_color_filter &&
1762 contents->ApplyColorFilter([&](Color color) -> Color {
1763 if (paint.color_filter) {
1764 color = GetCPUColorFilterProc(paint.color_filter)(color);
1767 color = color.ApplyColorMatrix(kColorInversion);
1771 needs_color_filter =
false;
1775 contents->SetGeometry(geometry);
1781 FillRectGeometry out_rect(
Rect{});
1783 contents, needs_color_filter ? paint.
color_filter : nullptr,
1784 needs_color_filter ? paint.invert_colors : false, &out_rect);
1786 AddRenderEntityToCurrentPass(entity, reuse_depth);
1790 std::shared_ptr<Contents> contents_copy = std::move(contents);
1794 if (needs_color_filter &&
1810 std::shared_ptr<FilterContents> filter =
WrapInput(
1814 AddRenderEntityToCurrentPass(entity, reuse_depth);
1819 AddRenderEntityToCurrentPass(entity, reuse_depth);
1822void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
1827 entity.SetTransform(
1828 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1829 entity.GetTransform());
1830 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
1831 if (entity.GetBlendMode() == BlendMode::kSrcOver &&
1832 entity.GetContents()->IsOpaque(entity.GetTransform())) {
1833 entity.SetBlendMode(BlendMode::kSrc);
1839 if (render_passes_.back().IsApplyingClearColor()) {
1840 std::optional<Color> maybe_color = entity.AsBackgroundColor(
1841 render_passes_.back().GetInlinePassContext()->GetTexture()->GetSize());
1842 if (maybe_color.has_value()) {
1843 Color color = maybe_color.value();
1844 RenderTarget& render_target = render_passes_.back()
1845 .GetInlinePassContext()
1848 ColorAttachment attachment = render_target.GetColorAttachment(0);
1851 attachment.clear_color = attachment.clear_color.Unpremultiply()
1852 .Blend(color, entity.GetBlendMode())
1854 render_target.SetColorAttachment(attachment, 0u);
1865 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1866 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1867 entity.SetClipDepth(current_depth_);
1869 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1870 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
1871 ApplyFramebufferBlend(entity);
1882 auto input_texture = FlipBackdrop(GetGlobalPassPosition(),
1886 if (!input_texture) {
1894 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
1895 entity.GetContents()->SetCoverageHint(Rect::Intersection(
1896 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
1898 FilterInput::Vector inputs = {
1899 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
1900 FilterInput::Make(entity.GetContents())};
1902 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
1903 entity.SetContents(std::move(contents));
1904 entity.SetBlendMode(BlendMode::kSrc);
1908 const std::shared_ptr<RenderPass>& result =
1909 render_passes_.back().GetInlinePassContext()->GetRenderPass();
1917 entity.Render(renderer_, *result);
1920RenderPass& Canvas::GetCurrentRenderPass()
const {
1921 return *render_passes_.back().GetInlinePassContext()->GetRenderPass();
1924void Canvas::SetBackdropData(
1925 std::unordered_map<int64_t, BackdropData> backdrop_data,
1926 size_t backdrop_count) {
1927 backdrop_data_ = std::move(backdrop_data);
1928 backdrop_count_ = backdrop_count;
1931std::shared_ptr<Texture> Canvas::FlipBackdrop(
Point global_pass_position,
1932 bool should_remove_texture,
1933 bool should_use_onscreen,
1934 bool post_depth_increment) {
1936 render_passes_.pop_back();
1952 <<
"Failed to end the current render pass in order to read from "
1953 "the backdrop texture and apply an advanced blend or backdrop "
1958 render_passes_.emplace_back(std::move(rendering_config));
1962 const std::shared_ptr<Texture>& input_texture =
1965 if (!input_texture) {
1966 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
1967 "apply an advanced blend or backdrop filter.";
1970 render_passes_.emplace_back(std::move(rendering_config));
1974 if (should_use_onscreen) {
1975 ColorAttachment color0 = render_target_.GetColorAttachment(0);
1979 color0.load_action = color0.resolve_texture !=
nullptr
1980 ? LoadAction::kDontCare
1981 : LoadAction::kLoad;
1982 render_target_.SetColorAttachment(color0, 0);
1984 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1986 renderer_.GetDeviceCapabilities().SupportsReadFromResolve(),
1987 renderer_.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
1989 render_passes_.push_back(
1990 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1991 requires_readback_ =
false;
1993 render_passes_.emplace_back(std::move(rendering_config));
1996 if (should_remove_texture) {
1997 render_passes_.back().GetEntityPassTarget()->RemoveSecondary();
2000 RenderPass& current_render_pass =
2001 *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2010 Rect size_rect = Rect::MakeSize(input_texture->GetSize());
2011 auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
2012 msaa_backdrop_contents->SetStencilEnabled(
false);
2013 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
2014 msaa_backdrop_contents->SetSourceRect(size_rect);
2015 msaa_backdrop_contents->SetTexture(input_texture);
2017 Entity msaa_backdrop_entity;
2018 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
2019 msaa_backdrop_entity.SetBlendMode(BlendMode::kSrc);
2020 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
2021 if (!msaa_backdrop_entity.Render(renderer_, current_render_pass)) {
2028 auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
2029 uint64_t current_depth =
2030 post_depth_increment ? current_depth_ - 1 : current_depth_;
2031 for (
const auto& replay : replay_entities) {
2032 if (replay.clip_depth <= current_depth) {
2036 SetClipScissor(replay.clip_coverage, current_render_pass,
2037 global_pass_position);
2038 if (!replay.clip_contents.Render(renderer_, current_render_pass,
2039 replay.clip_depth)) {
2044 return input_texture;
2047bool Canvas::SupportsBlitToOnscreen()
const {
2048 return renderer_.GetContext()
2050 ->SupportsTextureToTextureBlits() &&
2051 renderer_.GetContext()->GetBackendType() ==
2052 Context::BackendType::kMetal;
2055bool Canvas::BlitToOnscreen(
bool is_onscreen) {
2056 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
2057 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
2058 auto offscreen_target = render_passes_.back()
2059 .GetInlinePassContext()
2062 if (SupportsBlitToOnscreen()) {
2063 auto blit_pass = command_buffer->CreateBlitPass();
2064 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
2065 render_target_.GetRenderTargetTexture());
2066 if (!blit_pass->EncodeCommands()) {
2071 auto render_pass = command_buffer->CreateRenderPass(render_target_);
2072 render_pass->SetLabel(
"EntityPass Root Render Pass");
2075 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
2076 auto contents = TextureContents::MakeRect(size_rect);
2077 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
2078 contents->SetSourceRect(size_rect);
2079 contents->SetLabel(
"Root pass blit");
2082 entity.SetContents(contents);
2083 entity.SetBlendMode(BlendMode::kSrc);
2085 if (!entity.Render(renderer_, *render_pass)) {
2091 if (!render_pass->EncodeCommands()) {
2098 return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer));
2100 return renderer_.GetContext()->EnqueueCommandBuffer(
2101 std::move(command_buffer));
2105bool Canvas::EnsureFinalMipmapGeneration()
const {
2106 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2109 std::shared_ptr<CommandBuffer> cmd_buffer =
2110 renderer_.GetContext()->CreateCommandBuffer();
2114 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2118 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2119 blit_pass->EncodeCommands();
2120 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2123void Canvas::EndReplay() {
2125 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2126 render_passes_.back().GetInlinePassContext()->EndPass(
2127 !requires_readback_ && is_onscreen_);
2128 backdrop_data_.clear();
2133 if (requires_readback_) {
2134 BlitToOnscreen(is_onscreen_);
2136 if (!EnsureFinalMipmapGeneration()) {
2139 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2143 render_passes_.clear();
2144 renderer_.GetRenderTargetCache()->End();
2145 clip_geometry_.clear();
2148 Initialize(initial_cull_rect_);
2151LazyRenderingConfig::LazyRenderingConfig(
2153 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
2154 : entity_pass_target_(
std::move(p_entity_pass_target)) {
2155 inline_pass_context_ =
2156 std::make_unique<InlinePassContext>(renderer, *entity_pass_target_);
2160 return !inline_pass_context_->IsActive();
2164 return entity_pass_target_.get();
2168 return inline_pass_context_.get();
virtual T type() const =0
virtual const DlBlendColorFilter * asBlend() const
virtual const DlMatrixColorFilter * asMatrix() const
virtual bool modifies_transparent_black() const =0
virtual const DlImageColorSource * asImage() const
DlImageSampling sampling() const
DlTileMode vertical_tile_mode() const
DlTileMode horizontal_tile_mode() const
sk_sp< const DlImage > image() const
void get_matrix(float matrix[20]) const
const DlMatrix & matrix() const
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 std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
const Capabilities & GetDeviceCapabilities() 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)
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)
ReplayResult & GetLastReplayResult()
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.
virtual std::optional< Rect > GetCoverage(const Matrix &transform) const =0
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 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)
FlutterVulkanImage * image
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
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...
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.
static const constexpr ColorMatrix kColorInversion
A color matrix which inverts colors.
constexpr bool IncludeCenter() const
constexpr bool IsFullCircle() const
constexpr Degrees GetSweep() const
constexpr Degrees GetStart() const
const Rect & GetOvalBounds() const
Return the bounds of the oval in which this arc is inscribed.
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 Rect & GetBounds() const
constexpr const RoundingRadii & GetRadii() 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 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 std::optional< TRect > Intersection(const TRect &o) 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...
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
constexpr auto GetLeft() const
Round(const TRect< U > &r)
RoundOut(const TRect< U > &r)
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr auto GetRight() const
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
static constexpr TRect MakeSize(const TSize< U > &size)
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
static constexpr TRect MakeMaximum()
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
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...
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
std::vector< Point > points
#define TRACE_EVENT0(category_group, name)