11 #include "display_list/effects/dl_color_source.h"
12 #include "display_list/effects/dl_image_filter.h"
13 #include "flutter/fml/logging.h"
14 #include "flutter/fml/trace_event.h"
47 static bool UseColorSourceContents(
48 const std::shared_ptr<VerticesGeometry>& vertices,
52 if (vertices->HasVertexColors()) {
55 if (vertices->HasTextureCoordinates() &&
56 (!paint.color_source ||
57 paint.color_source->type() == flutter::DlColorSourceType::kColor)) {
60 return !vertices->HasTextureCoordinates();
63 static void SetClipScissor(std::optional<Rect> clip_coverage,
65 Point global_pass_position) {
69 if (clip_coverage.has_value()) {
70 clip_coverage = clip_coverage->
Shift(-global_pass_position);
73 scissor = scissor.Intersection(
IRect::MakeSize(pass.GetRenderTargetSize()))
76 pass.SetScissor(scissor);
79 static void ApplyFramebufferBlend(Entity& entity) {
80 auto src_contents = entity.GetContents();
81 auto contents = std::make_shared<FramebufferBlendContents>();
82 contents->SetChildContents(src_contents);
83 contents->SetBlendMode(entity.GetBlendMode());
84 entity.SetContents(std::move(contents));
96 static std::shared_ptr<Texture> FlipBackdrop(
97 std::vector<LazyRenderingConfig>& render_passes,
98 Point global_pass_position,
99 EntityPassClipStack& clip_coverage_stack,
100 ContentContext& renderer) {
101 auto rendering_config = std::move(render_passes.back());
102 render_passes.pop_back();
115 rendering_config.inline_pass_context->GetRenderPass(0);
116 if (!rendering_config.inline_pass_context->EndPass()) {
118 <<
"Failed to end the current render pass in order to read from "
119 "the backdrop texture and apply an advanced blend or backdrop "
124 render_passes.push_back(LazyRenderingConfig(
125 renderer, std::move(rendering_config.entity_pass_target),
126 std::move(rendering_config.inline_pass_context)));
130 std::shared_ptr<Texture> input_texture =
131 rendering_config.inline_pass_context->GetTexture();
133 if (!input_texture) {
134 VALIDATION_LOG <<
"Failed to fetch the color texture in order to "
135 "apply an advanced blend or backdrop filter.";
138 render_passes.push_back(LazyRenderingConfig(
139 renderer, std::move(rendering_config.entity_pass_target),
140 std::move(rendering_config.inline_pass_context)));
144 render_passes.push_back(LazyRenderingConfig(
145 renderer, std::move(rendering_config.entity_pass_target),
146 std::move(rendering_config.inline_pass_context)));
156 msaa_backdrop_contents->SetStencilEnabled(
false);
157 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
158 msaa_backdrop_contents->SetSourceRect(size_rect);
159 msaa_backdrop_contents->SetTexture(input_texture);
161 Entity msaa_backdrop_entity;
162 msaa_backdrop_entity.SetContents(std::move(msaa_backdrop_contents));
164 msaa_backdrop_entity.SetClipDepth(std::numeric_limits<uint32_t>::max());
165 if (!msaa_backdrop_entity.Render(
167 *render_passes.back().inline_pass_context->GetRenderPass(0).pass)) {
174 auto& replay_entities = clip_coverage_stack.GetReplayEntities();
175 for (
const auto& replay : replay_entities) {
177 replay.clip_coverage,
178 *render_passes.back().inline_pass_context->GetRenderPass(0).pass,
179 global_pass_position);
180 if (!replay.entity.Render(
182 *render_passes.back().inline_pass_context->GetRenderPass(0).pass)) {
187 return input_texture;
192 static std::shared_ptr<Contents> CreateContentsForSubpassTarget(
194 const std::shared_ptr<Texture>& target,
195 const Matrix& effect_transform) {
197 contents->SetTexture(target);
198 contents->SetLabel(
"Subpass");
200 contents->SetOpacity(paint.color.alpha);
201 contents->SetDeferApplyingOpacity(
true);
203 return paint.WithFiltersForSubpassTarget(std::move(contents),
207 static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
208 RenderTarget::AttachmentConfig{
214 static std::unique_ptr<EntityPassTarget> CreateRenderTarget(
215 ContentContext& renderer,
217 const Color& clear_color) {
218 const std::shared_ptr<Context>& context = renderer.GetContext();
226 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
227 target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
233 RenderTarget::AttachmentConfigMSAA{
238 .clear_color = clear_color},
239 kDefaultStencilConfig);
241 target = renderer.GetRenderTargetCache()->CreateOffscreen(
246 RenderTarget::AttachmentConfig{
250 .clear_color = clear_color,
252 kDefaultStencilConfig
256 return std::make_unique<EntityPassTarget>(
257 target, renderer.GetDeviceCapabilities().SupportsReadFromResolve(),
258 renderer.GetDeviceCapabilities().SupportsImplicitResolvingMSAA());
265 bool requires_readback)
266 : renderer_(renderer),
267 render_target_(render_target),
268 requires_readback_(requires_readback),
270 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
271 Initialize(std::nullopt);
277 bool requires_readback,
279 : renderer_(renderer),
280 render_target_(render_target),
281 requires_readback_(requires_readback),
283 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
284 Initialize(cull_rect);
290 bool requires_readback,
292 : renderer_(renderer),
293 render_target_(render_target),
294 requires_readback_(requires_readback),
296 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
302 void Canvas::Initialize(std::optional<Rect> cull_rect) {
303 initial_cull_rect_ = cull_rect;
310 void Canvas::Reset() {
312 transform_stack_ = {};
324 transform_stack_.back().transform = {};
332 return transform_stack_.back().transform;
355 Point Canvas::GetGlobalPassPosition()
const {
356 if (save_layer_state_.empty()) {
359 return save_layer_state_.back().coverage.GetOrigin();
363 size_t Canvas::GetClipHeightFloor()
const {
364 if (transform_stack_.size() > 1) {
365 return transform_stack_[transform_stack_.size() - 2].clip_height;
371 return transform_stack_.size();
374 bool Canvas::IsSkipping()
const {
375 return transform_stack_.back().skipping;
393 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
397 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
407 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
410 bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
412 const Paint& paint) {
414 (paint.
color_source->type() != flutter::DlColorSourceType::kColor ||
435 Color rrect_color = paint.
color;
468 (!rrect_color.IsOpaque() ||
470 Rect render_bounds = rect;
484 rrect_paint.color = rrect_color.WithAlpha(1);
486 rrect_paint.color = rrect_color;
492 auto draw_blurred_rrect = [
this, &rect, &corner_radii, &rrect_paint]() {
493 auto contents = std::make_shared<SolidRRectBlurContents>();
495 contents->SetColor(rrect_paint.color);
496 contents->SetSigma(rrect_paint.mask_blur_descriptor->sigma);
497 contents->SetRRect(rect, corner_radii);
499 Entity blurred_rrect_entity;
501 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
503 rrect_paint.mask_blur_descriptor = std::nullopt;
504 blurred_rrect_entity.SetContents(
505 rrect_paint.WithFilters(std::move(contents)));
506 AddRenderEntityToCurrentPass(blurred_rrect_entity);
509 switch (rrect_paint.mask_blur_descriptor->style) {
511 draw_blurred_rrect();
516 draw_blurred_rrect();
520 entity.SetBlendMode(rrect_paint.blend_mode);
522 RoundRectGeometry geom(rect, corner_radii);
523 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, rrect_paint,
530 draw_blurred_rrect();
536 draw_blurred_rrect();
552 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
561 if (AttemptDrawBlurredRRect(rect, {}, paint)) {
570 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
591 if (AttemptDrawBlurredRRect(rect, rect.
GetSize() * 0.5f, paint)) {
600 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
604 const Size& corner_radii,
605 const Paint& paint) {
606 if (AttemptDrawBlurredRRect(rect, corner_radii, paint)) {
616 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
630 const Paint& paint) {
631 Size half_size(radius, radius);
632 if (AttemptDrawBlurredRRect(
634 {radius, radius}, paint)) {
644 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
647 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
653 clip_geometry_.push_back(std::move(geometry));
655 auto contents = std::make_shared<ClipContents>();
656 contents->SetGeometry(clip_geometry_.back().get());
657 contents->SetClipOperation(clip_op);
663 AddClipEntityToCurrentPass(entity);
665 ++transform_stack_.back().clip_height;
666 ++transform_stack_.back().num_clips;
669 void Canvas::RestoreClip() {
674 auto clip_restore = std::make_shared<ClipRestoreContents>();
675 clip_restore->SetRestoreHeight(GetClipHeight());
678 AddRenderEntityToCurrentPass(entity);
695 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
707 const auto dest = source.Shift(
offset);
709 DrawImageRect(image, source, dest, paint, std::move(sampler));
722 auto size = image->GetSize();
724 if (size.IsEmpty()) {
729 texture_contents->SetTexture(image);
730 texture_contents->SetSourceRect(source);
731 texture_contents->SetStrictSourceRect(src_rect_constraint ==
733 texture_contents->SetSamplerDescriptor(std::move(sampler));
734 texture_contents->SetOpacity(paint.
color.
alpha);
735 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
743 AddRenderEntityToCurrentPass(entity);
751 AddRenderEntityToCurrentPass(entity);
754 size_t Canvas::GetClipHeight()
const {
755 return transform_stack_.back().clip_height;
760 const Paint& paint) {
765 paint.
color_source->type() == flutter::DlColorSourceType::kColor) {
774 if (UseColorSourceContents(vertices, paint)) {
775 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
781 auto contents = std::make_shared<VerticesSimpleBlendContents>();
782 contents->SetBlendMode(blend_mode);
784 contents->SetGeometry(vertices);
786 AddRenderEntityToCurrentPass(entity);
793 paint.
color_source->type() == flutter::DlColorSourceType::kImage) {
794 const flutter::DlImageColorSource* image_color_source =
796 FML_DCHECK(image_color_source &&
797 image_color_source->image()->impeller_texture());
798 auto texture = image_color_source->image()->impeller_texture();
800 image_color_source->horizontal_tile_mode());
803 auto sampler_descriptor =
805 auto effect_transform =
808 auto contents = std::make_shared<VerticesSimpleBlendContents>();
809 contents->SetBlendMode(blend_mode);
811 contents->SetGeometry(vertices);
812 contents->SetEffectTransform(effect_transform);
813 contents->SetTexture(texture);
814 contents->SetTileMode(x_tile_mode, y_tile_mode);
817 AddRenderEntityToCurrentPass(entity);
821 auto src_paint = paint;
824 std::shared_ptr<ColorSourceContents> src_contents =
825 src_paint.CreateContents();
826 src_contents->SetGeometry(vertices.get());
834 auto size = src_contents->GetColorSourceSize();
835 if (size.has_value()) {
838 auto cvg = vertices->GetCoverage(
Matrix{});
839 FML_CHECK(cvg.has_value());
843 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
845 src_contents = src_paint.CreateContents();
848 src_contents->SetGeometry(clip_geometry_.back().get());
850 auto contents = std::make_shared<VerticesSimpleBlendContents>();
851 contents->SetBlendMode(blend_mode);
853 contents->SetGeometry(vertices);
854 contents->SetLazyTextureCoverage(src_coverage);
855 contents->SetLazyTexture(
861 ->RenderToSnapshot(renderer, {},
Rect::Round(src_coverage))
865 AddRenderEntityToCurrentPass(entity);
869 const Paint& paint) {
877 AddRenderEntityToCurrentPass(entity);
883 void Canvas::SetupRenderPass() {
889 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
894 *renderer_.
GetContext()->GetResourceAllocator(),
895 color0.texture->GetSize(),
896 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
897 "ImpellerOnscreen", kDefaultStencilConfig);
909 if (requires_readback_) {
910 auto entity_pass_target =
911 CreateRenderTarget(renderer_,
912 color0.texture->GetSize(),
914 render_passes_.push_back(
915 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
917 auto entity_pass_target = std::make_unique<EntityPassTarget>(
922 render_passes_.push_back(
923 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
927 void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
928 auto entry = CanvasStackEntry{};
929 entry.skipping =
true;
930 entry.clip_depth = current_depth_ + total_content_depth;
931 transform_stack_.push_back(entry);
936 return SkipUntilMatchingRestore(total_content_depth);
940 entry.
transform = transform_stack_.back().transform;
941 entry.clip_depth = current_depth_ + total_content_depth;
942 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
943 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
944 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
945 <<
" after allocating " << total_content_depth;
946 entry.clip_height = transform_stack_.back().clip_height;
948 transform_stack_.push_back(entry);
959 if (!maybe_current_clip_coverage.has_value()) {
963 auto current_clip_coverage = maybe_current_clip_coverage.value();
967 std::optional<Rect> maybe_coverage_limit =
969 Size(render_passes_.back()
970 .inline_pass_context->GetTexture()
974 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
978 return maybe_coverage_limit->Intersection(
983 std::optional<Rect> bounds,
984 const flutter::DlImageFilter* backdrop_filter,
986 uint32_t total_content_depth,
987 bool can_distribute_opacity) {
988 TRACE_EVENT0(
"flutter",
"Canvas::saveLayer");
990 return SkipUntilMatchingRestore(total_content_depth);
994 if (!maybe_coverage_limit.has_value()) {
995 return SkipUntilMatchingRestore(total_content_depth);
997 auto coverage_limit = maybe_coverage_limit.value();
999 if (can_distribute_opacity && !backdrop_filter &&
1002 Save(total_content_depth);
1003 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1007 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1008 Rect(), transform_stack_.back().transform,
1013 transform_stack_.back().transform,
1021 if (!maybe_subpass_coverage.has_value()) {
1022 return SkipUntilMatchingRestore(total_content_depth);
1025 auto subpass_coverage = maybe_subpass_coverage.value();
1036 bool did_round_out =
false;
1040 did_round_out =
true;
1044 return SkipUntilMatchingRestore(total_content_depth);
1052 ->GetMaximumRenderPassAttachmentSize());
1055 std::shared_ptr<FilterContents> backdrop_filter_contents;
1056 Point local_position = {0, 0};
1057 if (backdrop_filter) {
1058 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1060 [backdrop_filter = backdrop_filter](
1063 auto filter =
WrapInput(backdrop_filter, input);
1064 filter->SetEffectTransform(effect_transform);
1065 filter->SetRenderingMode(rendering_mode);
1069 auto input_texture = FlipBackdrop(render_passes_,
1070 GetGlobalPassPosition(),
1071 clip_coverage_stack_,
1074 if (!input_texture) {
1079 backdrop_filter_contents = backdrop_filter_proc(
1081 transform_stack_.back().transform.Basis(),
1084 transform_stack_.back().transform.HasTranslation()
1090 Paint paint_copy = paint;
1091 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1092 transform_stack_.back().distributed_opacity = 1.0;
1094 render_passes_.push_back(
1096 CreateRenderTarget(renderer_,
1100 save_layer_state_.push_back(
SaveLayerState{paint_copy, subpass_coverage});
1103 entry.
transform = transform_stack_.back().transform;
1104 entry.
clip_depth = current_depth_ + total_content_depth;
1105 FML_DCHECK(entry.
clip_depth <= transform_stack_.back().clip_depth)
1106 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1107 <<
" after allocating " << total_content_depth;
1108 entry.
clip_height = transform_stack_.back().clip_height;
1111 transform_stack_.emplace_back(entry);
1118 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1120 if (backdrop_filter_contents) {
1123 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1126 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1130 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1135 FML_DCHECK(transform_stack_.size() > 0);
1136 if (transform_stack_.size() == 1) {
1153 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1154 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1155 current_depth_ = transform_stack_.back().clip_depth;
1158 transform_stack_.pop_back();
1162 if (transform_stack_.back().rendering_mode ==
1164 transform_stack_.back().rendering_mode ==
1166 auto lazy_render_pass = std::move(render_passes_.back());
1167 render_passes_.pop_back();
1169 lazy_render_pass.inline_pass_context->GetRenderPass(0);
1172 save_layer_state_.pop_back();
1173 auto global_pass_position = GetGlobalPassPosition();
1175 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1176 save_layer_state.
paint,
1177 lazy_render_pass.inline_pass_context->GetTexture(),
1179 transform_stack_.back().transform
1182 lazy_render_pass.inline_pass_context->EndPass();
1189 Point subpass_texture_position;
1190 if (transform_stack_.back().did_round_out) {
1193 subpass_texture_position =
1198 subpass_texture_position =
1212 ApplyFramebufferBlend(element_entity);
1223 auto input_texture =
1224 FlipBackdrop(render_passes_, GetGlobalPassPosition(),
1225 clip_coverage_stack_, renderer_);
1226 if (!input_texture) {
1236 contents->SetCoverageHint(element_entity.
GetCoverage());
1244 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass
1247 transform_stack_.pop_back();
1255 size_t num_clips = transform_stack_.back().num_clips;
1256 transform_stack_.pop_back();
1258 if (num_clips > 0) {
1265 auto clip_restore = std::make_shared<ClipRestoreContents>();
1266 clip_restore->SetRestoreHeight(GetClipHeight());
1270 if (current_clip_coverage.has_value()) {
1273 current_clip_coverage =
1274 current_clip_coverage->Shift(-GetGlobalPassPosition());
1278 if (clip_coverage.coverage.has_value()) {
1280 clip_coverage.coverage->Shift(GetGlobalPassPosition());
1285 GetClipHeightFloor(),
1286 GetGlobalPassPosition());
1292 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass,
1293 GetGlobalPassPosition()
1303 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1311 const Paint& paint) {
1316 auto text_contents = std::make_shared<TextContents>();
1317 text_contents->SetTextFrame(text_frame);
1320 text_contents->SetColor(paint.
color);
1321 text_contents->SetOffset(position);
1322 text_contents->SetTextProperties(paint.
color,
1342 AddRenderEntityToCurrentPass(entity,
false);
1345 void Canvas::AddRenderEntityWithFiltersToCurrentPass(
Entity& entity,
1349 std::shared_ptr<ColorSourceContents> contents = paint.
CreateContents();
1352 contents->SetGeometry(geometry);
1354 AddRenderEntityToCurrentPass(entity, reuse_depth);
1362 if (needs_color_filter &&
1363 contents->ApplyColorFilter([&](Color
color) -> Color {
1364 if (paint.color_filter) {
1365 color = GetCPUColorFilterProc(paint.color_filter)(color);
1368 color = color.ApplyColorMatrix(kColorInversion);
1372 needs_color_filter =
false;
1376 contents->SetGeometry(geometry);
1382 RectGeometry out_rect(
Rect{});
1384 contents, needs_color_filter ? paint.
color_filter :
nullptr,
1385 needs_color_filter ? paint.
invert_colors :
false, &out_rect);
1387 AddRenderEntityToCurrentPass(entity, reuse_depth);
1391 std::shared_ptr<Contents> contents_copy = std::move(contents);
1395 if (needs_color_filter &&
1397 paint.
color_source->type() != flutter::DlColorSourceType::kImage)) {
1411 std::shared_ptr<FilterContents> filter =
WrapInput(
1415 AddRenderEntityToCurrentPass(entity, reuse_depth);
1420 AddRenderEntityToCurrentPass(entity, reuse_depth);
1423 void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
1428 entity.SetTransform(
1429 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1430 entity.GetTransform());
1431 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
1432 if (entity.GetBlendMode() == BlendMode::kSourceOver &&
1433 entity.GetContents()->IsOpaque(entity.GetTransform())) {
1434 entity.SetBlendMode(BlendMode::kSource);
1440 if (render_passes_.back().IsApplyingClearColor()) {
1441 std::optional<Color> maybe_color = entity.AsBackgroundColor(
1442 render_passes_.back().inline_pass_context->GetTexture()->GetSize());
1443 if (maybe_color.has_value()) {
1444 Color
color = maybe_color.value();
1445 RenderTarget& render_target = render_passes_.back()
1446 .inline_pass_context->GetPassTarget()
1448 ColorAttachment attachment =
1449 render_target.GetColorAttachments().find(0u)->second;
1452 attachment.clear_color = attachment.clear_color.Unpremultiply()
1453 .Blend(
color, entity.GetBlendMode())
1455 render_target.SetColorAttachment(attachment, 0u);
1466 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1467 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1468 entity.SetClipDepth(current_depth_);
1470 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1471 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
1472 ApplyFramebufferBlend(entity);
1483 auto input_texture = FlipBackdrop(render_passes_,
1484 GetGlobalPassPosition(),
1485 clip_coverage_stack_,
1488 if (!input_texture) {
1496 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
1497 entity.GetContents()->SetCoverageHint(Rect::Intersection(
1498 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
1500 FilterInput::Vector inputs = {
1501 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
1502 FilterInput::Make(entity.GetContents())};
1504 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
1505 entity.SetContents(std::move(contents));
1506 entity.SetBlendMode(BlendMode::kSource);
1510 InlinePassContext::RenderPassResult result =
1511 render_passes_.back().inline_pass_context->GetRenderPass(0);
1519 entity.Render(renderer_, *result.pass);
1522 void Canvas::AddClipEntityToCurrentPass(Entity& entity) {
1528 entity.SetTransform(
1529 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
transform);
1541 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1542 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1543 entity.SetClipDepth(transform_stack_.back().clip_depth);
1545 auto current_clip_coverage = clip_coverage_stack_.CurrentClipCoverage();
1546 if (current_clip_coverage.has_value()) {
1549 current_clip_coverage =
1550 current_clip_coverage->Shift(-GetGlobalPassPosition());
1553 auto clip_coverage = entity.GetClipCoverage(current_clip_coverage);
1554 if (clip_coverage.coverage.has_value()) {
1555 clip_coverage.coverage =
1556 clip_coverage.coverage->Shift(GetGlobalPassPosition());
1559 EntityPassClipStack::ClipStateResult clip_state_result =
1560 clip_coverage_stack_.ApplyClipState(
1561 clip_coverage, entity, GetClipHeightFloor(), GetGlobalPassPosition());
1563 if (clip_state_result.clip_did_change) {
1566 clip_coverage_stack_.CurrentClipCoverage(),
1567 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass,
1568 GetGlobalPassPosition());
1571 if (!clip_state_result.should_render) {
1577 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1580 bool Canvas::BlitToOnscreen() {
1581 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
1582 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
1583 auto offscreen_target = render_passes_.back()
1584 .inline_pass_context->GetPassTarget()
1587 if (renderer_.GetContext()
1589 ->SupportsTextureToTextureBlits()) {
1590 auto blit_pass = command_buffer->CreateBlitPass();
1591 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
1592 render_target_.GetRenderTargetTexture());
1593 if (!blit_pass->EncodeCommands(
1594 renderer_.GetContext()->GetResourceAllocator())) {
1598 if (!renderer_.GetContext()
1600 ->Submit({command_buffer})
1605 auto render_pass = command_buffer->CreateRenderPass(render_target_);
1606 render_pass->SetLabel(
"EntityPass Root Render Pass");
1609 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
1610 auto contents = TextureContents::MakeRect(size_rect);
1611 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
1612 contents->SetSourceRect(size_rect);
1613 contents->SetLabel(
"Root pass blit");
1616 entity.SetContents(contents);
1617 entity.SetBlendMode(BlendMode::kSource);
1619 if (!entity.Render(renderer_, *render_pass)) {
1625 if (!render_pass->EncodeCommands()) {
1629 if (!renderer_.GetContext()
1631 ->Submit({command_buffer})
1639 void Canvas::EndReplay() {
1640 FML_DCHECK(render_passes_.size() == 1u);
1641 render_passes_.back().inline_pass_context->GetRenderPass(0);
1642 render_passes_.back().inline_pass_context->EndPass();
1647 if (requires_readback_) {
1651 render_passes_.clear();
1652 renderer_.GetRenderTargetCache()->End();
1653 clip_geometry_.clear();
1656 Initialize(initial_cull_rect_);