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();
555 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint,
565 if (AttemptDrawBlurredRRect(rect, {}, paint)) {
574 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
595 if (AttemptDrawBlurredRRect(rect, rect.
GetSize() * 0.5f, paint)) {
604 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
608 const Size& corner_radii,
609 const Paint& paint) {
610 if (AttemptDrawBlurredRRect(rect, corner_radii, paint)) {
620 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
634 const Paint& paint) {
635 Size half_size(radius, radius);
636 if (AttemptDrawBlurredRRect(
638 {radius, radius}, paint)) {
648 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
651 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
657 clip_geometry_.push_back(std::move(geometry));
659 auto contents = std::make_shared<ClipContents>();
660 contents->SetGeometry(clip_geometry_.back().get());
661 contents->SetClipOperation(clip_op);
667 AddClipEntityToCurrentPass(entity);
669 ++transform_stack_.back().clip_height;
670 ++transform_stack_.back().num_clips;
673 void Canvas::RestoreClip() {
678 auto clip_restore = std::make_shared<ClipRestoreContents>();
679 clip_restore->SetRestoreHeight(GetClipHeight());
682 AddRenderEntityToCurrentPass(entity);
699 AddRenderEntityWithFiltersToCurrentPass(entity, &geom, paint);
711 const auto dest = source.Shift(
offset);
713 DrawImageRect(image, source, dest, paint, std::move(sampler));
726 auto size = image->GetSize();
728 if (size.IsEmpty()) {
733 texture_contents->SetTexture(image);
734 texture_contents->SetSourceRect(source);
735 texture_contents->SetStrictSourceRect(src_rect_constraint ==
737 texture_contents->SetSamplerDescriptor(std::move(sampler));
738 texture_contents->SetOpacity(paint.
color.
alpha);
739 texture_contents->SetDeferApplyingOpacity(paint.
HasColorFilter());
747 AddRenderEntityToCurrentPass(entity);
755 AddRenderEntityToCurrentPass(entity);
758 size_t Canvas::GetClipHeight()
const {
759 return transform_stack_.back().clip_height;
764 const Paint& paint) {
769 paint.
color_source->type() == flutter::DlColorSourceType::kColor) {
778 if (UseColorSourceContents(vertices, paint)) {
779 AddRenderEntityWithFiltersToCurrentPass(entity, vertices.get(), paint);
785 auto contents = std::make_shared<VerticesSimpleBlendContents>();
786 contents->SetBlendMode(blend_mode);
788 contents->SetGeometry(vertices);
790 AddRenderEntityToCurrentPass(entity);
797 paint.
color_source->type() == flutter::DlColorSourceType::kImage) {
798 const flutter::DlImageColorSource* image_color_source =
800 FML_DCHECK(image_color_source &&
801 image_color_source->image()->impeller_texture());
802 auto texture = image_color_source->image()->impeller_texture();
804 image_color_source->horizontal_tile_mode());
807 auto sampler_descriptor =
809 auto effect_transform =
812 auto contents = std::make_shared<VerticesSimpleBlendContents>();
813 contents->SetBlendMode(blend_mode);
815 contents->SetGeometry(vertices);
816 contents->SetEffectTransform(effect_transform);
817 contents->SetTexture(texture);
818 contents->SetTileMode(x_tile_mode, y_tile_mode);
821 AddRenderEntityToCurrentPass(entity);
825 auto src_paint = paint;
828 std::shared_ptr<ColorSourceContents> src_contents =
829 src_paint.CreateContents();
830 src_contents->SetGeometry(vertices.get());
838 auto size = src_contents->GetColorSourceSize();
839 if (size.has_value()) {
842 auto cvg = vertices->GetCoverage(
Matrix{});
843 FML_CHECK(cvg.has_value());
847 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
849 src_contents = src_paint.CreateContents();
852 src_contents->SetGeometry(clip_geometry_.back().get());
854 auto contents = std::make_shared<VerticesSimpleBlendContents>();
855 contents->SetBlendMode(blend_mode);
857 contents->SetGeometry(vertices);
858 contents->SetLazyTextureCoverage(src_coverage);
859 contents->SetLazyTexture(
865 ->RenderToSnapshot(renderer, {},
Rect::Round(src_coverage))
869 AddRenderEntityToCurrentPass(entity);
873 const Paint& paint) {
881 AddRenderEntityToCurrentPass(entity);
887 void Canvas::SetupRenderPass() {
893 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
898 *renderer_.
GetContext()->GetResourceAllocator(),
899 color0.texture->GetSize(),
900 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
901 "ImpellerOnscreen", kDefaultStencilConfig);
913 if (requires_readback_) {
914 auto entity_pass_target =
915 CreateRenderTarget(renderer_,
916 color0.texture->GetSize(),
918 render_passes_.push_back(
919 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
921 auto entity_pass_target = std::make_unique<EntityPassTarget>(
926 render_passes_.push_back(
927 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
931 void Canvas::SkipUntilMatchingRestore(
size_t total_content_depth) {
932 auto entry = CanvasStackEntry{};
933 entry.skipping =
true;
934 entry.clip_depth = current_depth_ + total_content_depth;
935 transform_stack_.push_back(entry);
940 return SkipUntilMatchingRestore(total_content_depth);
944 entry.
transform = transform_stack_.back().transform;
945 entry.clip_depth = current_depth_ + total_content_depth;
946 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
947 FML_DCHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
948 << entry.clip_depth <<
" <=? " << transform_stack_.back().clip_depth
949 <<
" after allocating " << total_content_depth;
950 entry.clip_height = transform_stack_.back().clip_height;
952 transform_stack_.push_back(entry);
963 if (!maybe_current_clip_coverage.has_value()) {
967 auto current_clip_coverage = maybe_current_clip_coverage.value();
971 std::optional<Rect> maybe_coverage_limit =
973 Size(render_passes_.back()
974 .inline_pass_context->GetTexture()
978 if (!maybe_coverage_limit.has_value() || maybe_coverage_limit->IsEmpty()) {
982 return maybe_coverage_limit->Intersection(
987 std::optional<Rect> bounds,
988 const flutter::DlImageFilter* backdrop_filter,
990 uint32_t total_content_depth,
991 bool can_distribute_opacity) {
992 TRACE_EVENT0(
"flutter",
"Canvas::saveLayer");
994 return SkipUntilMatchingRestore(total_content_depth);
998 if (!maybe_coverage_limit.has_value()) {
999 return SkipUntilMatchingRestore(total_content_depth);
1001 auto coverage_limit = maybe_coverage_limit.value();
1003 if (can_distribute_opacity && !backdrop_filter &&
1006 Save(total_content_depth);
1007 transform_stack_.back().distributed_opacity *= paint.
color.
alpha;
1011 std::shared_ptr<FilterContents> filter_contents = paint.
WithImageFilter(
1012 Rect(), transform_stack_.back().transform,
1017 transform_stack_.back().transform,
1025 if (!maybe_subpass_coverage.has_value()) {
1026 return SkipUntilMatchingRestore(total_content_depth);
1029 auto subpass_coverage = maybe_subpass_coverage.value();
1040 bool did_round_out =
false;
1044 did_round_out =
true;
1048 return SkipUntilMatchingRestore(total_content_depth);
1056 ->GetMaximumRenderPassAttachmentSize());
1059 std::shared_ptr<FilterContents> backdrop_filter_contents;
1060 Point local_position = {0, 0};
1061 if (backdrop_filter) {
1062 local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
1064 [backdrop_filter = backdrop_filter](
1067 auto filter =
WrapInput(backdrop_filter, input);
1068 filter->SetEffectTransform(effect_transform);
1069 filter->SetRenderingMode(rendering_mode);
1073 auto input_texture = FlipBackdrop(render_passes_,
1074 GetGlobalPassPosition(),
1075 clip_coverage_stack_,
1078 if (!input_texture) {
1083 backdrop_filter_contents = backdrop_filter_proc(
1085 transform_stack_.back().transform.Basis(),
1088 transform_stack_.back().transform.HasTranslation()
1094 Paint paint_copy = paint;
1095 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
1096 transform_stack_.back().distributed_opacity = 1.0;
1098 render_passes_.push_back(
1100 CreateRenderTarget(renderer_,
1104 save_layer_state_.push_back(
SaveLayerState{paint_copy, subpass_coverage});
1107 entry.
transform = transform_stack_.back().transform;
1108 entry.
clip_depth = current_depth_ + total_content_depth;
1109 FML_DCHECK(entry.
clip_depth <= transform_stack_.back().clip_depth)
1110 << entry.
clip_depth <<
" <=? " << transform_stack_.back().clip_depth
1111 <<
" after allocating " << total_content_depth;
1112 entry.
clip_height = transform_stack_.back().clip_height;
1115 transform_stack_.emplace_back(entry);
1122 clip_coverage_stack_.
PushSubpass(subpass_coverage, GetClipHeight());
1124 if (backdrop_filter_contents) {
1127 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
1130 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
1134 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1139 FML_DCHECK(transform_stack_.size() > 0);
1140 if (transform_stack_.size() == 1) {
1157 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1158 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1159 current_depth_ = transform_stack_.back().clip_depth;
1162 transform_stack_.pop_back();
1166 if (transform_stack_.back().rendering_mode ==
1168 transform_stack_.back().rendering_mode ==
1170 auto lazy_render_pass = std::move(render_passes_.back());
1171 render_passes_.pop_back();
1173 lazy_render_pass.inline_pass_context->GetRenderPass(0);
1176 save_layer_state_.pop_back();
1177 auto global_pass_position = GetGlobalPassPosition();
1179 std::shared_ptr<Contents> contents = CreateContentsForSubpassTarget(
1180 save_layer_state.
paint,
1181 lazy_render_pass.inline_pass_context->GetTexture(),
1183 transform_stack_.back().transform
1186 lazy_render_pass.inline_pass_context->EndPass();
1193 Point subpass_texture_position;
1194 if (transform_stack_.back().did_round_out) {
1197 subpass_texture_position =
1202 subpass_texture_position =
1216 ApplyFramebufferBlend(element_entity);
1227 auto input_texture =
1228 FlipBackdrop(render_passes_, GetGlobalPassPosition(),
1229 clip_coverage_stack_, renderer_);
1230 if (!input_texture) {
1240 contents->SetCoverageHint(element_entity.
GetCoverage());
1248 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass
1251 transform_stack_.pop_back();
1259 size_t num_clips = transform_stack_.back().num_clips;
1260 transform_stack_.pop_back();
1262 if (num_clips > 0) {
1269 auto clip_restore = std::make_shared<ClipRestoreContents>();
1270 clip_restore->SetRestoreHeight(GetClipHeight());
1274 if (current_clip_coverage.has_value()) {
1277 current_clip_coverage =
1278 current_clip_coverage->Shift(-GetGlobalPassPosition());
1282 if (clip_coverage.coverage.has_value()) {
1284 clip_coverage.coverage->Shift(GetGlobalPassPosition());
1289 GetClipHeightFloor(),
1290 GetGlobalPassPosition());
1296 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass,
1297 GetGlobalPassPosition()
1307 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1315 const Paint& paint) {
1320 auto text_contents = std::make_shared<TextContents>();
1321 text_contents->SetTextFrame(text_frame);
1324 text_contents->SetColor(paint.
color);
1325 text_contents->SetOffset(position);
1326 text_contents->SetTextProperties(paint.
color,
1346 AddRenderEntityToCurrentPass(entity,
false);
1349 void Canvas::AddRenderEntityWithFiltersToCurrentPass(
Entity& entity,
1353 std::shared_ptr<ColorSourceContents> contents = paint.
CreateContents();
1356 contents->SetGeometry(geometry);
1358 AddRenderEntityToCurrentPass(entity, reuse_depth);
1366 if (needs_color_filter &&
1367 contents->ApplyColorFilter([&](Color
color) -> Color {
1368 if (paint.color_filter) {
1369 color = GetCPUColorFilterProc(paint.color_filter)(color);
1372 color = color.ApplyColorMatrix(kColorInversion);
1376 needs_color_filter =
false;
1380 contents->SetGeometry(geometry);
1386 RectGeometry out_rect(
Rect{});
1388 contents, needs_color_filter ? paint.
color_filter :
nullptr,
1389 needs_color_filter ? paint.
invert_colors :
false, &out_rect);
1391 AddRenderEntityToCurrentPass(entity, reuse_depth);
1395 std::shared_ptr<Contents> contents_copy = std::move(contents);
1399 if (needs_color_filter &&
1401 paint.
color_source->type() != flutter::DlColorSourceType::kImage)) {
1415 std::shared_ptr<FilterContents> filter =
WrapInput(
1419 AddRenderEntityToCurrentPass(entity, reuse_depth);
1424 AddRenderEntityToCurrentPass(entity, reuse_depth);
1427 void Canvas::AddRenderEntityToCurrentPass(Entity& entity,
bool reuse_depth) {
1432 entity.SetTransform(
1433 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
1434 entity.GetTransform());
1435 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
1436 if (entity.GetBlendMode() == BlendMode::kSourceOver &&
1437 entity.GetContents()->IsOpaque(entity.GetTransform())) {
1438 entity.SetBlendMode(BlendMode::kSource);
1444 if (render_passes_.back().IsApplyingClearColor()) {
1445 std::optional<Color> maybe_color = entity.AsBackgroundColor(
1446 render_passes_.back().inline_pass_context->GetTexture()->GetSize());
1447 if (maybe_color.has_value()) {
1448 Color
color = maybe_color.value();
1449 RenderTarget& render_target = render_passes_.back()
1450 .inline_pass_context->GetPassTarget()
1452 ColorAttachment attachment =
1453 render_target.GetColorAttachments().find(0u)->second;
1456 attachment.clear_color = attachment.clear_color.Unpremultiply()
1457 .Blend(
color, entity.GetBlendMode())
1459 render_target.SetColorAttachment(attachment, 0u);
1470 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1471 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1472 entity.SetClipDepth(current_depth_);
1474 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
1475 if (renderer_.GetDeviceCapabilities().SupportsFramebufferFetch()) {
1476 ApplyFramebufferBlend(entity);
1487 auto input_texture = FlipBackdrop(render_passes_,
1488 GetGlobalPassPosition(),
1489 clip_coverage_stack_,
1492 if (!input_texture) {
1500 auto element_coverage_hint = entity.GetContents()->GetCoverageHint();
1501 entity.GetContents()->SetCoverageHint(Rect::Intersection(
1502 element_coverage_hint, clip_coverage_stack_.CurrentClipCoverage()));
1504 FilterInput::Vector inputs = {
1505 FilterInput::Make(input_texture, entity.GetTransform().Invert()),
1506 FilterInput::Make(entity.GetContents())};
1508 ColorFilterContents::MakeBlend(entity.GetBlendMode(), inputs);
1509 entity.SetContents(std::move(contents));
1510 entity.SetBlendMode(BlendMode::kSource);
1514 InlinePassContext::RenderPassResult result =
1515 render_passes_.back().inline_pass_context->GetRenderPass(0);
1523 entity.Render(renderer_, *result.pass);
1526 void Canvas::AddClipEntityToCurrentPass(Entity& entity) {
1532 entity.SetTransform(
1533 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) *
transform);
1545 FML_DCHECK(current_depth_ <= transform_stack_.back().clip_depth)
1546 << current_depth_ <<
" <=? " << transform_stack_.back().clip_depth;
1547 entity.SetClipDepth(transform_stack_.back().clip_depth);
1549 auto current_clip_coverage = clip_coverage_stack_.CurrentClipCoverage();
1550 if (current_clip_coverage.has_value()) {
1553 current_clip_coverage =
1554 current_clip_coverage->Shift(-GetGlobalPassPosition());
1557 auto clip_coverage = entity.GetClipCoverage(current_clip_coverage);
1558 if (clip_coverage.coverage.has_value()) {
1559 clip_coverage.coverage =
1560 clip_coverage.coverage->Shift(GetGlobalPassPosition());
1563 EntityPassClipStack::ClipStateResult clip_state_result =
1564 clip_coverage_stack_.ApplyClipState(
1565 clip_coverage, entity, GetClipHeightFloor(), GetGlobalPassPosition());
1567 if (clip_state_result.clip_did_change) {
1570 clip_coverage_stack_.CurrentClipCoverage(),
1571 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass,
1572 GetGlobalPassPosition());
1575 if (!clip_state_result.should_render) {
1581 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
1584 bool Canvas::BlitToOnscreen() {
1585 auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
1586 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
1587 auto offscreen_target = render_passes_.back()
1588 .inline_pass_context->GetPassTarget()
1591 if (renderer_.GetContext()
1593 ->SupportsTextureToTextureBlits()) {
1594 auto blit_pass = command_buffer->CreateBlitPass();
1595 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
1596 render_target_.GetRenderTargetTexture());
1597 if (!blit_pass->EncodeCommands(
1598 renderer_.GetContext()->GetResourceAllocator())) {
1602 if (!renderer_.GetContext()
1604 ->Submit({command_buffer})
1609 auto render_pass = command_buffer->CreateRenderPass(render_target_);
1610 render_pass->SetLabel(
"EntityPass Root Render Pass");
1613 auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
1614 auto contents = TextureContents::MakeRect(size_rect);
1615 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
1616 contents->SetSourceRect(size_rect);
1617 contents->SetLabel(
"Root pass blit");
1620 entity.SetContents(contents);
1621 entity.SetBlendMode(BlendMode::kSource);
1623 if (!entity.Render(renderer_, *render_pass)) {
1629 if (!render_pass->EncodeCommands()) {
1633 if (!renderer_.GetContext()
1635 ->Submit({command_buffer})
1643 void Canvas::EndReplay() {
1644 FML_DCHECK(render_passes_.size() == 1u);
1645 render_passes_.back().inline_pass_context->GetRenderPass(0);
1646 render_passes_.back().inline_pass_context->EndPass();
1651 if (requires_readback_) {
1655 render_passes_.clear();
1656 renderer_.GetRenderTargetCache()->End();
1657 clip_geometry_.clear();
1660 Initialize(initial_cull_rect_);