9#include <unordered_map>
74constexpr Scalar kAntialiasPadding = 1.0f;
82static bool UseColorSourceContents(
83 const std::shared_ptr<VerticesGeometry>& vertices,
87 if (vertices->HasVertexColors()) {
90 if (vertices->HasTextureCoordinates() && !paint.color_source) {
93 return !vertices->HasTextureCoordinates();
96static void SetClipScissor(std::optional<Rect> clip_coverage,
98 Point global_pass_position) {
102 if (clip_coverage.has_value()) {
103 clip_coverage = clip_coverage->Shift(-global_pass_position);
110 pass.SetScissor(scissor);
113static void ApplyFramebufferBlend(Entity& entity) {
114 auto src_contents = entity.GetContents();
115 auto contents = std::make_shared<FramebufferBlendContents>();
116 contents->SetChildContents(src_contents);
117 contents->SetBlendMode(entity.GetBlendMode());
118 entity.SetContents(std::move(contents));
124static std::shared_ptr<Contents> CreateContentsForSubpassTarget(
125 const ContentContext& renderer,
127 const std::shared_ptr<Texture>&
target,
128 const Matrix& effect_transform) {
130 contents->SetTexture(
target);
131 contents->SetLabel(
"Subpass");
133 contents->SetOpacity(paint.color.alpha);
134 contents->SetDeferApplyingOpacity(
true);
136 return paint.WithFiltersForSubpassTarget(renderer, std::move(contents),
140static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
141 RenderTarget::AttachmentConfig{
147static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
148 ContentContext& renderer,
150 const Color& clear_color) {
151 const std::shared_ptr<Context>&
context = renderer.GetContext();
159 if (
context->GetCapabilities()->SupportsOffscreenMSAA()) {
160 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
166 RenderTarget::AttachmentConfigMSAA{
171 .clear_color = clear_color},
172 kDefaultStencilConfig);
174 target = renderer.GetRenderTargetCache()->CreateOffscreen(
179 RenderTarget::AttachmentConfig{
183 .clear_color = clear_color,
185 kDefaultStencilConfig
189 return std::make_unique<EntityPassTarget>(
191 renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
192 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
201 : rect_(rect), corner_radius_(corner_radius) {}
206 auto contents = std::make_shared<SolidRRectBlurContents>();
207 contents->SetSigma(sigma);
208 contents->SetShape(rect_, corner_radius_);
213 return geom_.emplace(rect_,
Size(corner_radius_));
218 const Scalar corner_radius_;
220 std::optional<RoundRectGeometry> geom_;
226 : rect_(rect), corner_radius_(corner_radius) {}
231 auto contents = std::make_shared<SolidRSuperellipseBlurContents>();
232 contents->SetSigma(sigma);
233 contents->SetShape(rect_, corner_radius_);
238 return geom_.emplace(rect_, corner_radius_);
243 const Scalar corner_radius_;
245 std::optional<RoundSuperellipseGeometry> geom_;
265 std::shared_ptr<ShadowVertices> shadow_vertices,
269 shadow_vertices_(
std::move(shadow_vertices)) {}
272 return shadow_vertices_->GetBounds().value_or(
Rect());
286 return source_geometry_.emplace(source_);
292 const std::shared_ptr<ShadowVertices> shadow_vertices_;
295 std::optional<FillPathFromSourceGeometry> source_geometry_;
301 bool requires_readback)
302 : renderer_(renderer),
303 render_target_(render_target),
304 is_onscreen_(is_onscreen),
305 requires_readback_(requires_readback),
307 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
308 Initialize(std::nullopt);
315 bool requires_readback,
317 : renderer_(renderer),
318 render_target_(render_target),
319 is_onscreen_(is_onscreen),
320 requires_readback_(requires_readback),
322 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
323 Initialize(cull_rect);
330 bool requires_readback,
332 : renderer_(renderer),
333 render_target_(render_target),
334 is_onscreen_(is_onscreen),
335 requires_readback_(requires_readback),
337 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
343void Canvas::Initialize(std::optional<Rect> cull_rect) {
344 initial_cull_rect_ = cull_rect;
351void Canvas::Reset() {
353 transform_stack_ = {};
365 transform_stack_.back().transform = {};
373 return transform_stack_.back().transform;
396Point Canvas::GetGlobalPassPosition()
const {
397 if (save_layer_state_.empty()) {
400 return save_layer_state_.back().coverage.GetOrigin();
404size_t Canvas::GetClipHeightFloor()
const {
405 if (transform_stack_.size() > 1) {
406 return transform_stack_[transform_stack_.size() - 2].clip_height;
412 return transform_stack_.size();
415bool Canvas::IsSkipping()
const {
416 return transform_stack_.back().skipping;
428 if (IsShadowBlurDrawOperation(paint)) {
429 if (AttemptDrawBlurredPathSource(path, paint)) {
440 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
443 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
453 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
460bool Canvas::AttemptColorFilterOptimization(
461 const std::shared_ptr<Texture>&
image,
478 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
483 blend_filter->
mode(),
485 src_rect_constraint ==
488 auto atlas_contents = std::make_shared<AtlasContents>();
489 atlas_contents->SetGeometry(&geometry);
495 entity.SetContents(atlas_contents);
497 AddRenderEntityToCurrentPass(entity);
508 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
515 src_rect_constraint ==
518 auto atlas_contents = std::make_shared<ColorFilterAtlasContents>();
519 atlas_contents->SetGeometry(&geometry);
523 atlas_contents->SetMatrix(color_matrix);
528 entity.SetContents(atlas_contents);
530 AddRenderEntityToCurrentPass(entity);
535bool Canvas::AttemptDrawAntialiasedCircle(
const Point& center,
537 const Paint& paint) {
538 if (paint.HasColorFilter() || paint.image_filter || paint.invert_colors ||
539 paint.color_source || paint.mask_blur_descriptor.has_value()) {
545 entity.SetBlendMode(paint.blend_mode);
548 std::unique_ptr<CircleGeometry> geom;
550 geom = std::make_unique<CircleGeometry>(center, radius, paint.stroke.width);
552 geom = std::make_unique<CircleGeometry>(center, radius);
554 geom->SetAntialiasPadding(kAntialiasPadding);
558 entity.SetContents(std::move(contents));
559 AddRenderEntityToCurrentPass(entity);
564bool Canvas::IsShadowBlurDrawOperation(
const Paint& paint) {
569 if (paint.color_source) {
573 if (!paint.mask_blur_descriptor.has_value()) {
584 Radius radius = paint.mask_blur_descriptor->sigma;
592bool Canvas::AttemptDrawBlurredPathSource(
const PathSource& source,
593 const Paint& paint) {
600 if (paint.mask_blur_descriptor.has_value()) {
604 static constexpr Scalar kSigmaScale = 2.8f;
606 Sigma sigma = paint.mask_blur_descriptor->sigma;
608 Scalar basis_scale = matrix.GetMaxBasisLengthXY();
609 Scalar device_radius = sigma.sigma * kSigmaScale * basis_scale;
610 std::shared_ptr<ShadowVertices> shadow_vertices =
613 if (shadow_vertices) {
614 PathBlurShape shape(source, std::move(shadow_vertices), sigma);
615 return AttemptDrawBlur(shape, paint);
621Scalar Canvas::GetCommonRRectLikeRadius(
const RoundingRadii& radii) {
622 if (!radii.AreAllCornersSame()) {
625 const Size& corner_radii = radii.top_left;
627 return corner_radii.
width;
632bool Canvas::AttemptDrawBlurredRRect(
const RoundRect& round_rect,
633 const Paint& paint) {
634 Scalar radius = GetCommonRRectLikeRadius(round_rect.GetRadii());
636 RoundRectPathSource source(round_rect);
637 return AttemptDrawBlurredPathSource(source, paint);
639 RRectBlurShape shape(round_rect.GetBounds(), radius);
640 return AttemptDrawBlur(shape, paint);
643bool Canvas::AttemptDrawBlurredRSuperellipse(
const RoundSuperellipse& rse,
644 const Paint& paint) {
645 Scalar radius = GetCommonRRectLikeRadius(rse.GetRadii());
647 RoundSuperellipsePathSource source(rse);
648 return AttemptDrawBlurredPathSource(source, paint);
650 RSuperellipseBlurShape shape(rse.GetBounds(), radius);
651 return AttemptDrawBlur(shape, paint);
654bool Canvas::AttemptDrawBlur(BlurShape& shape,
const Paint& paint) {
659 Color rrect_color = paint.color;
660 if (paint.invert_colors) {
663 if (paint.color_filter) {
667 Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor};
669 if (!rrect_paint.mask_blur_descriptor.has_value()) {
696 if ((paint.mask_blur_descriptor->style !=
698 paint.image_filter) ||
701 Rect render_bounds = shape.GetBounds();
702 if (paint.mask_blur_descriptor->style !=
705 render_bounds.
Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
711 .image_filter = paint.image_filter,
712 .blend_mode = paint.blend_mode,
715 rrect_paint.color = rrect_color.WithAlpha(1);
717 rrect_paint.color = rrect_color;
718 rrect_paint.blend_mode = paint.blend_mode;
719 rrect_paint.image_filter = paint.image_filter;
723 auto draw_blurred_rrect = [
this, &rrect_paint, &shape]() {
724 std::shared_ptr<SolidBlurContents> contents =
725 shape.BuildBlurContent(rrect_paint.mask_blur_descriptor->sigma);
728 contents->SetColor(rrect_paint.color);
730 Entity blurred_rrect_entity;
732 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
734 rrect_paint.mask_blur_descriptor = std::nullopt;
735 blurred_rrect_entity.SetContents(
736 rrect_paint.WithFilters(renderer_, std::move(contents)));
737 AddRenderEntityToCurrentPass(blurred_rrect_entity);
740 switch (rrect_paint.mask_blur_descriptor->style) {
742 draw_blurred_rrect();
747 draw_blurred_rrect();
751 entity.SetBlendMode(rrect_paint.blend_mode);
753 const Geometry& geom = shape.BuildDrawGeometry();
754 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, rrect_paint,
759 const Geometry& geom = shape.BuildDrawGeometry();
761 draw_blurred_rrect();
765 const Geometry& geom = shape.BuildDrawGeometry();
767 draw_blurred_rrect();
785 auto geometry = std::make_unique<LineGeometry>(p0,
p1, paint.
stroke);
787 if ((renderer_.
GetContext()->GetFlags().antialiased_lines ||
788 renderer_.
GetContext()->GetFlags().use_sdfs) &&
793 AddRenderEntityToCurrentPass(entity, reuse_depth);
795 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
804 const Paint& paint) {
814 if (
length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
820 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
827 if (IsShadowBlurDrawOperation(paint)) {
829 if (AttemptDrawBlur(shape, paint)) {
834 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
840 AddRenderSDFEntityToCurrentPass(paint,
params);
850 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
853 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
869 if (IsShadowBlurDrawOperation(paint)) {
874 if (AttemptDrawBlur(shape, paint)) {
879 if (AttemptDrawBlurredPathSource(source, paint)) {
889 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
899 AddRenderSDFEntityToCurrentPass(paint,
params);
905 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
908 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
919 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
932 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
945 return DrawOval(oval_bounds, paint);
955 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
961 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
965 if (IsShadowBlurDrawOperation(paint)) {
966 if (AttemptDrawBlurredRRect(round_rect, paint)) {
973 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
980 ? std::make_optional(paint.
stroke)
982 AddRenderSDFEntityToCurrentPass(paint,
params);
994 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1004 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1007 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1013 const Paint& paint) {
1020 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1023 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1028 const Paint& paint) {
1029 if (IsShadowBlurDrawOperation(paint)) {
1030 if (AttemptDrawBlurredRSuperellipse(round_superellipse, paint)) {
1039 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
1044 if (round_superellipse_params.all_corners_same) {
1048 round_superellipse_params,
1051 AddRenderSDFEntityToCurrentPass(paint,
params);
1057 round_superellipse_params,
1060 const Geometry* geom = contents->GetGeometry();
1063 std::shared_ptr<Contents> color_source_contents =
1065 std::shared_ptr<Contents> final_contents =
1070 Paint new_paint = paint;
1072 AddRenderEntityWithFiltersToCurrentPass(entity, geom, new_paint,
1075 std::move(final_contents));
1077 AddRenderEntityWithFiltersToCurrentPass(entity, geom, paint,
1080 std::move(contents));
1089 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1092 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1098 const Paint& paint) {
1099 if (IsShadowBlurDrawOperation(paint)) {
1102 if (AttemptDrawBlur(shape, paint)) {
1107 if (renderer_.
GetContext()->GetFlags().use_sdfs &&
1110 paint.
color, center, radius,
1112 AddRenderSDFEntityToCurrentPass(paint,
params);
1116 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
1126 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1129 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1150 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1151 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1152 uint32_t clip_depth = transform_stack_.back().clip_depth;
1154 const Matrix clip_transform =
1158 std::optional<Rect> clip_coverage = geometry.
GetCoverage(clip_transform);
1159 if (!clip_coverage.has_value()) {
1164 clip_coverage.value(),
1173 GetGlobalPassPosition(),
1175 GetClipHeightFloor(),
1182 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1183 GetGlobalPassPosition());
1186 ++transform_stack_.back().clip_height;
1187 ++transform_stack_.back().num_clips;
1204 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1211 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1230 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1258 if (size.IsEmpty()) {
1262 std::optional<Rect> clipped_source =
1264 if (!clipped_source) {
1268 if (AttemptColorFilterOptimization(
image, source, dest, paint, sampler,
1269 src_rect_constraint)) {
1273 if (*clipped_source != source) {
1283 texture_contents->SetTexture(
image);
1284 texture_contents->SetSourceRect(*clipped_source);
1285 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1287 texture_contents->SetSamplerDescriptor(sampler);
1288 texture_contents->SetOpacity(paint.
color.
alpha);
1289 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
1297 paint.
WithFilters(renderer_, std::move(texture_contents)));
1298 AddRenderEntityToCurrentPass(entity);
1307 AddRenderEntityToCurrentPass(entity);
1310size_t Canvas::GetClipHeight()
const {
1311 return transform_stack_.back().clip_height;
1316 const Paint& paint) {
1329 if (UseColorSourceContents(vertices, paint)) {
1330 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1336 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1337 contents->SetBlendMode(blend_mode);
1339 contents->SetGeometry(vertices);
1341 AddRenderEntityToCurrentPass(entity);
1353 image_color_source->
image()->asImpellerImage()->GetCachedTexture(
1360 auto sampler_descriptor =
1362 auto effect_transform = image_color_source->
matrix();
1364 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1365 contents->SetBlendMode(blend_mode);
1367 contents->SetGeometry(vertices);
1368 contents->SetEffectTransform(effect_transform);
1369 contents->SetTexture(
texture);
1370 contents->SetTileMode(x_tile_mode, y_tile_mode);
1371 contents->SetSamplerDescriptor(sampler_descriptor);
1374 AddRenderEntityToCurrentPass(entity);
1378 auto src_paint = paint;
1381 std::shared_ptr<ColorSourceContents> src_contents =
1382 src_paint.CreateContents(renderer_, vertices.get());
1390 auto size = src_contents->GetColorSourceSize();
1391 if (size.has_value()) {
1394 auto cvg = vertices->GetCoverage(
Matrix{});
1396 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1397 if (texture_coverage.has_value()) {
1400 texture_coverage->GetSize().Max({1, 1}));
1403 src_coverage = cvg.value();
1408 src_paint.CreateContents(renderer_, clip_geometry_.back().get());
1410 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1411 contents->SetBlendMode(blend_mode);
1413 contents->SetGeometry(vertices);
1414 contents->SetLazyTextureCoverage(src_coverage);
1415 contents->SetLazyTexture(
1416 [src_contents, src_coverage](
1421 auto snapshot = src_contents->RenderToSnapshot(
1422 renderer, {}, {.coverage_limit =
Rect::Round(src_coverage)});
1423 return snapshot.has_value() ? snapshot->texture :
nullptr;
1426 AddRenderEntityToCurrentPass(entity);
1430 const Paint& paint) {
1438 AddRenderEntityToCurrentPass(entity);
1444void Canvas::SetupRenderPass() {
1450 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
1455 *renderer_.
GetContext()->GetResourceAllocator(),
1457 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA() &&
1458 color0.
texture->GetTextureDescriptor().sample_count >
1460 "ImpellerOnscreen", kDefaultStencilConfig);
1472 if (requires_readback_) {
1473 auto entity_pass_target =
1474 CreateRenderTarget(renderer_,
1477 render_passes_.push_back(
1478 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1480 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1485 render_passes_.push_back(
1486 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1490void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
1491 auto entry = CanvasStackEntry{};
1492 entry.skipping =
true;
1493 entry.clip_depth = current_depth_ + total_content_depth;
1494 transform_stack_.push_back(entry);
1499 return SkipUntilMatchingRestore(total_content_depth);
1503 entry.
transform = transform_stack_.back().transform;
1504 entry.clip_depth = current_depth_ + total_content_depth;
1505 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1506 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1507 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1508 <<
" after allocating " << total_content_depth;
1509 entry.clip_height = transform_stack_.back().clip_height;
1511 transform_stack_.push_back(entry);
1518 return std::nullopt;
1521 std::optional<Rect> maybe_current_clip_coverage =
1523 if (!maybe_current_clip_coverage.has_value()) {
1524 return std::nullopt;
1527 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1531 std::shared_ptr<Texture> back_texture =
1533 FML_CHECK(back_texture) <<
"Context is valid:"
1538 std::optional<Rect> maybe_coverage_limit =
1540 Size(back_texture->GetSize()))
1543 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1544 return std::nullopt;
1547 return maybe_coverage_limit->Intersection(
1552 std::optional<Rect> bounds,
1555 uint32_t total_content_depth,
1556 bool can_distribute_opacity,
1557 std::optional<int64_t> backdrop_id) {
1560 return SkipUntilMatchingRestore(total_content_depth);
1564 if (!maybe_coverage_limit.has_value()) {
1565 return SkipUntilMatchingRestore(total_content_depth);
1567 auto coverage_limit = maybe_coverage_limit.value();
1569 if (can_distribute_opacity && !backdrop_filter &&
1572 Save(total_content_depth);
1573 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1577 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1578 renderer_,
Rect(), transform_stack_.back().transform,
1583 transform_stack_.back().transform,
1588 !!backdrop_filter ||
1593 if (!maybe_subpass_coverage.has_value()) {
1594 return SkipUntilMatchingRestore(total_content_depth);
1597 auto subpass_coverage = maybe_subpass_coverage.value();
1608 bool did_round_out =
false;
1609 Point coverage_origin_adjustment =
Point{0, 0};
1613 did_round_out =
true;
1617 coverage_origin_adjustment =
1618 Point(subpass_coverage.GetLeftTop().x -
1619 std::floor(subpass_coverage.GetLeftTop().x),
1620 subpass_coverage.GetLeftTop().y -
1621 std::floor(subpass_coverage.GetLeftTop().y));
1624 return SkipUntilMatchingRestore(total_content_depth);
1632 ->GetMaximumRenderPassAttachmentSize());
1635 std::shared_ptr<FilterContents> backdrop_filter_contents;
1637 if (backdrop_filter) {
1638 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1640 std::shared_ptr<Texture> input_texture;
1645 bool will_cache_backdrop_texture =
false;
1650 size_t backdrop_count = 1;
1651 if (backdrop_id.has_value()) {
1652 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1653 backdrop_data_.find(backdrop_id.value());
1654 if (backdrop_data_it != backdrop_data_.end()) {
1655 backdrop_data = &backdrop_data_it->second;
1656 will_cache_backdrop_texture =
1658 backdrop_count = backdrop_data_it->second.backdrop_count;
1662 if (!will_cache_backdrop_texture || !backdrop_data->
texture_slot) {
1663 backdrop_count_ -= backdrop_count;
1669 const bool should_use_onscreen =
1671 backdrop_count_ == 0 && render_passes_.size() == 1u;
1672 input_texture = FlipBackdrop(
1673 GetGlobalPassPosition(),
1674 will_cache_backdrop_texture,
1677 if (!input_texture) {
1682 if (will_cache_backdrop_texture) {
1689 backdrop_filter_contents =
1692 backdrop_filter_contents->SetEffectTransform(
1693 transform_stack_.back().transform.Basis());
1694 backdrop_filter_contents->SetRenderingMode(
1695 transform_stack_.back().transform.HasTranslation()
1699 if (will_cache_backdrop_texture) {
1707 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1710 std::optional<Snapshot> maybe_snapshot =
1712 if (maybe_snapshot.has_value()) {
1713 const Snapshot& snapshot = maybe_snapshot.value();
1715 subpass_coverage.Shift(-GetGlobalPassPosition()));
1718 contents->SetTexture(snapshot.
texture);
1719 contents->SetSourceRect(scaled);
1729 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1737 Paint paint_copy = paint;
1738 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1739 transform_stack_.back().distributed_opacity = 1.0;
1741 render_passes_.push_back(
1743 CreateRenderTarget(renderer_,
1748 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1751 entry.
transform = transform_stack_.back().transform;
1752 entry.
clip_depth = current_depth_ + total_content_depth;
1754 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1755 <<
" after allocating " << total_content_depth;
1756 entry.
clip_height = transform_stack_.back().clip_height;
1759 transform_stack_.emplace_back(entry);
1766 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1768 if (!backdrop_filter_contents) {
1774 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1777 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1778 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1783 if (transform_stack_.size() == 1) {
1800 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1801 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1802 current_depth_ = transform_stack_.back().clip_depth;
1805 transform_stack_.pop_back();
1809 if (transform_stack_.back().rendering_mode ==
1811 transform_stack_.back().rendering_mode ==
1813 auto lazy_render_pass = std::move(render_passes_.back());
1814 render_passes_.pop_back();
1816 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1819 save_layer_state_.pop_back();
1820 auto global_pass_position = GetGlobalPassPosition();
1822 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1823 renderer_, save_layer_state.
paint,
1824 lazy_render_pass.GetInlinePassContext()->GetTexture(),
1826 transform_stack_.back().transform
1829 lazy_render_pass.GetInlinePassContext()->EndPass();
1836 Point subpass_texture_position;
1837 if (transform_stack_.back().did_round_out) {
1840 subpass_texture_position =
1845 subpass_texture_position =
1859 ApplyFramebufferBlend(element_entity);
1870 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1871 if (!input_texture) {
1881 contents->SetCoverageHint(element_entity.
GetCoverage());
1889 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1892 transform_stack_.pop_back();
1900 size_t num_clips = transform_stack_.back().num_clips;
1901 transform_stack_.pop_back();
1903 if (num_clips > 0) {
1914 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1915 GetGlobalPassPosition()
1923bool Canvas::AttemptBlurredTextOptimization(
1924 const std::shared_ptr<TextFrame>& text_frame,
1925 const std::shared_ptr<TextContents>& text_contents,
1927 const Paint& paint) {
1941 std::shared_ptr<FilterContents> filter =
1946 std::optional<Glyph> maybe_glyph = text_frame->AsSingleGlyph();
1947 int64_t identifier = maybe_glyph.has_value()
1948 ? maybe_glyph.value().index
1949 :
reinterpret_cast<int64_t
>(text_frame.get());
1950 TextShadowCache::TextShadowCacheKey cache_key(
1953 maybe_glyph.has_value(),
1954 text_frame->GetFont(),
1959 renderer_, entity, filter, cache_key);
1960 if (result.has_value()) {
1961 AddRenderEntityToCurrentPass(result.value(),
false);
1975 const Paint& paint) {
1977 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1993 auto text_contents = std::make_shared<TextContents>();
1994 text_contents->SetTextFrame(text_frame);
1995 text_contents->SetPosition(position);
1998 text_contents->SetColor(paint.
color);
1999 text_contents->SetTextProperties(paint.
color, paint.
GetStroke());
2003 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
2009 AddRenderEntityToCurrentPass(entity,
false);
2012void Canvas::AddRenderSDFEntityToCurrentPass(
const Paint& paint,
2024 auto geometry = std::make_unique<UberSDFGeometry>(
params);
2026 const Geometry* geom = contents->GetGeometry();
2031 std::shared_ptr<Contents> color_source_contents =
2037 Paint new_paint = paint;
2039 AddRenderEntityWithFiltersToCurrentPass(entity, geom, new_paint,
2042 std::move(final_contents));
2044 AddRenderEntityWithFiltersToCurrentPass(entity, geom, paint,
2047 std::move(contents));
2051void Canvas::AddRenderEntityWithFiltersToCurrentPass(
2053 const Geometry* geometry,
2056 std::shared_ptr<Contents> override_contents) {
2057 std::shared_ptr<ColorSourceContents> color_source_contents;
2058 std::shared_ptr<Contents> contents;
2059 if (override_contents) {
2060 contents = std::move(override_contents);
2062 color_source_contents = paint.CreateContents(renderer_, geometry);
2063 contents = color_source_contents;
2066 if (!paint.color_filter && !paint.invert_colors && !paint.image_filter &&
2067 !paint.mask_blur_descriptor.has_value()) {
2068 entity.SetContents(std::move(contents));
2069 AddRenderEntityToCurrentPass(entity, reuse_depth);
2076 bool needs_color_filter = paint.color_filter || paint.invert_colors;
2077 if (needs_color_filter &&
2078 contents->ApplyColorFilter([&](Color color) -> Color {
2079 if (paint.color_filter) {
2080 color = GetCPUColorFilterProc(paint.color_filter)(color);
2082 if (paint.invert_colors) {
2083 color = color.ApplyColorMatrix(kColorInversion);
2087 needs_color_filter =
false;
2090 bool can_apply_mask_filter = geometry->CanApplyMaskFilter();
2092 if (can_apply_mask_filter && paint.mask_blur_descriptor.has_value()) {
2096 FML_DCHECK(color_source_contents) <<
"Mask blur is only supported when no "
2097 "override contents are provided.";
2098 FillRectGeometry out_rect(
Rect{});
2099 auto filter = paint.mask_blur_descriptor->CreateMaskBlur(
2100 paint, renderer_, geometry, color_source_contents, needs_color_filter,
2102 entity.SetContents(std::move(filter));
2103 AddRenderEntityToCurrentPass(entity, reuse_depth);
2107 std::shared_ptr<Contents> contents_copy = std::move(contents);
2111 if (needs_color_filter &&
2112 (!paint.color_source ||
2114 if (paint.color_filter) {
2119 if (paint.invert_colors) {
2126 if (paint.image_filter) {
2127 std::shared_ptr<FilterContents> filter =
2128 WrapInput(renderer_, paint.image_filter,
2131 entity.SetContents(filter);
2132 AddRenderEntityToCurrentPass(entity, reuse_depth);
2136 entity.SetContents(std::move(contents_copy));
2137 AddRenderEntityToCurrentPass(entity, reuse_depth);
2140void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
2145 entity.SetTransform(
2146 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
2147 entity.GetTransform());
2148 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
2149 if (entity.GetBlendMode() == BlendMode::kSrcOver &&
2150 entity.GetContents()->IsOpaque(entity.GetTransform())) {
2151 entity.SetBlendMode(BlendMode::kSrc);
2157 if (render_passes_.back().IsApplyingClearColor()) {
2158 std::optional<Color> maybe_color = entity.AsBackgroundColor(
2159 render_passes_.back().GetInlinePassContext()->GetTexture()->GetSize());
2160 if (maybe_color.has_value()) {
2161 Color color = maybe_color.value();
2162 RenderTarget& render_target = render_passes_.back()
2163 .GetInlinePassContext()
2166 ColorAttachment attachment = render_target.GetColorAttachment(0);
2169 attachment.clear_color = attachment.clear_color.Unpremultiply()
2170 .Blend(color, entity.GetBlendMode())
2172 render_target.SetColorAttachment(attachment, 0u);
2183 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
2184 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
2185 entity.SetClipDepth(current_depth_);
2187 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
2188 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
2189 ApplyFramebufferBlend(entity);
2200 auto input_texture = FlipBackdrop(GetGlobalPassPosition(),
2204 if (!input_texture) {
2212 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
2213 entity.GetContents()->SetCoverageHint(Rect::Intersection(
2214 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
2216 FilterInput::Vector inputs = {
2217 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
2218 FilterInput::Make(entity.GetContents())};
2220 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
2221 entity.SetContents(std::move(contents));
2222 entity.SetBlendMode(BlendMode::kSrc);
2226 const std::shared_ptr<RenderPass>& result =
2227 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2235 entity.Render(renderer_, *result);
2238RenderPass& Canvas::GetCurrentRenderPass()
const {
2239 return *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2242void Canvas::SetBackdropData(
2243 std::unordered_map<int64_t, BackdropData> backdrop_data,
2244 size_t backdrop_count) {
2245 backdrop_data_ = std::move(backdrop_data);
2246 backdrop_count_ = backdrop_count;
2249std::shared_ptr<Texture> Canvas::FlipBackdrop(
Point global_pass_position,
2250 bool should_remove_texture,
2251 bool should_use_onscreen,
2252 bool post_depth_increment) {
2254 render_passes_.pop_back();
2270 <<
"Failed to end the current render pass in order to read from "
2271 "the backdrop texture and apply an advanced blend or backdrop "
2276 render_passes_.emplace_back(std::move(rendering_config));
2280 const std::shared_ptr<Texture>& input_texture =
2283 if (!input_texture) {
2284 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
2285 "apply an advanced blend or backdrop filter.";
2288 render_passes_.emplace_back(std::move(rendering_config));
2292 if (should_use_onscreen) {
2293 ColorAttachment color0 = render_target_.GetColorAttachment(0);
2297 color0.load_action = color0.resolve_texture !=
nullptr
2298 ? LoadAction::kDontCare
2299 : LoadAction::kLoad;
2300 render_target_.SetColorAttachment(color0, 0);
2302 auto entity_pass_target = std::make_unique<EntityPassTarget>(
2304 renderer_.GetDeviceCapabilities().SupportsReadFromResolve(),
2305 renderer_.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
2307 render_passes_.push_back(
2308 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
2309 requires_readback_ =
false;
2311 render_passes_.emplace_back(std::move(rendering_config));
2314 if (should_remove_texture) {
2315 render_passes_.back().GetEntityPassTarget()->RemoveSecondary();
2318 RenderPass& current_render_pass =
2319 *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2328 Rect size_rect = Rect::MakeSize(input_texture->GetSize());
2329 auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
2330 msaa_backdrop_contents->SetStencilEnabled(
false);
2331 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
2332 msaa_backdrop_contents->SetSourceRect(size_rect);
2333 msaa_backdrop_contents->SetTexture(input_texture);
2335 Entity msaa_backdrop_entity;
2336 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
2337 msaa_backdrop_entity.SetBlendMode(BlendMode::kSrc);
2338 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
2339 if (!msaa_backdrop_entity.Render(renderer_, current_render_pass)) {
2346 auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
2347 uint64_t current_depth =
2348 post_depth_increment ? current_depth_ - 1 : current_depth_;
2349 for (
const auto& replay : replay_entities) {
2350 if (replay.clip_depth <= current_depth) {
2354 SetClipScissor(replay.clip_coverage, current_render_pass,
2355 global_pass_position);
2356 if (!replay.clip_contents.Render(renderer_, current_render_pass,
2357 replay.clip_depth)) {
2362 return input_texture;
2365bool Canvas::SupportsBlitToOnscreen()
const {
2366 return renderer_.GetContext()
2368 ->SupportsTextureToTextureBlits() &&
2369 renderer_.GetContext()->GetBackendType() ==
2370 Context::BackendType::kMetal;
2373bool Canvas::BlitToOnscreen(
bool is_onscreen) {
2374 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
2376 auto offscreen_target = render_passes_.back()
2377 .GetInlinePassContext()
2380 if (SupportsBlitToOnscreen()) {
2382 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
2383 render_target_.GetRenderTargetTexture());
2384 if (!blit_pass->EncodeCommands()) {
2390 render_pass->SetLabel(
"EntityPass Root Render Pass");
2393 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
2394 auto contents = TextureContents::MakeRect(size_rect);
2395 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
2396 contents->SetSourceRect(size_rect);
2397 contents->SetLabel(
"Root pass blit");
2400 entity.SetContents(contents);
2401 entity.SetBlendMode(BlendMode::kSrc);
2416 return renderer_.GetContext()->SubmitOnscreen(std::move(
command_buffer));
2418 return renderer_.GetContext()->EnqueueCommandBuffer(
2423bool Canvas::EnsureFinalMipmapGeneration()
const {
2424 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2427 std::shared_ptr<CommandBuffer> cmd_buffer =
2428 renderer_.GetContext()->CreateCommandBuffer();
2432 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2436 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2437 blit_pass->EncodeCommands();
2438 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2441void Canvas::EndReplay() {
2443 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2444 render_passes_.back().GetInlinePassContext()->EndPass(
2445 !requires_readback_ && is_onscreen_);
2446 backdrop_data_.clear();
2451 if (requires_readback_) {
2452 BlitToOnscreen(is_onscreen_);
2454 if (!EnsureFinalMipmapGeneration()) {
2457 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2461 render_passes_.clear();
2462 renderer_.GetRenderTargetCache()->End();
2463 clip_geometry_.clear();
2466 Initialize(initial_cull_rect_);
2469bool Canvas::IsCompatibleWithSDFRendering(
const Paint& paint) {
2478 case BlendMode::kClear:
2479 case BlendMode::kSrc:
2480 case BlendMode::kSrcIn:
2481 case BlendMode::kDstIn:
2482 case BlendMode::kSrcOut:
2483 case BlendMode::kDstATop:
2484 case BlendMode::kPlus:
2485 case BlendMode::kModulate:
2488 case BlendMode::kDst:
2489 case BlendMode::kSrcOver:
2490 case BlendMode::kDstOver:
2491 case BlendMode::kDstOut:
2492 case BlendMode::kSrcATop:
2493 case BlendMode::kXor:
2494 case BlendMode::kScreen:
2495 case BlendMode::kOverlay:
2496 case BlendMode::kDarken:
2497 case BlendMode::kLighten:
2498 case BlendMode::kColorDodge:
2499 case BlendMode::kColorBurn:
2500 case BlendMode::kHardLight:
2501 case BlendMode::kSoftLight:
2502 case BlendMode::kDifference:
2503 case BlendMode::kExclusion:
2504 case BlendMode::kMultiply:
2505 case BlendMode::kHue:
2506 case BlendMode::kSaturation:
2507 case BlendMode::kColor:
2508 case BlendMode::kLuminosity:
2513LazyRenderingConfig::LazyRenderingConfig(
2515 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
2516 : entity_pass_target_(
std::move(p_entity_pass_target)) {
2517 inline_pass_context_ =
2518 std::make_unique<InlinePassContext>(renderer, *entity_pass_target_);
2522 return !inline_pass_context_->IsActive();
2526 return entity_pass_target_.get();
2530 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.
static std::unique_ptr< ComplexRoundedSuperellipseContents > Make(Color color, const Rect &bounds, const RoundSuperellipseParam &round_superellipse_params, std::optional< StrokeParameters > stroke)
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.
std::shared_ptr< ContextGLES > context
std::shared_ptr< RenderPass > render_pass
std::shared_ptr< CommandBuffer > command_buffer
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)
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 MakeRoundedSuperellipse(Color color, const Rect &bounds, const RoundSuperellipseParam &round_superellipse_params, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for an asymmetric round superellipse.
static UberSDFParameters MakeRect(Color color, const Rect &rect, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for a rectangle.
std::vector< Point > points
#define TRACE_EVENT0(category_group, name)