9#include <unordered_map>
69static bool UseColorSourceContents(
70 const std::shared_ptr<VerticesGeometry>& vertices,
74 if (vertices->HasVertexColors()) {
77 if (vertices->HasTextureCoordinates() && !paint.color_source) {
80 return !vertices->HasTextureCoordinates();
83static void SetClipScissor(std::optional<Rect> clip_coverage,
85 Point global_pass_position) {
89 if (clip_coverage.has_value()) {
90 clip_coverage = clip_coverage->Shift(-global_pass_position);
97 pass.SetScissor(scissor);
100static void ApplyFramebufferBlend(Entity& entity) {
101 auto src_contents = entity.GetContents();
102 auto contents = std::make_shared<FramebufferBlendContents>();
103 contents->SetChildContents(src_contents);
104 contents->SetBlendMode(entity.GetBlendMode());
105 entity.SetContents(std::move(contents));
111static std::shared_ptr<Contents> CreateContentsForSubpassTarget(
113 const std::shared_ptr<Texture>&
target,
114 const Matrix& effect_transform) {
116 contents->SetTexture(
target);
117 contents->SetLabel(
"Subpass");
119 contents->SetOpacity(paint.color.alpha);
120 contents->SetDeferApplyingOpacity(
true);
122 return paint.WithFiltersForSubpassTarget(std::move(contents),
126static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
127 RenderTarget::AttachmentConfig{
133static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
134 ContentContext& renderer,
136 const Color& clear_color) {
137 const std::shared_ptr<Context>& context = renderer.GetContext();
145 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
146 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
152 RenderTarget::AttachmentConfigMSAA{
157 .clear_color = clear_color},
158 kDefaultStencilConfig);
160 target = renderer.GetRenderTargetCache()->CreateOffscreen(
165 RenderTarget::AttachmentConfig{
169 .clear_color = clear_color,
171 kDefaultStencilConfig
175 return std::make_unique<EntityPassTarget>(
177 renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
178 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
187 : rect_(rect), corner_radius_(corner_radius) {}
192 auto contents = std::make_shared<SolidRRectBlurContents>();
193 contents->SetSigma(sigma);
194 contents->SetShape(rect_, corner_radius_);
199 return geom_.emplace(rect_,
Size(corner_radius_));
204 const Scalar corner_radius_;
206 std::optional<RoundRectGeometry> geom_;
212 : rect_(rect), corner_radius_(corner_radius) {}
217 auto contents = std::make_shared<SolidRSuperellipseBlurContents>();
218 contents->SetSigma(sigma);
219 contents->SetShape(rect_, corner_radius_);
224 return geom_.emplace(rect_, corner_radius_);
229 const Scalar corner_radius_;
231 std::optional<RoundSuperellipseGeometry> geom_;
251 std::shared_ptr<ShadowVertices> shadow_vertices,
255 shadow_vertices_(
std::move(shadow_vertices)) {}
258 return shadow_vertices_->GetBounds().value_or(
Rect());
272 return source_geometry_.emplace(source_);
278 const std::shared_ptr<ShadowVertices> shadow_vertices_;
281 std::optional<FillPathFromSourceGeometry> source_geometry_;
287 bool requires_readback)
288 : renderer_(renderer),
289 render_target_(render_target),
290 is_onscreen_(is_onscreen),
291 requires_readback_(requires_readback),
293 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
294 Initialize(std::nullopt);
301 bool requires_readback,
303 : renderer_(renderer),
304 render_target_(render_target),
305 is_onscreen_(is_onscreen),
306 requires_readback_(requires_readback),
308 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
309 Initialize(cull_rect);
316 bool requires_readback,
318 : renderer_(renderer),
319 render_target_(render_target),
320 is_onscreen_(is_onscreen),
321 requires_readback_(requires_readback),
323 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
329void Canvas::Initialize(std::optional<Rect> cull_rect) {
330 initial_cull_rect_ = cull_rect;
337void Canvas::Reset() {
339 transform_stack_ = {};
351 transform_stack_.back().transform = {};
359 return transform_stack_.back().transform;
382Point Canvas::GetGlobalPassPosition()
const {
383 if (save_layer_state_.empty()) {
386 return save_layer_state_.back().coverage.GetOrigin();
390size_t Canvas::GetClipHeightFloor()
const {
391 if (transform_stack_.size() > 1) {
392 return transform_stack_[transform_stack_.size() - 2].clip_height;
398 return transform_stack_.size();
401bool Canvas::IsSkipping()
const {
402 return transform_stack_.back().skipping;
414 if (IsShadowBlurDrawOperation(paint)) {
415 if (AttemptDrawBlurredPathSource(path, paint)) {
426 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
429 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
439 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
446bool Canvas::AttemptColorFilterOptimization(
447 const std::shared_ptr<Texture>&
image,
464 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
469 blend_filter->
mode(),
471 src_rect_constraint ==
474 auto atlas_contents = std::make_shared<AtlasContents>();
475 atlas_contents->SetGeometry(&geometry);
481 entity.SetContents(atlas_contents);
483 AddRenderEntityToCurrentPass(entity);
494 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
501 src_rect_constraint ==
504 auto atlas_contents = std::make_shared<ColorFilterAtlasContents>();
505 atlas_contents->SetGeometry(&geometry);
509 atlas_contents->SetMatrix(color_matrix);
514 entity.SetContents(atlas_contents);
516 AddRenderEntityToCurrentPass(entity);
521bool Canvas::AttemptDrawAntialiasedCircle(
const Point& center,
523 const Paint& paint) {
524 if (paint.HasColorFilter() || paint.image_filter || paint.invert_colors ||
525 paint.color_source || paint.mask_blur_descriptor.has_value()) {
531 entity.SetBlendMode(paint.blend_mode);
534 std::unique_ptr<CircleGeometry> geom;
536 geom = std::make_unique<CircleGeometry>(center, radius, paint.stroke.width);
538 geom = std::make_unique<CircleGeometry>(center, radius);
544 entity.SetContents(std::move(contents));
545 AddRenderEntityToCurrentPass(entity);
550bool Canvas::IsShadowBlurDrawOperation(
const Paint& paint) {
555 if (paint.color_source) {
559 if (!paint.mask_blur_descriptor.has_value()) {
570 Radius radius = paint.mask_blur_descriptor->sigma;
578bool Canvas::AttemptDrawBlurredPathSource(
const PathSource& source,
579 const Paint& paint) {
586 if (paint.mask_blur_descriptor.has_value()) {
590 static constexpr Scalar kSigmaScale = 2.8f;
592 Sigma sigma = paint.mask_blur_descriptor->sigma;
594 Scalar basis_scale = matrix.GetMaxBasisLengthXY();
595 Scalar device_radius = sigma.sigma * kSigmaScale * basis_scale;
596 std::shared_ptr<ShadowVertices> shadow_vertices =
599 if (shadow_vertices) {
600 PathBlurShape shape(source, std::move(shadow_vertices), sigma);
601 return AttemptDrawBlur(shape, paint);
607Scalar Canvas::GetCommonRRectLikeRadius(
const RoundingRadii& radii) {
608 if (!radii.AreAllCornersSame()) {
611 const Size& corner_radii = radii.top_left;
613 return corner_radii.
width;
618bool Canvas::AttemptDrawBlurredRRect(
const RoundRect& round_rect,
619 const Paint& paint) {
620 Scalar radius = GetCommonRRectLikeRadius(round_rect.GetRadii());
622 RoundRectPathSource source(round_rect);
623 return AttemptDrawBlurredPathSource(source, paint);
625 RRectBlurShape shape(round_rect.GetBounds(), radius);
626 return AttemptDrawBlur(shape, paint);
629bool Canvas::AttemptDrawBlurredRSuperellipse(
const RoundSuperellipse& rse,
630 const Paint& paint) {
631 Scalar radius = GetCommonRRectLikeRadius(rse.GetRadii());
633 RoundSuperellipsePathSource source(rse);
634 return AttemptDrawBlurredPathSource(source, paint);
636 RSuperellipseBlurShape shape(rse.GetBounds(), radius);
637 return AttemptDrawBlur(shape, paint);
640bool Canvas::AttemptDrawBlur(BlurShape& shape,
const Paint& paint) {
645 Color rrect_color = paint.color;
646 if (paint.invert_colors) {
649 if (paint.color_filter) {
653 Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor};
655 if (!rrect_paint.mask_blur_descriptor.has_value()) {
682 if ((paint.mask_blur_descriptor->style !=
684 paint.image_filter) ||
687 Rect render_bounds = shape.GetBounds();
688 if (paint.mask_blur_descriptor->style !=
691 render_bounds.
Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
697 .image_filter = paint.image_filter,
698 .blend_mode = paint.blend_mode,
701 rrect_paint.color = rrect_color.WithAlpha(1);
703 rrect_paint.color = rrect_color;
704 rrect_paint.blend_mode = paint.blend_mode;
705 rrect_paint.image_filter = paint.image_filter;
709 auto draw_blurred_rrect = [
this, &rrect_paint, &shape]() {
710 std::shared_ptr<SolidBlurContents> contents =
711 shape.BuildBlurContent(rrect_paint.mask_blur_descriptor->sigma);
714 contents->SetColor(rrect_paint.color);
716 Entity blurred_rrect_entity;
718 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
720 rrect_paint.mask_blur_descriptor = std::nullopt;
721 blurred_rrect_entity.SetContents(
722 rrect_paint.WithFilters(std::move(contents)));
723 AddRenderEntityToCurrentPass(blurred_rrect_entity);
726 switch (rrect_paint.mask_blur_descriptor->style) {
728 draw_blurred_rrect();
733 draw_blurred_rrect();
737 entity.SetBlendMode(rrect_paint.blend_mode);
739 const Geometry& geom = shape.BuildDrawGeometry();
740 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, rrect_paint,
745 const Geometry& geom = shape.BuildDrawGeometry();
747 draw_blurred_rrect();
751 const Geometry& geom = shape.BuildDrawGeometry();
753 draw_blurred_rrect();
771 auto geometry = std::make_unique<LineGeometry>(p0, p1, paint.
stroke);
773 if (renderer_.
GetContext()->GetFlags().antialiased_lines &&
778 AddRenderEntityToCurrentPass(entity, reuse_depth);
780 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
789 const Paint& paint) {
799 if (
length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
805 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
812 if (IsShadowBlurDrawOperation(paint)) {
814 if (AttemptDrawBlur(shape, paint)) {
825 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
828 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
844 if (IsShadowBlurDrawOperation(paint)) {
849 if (AttemptDrawBlur(shape, paint)) {
854 if (AttemptDrawBlurredPathSource(source, paint)) {
866 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
869 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
880 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
893 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
906 return DrawOval(oval_bounds, paint);
916 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
922 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
926 if (IsShadowBlurDrawOperation(paint)) {
927 if (AttemptDrawBlurredRRect(round_rect, paint)) {
940 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
950 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
953 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
959 const Paint& paint) {
966 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
969 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
974 const Paint& paint) {
975 if (IsShadowBlurDrawOperation(paint)) {
976 if (AttemptDrawBlurredRSuperellipse(round_superellipse, paint)) {
988 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
991 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
997 const Paint& paint) {
998 if (IsShadowBlurDrawOperation(paint)) {
1000 center.x + radius, center.y + radius);
1002 if (AttemptDrawBlur(shape, paint)) {
1007 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
1017 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1020 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1041 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1042 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1043 uint32_t clip_depth = transform_stack_.back().clip_depth;
1045 const Matrix clip_transform =
1049 std::optional<Rect> clip_coverage = geometry.
GetCoverage(clip_transform);
1050 if (!clip_coverage.has_value()) {
1055 clip_coverage.value(),
1064 GetGlobalPassPosition(),
1066 GetClipHeightFloor(),
1073 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1074 GetGlobalPassPosition());
1077 ++transform_stack_.back().clip_height;
1078 ++transform_stack_.back().num_clips;
1095 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1102 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1121 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
1149 if (size.IsEmpty()) {
1153 std::optional<Rect> clipped_source =
1155 if (!clipped_source) {
1159 if (AttemptColorFilterOptimization(
image, source, dest, paint, sampler,
1160 src_rect_constraint)) {
1164 if (*clipped_source != source) {
1174 texture_contents->SetTexture(
image);
1175 texture_contents->SetSourceRect(*clipped_source);
1176 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1178 texture_contents->SetSamplerDescriptor(sampler);
1179 texture_contents->SetOpacity(paint.
color.
alpha);
1180 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
1188 AddRenderEntityToCurrentPass(entity);
1196 AddRenderEntityToCurrentPass(entity);
1199size_t Canvas::GetClipHeight()
const {
1200 return transform_stack_.back().clip_height;
1205 const Paint& paint) {
1218 if (UseColorSourceContents(vertices, paint)) {
1219 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1225 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1226 contents->SetBlendMode(blend_mode);
1228 contents->SetGeometry(vertices);
1230 AddRenderEntityToCurrentPass(entity);
1241 image_color_source->
image()->impeller_texture());
1242 auto texture = image_color_source->
image()->impeller_texture();
1247 auto sampler_descriptor =
1249 auto effect_transform = image_color_source->
matrix();
1251 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1252 contents->SetBlendMode(blend_mode);
1254 contents->SetGeometry(vertices);
1255 contents->SetEffectTransform(effect_transform);
1256 contents->SetTexture(
texture);
1257 contents->SetTileMode(x_tile_mode, y_tile_mode);
1258 contents->SetSamplerDescriptor(sampler_descriptor);
1261 AddRenderEntityToCurrentPass(entity);
1265 auto src_paint = paint;
1268 std::shared_ptr<ColorSourceContents> src_contents =
1269 src_paint.CreateContents();
1270 src_contents->SetGeometry(vertices.get());
1278 auto size = src_contents->GetColorSourceSize();
1279 if (size.has_value()) {
1282 auto cvg = vertices->GetCoverage(
Matrix{});
1284 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1285 if (texture_coverage.has_value()) {
1288 texture_coverage->GetSize().Max({1, 1}));
1291 src_coverage = cvg.value();
1294 src_contents = src_paint.CreateContents();
1297 src_contents->SetGeometry(clip_geometry_.back().get());
1299 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1300 contents->SetBlendMode(blend_mode);
1302 contents->SetGeometry(vertices);
1303 contents->SetLazyTextureCoverage(src_coverage);
1304 contents->SetLazyTexture(
1309 auto snapshot = src_contents->RenderToSnapshot(
1310 renderer, {}, {.coverage_limit =
Rect::Round(src_coverage)});
1311 return snapshot.has_value() ? snapshot->texture :
nullptr;
1314 AddRenderEntityToCurrentPass(entity);
1318 const Paint& paint) {
1326 AddRenderEntityToCurrentPass(entity);
1332void Canvas::SetupRenderPass() {
1338 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
1343 *renderer_.
GetContext()->GetResourceAllocator(),
1345 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA() &&
1346 color0.
texture->GetTextureDescriptor().sample_count >
1348 "ImpellerOnscreen", kDefaultStencilConfig);
1360 if (requires_readback_) {
1361 auto entity_pass_target =
1362 CreateRenderTarget(renderer_,
1365 render_passes_.push_back(
1366 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1368 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1373 render_passes_.push_back(
1374 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1378void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
1379 auto entry = CanvasStackEntry{};
1380 entry.skipping =
true;
1381 entry.clip_depth = current_depth_ + total_content_depth;
1382 transform_stack_.push_back(entry);
1387 return SkipUntilMatchingRestore(total_content_depth);
1391 entry.
transform = transform_stack_.back().transform;
1392 entry.clip_depth = current_depth_ + total_content_depth;
1393 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1394 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1395 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1396 <<
" after allocating " << total_content_depth;
1397 entry.clip_height = transform_stack_.back().clip_height;
1399 transform_stack_.push_back(entry);
1406 return std::nullopt;
1409 std::optional<Rect> maybe_current_clip_coverage =
1411 if (!maybe_current_clip_coverage.has_value()) {
1412 return std::nullopt;
1415 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1419 std::shared_ptr<Texture> back_texture =
1421 FML_CHECK(back_texture) <<
"Context is valid:"
1426 std::optional<Rect> maybe_coverage_limit =
1428 Size(back_texture->GetSize()))
1431 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1432 return std::nullopt;
1435 return maybe_coverage_limit->Intersection(
1440 std::optional<Rect> bounds,
1443 uint32_t total_content_depth,
1444 bool can_distribute_opacity,
1445 std::optional<int64_t> backdrop_id) {
1448 return SkipUntilMatchingRestore(total_content_depth);
1452 if (!maybe_coverage_limit.has_value()) {
1453 return SkipUntilMatchingRestore(total_content_depth);
1455 auto coverage_limit = maybe_coverage_limit.value();
1457 if (can_distribute_opacity && !backdrop_filter &&
1460 Save(total_content_depth);
1461 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1465 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1466 Rect(), transform_stack_.back().transform,
1471 transform_stack_.back().transform,
1476 !!backdrop_filter ||
1481 if (!maybe_subpass_coverage.has_value()) {
1482 return SkipUntilMatchingRestore(total_content_depth);
1485 auto subpass_coverage = maybe_subpass_coverage.value();
1496 bool did_round_out =
false;
1497 Point coverage_origin_adjustment =
Point{0, 0};
1501 did_round_out =
true;
1505 coverage_origin_adjustment =
1506 Point(subpass_coverage.GetLeftTop().x -
1507 std::floor(subpass_coverage.GetLeftTop().x),
1508 subpass_coverage.GetLeftTop().y -
1509 std::floor(subpass_coverage.GetLeftTop().y));
1512 return SkipUntilMatchingRestore(total_content_depth);
1520 ->GetMaximumRenderPassAttachmentSize());
1523 std::shared_ptr<FilterContents> backdrop_filter_contents;
1525 if (backdrop_filter) {
1526 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1528 [backdrop_filter = backdrop_filter](
1532 filter->SetEffectTransform(effect_transform);
1533 filter->SetRenderingMode(rendering_mode);
1537 std::shared_ptr<Texture> input_texture;
1542 bool will_cache_backdrop_texture =
false;
1547 size_t backdrop_count = 1;
1548 if (backdrop_id.has_value()) {
1549 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1550 backdrop_data_.find(backdrop_id.value());
1551 if (backdrop_data_it != backdrop_data_.end()) {
1552 backdrop_data = &backdrop_data_it->second;
1553 will_cache_backdrop_texture =
1555 backdrop_count = backdrop_data_it->second.backdrop_count;
1559 if (!will_cache_backdrop_texture || !backdrop_data->
texture_slot) {
1560 backdrop_count_ -= backdrop_count;
1566 const bool should_use_onscreen =
1568 backdrop_count_ == 0 && render_passes_.size() == 1u;
1569 input_texture = FlipBackdrop(
1570 GetGlobalPassPosition(),
1571 will_cache_backdrop_texture,
1574 if (!input_texture) {
1579 if (will_cache_backdrop_texture) {
1586 backdrop_filter_contents = backdrop_filter_proc(
1588 transform_stack_.back().transform.Basis(),
1591 transform_stack_.back().transform.HasTranslation()
1595 if (will_cache_backdrop_texture) {
1603 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1606 std::optional<Snapshot> maybe_snapshot =
1608 if (maybe_snapshot.has_value()) {
1609 const Snapshot& snapshot = maybe_snapshot.value();
1611 subpass_coverage.Shift(-GetGlobalPassPosition()));
1614 contents->SetTexture(snapshot.
texture);
1615 contents->SetSourceRect(scaled);
1625 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1633 Paint paint_copy = paint;
1634 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1635 transform_stack_.back().distributed_opacity = 1.0;
1637 render_passes_.push_back(
1639 CreateRenderTarget(renderer_,
1644 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1647 entry.
transform = transform_stack_.back().transform;
1648 entry.
clip_depth = current_depth_ + total_content_depth;
1650 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1651 <<
" after allocating " << total_content_depth;
1652 entry.
clip_height = transform_stack_.back().clip_height;
1655 transform_stack_.emplace_back(entry);
1662 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1664 if (!backdrop_filter_contents) {
1670 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1673 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1674 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1679 if (transform_stack_.size() == 1) {
1696 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1697 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1698 current_depth_ = transform_stack_.back().clip_depth;
1701 transform_stack_.pop_back();
1705 if (transform_stack_.back().rendering_mode ==
1707 transform_stack_.back().rendering_mode ==
1709 auto lazy_render_pass = std::move(render_passes_.back());
1710 render_passes_.pop_back();
1712 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1715 save_layer_state_.pop_back();
1716 auto global_pass_position = GetGlobalPassPosition();
1718 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1719 save_layer_state.
paint,
1720 lazy_render_pass.GetInlinePassContext()->GetTexture(),
1722 transform_stack_.back().transform
1725 lazy_render_pass.GetInlinePassContext()->EndPass();
1732 Point subpass_texture_position;
1733 if (transform_stack_.back().did_round_out) {
1736 subpass_texture_position =
1741 subpass_texture_position =
1755 ApplyFramebufferBlend(element_entity);
1766 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1767 if (!input_texture) {
1777 contents->SetCoverageHint(element_entity.
GetCoverage());
1785 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1788 transform_stack_.pop_back();
1796 size_t num_clips = transform_stack_.back().num_clips;
1797 transform_stack_.pop_back();
1799 if (num_clips > 0) {
1810 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1811 GetGlobalPassPosition()
1819bool Canvas::AttemptBlurredTextOptimization(
1820 const std::shared_ptr<TextFrame>& text_frame,
1821 const std::shared_ptr<TextContents>& text_contents,
1823 const Paint& paint) {
1837 std::shared_ptr<FilterContents> filter =
1842 std::optional<Glyph> maybe_glyph = text_frame->AsSingleGlyph();
1843 int64_t identifier = maybe_glyph.has_value()
1844 ? maybe_glyph.value().index
1845 :
reinterpret_cast<int64_t
>(text_frame.get());
1846 TextShadowCache::TextShadowCacheKey cache_key(
1849 maybe_glyph.has_value(),
1850 text_frame->GetFont(),
1855 renderer_, entity, filter, cache_key);
1856 if (result.has_value()) {
1857 AddRenderEntityToCurrentPass(result.value(),
false);
1871 const Paint& paint) {
1873 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1889 auto text_contents = std::make_shared<TextContents>();
1890 text_contents->SetTextFrame(text_frame);
1892 text_contents->SetScale(max_scale);
1893 text_contents->SetColor(paint.
color);
1894 text_contents->SetOffset(position);
1895 text_contents->SetTextProperties(paint.
color,
1897 ? std::optional(paint.
stroke)
1903 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1909 AddRenderEntityToCurrentPass(entity,
false);
1912void Canvas::AddRenderEntityWithFiltersToCurrentPass(
Entity& entity,
1916 std::shared_ptr<ColorSourceContents> contents = paint.
CreateContents();
1919 contents->SetGeometry(geometry);
1921 AddRenderEntityToCurrentPass(entity, reuse_depth);
1929 if (needs_color_filter &&
1930 contents->ApplyColorFilter([&](Color color) -> Color {
1931 if (paint.color_filter) {
1932 color = GetCPUColorFilterProc(paint.color_filter)(color);
1935 color = color.ApplyColorMatrix(kColorInversion);
1939 needs_color_filter =
false;
1943 contents->SetGeometry(geometry);
1949 FillRectGeometry out_rect(
Rect{});
1951 contents, needs_color_filter ? paint.
color_filter : nullptr,
1952 needs_color_filter ? paint.invert_colors : false, &out_rect);
1954 AddRenderEntityToCurrentPass(entity, reuse_depth);
1958 std::shared_ptr<Contents> contents_copy = std::move(contents);
1962 if (needs_color_filter &&
1978 std::shared_ptr<FilterContents> filter =
WrapInput(
1982 AddRenderEntityToCurrentPass(entity, reuse_depth);
1987 AddRenderEntityToCurrentPass(entity, reuse_depth);
1990void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
1995 entity.SetTransform(
1996 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1997 entity.GetTransform());
1998 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
1999 if (entity.GetBlendMode() == BlendMode::kSrcOver &&
2000 entity.GetContents()->IsOpaque(entity.GetTransform())) {
2001 entity.SetBlendMode(BlendMode::kSrc);
2007 if (render_passes_.back().IsApplyingClearColor()) {
2008 std::optional<Color> maybe_color = entity.AsBackgroundColor(
2009 render_passes_.back().GetInlinePassContext()->GetTexture()->GetSize());
2010 if (maybe_color.has_value()) {
2011 Color color = maybe_color.value();
2012 RenderTarget& render_target = render_passes_.back()
2013 .GetInlinePassContext()
2016 ColorAttachment attachment = render_target.GetColorAttachment(0);
2019 attachment.clear_color = attachment.clear_color.Unpremultiply()
2020 .Blend(color, entity.GetBlendMode())
2022 render_target.SetColorAttachment(attachment, 0u);
2033 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
2034 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
2035 entity.SetClipDepth(current_depth_);
2037 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
2038 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
2039 ApplyFramebufferBlend(entity);
2050 auto input_texture = FlipBackdrop(GetGlobalPassPosition(),
2054 if (!input_texture) {
2062 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
2063 entity.GetContents()->SetCoverageHint(Rect::Intersection(
2064 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
2066 FilterInput::Vector inputs = {
2067 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
2068 FilterInput::Make(entity.GetContents())};
2070 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
2071 entity.SetContents(std::move(contents));
2072 entity.SetBlendMode(BlendMode::kSrc);
2076 const std::shared_ptr<RenderPass>& result =
2077 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2085 entity.Render(renderer_, *result);
2088RenderPass& Canvas::GetCurrentRenderPass()
const {
2089 return *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2092void Canvas::SetBackdropData(
2093 std::unordered_map<int64_t, BackdropData> backdrop_data,
2094 size_t backdrop_count) {
2095 backdrop_data_ = std::move(backdrop_data);
2096 backdrop_count_ = backdrop_count;
2099std::shared_ptr<Texture> Canvas::FlipBackdrop(
Point global_pass_position,
2100 bool should_remove_texture,
2101 bool should_use_onscreen,
2102 bool post_depth_increment) {
2104 render_passes_.pop_back();
2120 <<
"Failed to end the current render pass in order to read from "
2121 "the backdrop texture and apply an advanced blend or backdrop "
2126 render_passes_.emplace_back(std::move(rendering_config));
2130 const std::shared_ptr<Texture>& input_texture =
2133 if (!input_texture) {
2134 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
2135 "apply an advanced blend or backdrop filter.";
2138 render_passes_.emplace_back(std::move(rendering_config));
2142 if (should_use_onscreen) {
2143 ColorAttachment color0 = render_target_.GetColorAttachment(0);
2147 color0.load_action = color0.resolve_texture !=
nullptr
2148 ? LoadAction::kDontCare
2149 : LoadAction::kLoad;
2150 render_target_.SetColorAttachment(color0, 0);
2152 auto entity_pass_target = std::make_unique<EntityPassTarget>(
2154 renderer_.GetDeviceCapabilities().SupportsReadFromResolve(),
2155 renderer_.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
2157 render_passes_.push_back(
2158 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
2159 requires_readback_ =
false;
2161 render_passes_.emplace_back(std::move(rendering_config));
2164 if (should_remove_texture) {
2165 render_passes_.back().GetEntityPassTarget()->RemoveSecondary();
2168 RenderPass& current_render_pass =
2169 *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2178 Rect size_rect = Rect::MakeSize(input_texture->GetSize());
2179 auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
2180 msaa_backdrop_contents->SetStencilEnabled(
false);
2181 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
2182 msaa_backdrop_contents->SetSourceRect(size_rect);
2183 msaa_backdrop_contents->SetTexture(input_texture);
2185 Entity msaa_backdrop_entity;
2186 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
2187 msaa_backdrop_entity.SetBlendMode(BlendMode::kSrc);
2188 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
2189 if (!msaa_backdrop_entity.Render(renderer_, current_render_pass)) {
2196 auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
2197 uint64_t current_depth =
2198 post_depth_increment ? current_depth_ - 1 : current_depth_;
2199 for (
const auto& replay : replay_entities) {
2200 if (replay.clip_depth <= current_depth) {
2204 SetClipScissor(replay.clip_coverage, current_render_pass,
2205 global_pass_position);
2206 if (!replay.clip_contents.Render(renderer_, current_render_pass,
2207 replay.clip_depth)) {
2212 return input_texture;
2215bool Canvas::SupportsBlitToOnscreen()
const {
2216 return renderer_.GetContext()
2218 ->SupportsTextureToTextureBlits() &&
2219 renderer_.GetContext()->GetBackendType() ==
2220 Context::BackendType::kMetal;
2223bool Canvas::BlitToOnscreen(
bool is_onscreen) {
2224 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
2225 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
2226 auto offscreen_target = render_passes_.back()
2227 .GetInlinePassContext()
2230 if (SupportsBlitToOnscreen()) {
2231 auto blit_pass = command_buffer->CreateBlitPass();
2232 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
2233 render_target_.GetRenderTargetTexture());
2234 if (!blit_pass->EncodeCommands()) {
2239 auto render_pass = command_buffer->CreateRenderPass(render_target_);
2240 render_pass->SetLabel(
"EntityPass Root Render Pass");
2243 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
2244 auto contents = TextureContents::MakeRect(size_rect);
2245 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
2246 contents->SetSourceRect(size_rect);
2247 contents->SetLabel(
"Root pass blit");
2250 entity.SetContents(contents);
2251 entity.SetBlendMode(BlendMode::kSrc);
2253 if (!entity.Render(renderer_, *render_pass)) {
2259 if (!render_pass->EncodeCommands()) {
2266 return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer));
2268 return renderer_.GetContext()->EnqueueCommandBuffer(
2269 std::move(command_buffer));
2273bool Canvas::EnsureFinalMipmapGeneration()
const {
2274 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2277 std::shared_ptr<CommandBuffer> cmd_buffer =
2278 renderer_.GetContext()->CreateCommandBuffer();
2282 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2286 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2287 blit_pass->EncodeCommands();
2288 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2291void Canvas::EndReplay() {
2293 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2294 render_passes_.back().GetInlinePassContext()->EndPass(
2295 !requires_readback_ && is_onscreen_);
2296 backdrop_data_.clear();
2301 if (requires_readback_) {
2302 BlitToOnscreen(is_onscreen_);
2304 if (!EnsureFinalMipmapGeneration()) {
2307 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2311 render_passes_.clear();
2312 renderer_.GetRenderTargetCache()->End();
2313 clip_geometry_.clear();
2316 Initialize(initial_cull_rect_);
2319LazyRenderingConfig::LazyRenderingConfig(
2321 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
2322 : entity_pass_target_(
std::move(p_entity_pass_target)) {
2323 inline_pass_context_ =
2324 std::make_unique<InlinePassContext>(renderer, *entity_pass_target_);
2328 return !inline_pass_context_->IsActive();
2332 return entity_pass_target_.get();
2336 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)
size_t GetSaveCount() const
void Concat(const Matrix &transform)
void Transform(const Matrix &transform)
void DrawDashedLine(const Point &p0, const Point &p1, Scalar on_length, Scalar off_length, const Paint &paint)
void DrawDiffRoundRect(const RoundRect &outer, const RoundRect &inner, const Paint &paint)
void DrawPath(const flutter::DlPath &path, const Paint &paint)
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
void PreConcat(const Matrix &transform)
void Rotate(Radians radians)
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
void DrawImage(const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, const SamplerDescriptor &sampler={})
void DrawPaint(const Paint &paint)
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
void Skew(Scalar sx, Scalar sy)
void Scale(const Vector2 &scale)
void Save(uint32_t total_content_depth=kMaxDepth)
void DrawRect(const Rect &rect, const Paint &paint)
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
void Translate(const Vector3 &offset)
void DrawCircle(const Point ¢er, Scalar radius, const Paint &paint)
void DrawArc(const Arc &arc, const Paint &paint)
virtual bool SupportsImplicitResolvingMSAA() const =0
Whether the context backend supports multisampled rendering to the on-screen surface without requirin...
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
virtual bool SupportsReadFromResolve() const =0
Whether the context backend supports binding the current RenderPass attachments. This is supported if...
static std::unique_ptr< CircleContents > Make(std::unique_ptr< CircleGeometry > geometry, Color color, bool stroked)
void SetGeometry(GeometryResult geometry)
Set the pre-tessellated clip geometry.
void SetClipOperation(Entity::ClipOperation clip_op)
bool Render(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth) const
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
const Capabilities & GetDeviceCapabilities() const
TextShadowCache & GetTextShadowCache() const
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
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
virtual GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const =0
virtual bool CanApplyMaskFilter() const
virtual bool IsAxisAlignedRect() const
bool EndPass(bool is_onscreen=false)
std::shared_ptr< Texture > GetTexture()
const std::shared_ptr< RenderPass > & GetRenderPass()
bool IsApplyingClearColor() const
Whether or not the clear color texture can still be updated.
EntityPassTarget * GetEntityPassTarget() const
InlinePassContext * GetInlinePassContext() const
static std::unique_ptr< LineContents > Make(std::unique_ptr< LineGeometry > geometry, Color color)
A geometry class specialized for Canvas::DrawPoints.
ColorAttachment GetColorAttachment(size_t index) const
Get the color attachment at [index].
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
ISize GetRenderTargetSize() const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
void SetupDepthStencilAttachments(const Context &context, Allocator &allocator, ISize size, bool msaa, std::string_view label="Offscreen", RenderTarget::AttachmentConfig stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &depth_stencil_texture=nullptr)
A Geometry class that generates fillable vertices (with or without texture coordinates) directly from...
A Geometry class that generates fillable vertices (with or without texture coordinates) directly from...
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)
FlutterVulkanImage * image
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
ISize subpass_size
The output size of the down-sampling pass.
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Color ToColor(const flutter::DlColor &color)
static constexpr Scalar kMaxTextScale
std::shared_ptr< ColorFilterContents > WrapWithGPUColorFilter(const flutter::DlColorFilter *filter, const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
@ kStrict
Sample only within the source rectangle. May be slower.
std::shared_ptr< FilterContents > WrapInput(const flutter::DlImageFilter *filter, const FilterInput::Ref &input)
Generate a new FilterContents using this filter's configuration.
constexpr float kEhCloseEnough
std::shared_ptr< ColorFilterContents > WrapWithInvertColors(const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
@ kRound
Points are drawn as squares.
ColorFilterProc GetCPUColorFilterProc(const flutter::DlColorFilter *filter)
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
std::optional< Rect > ComputeSaveLayerCoverage(const Rect &content_coverage, const Matrix &effect_transform, const Rect &coverage_limit, const std::shared_ptr< FilterContents > &image_filter, bool flood_output_coverage, bool flood_input_coverage)
Compute the coverage of a subpass in the global coordinate space.
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< Contents > WithFilters(std::shared_ptr< Contents > input) const
Wrap this paint's configured filters to the given contents.
const flutter::DlColorFilter * color_filter
const flutter::DlColorSource * color_source
const flutter::DlImageFilter * image_filter
static bool CanApplyOpacityPeephole(const Paint &paint)
Whether or not a save layer with the provided paint can perform the opacity peephole optimization.
std::optional< MaskBlurDescriptor > mask_blur_descriptor
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
std::shared_ptr< ColorSourceContents > CreateContents() const
bool HasColorFilter() const
Whether this paint has a color filter that can apply opacity.
constexpr const RoundingRadii & GetRadii() const
constexpr const Rect & GetBounds() const
constexpr const Rect & GetBounds() const
constexpr const RoundingRadii & GetRadii() const
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 MakeSize(const TSize< U > &size)
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
static constexpr TRect MakeMaximum()
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
std::vector< Point > points
#define TRACE_EVENT0(category_group, name)