9#include <unordered_map>
65static bool UseColorSourceContents(
66 const std::shared_ptr<VerticesGeometry>& vertices,
70 if (vertices->HasVertexColors()) {
73 if (vertices->HasTextureCoordinates() && !paint.color_source) {
76 return !vertices->HasTextureCoordinates();
79static void SetClipScissor(std::optional<Rect> clip_coverage,
81 Point global_pass_position) {
85 if (clip_coverage.has_value()) {
86 clip_coverage = clip_coverage->Shift(-global_pass_position);
93 pass.SetScissor(scissor);
96static void ApplyFramebufferBlend(Entity& entity) {
97 auto src_contents = entity.GetContents();
98 auto contents = std::make_shared<FramebufferBlendContents>();
99 contents->SetChildContents(src_contents);
100 contents->SetBlendMode(entity.GetBlendMode());
101 entity.SetContents(std::move(contents));
107static std::shared_ptr<Contents> CreateContentsForSubpassTarget(
109 const std::shared_ptr<Texture>&
target,
110 const Matrix& effect_transform) {
112 contents->SetTexture(
target);
113 contents->SetLabel(
"Subpass");
115 contents->SetOpacity(paint.color.alpha);
116 contents->SetDeferApplyingOpacity(
true);
118 return paint.WithFiltersForSubpassTarget(std::move(contents),
122static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
123 RenderTarget::AttachmentConfig{
129static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
130 ContentContext& renderer,
132 const Color& clear_color) {
133 const std::shared_ptr<Context>& context = renderer.GetContext();
141 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
142 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
148 RenderTarget::AttachmentConfigMSAA{
153 .clear_color = clear_color},
154 kDefaultStencilConfig);
156 target = renderer.GetRenderTargetCache()->CreateOffscreen(
161 RenderTarget::AttachmentConfig{
165 .clear_color = clear_color,
167 kDefaultStencilConfig
171 return std::make_unique<EntityPassTarget>(
173 renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
174 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
180std::shared_ptr<SolidRRectLikeBlurContents>
181Canvas::RRectBlurShape::BuildBlurContent() {
182 return std::make_shared<SolidRRectBlurContents>();
185Geometry& Canvas::RRectBlurShape::BuildGeometry(
Rect rect,
Scalar radius) {
186 return geom_.emplace(rect,
Size{radius, radius});
189std::shared_ptr<SolidRRectLikeBlurContents>
190Canvas::RSuperellipseBlurShape::BuildBlurContent() {
191 return std::make_shared<SolidRSuperellipseBlurContents>();
194Geometry& Canvas::RSuperellipseBlurShape::BuildGeometry(
Rect rect,
196 return geom_.emplace(rect, radius);
202 bool requires_readback)
203 : renderer_(renderer),
204 render_target_(render_target),
205 is_onscreen_(is_onscreen),
206 requires_readback_(requires_readback),
208 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
209 Initialize(std::nullopt);
216 bool requires_readback,
218 : renderer_(renderer),
219 render_target_(render_target),
220 is_onscreen_(is_onscreen),
221 requires_readback_(requires_readback),
223 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
224 Initialize(cull_rect);
231 bool requires_readback,
233 : renderer_(renderer),
234 render_target_(render_target),
235 is_onscreen_(is_onscreen),
236 requires_readback_(requires_readback),
238 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
244void Canvas::Initialize(std::optional<Rect> cull_rect) {
245 initial_cull_rect_ = cull_rect;
252void Canvas::Reset() {
254 transform_stack_ = {};
266 transform_stack_.back().transform = {};
274 return transform_stack_.back().transform;
297Point Canvas::GetGlobalPassPosition()
const {
298 if (save_layer_state_.empty()) {
301 return save_layer_state_.back().coverage.GetOrigin();
305size_t Canvas::GetClipHeightFloor()
const {
306 if (transform_stack_.size() > 1) {
307 return transform_stack_[transform_stack_.size() - 2].clip_height;
313 return transform_stack_.size();
316bool Canvas::IsSkipping()
const {
317 return transform_stack_.back().skipping;
335 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
338 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
348 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
355bool Canvas::AttemptColorFilterOptimization(
356 const std::shared_ptr<Texture>&
image,
373 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
378 blend_filter->
mode(),
380 src_rect_constraint ==
383 auto atlas_contents = std::make_shared<AtlasContents>();
384 atlas_contents->SetGeometry(&geometry);
390 entity.SetContents(atlas_contents);
392 AddRenderEntityToCurrentPass(entity);
403 DrawImageRectAtlasGeometry geometry = DrawImageRectAtlasGeometry(
410 src_rect_constraint ==
413 auto atlas_contents = std::make_shared<ColorFilterAtlasContents>();
414 atlas_contents->SetGeometry(&geometry);
418 atlas_contents->SetMatrix(color_matrix);
423 entity.SetContents(atlas_contents);
425 AddRenderEntityToCurrentPass(entity);
430bool Canvas::AttemptDrawAntialiasedCircle(
const Point& center,
432 const Paint& paint) {
433 if (paint.HasColorFilter() || paint.image_filter || paint.invert_colors ||
434 paint.color_source || paint.mask_blur_descriptor.has_value()) {
440 entity.SetBlendMode(paint.blend_mode);
443 std::unique_ptr<CircleGeometry> geom;
445 geom = std::make_unique<CircleGeometry>(center, radius, paint.stroke.width);
447 geom = std::make_unique<CircleGeometry>(center, radius);
453 entity.SetContents(std::move(contents));
454 AddRenderEntityToCurrentPass(entity);
459bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
461 const Paint& paint) {
462 RRectBlurShape rrect_shape;
463 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint, rrect_shape);
466bool Canvas::AttemptDrawBlurredRSuperellipse(
const Rect& rect,
468 const Paint& paint) {
469 RSuperellipseBlurShape rsuperellipse_shape;
470 return AttemptDrawBlurredRRectLike(rect, corner_radii, paint,
471 rsuperellipse_shape);
474bool Canvas::AttemptDrawBlurredRRectLike(
const Rect& rect,
477 RRectLikeBlurShape& shape) {
482 if (paint.color_source) {
486 if (!paint.mask_blur_descriptor.has_value()) {
496 if (fabsf(corner_radii.width - corner_radii.height) >
kEhCloseEnough) {
499 Scalar corner_radius = corner_radii.width;
503 Color rrect_color = paint.color;
504 if (paint.invert_colors) {
507 if (paint.color_filter) {
511 Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor};
532 if ((paint.mask_blur_descriptor->style !=
534 paint.image_filter) ||
537 Rect render_bounds = rect;
538 if (paint.mask_blur_descriptor->style !=
541 render_bounds.
Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
547 .image_filter = paint.image_filter,
548 .blend_mode = paint.blend_mode,
551 rrect_paint.color = rrect_color.WithAlpha(1);
553 rrect_paint.color = rrect_color;
554 rrect_paint.blend_mode = paint.blend_mode;
555 rrect_paint.image_filter = paint.image_filter;
559 auto draw_blurred_rrect = [
this, &rect, corner_radius, &rrect_paint,
561 auto contents = shape.BuildBlurContent();
563 contents->SetColor(rrect_paint.color);
564 contents->SetSigma(rrect_paint.mask_blur_descriptor->sigma);
565 contents->SetShape(rect, corner_radius);
567 Entity blurred_rrect_entity;
569 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
571 rrect_paint.mask_blur_descriptor = std::nullopt;
572 blurred_rrect_entity.SetContents(
573 rrect_paint.WithFilters(std::move(contents)));
574 AddRenderEntityToCurrentPass(blurred_rrect_entity);
577 switch (rrect_paint.mask_blur_descriptor->style) {
579 draw_blurred_rrect();
584 draw_blurred_rrect();
588 entity.SetBlendMode(rrect_paint.blend_mode);
590 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
591 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, rrect_paint,
596 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
598 draw_blurred_rrect();
602 Geometry& geom = shape.BuildGeometry(rect, corner_radius);
604 draw_blurred_rrect();
622 auto geometry = std::make_unique<LineGeometry>(p0, p1, paint.
stroke);
624 if (renderer_.
GetContext()->GetFlags().antialiased_lines &&
629 AddRenderEntityToCurrentPass(entity, reuse_depth);
631 AddRenderEntityWithFiltersToCurrentPass(entity, geometry.get(), paint,
640 const Paint& paint) {
650 if (
length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
656 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
663 if (AttemptDrawBlurredRRect(rect, {}, paint)) {
673 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
676 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
692 if (AttemptDrawBlurredRRect(rect, rect.
GetSize() * 0.5f, paint)) {
702 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
705 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
716 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
729 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
742 return DrawOval(oval_bounds, paint);
755 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
761 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
766 auto& radii = round_rect.
GetRadii();
767 if (radii.AreAllCornersSame()) {
768 if (AttemptDrawBlurredRRect(rect, radii.top_left, paint)) {
778 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
789 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
792 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
798 const Paint& paint) {
805 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
808 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
813 const Paint& paint) {
814 auto& rect = round_superellipse.
GetBounds();
815 auto& radii = round_superellipse.
GetRadii();
816 if (radii.AreAllCornersSame() &&
817 AttemptDrawBlurredRSuperellipse(rect, radii.top_left, paint)) {
827 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
830 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
836 const Paint& paint) {
837 Size half_size(radius, radius);
838 if (AttemptDrawBlurredRRect(
840 {radius, radius}, paint)) {
844 if (AttemptDrawAntialiasedCircle(center, radius, paint)) {
854 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
857 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
878 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
879 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
880 uint32_t clip_depth = transform_stack_.back().clip_depth;
882 const Matrix clip_transform =
886 std::optional<Rect> clip_coverage = geometry.
GetCoverage(clip_transform);
887 if (!clip_coverage.has_value()) {
892 clip_coverage.value(),
901 GetGlobalPassPosition(),
903 GetClipHeightFloor(),
910 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
911 GetGlobalPassPosition());
914 ++transform_stack_.back().clip_height;
915 ++transform_stack_.back().num_clips;
932 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
939 renderer_, *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
958 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
986 if (size.IsEmpty()) {
990 std::optional<Rect> clipped_source =
992 if (!clipped_source) {
996 if (AttemptColorFilterOptimization(
image, source, dest, paint, sampler,
997 src_rect_constraint)) {
1001 if (*clipped_source != source) {
1011 texture_contents->SetTexture(
image);
1012 texture_contents->SetSourceRect(*clipped_source);
1013 texture_contents->SetStrictSourceRect(src_rect_constraint ==
1015 texture_contents->SetSamplerDescriptor(sampler);
1016 texture_contents->SetOpacity(paint.
color.
alpha);
1017 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
1025 AddRenderEntityToCurrentPass(entity);
1033 AddRenderEntityToCurrentPass(entity);
1036size_t Canvas::GetClipHeight()
const {
1037 return transform_stack_.back().clip_height;
1042 const Paint& paint) {
1055 if (UseColorSourceContents(vertices, paint)) {
1056 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
1062 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1063 contents->SetBlendMode(blend_mode);
1065 contents->SetGeometry(vertices);
1067 AddRenderEntityToCurrentPass(entity);
1078 image_color_source->
image()->impeller_texture());
1079 auto texture = image_color_source->
image()->impeller_texture();
1084 auto sampler_descriptor =
1086 auto effect_transform = image_color_source->
matrix();
1088 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1089 contents->SetBlendMode(blend_mode);
1091 contents->SetGeometry(vertices);
1092 contents->SetEffectTransform(effect_transform);
1093 contents->SetTexture(
texture);
1094 contents->SetTileMode(x_tile_mode, y_tile_mode);
1095 contents->SetSamplerDescriptor(sampler_descriptor);
1098 AddRenderEntityToCurrentPass(entity);
1102 auto src_paint = paint;
1105 std::shared_ptr<ColorSourceContents> src_contents =
1106 src_paint.CreateContents();
1107 src_contents->SetGeometry(vertices.get());
1115 auto size = src_contents->GetColorSourceSize();
1116 if (size.has_value()) {
1119 auto cvg = vertices->GetCoverage(
Matrix{});
1121 auto texture_coverage = vertices->GetTextureCoordinateCoverage();
1122 if (texture_coverage.has_value()) {
1125 texture_coverage->GetSize().Max({1, 1}));
1128 src_coverage = cvg.value();
1131 src_contents = src_paint.CreateContents();
1134 src_contents->SetGeometry(clip_geometry_.back().get());
1136 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1137 contents->SetBlendMode(blend_mode);
1139 contents->SetGeometry(vertices);
1140 contents->SetLazyTextureCoverage(src_coverage);
1141 contents->SetLazyTexture(
1146 auto snapshot = src_contents->RenderToSnapshot(
1147 renderer, {}, {.coverage_limit =
Rect::Round(src_coverage)});
1148 return snapshot.has_value() ? snapshot->texture :
nullptr;
1151 AddRenderEntityToCurrentPass(entity);
1155 const Paint& paint) {
1163 AddRenderEntityToCurrentPass(entity);
1169void Canvas::SetupRenderPass() {
1175 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
1180 *renderer_.
GetContext()->GetResourceAllocator(),
1182 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
1183 "ImpellerOnscreen", kDefaultStencilConfig);
1195 if (requires_readback_) {
1196 auto entity_pass_target =
1197 CreateRenderTarget(renderer_,
1200 render_passes_.push_back(
1201 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1203 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1208 render_passes_.push_back(
1209 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1213void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
1214 auto entry = CanvasStackEntry{};
1215 entry.skipping =
true;
1216 entry.clip_depth = current_depth_ + total_content_depth;
1217 transform_stack_.push_back(entry);
1222 return SkipUntilMatchingRestore(total_content_depth);
1226 entry.
transform = transform_stack_.back().transform;
1227 entry.clip_depth = current_depth_ + total_content_depth;
1228 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
1229 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
1230 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1231 <<
" after allocating " << total_content_depth;
1232 entry.clip_height = transform_stack_.back().clip_height;
1234 transform_stack_.push_back(entry);
1241 return std::nullopt;
1244 std::optional<Rect> maybe_current_clip_coverage =
1246 if (!maybe_current_clip_coverage.has_value()) {
1247 return std::nullopt;
1250 Rect current_clip_coverage = maybe_current_clip_coverage.value();
1254 std::shared_ptr<Texture> back_texture =
1256 FML_CHECK(back_texture) <<
"Context is valid:"
1261 std::optional<Rect> maybe_coverage_limit =
1263 Size(back_texture->GetSize()))
1266 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
1267 return std::nullopt;
1270 return maybe_coverage_limit->Intersection(
1275 std::optional<Rect> bounds,
1278 uint32_t total_content_depth,
1279 bool can_distribute_opacity,
1280 std::optional<int64_t> backdrop_id) {
1283 return SkipUntilMatchingRestore(total_content_depth);
1287 if (!maybe_coverage_limit.has_value()) {
1288 return SkipUntilMatchingRestore(total_content_depth);
1290 auto coverage_limit = maybe_coverage_limit.value();
1292 if (can_distribute_opacity && !backdrop_filter &&
1295 Save(total_content_depth);
1296 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1300 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1301 Rect(), transform_stack_.back().transform,
1306 transform_stack_.back().transform,
1311 !!backdrop_filter ||
1316 if (!maybe_subpass_coverage.has_value()) {
1317 return SkipUntilMatchingRestore(total_content_depth);
1320 auto subpass_coverage = maybe_subpass_coverage.value();
1331 bool did_round_out =
false;
1332 Point coverage_origin_adjustment =
Point{0, 0};
1336 did_round_out =
true;
1340 coverage_origin_adjustment =
1341 Point(subpass_coverage.GetLeftTop().x -
1342 std::floor(subpass_coverage.GetLeftTop().x),
1343 subpass_coverage.GetLeftTop().y -
1344 std::floor(subpass_coverage.GetLeftTop().y));
1347 return SkipUntilMatchingRestore(total_content_depth);
1355 ->GetMaximumRenderPassAttachmentSize());
1358 std::shared_ptr<FilterContents> backdrop_filter_contents;
1360 if (backdrop_filter) {
1361 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1363 [backdrop_filter = backdrop_filter](
1367 filter->SetEffectTransform(effect_transform);
1368 filter->SetRenderingMode(rendering_mode);
1372 std::shared_ptr<Texture> input_texture;
1377 bool will_cache_backdrop_texture =
false;
1382 size_t backdrop_count = 1;
1383 if (backdrop_id.has_value()) {
1384 std::unordered_map<int64_t, BackdropData>::iterator backdrop_data_it =
1385 backdrop_data_.find(backdrop_id.value());
1386 if (backdrop_data_it != backdrop_data_.end()) {
1387 backdrop_data = &backdrop_data_it->second;
1388 will_cache_backdrop_texture =
1390 backdrop_count = backdrop_data_it->second.backdrop_count;
1394 if (!will_cache_backdrop_texture || !backdrop_data->
texture_slot) {
1395 backdrop_count_ -= backdrop_count;
1401 const bool should_use_onscreen =
1403 backdrop_count_ == 0 && render_passes_.size() == 1u;
1404 input_texture = FlipBackdrop(
1405 GetGlobalPassPosition(),
1406 will_cache_backdrop_texture,
1409 if (!input_texture) {
1414 if (will_cache_backdrop_texture) {
1421 backdrop_filter_contents = backdrop_filter_proc(
1423 transform_stack_.back().transform.Basis(),
1426 transform_stack_.back().transform.HasTranslation()
1430 if (will_cache_backdrop_texture) {
1438 backdrop_filter_contents->RenderToSnapshot(renderer_, {}, {});
1441 std::optional<Snapshot> maybe_snapshot =
1443 if (maybe_snapshot.has_value()) {
1444 const Snapshot& snapshot = maybe_snapshot.value();
1446 subpass_coverage.Shift(-GetGlobalPassPosition()));
1449 contents->SetTexture(snapshot.
texture);
1450 contents->SetSourceRect(scaled);
1460 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1468 Paint paint_copy = paint;
1469 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1470 transform_stack_.back().distributed_opacity = 1.0;
1472 render_passes_.push_back(
1474 CreateRenderTarget(renderer_,
1479 paint_copy, subpass_coverage.Shift(-coverage_origin_adjustment)});
1482 entry.
transform = transform_stack_.back().transform;
1483 entry.
clip_depth = current_depth_ + total_content_depth;
1485 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1486 <<
" after allocating " << total_content_depth;
1487 entry.
clip_height = transform_stack_.back().clip_height;
1490 transform_stack_.emplace_back(entry);
1497 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1499 if (!backdrop_filter_contents) {
1505 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1508 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1509 backdrop_entity.
Render(renderer_, GetCurrentRenderPass());
1514 if (transform_stack_.size() == 1) {
1531 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1532 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1533 current_depth_ = transform_stack_.back().clip_depth;
1536 transform_stack_.pop_back();
1540 if (transform_stack_.back().rendering_mode ==
1542 transform_stack_.back().rendering_mode ==
1544 auto lazy_render_pass = std::move(render_passes_.back());
1545 render_passes_.pop_back();
1547 lazy_render_pass.GetInlinePassContext()->GetRenderPass();
1550 save_layer_state_.pop_back();
1551 auto global_pass_position = GetGlobalPassPosition();
1553 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1554 save_layer_state.
paint,
1555 lazy_render_pass.GetInlinePassContext()->GetTexture(),
1557 transform_stack_.back().transform
1560 lazy_render_pass.GetInlinePassContext()->EndPass();
1567 Point subpass_texture_position;
1568 if (transform_stack_.back().did_round_out) {
1571 subpass_texture_position =
1576 subpass_texture_position =
1590 ApplyFramebufferBlend(element_entity);
1601 auto input_texture = FlipBackdrop(GetGlobalPassPosition());
1602 if (!input_texture) {
1612 contents->SetCoverageHint(element_entity.
GetCoverage());
1620 *render_passes_.back().GetInlinePassContext()->GetRenderPass()
1623 transform_stack_.pop_back();
1631 size_t num_clips = transform_stack_.back().num_clips;
1632 transform_stack_.pop_back();
1634 if (num_clips > 0) {
1645 *render_passes_.back().GetInlinePassContext()->GetRenderPass(),
1646 GetGlobalPassPosition()
1654bool Canvas::AttemptBlurredTextOptimization(
1655 const std::shared_ptr<TextFrame>& text_frame,
1656 const std::shared_ptr<TextContents>& text_contents,
1658 const Paint& paint) {
1672 std::shared_ptr<FilterContents> filter =
1677 std::optional<Glyph> maybe_glyph = text_frame->AsSingleGlyph();
1678 int64_t identifier = maybe_glyph.has_value()
1679 ? maybe_glyph.value().index
1680 :
reinterpret_cast<int64_t
>(text_frame.get());
1681 TextShadowCache::TextShadowCacheKey cache_key(
1684 maybe_glyph.has_value(),
1685 text_frame->GetFont(),
1690 renderer_, entity, filter, cache_key);
1691 if (result.has_value()) {
1692 AddRenderEntityToCurrentPass(result.value(),
false);
1706 const Paint& paint) {
1708 if (max_scale * text_frame->GetFont().GetMetrics().point_size >
1724 auto text_contents = std::make_shared<TextContents>();
1725 text_contents->SetTextFrame(text_frame);
1727 text_contents->SetScale(max_scale);
1728 text_contents->SetColor(paint.
color);
1729 text_contents->SetOffset(position);
1730 text_contents->SetTextProperties(paint.
color,
1732 ? std::optional(paint.
stroke)
1738 if (AttemptBlurredTextOptimization(text_frame, text_contents, entity,
1744 AddRenderEntityToCurrentPass(entity,
false);
1747void Canvas::AddRenderEntityWithFiltersToCurrentPass(
Entity& entity,
1751 std::shared_ptr<ColorSourceContents> contents = paint.
CreateContents();
1754 contents->SetGeometry(geometry);
1756 AddRenderEntityToCurrentPass(entity, reuse_depth);
1764 if (needs_color_filter &&
1765 contents->ApplyColorFilter([&](Color color) -> Color {
1766 if (paint.color_filter) {
1767 color = GetCPUColorFilterProc(paint.color_filter)(color);
1770 color = color.ApplyColorMatrix(kColorInversion);
1774 needs_color_filter =
false;
1778 contents->SetGeometry(geometry);
1784 FillRectGeometry out_rect(
Rect{});
1786 contents, needs_color_filter ? paint.
color_filter : nullptr,
1787 needs_color_filter ? paint.invert_colors : false, &out_rect);
1789 AddRenderEntityToCurrentPass(entity, reuse_depth);
1793 std::shared_ptr<Contents> contents_copy = std::move(contents);
1797 if (needs_color_filter &&
1813 std::shared_ptr<FilterContents> filter =
WrapInput(
1817 AddRenderEntityToCurrentPass(entity, reuse_depth);
1822 AddRenderEntityToCurrentPass(entity, reuse_depth);
1825void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
1830 entity.SetTransform(
1831 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1832 entity.GetTransform());
1833 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
1834 if (entity.GetBlendMode() == BlendMode::kSrcOver &&
1835 entity.GetContents()->IsOpaque(entity.GetTransform())) {
1836 entity.SetBlendMode(BlendMode::kSrc);
1842 if (render_passes_.back().IsApplyingClearColor()) {
1843 std::optional<Color> maybe_color = entity.AsBackgroundColor(
1844 render_passes_.back().GetInlinePassContext()->GetTexture()->GetSize());
1845 if (maybe_color.has_value()) {
1846 Color color = maybe_color.value();
1847 RenderTarget& render_target = render_passes_.back()
1848 .GetInlinePassContext()
1851 ColorAttachment attachment = render_target.GetColorAttachment(0);
1854 attachment.clear_color = attachment.clear_color.Unpremultiply()
1855 .Blend(color, entity.GetBlendMode())
1857 render_target.SetColorAttachment(attachment, 0u);
1868 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1869 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1870 entity.SetClipDepth(current_depth_);
1872 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1873 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
1874 ApplyFramebufferBlend(entity);
1885 auto input_texture = FlipBackdrop(GetGlobalPassPosition(),
1889 if (!input_texture) {
1897 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
1898 entity.GetContents()->SetCoverageHint(Rect::Intersection(
1899 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
1901 FilterInput::Vector inputs = {
1902 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
1903 FilterInput::Make(entity.GetContents())};
1905 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
1906 entity.SetContents(std::move(contents));
1907 entity.SetBlendMode(BlendMode::kSrc);
1911 const std::shared_ptr<RenderPass>& result =
1912 render_passes_.back().GetInlinePassContext()->GetRenderPass();
1920 entity.Render(renderer_, *result);
1923RenderPass& Canvas::GetCurrentRenderPass()
const {
1924 return *render_passes_.back().GetInlinePassContext()->GetRenderPass();
1927void Canvas::SetBackdropData(
1928 std::unordered_map<int64_t, BackdropData> backdrop_data,
1929 size_t backdrop_count) {
1930 backdrop_data_ = std::move(backdrop_data);
1931 backdrop_count_ = backdrop_count;
1934std::shared_ptr<Texture> Canvas::FlipBackdrop(
Point global_pass_position,
1935 bool should_remove_texture,
1936 bool should_use_onscreen,
1937 bool post_depth_increment) {
1939 render_passes_.pop_back();
1955 <<
"Failed to end the current render pass in order to read from "
1956 "the backdrop texture and apply an advanced blend or backdrop "
1961 render_passes_.emplace_back(std::move(rendering_config));
1965 const std::shared_ptr<Texture>& input_texture =
1968 if (!input_texture) {
1969 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
1970 "apply an advanced blend or backdrop filter.";
1973 render_passes_.emplace_back(std::move(rendering_config));
1977 if (should_use_onscreen) {
1978 ColorAttachment color0 = render_target_.GetColorAttachment(0);
1982 color0.load_action = color0.resolve_texture !=
nullptr
1983 ? LoadAction::kDontCare
1984 : LoadAction::kLoad;
1985 render_target_.SetColorAttachment(color0, 0);
1987 auto entity_pass_target = std::make_unique<EntityPassTarget>(
1989 renderer_.GetDeviceCapabilities().SupportsReadFromResolve(),
1990 renderer_.GetDeviceCapabilities().SupportsImplicitResolvingMSAA()
1992 render_passes_.push_back(
1993 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
1994 requires_readback_ =
false;
1996 render_passes_.emplace_back(std::move(rendering_config));
1999 if (should_remove_texture) {
2000 render_passes_.back().GetEntityPassTarget()->RemoveSecondary();
2003 RenderPass& current_render_pass =
2004 *render_passes_.back().GetInlinePassContext()->GetRenderPass();
2013 Rect size_rect = Rect::MakeSize(input_texture->GetSize());
2014 auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
2015 msaa_backdrop_contents->SetStencilEnabled(
false);
2016 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
2017 msaa_backdrop_contents->SetSourceRect(size_rect);
2018 msaa_backdrop_contents->SetTexture(input_texture);
2020 Entity msaa_backdrop_entity;
2021 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
2022 msaa_backdrop_entity.SetBlendMode(BlendMode::kSrc);
2023 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
2024 if (!msaa_backdrop_entity.Render(renderer_, current_render_pass)) {
2031 auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
2032 uint64_t current_depth =
2033 post_depth_increment ? current_depth_ - 1 : current_depth_;
2034 for (
const auto& replay : replay_entities) {
2035 if (replay.clip_depth <= current_depth) {
2039 SetClipScissor(replay.clip_coverage, current_render_pass,
2040 global_pass_position);
2041 if (!replay.clip_contents.Render(renderer_, current_render_pass,
2042 replay.clip_depth)) {
2047 return input_texture;
2050bool Canvas::SupportsBlitToOnscreen()
const {
2051 return renderer_.GetContext()
2053 ->SupportsTextureToTextureBlits() &&
2054 renderer_.GetContext()->GetBackendType() ==
2055 Context::BackendType::kMetal;
2058bool Canvas::BlitToOnscreen(
bool is_onscreen) {
2059 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
2060 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
2061 auto offscreen_target = render_passes_.back()
2062 .GetInlinePassContext()
2065 if (SupportsBlitToOnscreen()) {
2066 auto blit_pass = command_buffer->CreateBlitPass();
2067 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
2068 render_target_.GetRenderTargetTexture());
2069 if (!blit_pass->EncodeCommands()) {
2074 auto render_pass = command_buffer->CreateRenderPass(render_target_);
2075 render_pass->SetLabel(
"EntityPass Root Render Pass");
2078 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
2079 auto contents = TextureContents::MakeRect(size_rect);
2080 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
2081 contents->SetSourceRect(size_rect);
2082 contents->SetLabel(
"Root pass blit");
2085 entity.SetContents(contents);
2086 entity.SetBlendMode(BlendMode::kSrc);
2088 if (!entity.Render(renderer_, *render_pass)) {
2094 if (!render_pass->EncodeCommands()) {
2101 return renderer_.GetContext()->SubmitOnscreen(std::move(command_buffer));
2103 return renderer_.GetContext()->EnqueueCommandBuffer(
2104 std::move(command_buffer));
2108bool Canvas::EnsureFinalMipmapGeneration()
const {
2109 if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
2112 std::shared_ptr<CommandBuffer> cmd_buffer =
2113 renderer_.GetContext()->CreateCommandBuffer();
2117 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
2121 blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
2122 blit_pass->EncodeCommands();
2123 return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
2126void Canvas::EndReplay() {
2128 render_passes_.back().GetInlinePassContext()->GetRenderPass();
2129 render_passes_.back().GetInlinePassContext()->EndPass(
2130 !requires_readback_ && is_onscreen_);
2131 backdrop_data_.clear();
2136 if (requires_readback_) {
2137 BlitToOnscreen(is_onscreen_);
2139 if (!EnsureFinalMipmapGeneration()) {
2142 if (!renderer_.GetContext()->FlushCommandBuffers()) {
2146 render_passes_.clear();
2147 renderer_.GetRenderTargetCache()->End();
2148 clip_geometry_.clear();
2151 Initialize(initial_cull_rect_);
2154LazyRenderingConfig::LazyRenderingConfig(
2156 std::unique_ptr<EntityPassTarget> p_entity_pass_target)
2157 : entity_pass_target_(
std::move(p_entity_pass_target)) {
2158 inline_pass_context_ =
2159 std::make_unique<InlinePassContext>(renderer, *entity_pass_target_);
2163 return !inline_pass_context_->IsActive();
2167 return entity_pass_target_.get();
2171 return inline_pass_context_.get();
virtual T type() const =0
virtual const DlBlendColorFilter * asBlend() const
virtual const DlMatrixColorFilter * asMatrix() const
virtual bool modifies_transparent_black() const =0
virtual const DlImageColorSource * asImage() const
DlImageSampling sampling() const
DlTileMode vertical_tile_mode() const
DlTileMode horizontal_tile_mode() const
sk_sp< const DlImage > image() const
void get_matrix(float matrix[20]) const
const DlMatrix & matrix() const
A Geometry that produces fillable vertices representing the stroked outline of an |Arc| object using ...
void ClipGeometry(const Geometry &geometry, Entity::ClipOperation clip_op, bool is_aa=true)
static constexpr uint32_t kMaxDepth
Canvas(ContentContext &renderer, const RenderTarget &render_target, bool is_onscreen, bool requires_readback)
void DrawRoundSuperellipse(const RoundSuperellipse &rse, const Paint &paint)
std::optional< Rect > GetLocalCoverageLimit() const
Return the culling bounds of the current render target, or nullopt if there is no coverage.
void SaveLayer(const Paint &paint, std::optional< Rect > bounds=std::nullopt, const flutter::DlImageFilter *backdrop_filter=nullptr, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, uint32_t total_content_depth=kMaxDepth, bool can_distribute_opacity=false, std::optional< int64_t > backdrop_id=std::nullopt)
const Matrix & GetCurrentTransform() const
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
void DrawOval(const Rect &rect, const Paint &paint)
void DrawImageRect(const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, const SamplerDescriptor &sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
void RestoreToCount(size_t count)
size_t GetSaveCount() const
void Concat(const Matrix &transform)
void Transform(const Matrix &transform)
void DrawDashedLine(const Point &p0, const Point &p1, Scalar on_length, Scalar off_length, const Paint &paint)
void DrawDiffRoundRect(const RoundRect &outer, const RoundRect &inner, const Paint &paint)
void DrawPath(const flutter::DlPath &path, const Paint &paint)
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
void PreConcat(const Matrix &transform)
void Rotate(Radians radians)
void DrawPoints(const Point points[], uint32_t count, Scalar radius, const Paint &paint, PointStyle point_style)
void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
void DrawImage(const std::shared_ptr< Texture > &image, Point offset, const Paint &paint, const SamplerDescriptor &sampler={})
void DrawPaint(const Paint &paint)
void DrawRoundRect(const RoundRect &rect, const Paint &paint)
void Skew(Scalar sx, Scalar sy)
void Scale(const Vector2 &scale)
void Save(uint32_t total_content_depth=kMaxDepth)
void DrawRect(const Rect &rect, const Paint &paint)
void DrawAtlas(const std::shared_ptr< AtlasContents > &atlas_contents, const Paint &paint)
void DrawLine(const Point &p0, const Point &p1, const Paint &paint, bool reuse_depth=false)
void Translate(const Vector3 &offset)
void DrawCircle(const Point ¢er, Scalar radius, const Paint &paint)
void DrawArc(const Arc &arc, const Paint &paint)
virtual bool SupportsImplicitResolvingMSAA() const =0
Whether the context backend supports multisampled rendering to the on-screen surface without requirin...
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
virtual bool SupportsReadFromResolve() const =0
Whether the context backend supports binding the current RenderPass attachments. This is supported if...
static std::unique_ptr< CircleContents > Make(std::unique_ptr< CircleGeometry > geometry, Color color, bool stroked)
void SetGeometry(GeometryResult geometry)
Set the pre-tessellated clip geometry.
void SetClipOperation(Entity::ClipOperation clip_op)
bool Render(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth) const
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
const Capabilities & GetDeviceCapabilities() const
TextShadowCache & GetTextShadowCache() const
std::shared_ptr< Context > GetContext() const
A geometry that implements "drawPaint" like behavior by covering the entire render pass area.
A Geometry class that can directly generate vertices (with or without texture coordinates) for filled...
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
std::optional< Rect > GetCoverage() const
@ kSubpassPrependSnapshotTransform
@ kSubpassAppendSnapshotTransform
const std::shared_ptr< Contents > & GetContents() const
void SetClipDepth(uint32_t clip_depth)
BlendMode GetBlendMode() const
void SetContents(std::shared_ptr< Contents > contents)
void SetBlendMode(BlendMode blend_mode)
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
static constexpr BlendMode kLastPipelineBlendMode
static bool IsBlendModeDestructive(BlendMode blend_mode)
Returns true if the blend mode is "destructive", meaning that even fully transparent source colors wo...
A class that tracks all clips that have been recorded in the current entity pass stencil.
std::optional< Rect > CurrentClipCoverage() const
void PushSubpass(std::optional< Rect > subpass_coverage, size_t clip_height)
ClipStateResult RecordClip(const ClipContents &clip_contents, Matrix transform, Point global_pass_position, uint32_t clip_depth, size_t clip_height_floor, bool is_aa)
ClipStateResult RecordRestore(Point global_pass_position, size_t restore_height)
ReplayResult & GetLastReplayResult()
A Geometry that produces fillable vertices for the gap between a pair of |RoundRect| objects using th...
A Geometry that produces fillable vertices from a |DlPath| object using the |FillPathSourceGeometry| ...
A Geometry class that produces fillable vertices from any |RoundRect| object regardless of radii unif...
@ kNormal
Blurred inside and outside.
@ kOuter
Nothing inside, blurred outside.
@ kInner
Blurred inside, nothing outside.
@ kSolid
Solid inside, blurred outside.
virtual std::optional< Rect > GetCoverage(const Matrix &transform) const =0
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
virtual GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const =0
virtual bool CanApplyMaskFilter() const
virtual bool IsAxisAlignedRect() const
bool EndPass(bool is_onscreen=false)
std::shared_ptr< Texture > GetTexture()
const std::shared_ptr< RenderPass > & GetRenderPass()
bool IsApplyingClearColor() const
Whether or not the clear color texture can still be updated.
EntityPassTarget * GetEntityPassTarget() const
InlinePassContext * GetInlinePassContext() const
static std::unique_ptr< LineContents > Make(std::unique_ptr< LineGeometry > geometry, Color color)
A geometry class specialized for Canvas::DrawPoints.
ColorAttachment GetColorAttachment(size_t index) const
Get the color attachment at [index].
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
ISize GetRenderTargetSize() const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
void SetupDepthStencilAttachments(const Context &context, Allocator &allocator, ISize size, bool msaa, std::string_view label="Offscreen", RenderTarget::AttachmentConfig stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &depth_stencil_texture=nullptr)
A Geometry class that generates fillable vertices (with or without texture coordinates) directly from...
A Geometry class that generates fillable vertices (with or without texture coordinates) directly from...
A Geometry that produces fillable vertices representing the stroked outline of a |DlPath| object usin...
A Geometry that produces fillable vertices representing the stroked outline of a pair of nested |Roun...
A Geometry class that produces fillable vertices representing the stroked outline of an ellipse with ...
A Geometry that produces fillable vertices representing the stroked outline of a |DlPath| object usin...
A Geometry class that produces fillable vertices representing the stroked outline of any |Roundrect| ...
A Geometry class that produces fillable vertices representing the stroked outline of any |RoundSupere...
std::optional< Entity > Lookup(const ContentContext &renderer, const Entity &entity, const std::shared_ptr< FilterContents > &contents, const TextShadowCacheKey &)
Lookup the entity in the cache with the given filter/text contents, returning the new entity to rende...
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
FlutterVulkanImage * image
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
ISize subpass_size
The output size of the down-sampling pass.
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Color ToColor(const flutter::DlColor &color)
static constexpr Scalar kMaxTextScale
std::shared_ptr< ColorFilterContents > WrapWithGPUColorFilter(const flutter::DlColorFilter *filter, const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
@ kStrict
Sample only within the source rectangle. May be slower.
std::shared_ptr< FilterContents > WrapInput(const flutter::DlImageFilter *filter, const FilterInput::Ref &input)
Generate a new FilterContents using this filter's configuration.
constexpr float kEhCloseEnough
std::shared_ptr< ColorFilterContents > WrapWithInvertColors(const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
@ kRound
Points are drawn as squares.
ColorFilterProc GetCPUColorFilterProc(const flutter::DlColorFilter *filter)
@ kMayClipContents
The caller claims the bounds are a subset of an estimate of the reasonably tight bounds but likely cl...
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
std::optional< Rect > ComputeSaveLayerCoverage(const Rect &content_coverage, const Matrix &effect_transform, const Rect &coverage_limit, const std::shared_ptr< FilterContents > &image_filter, bool flood_output_coverage, bool flood_input_coverage)
Compute the coverage of a subpass in the global coordinate space.
static const constexpr ColorMatrix kColorInversion
A color matrix which inverts colors.
constexpr bool IncludeCenter() const
constexpr bool IsFullCircle() const
constexpr Degrees GetSweep() const
constexpr Degrees GetStart() const
const Rect & GetOvalBounds() const
Return the bounds of the oval in which this arc is inscribed.
std::shared_ptr< Texture > texture
std::shared_ptr< Texture > texture_slot
std::optional< Snapshot > shared_filter_snapshot
Entity::RenderingMode rendering_mode
static constexpr Color BlackTransparent()
static constexpr Color Khaki()
static constexpr Color White()
constexpr Color WithAlpha(Scalar new_alpha) const
ClipContents clip_contents
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...
std::shared_ptr< Contents > WithFilters(std::shared_ptr< Contents > input) const
Wrap this paint's configured filters to the given contents.
const flutter::DlColorFilter * color_filter
const flutter::DlColorSource * color_source
const flutter::DlImageFilter * image_filter
static bool CanApplyOpacityPeephole(const Paint &paint)
Whether or not a save layer with the provided paint can perform the opacity peephole optimization.
std::optional< MaskBlurDescriptor > mask_blur_descriptor
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
std::shared_ptr< ColorSourceContents > CreateContents() const
bool HasColorFilter() const
Whether this paint has a color filter that can apply opacity.
constexpr const RoundingRadii & GetRadii() const
constexpr const Rect & GetBounds() const
constexpr const Rect & GetBounds() const
constexpr const RoundingRadii & GetRadii() const
Represents a texture and its intended draw transform/sampler configuration.
Matrix transform
The transform that should be applied to this texture for rendering.
std::shared_ptr< Texture > texture
SamplerDescriptor sampler_descriptor
constexpr Type GetDistance(const TPoint &p) const
constexpr auto GetBottom() const
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
constexpr auto GetTop() const
constexpr std::optional< TRect > Intersection(const TRect &o) const
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
constexpr auto GetLeft() const
Round(const TRect< U > &r)
RoundOut(const TRect< U > &r)
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr auto GetRight() const
constexpr bool IsSquare() const
Returns true if width and height are equal and neither is NaN.
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
static constexpr TRect MakeSize(const TSize< U > &size)
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
static constexpr TRect MakeMaximum()
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
std::vector< Point > points
#define TRACE_EVENT0(category_group, name)