9#include <unordered_map>
73constexpr Scalar kAntialiasPadding = 1.0f;
81static bool UseColorSourceContents(
82 const std::shared_ptr<VerticesGeometry>& vertices,
86 if (vertices->HasVertexColors()) {
89 if (vertices->HasTextureCoordinates() && !paint.color_source) {
92 return !vertices->HasTextureCoordinates();
95static void SetClipScissor(std::optional<Rect> clip_coverage,
97 Point global_pass_position) {
101 if (clip_coverage.has_value()) {
102 clip_coverage = clip_coverage->Shift(-global_pass_position);
109 pass.SetScissor(scissor);
112static void ApplyFramebufferBlend(Entity& entity) {
113 auto src_contents = entity.GetContents();
114 auto contents = std::make_shared<FramebufferBlendContents>();
115 contents->SetChildContents(src_contents);
116 contents->SetBlendMode(entity.GetBlendMode());
117 entity.SetContents(std::move(contents));
123static std::shared_ptr<Contents> CreateContentsForSubpassTarget(
124 const ContentContext& renderer,
126 const std::shared_ptr<Texture>&
target,
127 const Matrix& effect_transform) {
129 contents->SetTexture(
target);
130 contents->SetLabel(
"Subpass");
132 contents->SetOpacity(paint.color.alpha);
133 contents->SetDeferApplyingOpacity(
true);
135 return paint.WithFiltersForSubpassTarget(renderer, std::move(contents),
139static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
140 RenderTarget::AttachmentConfig{
146static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
147 ContentContext& renderer,
149 const Color& clear_color) {
150 const std::shared_ptr<Context>& context = renderer.GetContext();
158 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
159 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
165 RenderTarget::AttachmentConfigMSAA{
170 .clear_color = clear_color},
171 kDefaultStencilConfig);
173 target = renderer.GetRenderTargetCache()->CreateOffscreen(
178 RenderTarget::AttachmentConfig{
182 .clear_color = clear_color,
184 kDefaultStencilConfig
188 return std::make_unique<EntityPassTarget>(
190 renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
191 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
200 : rect_(rect), corner_radius_(corner_radius) {}
205 auto contents = std::make_shared<SolidRRectBlurContents>();
206 contents->SetSigma(sigma);
207 contents->SetShape(rect_, corner_radius_);
212 return geom_.emplace(rect_,
Size(corner_radius_));
217 const Scalar corner_radius_;
219 std::optional<RoundRectGeometry> geom_;
225 : rect_(rect), corner_radius_(corner_radius) {}
230 auto contents = std::make_shared<SolidRSuperellipseBlurContents>();
231 contents->SetSigma(sigma);
232 contents->SetShape(rect_, corner_radius_);
237 return geom_.emplace(rect_, corner_radius_);
242 const Scalar corner_radius_;
244 std::optional<RoundSuperellipseGeometry> geom_;
264 std::shared_ptr<ShadowVertices> shadow_vertices,
268 shadow_vertices_(
std::move(shadow_vertices)) {}
271 return shadow_vertices_->GetBounds().value_or(
Rect());
285 return source_geometry_.emplace(source_);
291 const std::shared_ptr<ShadowVertices> shadow_vertices_;
294 std::optional<FillPathFromSourceGeometry> source_geometry_;
300 bool requires_readback)
301 : renderer_(renderer),
302 render_target_(render_target),
303 is_onscreen_(is_onscreen),
304 requires_readback_(requires_readback),
306 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
307 Initialize(std::nullopt);
314 bool requires_readback,
316 : renderer_(renderer),
317 render_target_(render_target),
318 is_onscreen_(is_onscreen),
319 requires_readback_(requires_readback),
321 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
322 Initialize(cull_rect);
329 bool requires_readback,
331 : renderer_(renderer),
332 render_target_(render_target),
333 is_onscreen_(is_onscreen),
334 requires_readback_(requires_readback),
336 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
342void Canvas::Initialize(std::optional<Rect> cull_rect) {
343 initial_cull_rect_ = cull_rect;
350void Canvas::Reset() {
352 transform_stack_ = {};
364 transform_stack_.back().transform = {};
372 return transform_stack_.back().transform;
395Point Canvas::GetGlobalPassPosition()
const {
396 if (save_layer_state_.empty()) {
399 return save_layer_state_.back().coverage.GetOrigin();
403size_t Canvas::GetClipHeightFloor()
const {
404 if (transform_stack_.size() > 1) {
405 return transform_stack_[transform_stack_.size() - 2].clip_height;
411 return transform_stack_.size();
414bool Canvas::IsSkipping()
const {
415 return transform_stack_.back().skipping;
427 if (IsShadowBlurDrawOperation(paint)) {
428 if (AttemptDrawBlurredPathSource(path, paint)) {
439 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
442 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
452 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
459bool Canvas::AttemptColorFilterOptimization(
460 const std::shared_ptr<Texture>&
image,
477 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
482 blend_filter->
mode(),
484 src_rect_constraint ==
487 auto atlas_contents = std::make_shared<AtlasContents>();
488 atlas_contents->SetGeometry(&geometry);
494 entity.SetContents(atlas_contents);
496 AddRenderEntityToCurrentPass(entity);
507 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
514 src_rect_constraint ==
517 auto atlas_contents = std::make_shared<ColorFilterAtlasContents>();
518 atlas_contents->SetGeometry(&geometry);
522 atlas_contents->SetMatrix(color_matrix);
527 entity.SetContents(atlas_contents);
529 AddRenderEntityToCurrentPass(entity);
534bool Canvas::AttemptDrawAntialiasedCircle(
const Point& center,
536 const Paint& paint) {
537 if (paint.HasColorFilter() || paint.image_filter || paint.invert_colors ||
538 paint.color_source || paint.mask_blur_descriptor.has_value()) {
544 entity.SetBlendMode(paint.blend_mode);
547 std::unique_ptr<CircleGeometry> geom;
549 geom = std::make_unique<CircleGeometry>(center, radius, paint.stroke.width);
551 geom = std::make_unique<CircleGeometry>(center, radius);
553 geom->SetAntialiasPadding(kAntialiasPadding);
557 entity.SetContents(std::move(contents));
558 AddRenderEntityToCurrentPass(entity);
563bool Canvas::IsShadowBlurDrawOperation(
const Paint& paint) {
568 if (paint.color_source) {
572 if (!paint.mask_blur_descriptor.has_value()) {
583 Radius radius = paint.mask_blur_descriptor->sigma;
591bool Canvas::AttemptDrawBlurredPathSource(
const PathSource& source,
592 const Paint& paint) {
599 if (paint.mask_blur_descriptor.has_value()) {
603 static constexpr Scalar kSigmaScale = 2.8f;
605 Sigma sigma = paint.mask_blur_descriptor->sigma;
607 Scalar basis_scale = matrix.GetMaxBasisLengthXY();
608 Scalar device_radius = sigma.sigma * kSigmaScale * basis_scale;
609 std::shared_ptr<ShadowVertices> shadow_vertices =
612 if (shadow_vertices) {
613 PathBlurShape shape(source, std::move(shadow_vertices), sigma);
614 return AttemptDrawBlur(shape, paint);
620Scalar Canvas::GetCommonRRectLikeRadius(
const RoundingRadii& radii) {
621 if (!radii.AreAllCornersSame()) {
624 const Size& corner_radii = radii.top_left;
626 return corner_radii.
width;
631bool Canvas::AttemptDrawBlurredRRect(
const RoundRect& round_rect,
632 const Paint& paint) {
633 Scalar radius = GetCommonRRectLikeRadius(round_rect.GetRadii());
635 RoundRectPathSource source(round_rect);
636 return AttemptDrawBlurredPathSource(source, paint);
638 RRectBlurShape shape(round_rect.GetBounds(), radius);
639 return AttemptDrawBlur(shape, paint);
642bool Canvas::AttemptDrawBlurredRSuperellipse(
const RoundSuperellipse& rse,
643 const Paint& paint) {
644 Scalar radius = GetCommonRRectLikeRadius(rse.GetRadii());
646 RoundSuperellipsePathSource source(rse);
647 return AttemptDrawBlurredPathSource(source, paint);
649 RSuperellipseBlurShape shape(rse.GetBounds(), radius);
650 return AttemptDrawBlur(shape, paint);
653bool Canvas::AttemptDrawBlur(BlurShape& shape,
const Paint& paint) {
658 Color rrect_color = paint.color;
659 if (paint.invert_colors) {
662 if (paint.color_filter) {
666 Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor};
668 if (!rrect_paint.mask_blur_descriptor.has_value()) {
695 if ((paint.mask_blur_descriptor->style !=
697 paint.image_filter) ||
700 Rect render_bounds = shape.GetBounds();
701 if (paint.mask_blur_descriptor->style !=
704 render_bounds.
Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
710 .image_filter = paint.image_filter,
711 .blend_mode = paint.blend_mode,
714 rrect_paint.color = rrect_color.WithAlpha(1);
716 rrect_paint.color = rrect_color;
717 rrect_paint.blend_mode = paint.blend_mode;
718 rrect_paint.image_filter = paint.image_filter;
722 auto draw_blurred_rrect = [
this, &rrect_paint, &shape]() {
723 std::shared_ptr<SolidBlurContents> contents =
724 shape.BuildBlurContent(rrect_paint.mask_blur_descriptor->sigma);
727 contents->SetColor(rrect_paint.color);
729 Entity blurred_rrect_entity;
731 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
733 rrect_paint.mask_blur_descriptor = std::nullopt;
734 blurred_rrect_entity.SetContents(
735 rrect_paint.WithFilters(renderer_, std::move(contents)));
736 AddRenderEntityToCurrentPass(blurred_rrect_entity);
739 switch (rrect_paint.mask_blur_descriptor->style) {
741 draw_blurred_rrect();
746 draw_blurred_rrect();
750 entity.SetBlendMode(rrect_paint.blend_mode);
752 const Geometry& geom = shape.BuildDrawGeometry();
753 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, rrect_paint,
758 const Geometry& geom = shape.BuildDrawGeometry();
760 draw_blurred_rrect();
764 const Geometry& geom = shape.BuildDrawGeometry();
766 draw_blurred_rrect();
784 auto geometry = std::make_unique<LineGeometry>(p0,
p1, paint.
stroke);
786 if ((renderer_.
GetContext()->GetFlags().antialiased_lines ||
787 renderer_.
GetContext()->GetFlags().use_sdfs) &&
792 AddRenderEntityToCurrentPass(entity, reuse_depth);
794 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
803 const Paint& paint) {
813 if (
length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
819 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
826 if (IsShadowBlurDrawOperation(paint)) {
828 if (AttemptDrawBlur(shape, paint)) {
833 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
839 AddRenderSDFEntityToCurrentPass(paint,
params);
849 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
852 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
868 if (IsShadowBlurDrawOperation(paint)) {
873 if (AttemptDrawBlur(shape, paint)) {
878 if (AttemptDrawBlurredPathSource(source, paint)) {
888 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
898 AddRenderSDFEntityToCurrentPass(paint,
params);
904 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
907 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
918 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
931 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
944 return DrawOval(oval_bounds, paint);
954 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
960 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
964 if (IsShadowBlurDrawOperation(paint)) {
965 if (AttemptDrawBlurredRRect(round_rect, paint)) {
972 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
979 ? std::make_optional(paint.
stroke)
981 AddRenderSDFEntityToCurrentPass(paint,
params);
993 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1003 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1006 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1012 const Paint& paint) {
1019 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1022 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1027 const Paint& paint) {
1028 if (IsShadowBlurDrawOperation(paint)) {
1029 if (AttemptDrawBlurredRSuperellipse(round_superellipse, paint)) {
1038 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
1045 round_superellipse_params.top_right.top;
1047 round_superellipse_params.top_right.right;
1063 octant_top.
se_a - octant_right.
se_a,
1065 Point(round_superellipse_params.top_right.signed_scale.Abs()),
1068 AddRenderSDFEntityToCurrentPass(paint,
params);
1076 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1079 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1085 const Paint& paint) {
1086 if (IsShadowBlurDrawOperation(paint)) {
1089 if (AttemptDrawBlur(shape, paint)) {
1094 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
1097 paint.
color, center, radius,
1099 AddRenderSDFEntityToCurrentPass(paint,
params);
1103 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
1113 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1116 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1137 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1138 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1139 uint32_t clip_depth = transform_stack_.back().clip_depth;
1141 const Matrix clip_transform =
1145 std::optional<Rect> clip_coverage = geometry.
GetCoverage(clip_transform);
1146 if (!clip_coverage.has_value()) {
1151 clip_coverage.value(),
1160 GetGlobalPassPosition(),
1162 GetClipHeightFloor(),
1169 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1170 GetGlobalPassPosition());
1173 ++transform_stack_.back().clip_height;
1174 ++transform_stack_.back().num_clips;
1191 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1198 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1217 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1245 if (size.IsEmpty()) {
1249 std::optional<Rect> clipped_source =
1251 if (!clipped_source) {
1255 if (AttemptColorFilterOptimization(
image, source, dest, paint, sampler,
1256 src_rect_constraint)) {
1260 if (*clipped_source != source) {
1270 texture_contents->SetTexture(
image);
1271 texture_contents->SetSourceRect(*clipped_source);
1272 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1274 texture_contents->SetSamplerDescriptor(sampler);
1275 texture_contents->SetOpacity(paint.
color.
alpha);
1276 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
1284 paint.
WithFilters(renderer_, std::move(texture_contents)));
1285 AddRenderEntityToCurrentPass(entity);
1294 AddRenderEntityToCurrentPass(entity);
1297size_t Canvas::GetClipHeight()
const {
1298 return transform_stack_.back().clip_height;
1303 const Paint& paint) {
1316 if (UseColorSourceContents(vertices, paint)) {
1317 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1323 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1324 contents->SetBlendMode(blend_mode);
1326 contents->SetGeometry(vertices);
1328 AddRenderEntityToCurrentPass(entity);
1340 image_color_source->
image()->asImpellerImage()->GetCachedTexture(
1347 auto sampler_descriptor =
1349 auto effect_transform = image_color_source->
matrix();
1351 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1352 contents->SetBlendMode(blend_mode);
1354 contents->SetGeometry(vertices);
1355 contents->SetEffectTransform(effect_transform);
1356 contents->SetTexture(
texture);
1357 contents->SetTileMode(x_tile_mode, y_tile_mode);
1358 contents->SetSamplerDescriptor(sampler_descriptor);
1361 AddRenderEntityToCurrentPass(entity);
1365 auto src_paint = paint;
1368 std::shared_ptr<ColorSourceContents> src_contents =
1369 src_paint.CreateContents(renderer_, vertices.get());
1377 auto size = src_contents->GetColorSourceSize();
1378 if (size.has_value()) {
1381 auto cvg = vertices->GetCoverage(
Matrix{});
1383 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1384 if (texture_coverage.has_value()) {
1387 texture_coverage->GetSize().Max({1, 1}));
1390 src_coverage = cvg.value();
1395 src_paint.CreateContents(renderer_, clip_geometry_.back().get());
1397 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1398 contents->SetBlendMode(blend_mode);
1400 contents->SetGeometry(vertices);
1401 contents->SetLazyTextureCoverage(src_coverage);
1402 contents->SetLazyTexture(
1403 [src_contents, src_coverage](
1408 auto snapshot = src_contents->RenderToSnapshot(
1409 renderer, {}, {.coverage_limit =
Rect::Round(src_coverage)});
1410 return snapshot.has_value() ? snapshot->texture :
nullptr;
1413 AddRenderEntityToCurrentPass(entity);
1417 const Paint& paint) {
1425 AddRenderEntityToCurrentPass(entity);
1431void Canvas::SetupRenderPass() {
1437 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
1442 *renderer_.
GetContext()->GetResourceAllocator(),
1444 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA() &&
1445 color0.
texture->GetTextureDescriptor().sample_count >
1447 "ImpellerOnscreen", kDefaultStencilConfig);
1459 if (requires_readback_) {
1460 auto entity_pass_target =
1461 CreateRenderTarget(renderer_,
1464 render_passes_.push_back(
1465 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1467 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1472 render_passes_.push_back(
1473 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1477void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
1478 auto entry = CanvasStackEntry{};
1479 entry.skipping =
true;
1480 entry.clip_depth = current_depth_ + total_content_depth;
1481 transform_stack_.push_back(entry);
1486 return SkipUntilMatchingRestore(total_content_depth);
1490 entry.
transform = transform_stack_.back().transform;
1491 entry.clip_depth = current_depth_ + total_content_depth;
1492 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1493 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1494 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1495 <<
" after allocating " << total_content_depth;
1496 entry.clip_height = transform_stack_.back().clip_height;
1498 transform_stack_.push_back(entry);
1505 return std::nullopt;
1508 std::optional<Rect> maybe_current_clip_coverage =
1510 if (!maybe_current_clip_coverage.has_value()) {
1511 return std::nullopt;
1514 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1518 std::shared_ptr<Texture> back_texture =
1520 FML_CHECK(back_texture) <<
"Context is valid:"
1525 std::optional<Rect> maybe_coverage_limit =
1527 Size(back_texture->GetSize()))
1530 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1531 return std::nullopt;
1534 return maybe_coverage_limit->Intersection(
1539 std::optional<Rect> bounds,
1542 uint32_t total_content_depth,
1543 bool can_distribute_opacity,
1544 std::optional<int64_t> backdrop_id) {
1547 return SkipUntilMatchingRestore(total_content_depth);
1551 if (!maybe_coverage_limit.has_value()) {
1552 return SkipUntilMatchingRestore(total_content_depth);
1554 auto coverage_limit = maybe_coverage_limit.value();
1556 if (can_distribute_opacity && !backdrop_filter &&
1559 Save(total_content_depth);
1560 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1564 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1565 renderer_,
Rect(), transform_stack_.back().transform,
1570 transform_stack_.back().transform,
1575 !!backdrop_filter ||
1580 if (!maybe_subpass_coverage.has_value()) {
1581 return SkipUntilMatchingRestore(total_content_depth);
1584 auto subpass_coverage = maybe_subpass_coverage.value();
1595 bool did_round_out =
false;
1596 Point coverage_origin_adjustment =
Point{0, 0};
1600 did_round_out =
true;
1604 coverage_origin_adjustment =
1605 Point(subpass_coverage.GetLeftTop().x -
1606 std::floor(subpass_coverage.GetLeftTop().x),
1607 subpass_coverage.GetLeftTop().y -
1608 std::floor(subpass_coverage.GetLeftTop().y));
1611 return SkipUntilMatchingRestore(total_content_depth);
1619 ->GetMaximumRenderPassAttachmentSize());
1622 std::shared_ptr<FilterContents> backdrop_filter_contents;
1624 if (backdrop_filter) {
1625 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1627 std::shared_ptr<Texture> input_texture;
1632 bool will_cache_backdrop_texture =
false;
1637 size_t backdrop_count = 1;
1638 if (backdrop_id.has_value()) {
1639 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1640 backdrop_data_.find(backdrop_id.value());
1641 if (backdrop_data_it != backdrop_data_.end()) {
1642 backdrop_data = &backdrop_data_it->second;
1643 will_cache_backdrop_texture =
1645 backdrop_count = backdrop_data_it->second.backdrop_count;
1649 if (!will_cache_backdrop_texture || !backdrop_data->
texture_slot) {
1650 backdrop_count_ -= backdrop_count;
1656 const bool should_use_onscreen =
1658 backdrop_count_ == 0 && render_passes_.size() == 1u;
1659 input_texture = FlipBackdrop(
1660 GetGlobalPassPosition(),
1661 will_cache_backdrop_texture,
1664 if (!input_texture) {
1669 if (will_cache_backdrop_texture) {
1676 backdrop_filter_contents =
1679 backdrop_filter_contents->SetEffectTransform(
1680 transform_stack_.back().transform.Basis());
1681 backdrop_filter_contents->SetRenderingMode(
1682 transform_stack_.back().transform.HasTranslation()
1686 if (will_cache_backdrop_texture) {
1694 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1697 std::optional<Snapshot> maybe_snapshot =
1699 if (maybe_snapshot.has_value()) {
1700 const Snapshot& snapshot = maybe_snapshot.value();
1702 subpass_coverage.Shift(-GetGlobalPassPosition()));
1705 contents->SetTexture(snapshot.
texture);
1706 contents->SetSourceRect(scaled);
1716 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1724 Paint paint_copy = paint;
1725 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1726 transform_stack_.back().distributed_opacity = 1.0;
1728 render_passes_.push_back(
1730 CreateRenderTarget(renderer_,
1735 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1738 entry.
transform = transform_stack_.back().transform;
1739 entry.
clip_depth = current_depth_ + total_content_depth;
1741 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1742 <<
" after allocating " << total_content_depth;
1743 entry.
clip_height = transform_stack_.back().clip_height;
1746 transform_stack_.emplace_back(entry);
1753 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1755 if (!backdrop_filter_contents) {
1761 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1764 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1765 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1770 if (transform_stack_.size() == 1) {
1787 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1788 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1789 current_depth_ = transform_stack_.back().clip_depth;
1792 transform_stack_.pop_back();
1796 if (transform_stack_.back().rendering_mode ==
1798 transform_stack_.back().rendering_mode ==
1800 auto lazy_render_pass = std::move(render_passes_.back());
1801 render_passes_.pop_back();
1803 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1806 save_layer_state_.pop_back();
1807 auto global_pass_position = GetGlobalPassPosition();
1809 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1810 renderer_, save_layer_state.
paint,
1811 lazy_render_pass.GetInlinePassContext()->GetTexture(),
1813 transform_stack_.back().transform
1816 lazy_render_pass.GetInlinePassContext()->EndPass();
1823 Point subpass_texture_position;
1824 if (transform_stack_.back().did_round_out) {
1827 subpass_texture_position =
1832 subpass_texture_position =
1846 ApplyFramebufferBlend(element_entity);
1857 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1858 if (!input_texture) {
1868 contents->SetCoverageHint(element_entity.
GetCoverage());
1876 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1879 transform_stack_.pop_back();
1887 size_t num_clips = transform_stack_.back().num_clips;
1888 transform_stack_.pop_back();
1890 if (num_clips > 0) {
1901 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1902 GetGlobalPassPosition()
1910bool Canvas::AttemptBlurredTextOptimization(
1911 const std::shared_ptr<TextFrame>& text_frame,
1912 const std::shared_ptr<TextContents>& text_contents,
1914 const Paint& paint) {
1928 std::shared_ptr<FilterContents> filter =
1933 std::optional<Glyph> maybe_glyph = text_frame->AsSingleGlyph();
1934 int64_t identifier = maybe_glyph.has_value()
1935 ? maybe_glyph.value().index
1936 :
reinterpret_cast<int64_t
>(text_frame.get());
1937 TextShadowCache::TextShadowCacheKey cache_key(
1940 maybe_glyph.has_value(),
1941 text_frame->GetFont(),
1946 renderer_, entity, filter, cache_key);
1947 if (result.has_value()) {
1948 AddRenderEntityToCurrentPass(result.value(),
false);
1962 const Paint& paint) {
1964 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1980 auto text_contents = std::make_shared<TextContents>();
1981 text_contents->SetTextFrame(text_frame);
1982 text_contents->SetPosition(position);
1985 text_contents->SetColor(paint.
color);
1986 text_contents->SetTextProperties(paint.
color, paint.
GetStroke());
1990 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1996 AddRenderEntityToCurrentPass(entity,
false);
1999void Canvas::AddRenderSDFEntityToCurrentPass(
const Paint& paint,
2011 auto geometry = std::make_unique<UberSDFGeometry>(
params);
2013 const Geometry* geom = contents->GetGeometry();
2018 std::shared_ptr<Contents> color_source_contents =
2024 Paint new_paint = paint;
2026 AddRenderEntityWithFiltersToCurrentPass(entity, geom, new_paint,
2029 std::move(final_contents));
2031 AddRenderEntityWithFiltersToCurrentPass(entity, geom, paint,
2034 std::move(contents));
2038void Canvas::AddRenderEntityWithFiltersToCurrentPass(
2040 const Geometry* geometry,
2043 std::shared_ptr<Contents> override_contents) {
2044 std::shared_ptr<ColorSourceContents> color_source_contents;
2045 std::shared_ptr<Contents> contents;
2046 if (override_contents) {
2047 contents = std::move(override_contents);
2049 color_source_contents = paint.CreateContents(renderer_, geometry);
2050 contents = color_source_contents;
2053 if (!paint.color_filter && !paint.invert_colors && !paint.image_filter &&
2054 !paint.mask_blur_descriptor.has_value()) {
2055 entity.SetContents(std::move(contents));
2056 AddRenderEntityToCurrentPass(entity, reuse_depth);
2063 bool needs_color_filter = paint.color_filter || paint.invert_colors;
2064 if (needs_color_filter &&
2065 contents->ApplyColorFilter([&](Color color) -> Color {
2066 if (paint.color_filter) {
2067 color = GetCPUColorFilterProc(paint.color_filter)(color);
2069 if (paint.invert_colors) {
2070 color = color.ApplyColorMatrix(kColorInversion);
2074 needs_color_filter =
false;
2077 bool can_apply_mask_filter = geometry->CanApplyMaskFilter();
2079 if (can_apply_mask_filter && paint.mask_blur_descriptor.has_value()) {
2083 FML_DCHECK(color_source_contents) <<
"Mask blur is only supported when no "
2084 "override contents are provided.";
2085 FillRectGeometry out_rect(
Rect{});
2086 auto filter = paint.mask_blur_descriptor->CreateMaskBlur(
2087 paint, renderer_, geometry, color_source_contents, needs_color_filter,
2089 entity.SetContents(std::move(filter));
2090 AddRenderEntityToCurrentPass(entity, reuse_depth);
2094 std::shared_ptr<Contents> contents_copy = std::move(contents);
2098 if (needs_color_filter &&
2099 (!paint.color_source ||
2101 if (paint.color_filter) {
2106 if (paint.invert_colors) {
2113 if (paint.image_filter) {
2114 std::shared_ptr<FilterContents> filter =
2115 WrapInput(renderer_, paint.image_filter,
2118 entity.SetContents(filter);
2119 AddRenderEntityToCurrentPass(entity, reuse_depth);
2123 entity.SetContents(std::move(contents_copy));
2124 AddRenderEntityToCurrentPass(entity, reuse_depth);
2127void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
2132 entity.SetTransform(
2133 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
2134 entity.GetTransform());
2135 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
2136 if (entity.GetBlendMode() == BlendMode::kSrcOver &&
2137 entity.GetContents()->IsOpaque(entity.GetTransform())) {
2138 entity.SetBlendMode(BlendMode::kSrc);
2144 if (render_passes_.back().IsApplyingClearColor()) {
2145 std::optional<Color> maybe_color = entity.AsBackgroundColor(
2146 render_passes_.back().GetInlinePassContext()->GetTexture()->GetSize());
2147 if (maybe_color.has_value()) {
2148 Color color = maybe_color.value();
2149 RenderTarget& render_target = render_passes_.back()
2150 .GetInlinePassContext()
2153 ColorAttachment attachment = render_target.GetColorAttachment(0);
2156 attachment.clear_color = attachment.clear_color.Unpremultiply()
2157 .Blend(color, entity.GetBlendMode())
2159 render_target.SetColorAttachment(attachment, 0u);
2170 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
2171 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
2172 entity.SetClipDepth(current_depth_);
2174 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
2175 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
2176 ApplyFramebufferBlend(entity);
2187 auto input_texture = FlipBackdrop(GetGlobalPassPosition(),
2191 if (!input_texture) {
2199 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
2200 entity.GetContents()->SetCoverageHint(Rect::Intersection(
2201 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
2203 FilterInput::Vector inputs = {
2204 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
2205 FilterInput::Make(entity.GetContents())};
2207 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
2208 entity.SetContents(std::move(contents));
2209 entity.SetBlendMode(BlendMode::kSrc);
2213 const std::shared_ptr<RenderPass>& result =
2214 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2222 entity.Render(renderer_, *result);
2225RenderPass& Canvas::GetCurrentRenderPass()
const {
2226 return *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2229void Canvas::SetBackdropData(
2230 std::unordered_map<int64_t, BackdropData> backdrop_data,
2231 size_t backdrop_count) {
2232 backdrop_data_ = std::move(backdrop_data);
2233 backdrop_count_ = backdrop_count;
2236std::shared_ptr<Texture> Canvas::FlipBackdrop(
Point global_pass_position,
2237 bool should_remove_texture,
2238 bool should_use_onscreen,
2239 bool post_depth_increment) {
2241 render_passes_.pop_back();
2257 <<
"Failed to end the current render pass in order to read from "
2258 "the backdrop texture and apply an advanced blend or backdrop "
2263 render_passes_.emplace_back(std::move(rendering_config));
2267 const std::shared_ptr<Texture>& input_texture =
2270 if (!input_texture) {
2271 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
2272 "apply an advanced blend or backdrop filter.";
2275 render_passes_.emplace_back(std::move(rendering_config));
2279 if (should_use_onscreen) {
2280 ColorAttachment color0 = render_target_.GetColorAttachment(0);
2284 color0.load_action = color0.resolve_texture !=
nullptr
2285 ? LoadAction::kDontCare
2286 : LoadAction::kLoad;
2287 render_target_.SetColorAttachment(color0, 0);
2289 auto entity_pass_target = std::make_unique<EntityPassTarget>(
2291 renderer_.GetDeviceCapabilities().SupportsReadFromResolve(),
2292 renderer_.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
2294 render_passes_.push_back(
2295 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
2296 requires_readback_ =
false;
2298 render_passes_.emplace_back(std::move(rendering_config));
2301 if (should_remove_texture) {
2302 render_passes_.back().GetEntityPassTarget()->RemoveSecondary();
2305 RenderPass& current_render_pass =
2306 *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2315 Rect size_rect = Rect::MakeSize(input_texture->GetSize());
2316 auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
2317 msaa_backdrop_contents->SetStencilEnabled(
false);
2318 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
2319 msaa_backdrop_contents->SetSourceRect(size_rect);
2320 msaa_backdrop_contents->SetTexture(input_texture);
2322 Entity msaa_backdrop_entity;
2323 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
2324 msaa_backdrop_entity.SetBlendMode(BlendMode::kSrc);
2325 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
2326 if (!msaa_backdrop_entity.Render(renderer_, current_render_pass)) {
2333 auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
2334 uint64_t current_depth =
2335 post_depth_increment ? current_depth_ - 1 : current_depth_;
2336 for (
const auto& replay : replay_entities) {
2337 if (replay.clip_depth <= current_depth) {
2341 SetClipScissor(replay.clip_coverage, current_render_pass,
2342 global_pass_position);
2343 if (!replay.clip_contents.Render(renderer_, current_render_pass,
2344 replay.clip_depth)) {
2349 return input_texture;
2352bool Canvas::SupportsBlitToOnscreen()
const {
2353 return renderer_.GetContext()
2355 ->SupportsTextureToTextureBlits() &&
2356 renderer_.GetContext()->GetBackendType() ==
2357 Context::BackendType::kMetal;
2360bool Canvas::BlitToOnscreen(
bool is_onscreen) {
2361 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
2362 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
2363 auto offscreen_target = render_passes_.back()
2364 .GetInlinePassContext()
2367 if (SupportsBlitToOnscreen()) {
2368 auto blit_pass = command_buffer->CreateBlitPass();
2369 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
2370 render_target_.GetRenderTargetTexture());
2371 if (!blit_pass->EncodeCommands()) {
2376 auto render_pass = command_buffer->CreateRenderPass(render_target_);
2377 render_pass->SetLabel(
"EntityPass Root Render Pass");
2380 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
2381 auto contents = TextureContents::MakeRect(size_rect);
2382 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
2383 contents->SetSourceRect(size_rect);
2384 contents->SetLabel(
"Root pass blit");
2387 entity.SetContents(contents);
2388 entity.SetBlendMode(BlendMode::kSrc);
2390 if (!entity.Render(renderer_, *render_pass)) {
2396 if (!render_pass->EncodeCommands()) {
2403 return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer));
2405 return renderer_.GetContext()->EnqueueCommandBuffer(
2406 std::move(command_buffer));
2410bool Canvas::EnsureFinalMipmapGeneration()
const {
2411 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2414 std::shared_ptr<CommandBuffer> cmd_buffer =
2415 renderer_.GetContext()->CreateCommandBuffer();
2419 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2423 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2424 blit_pass->EncodeCommands();
2425 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2428void Canvas::EndReplay() {
2430 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2431 render_passes_.back().GetInlinePassContext()->EndPass(
2432 !requires_readback_ && is_onscreen_);
2433 backdrop_data_.clear();
2438 if (requires_readback_) {
2439 BlitToOnscreen(is_onscreen_);
2441 if (!EnsureFinalMipmapGeneration()) {
2444 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2448 render_passes_.clear();
2449 renderer_.GetRenderTargetCache()->End();
2450 clip_geometry_.clear();
2453 Initialize(initial_cull_rect_);
2456bool Canvas::IsCompatibleWithSDFRendering(
const Paint& paint) {
2465 case BlendMode::kClear:
2466 case BlendMode::kSrc:
2467 case BlendMode::kSrcIn:
2468 case BlendMode::kDstIn:
2469 case BlendMode::kSrcOut:
2470 case BlendMode::kDstATop:
2471 case BlendMode::kPlus:
2472 case BlendMode::kModulate:
2475 case BlendMode::kDst:
2476 case BlendMode::kSrcOver:
2477 case BlendMode::kDstOver:
2478 case BlendMode::kDstOut:
2479 case BlendMode::kSrcATop:
2480 case BlendMode::kXor:
2481 case BlendMode::kScreen:
2482 case BlendMode::kOverlay:
2483 case BlendMode::kDarken:
2484 case BlendMode::kLighten:
2485 case BlendMode::kColorDodge:
2486 case BlendMode::kColorBurn:
2487 case BlendMode::kHardLight:
2488 case BlendMode::kSoftLight:
2489 case BlendMode::kDifference:
2490 case BlendMode::kExclusion:
2491 case BlendMode::kMultiply:
2492 case BlendMode::kHue:
2493 case BlendMode::kSaturation:
2494 case BlendMode::kColor:
2495 case BlendMode::kLuminosity:
2500LazyRenderingConfig::LazyRenderingConfig(
2502 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
2503 : entity_pass_target_(
std::move(p_entity_pass_target)) {
2504 inline_pass_context_ =
2505 std::make_unique<InlinePassContext>(renderer, *entity_pass_target_);
2509 return !inline_pass_context_->IsActive();
2513 return entity_pass_target_.get();
2517 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 ...
const Geometry & BuildDrawGeometry() override
PathBlurShape(const PathSource &source, std::shared_ptr< ShadowVertices > shadow_vertices, Sigma sigma)
Rect GetBounds() const override
std::shared_ptr< SolidBlurContents > BuildBlurContent(Sigma sigma) override
Rect GetBounds() const override
RRectBlurShape(const Rect &rect, Scalar corner_radius)
const Geometry & BuildDrawGeometry() override
std::shared_ptr< SolidBlurContents > BuildBlurContent(Sigma sigma) override
std::shared_ptr< SolidBlurContents > BuildBlurContent(Sigma sigma) override
const Geometry & BuildDrawGeometry() override
Rect GetBounds() const override
RSuperellipseBlurShape(const Rect &rect, Scalar corner_radius)
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)
static bool IsCompatibleWithSDFRendering(const Paint &paint)
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)
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
Tessellator & GetTessellator() 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...
A PathSource object that provides path iteration for any ellipse inscribed within a Rect bounds.
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
The coverage rectangle of this geometry, transformed by the transform argument.
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
virtual GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) 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...
static std::shared_ptr< ShadowVertices > MakeAmbientShadowVertices(Tessellator &tessellator, const PathSource &source, Scalar occluder_height, const Matrix &matrix)
static std::shared_ptr< ShadowVerticesContents > Make(const std::shared_ptr< ShadowVertices > &geometry)
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)
static std::unique_ptr< UberSDFContents > Make(const UberSDFParameters ¶ms, std::unique_ptr< Geometry > geometry)
const EmbeddedViewParams * params
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.
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)
std::shared_ptr< FilterContents > WrapInput(const ContentContext &renderer, const flutter::DlImageFilter *filter, const FilterInput::Ref &input)
Generate a new FilterContents using this filter's configuration.
@ 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.
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
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< FilterContents > WithImageFilter(const ContentContext &renderer, const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
const flutter::DlColorFilter * color_filter
const flutter::DlColorSource * color_source
const flutter::DlImageFilter * image_filter
std::shared_ptr< Contents > WithFilters(const ContentContext &renderer, std::shared_ptr< Contents > input) const
Wrap this paint's configured filters to the given contents.
static bool CanApplyOpacityPeephole(const Paint &paint)
Whether or not a save layer with the provided paint can perform the opacity peephole optimization.
std::optional< StrokeParameters > GetStroke() const
Return an optional StrokeParameters if this Paint is a stroked Paint, otherwise return a nullopt.
std::optional< MaskBlurDescriptor > mask_blur_descriptor
std::shared_ptr< ColorSourceContents > CreateContents(const ContentContext &renderer, const Geometry *geometry) 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
static RoundSuperellipseParam MakeBoundsRadii(const Rect &bounds, const RoundingRadii &radii)
static constexpr RoundingRadii MakeRadii(Size radii)
constexpr bool AreAllCornersCircular() const
constexpr bool AreAllCornersSame(Scalar tolerance=kEhCloseEnough) const
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
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 MakeCircleBounds(const TPoint< Type > ¢er, Type radius)
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)
Parameters for rendering shapes using the UberSDF shader.
static UberSDFParameters MakeCircle(Color color, const Point ¢er, Scalar radius, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for a circle.
static UberSDFParameters MakeOval(Color color, const Rect &bounds, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for an Oval.
static UberSDFParameters MakeRoundedRect(Color color, const Rect &rect, const RoundingRadii &radii, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for a rounded rectangle.
static UberSDFParameters MakeRect(Color color, const Rect &rect, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for a rectangle.
static UberSDFParameters MakeRoundedSuperellipse(Color color, Rect bounds, Point superellipse_degree, Point superellipse_a, RoundingRadii radii, Point corner_angle_span, Point corner_circle_center_top, Point corner_circle_center_right, Scalar superellipse_c, Point superellipse_scale, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for a symmetric round superellipse.
std::vector< Point > points
#define TRACE_EVENT0(category_group, name)