6 #include "fml/logging.h"
23 Point global_pass_position) {
27 if (clip_coverage.has_value()) {
28 clip_coverage = clip_coverage->
Shift(-global_pass_position);
31 scissor = scissor.Intersection(
IRect::MakeSize(pass.GetRenderTargetSize()))
34 pass.SetScissor(scissor);
37 static void ApplyFramebufferBlend(Entity& entity) {
38 auto src_contents = entity.GetContents();
39 auto contents = std::make_shared<FramebufferBlendContents>();
40 contents->SetChildContents(src_contents);
41 contents->SetBlendMode(entity.GetBlendMode());
42 entity.SetContents(std::move(contents));
59 const Color& clear_color) {
60 const std::shared_ptr<Context>& context = renderer.
GetContext();
74 if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
86 .clear_color = clear_color},
98 .clear_color = clear_color,
104 return std::make_unique<EntityPassTarget>(
111 bool requires_readback)
114 render_target_(render_target),
115 requires_readback_(requires_readback),
117 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
123 bool requires_readback,
127 render_target_(render_target),
128 requires_readback_(requires_readback),
130 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
136 bool requires_readback,
140 render_target_(render_target),
141 requires_readback_(requires_readback),
143 Rect::MakeSize(render_target.GetRenderTargetSize()))) {
147 void ExperimentalCanvas::SetupRenderPass() {
153 if (!stencil_attachment.has_value() || !depth_attachment.has_value()) {
158 *renderer_.
GetContext()->GetResourceAllocator(),
159 color0.texture->GetSize(),
160 renderer_.
GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
173 if (requires_readback_) {
176 color0.texture->GetSize(),
180 render_passes_.push_back(
181 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
183 auto entity_pass_target = std::make_unique<EntityPassTarget>(
188 render_passes_.push_back(
189 LazyRenderingConfig(renderer_, std::move(entity_pass_target)));
201 <<
" after allocating " << total_content_depth;
209 std::optional<Rect> bounds,
210 const std::shared_ptr<ImageFilter>& backdrop_filter,
212 uint32_t total_content_depth,
213 bool can_distribute_opacity) {
216 if (!bounds.has_value()) {
222 if (bounds->IsEmpty()) {
223 Save(total_content_depth);
230 GetGlobalPassPosition(),
231 Size(render_passes_.back().inline_pass_context->GetTexture()->GetSize()));
234 if (backdrop_filter) {
236 Save(total_content_depth);
240 if (!maybe_clip_coverage.has_value()) {
241 Save(total_content_depth);
244 auto clip_coverage = maybe_clip_coverage.value();
245 if (clip_coverage.IsEmpty() ||
247 Save(total_content_depth);
252 if (can_distribute_opacity && !backdrop_filter &&
254 Save(total_content_depth);
260 std::shared_ptr<FilterContents> backdrop_filter_contents;
261 Point local_position = {0, 0};
262 if (backdrop_filter) {
264 if (current_clip_coverage.has_value()) {
266 current_clip_coverage->GetOrigin() - GetGlobalPassPosition();
269 [backdrop_filter = backdrop_filter->Clone()](
272 auto filter = backdrop_filter->WrapInput(input);
273 filter->SetEffectTransform(effect_transform);
274 filter->SetRenderingMode(rendering_mode);
278 auto rendering_config = std::move(render_passes_.back());
279 render_passes_.pop_back();
287 rendering_config.inline_pass_context->GetRenderPass(0);
290 rendering_config.inline_pass_context->GetTexture()->GetSize();
292 std::shared_ptr<Texture> input_texture =
293 rendering_config.entity_pass_target->Flip(
294 *renderer_.
GetContext()->GetResourceAllocator());
296 backdrop_filter_contents = backdrop_filter_proc(
308 rendering_config.inline_pass_context->EndPass();
313 renderer_, std::move(rendering_config.entity_pass_target)));
323 msaa_backdrop_contents->SetStencilEnabled(
false);
324 msaa_backdrop_contents->SetLabel(
"MSAA backdrop");
325 msaa_backdrop_contents->SetSourceRect(size_rect);
326 msaa_backdrop_contents->SetTexture(
327 rendering_config.inline_pass_context->GetTexture());
329 Entity msaa_backdrop_entity;
330 msaa_backdrop_entity.
SetContents(std::move(msaa_backdrop_contents));
332 msaa_backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
333 if (!msaa_backdrop_entity.
Render(renderer_,
334 *render_passes_.back()
335 .inline_pass_context->GetRenderPass(0)
337 VALIDATION_LOG <<
"Failed to render MSAA backdrop filter entity.";
344 for (
const auto& replay : replay_entities) {
347 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass,
348 GetGlobalPassPosition());
349 if (!replay.entity.Render(renderer_,
350 *render_passes_.back()
351 .inline_pass_context->GetRenderPass(0)
366 if (backdrop_filter_contents) {
382 save_layer_state_.push_back(
SaveLayerState{paint_copy, subpass_coverage});
390 <<
" after allocating " << total_content_depth;
402 if (backdrop_filter_contents) {
405 backdrop_entity.
SetContents(std::move(backdrop_filter_contents));
408 backdrop_entity.
SetClipDepth(std::numeric_limits<uint32_t>::max());
412 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
443 auto lazy_render_pass = std::move(render_passes_.back());
444 render_passes_.pop_back();
446 lazy_render_pass.inline_pass_context->GetRenderPass(0);
449 save_layer_state_.pop_back();
451 std::shared_ptr<Contents> contents =
454 lazy_render_pass.inline_pass_context->GetTexture(),
457 lazy_render_pass.inline_pass_context->EndPass();
471 Point subpass_texture_position =
484 ApplyFramebufferBlend(element_entity);
486 VALIDATION_LOG <<
"Emulated advanced blends are currently unsupported.";
493 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass
514 auto clip_restore = std::make_shared<ClipRestoreContents>();
519 if (current_clip_coverage.has_value()) {
522 current_clip_coverage =
523 current_clip_coverage->Shift(-GetGlobalPassPosition());
527 if (clip_coverage.coverage.has_value()) {
529 clip_coverage.coverage->Shift(GetGlobalPassPosition());
534 GetClipHeightFloor(),
535 GetGlobalPassPosition());
541 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass,
542 GetGlobalPassPosition()
552 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
559 const std::shared_ptr<TextFrame>& text_frame,
566 auto text_contents = std::make_shared<TextContents>();
567 text_contents->SetTextFrame(text_frame);
568 text_contents->SetForceTextColor(
paint.mask_blur_descriptor.has_value());
570 text_contents->SetColor(
paint.color);
571 text_contents->SetOffset(position);
572 text_contents->SetTextProperties(
paint.color,
592 AddRenderEntityToCurrentPass(std::move(entity),
false);
595 void ExperimentalCanvas::AddRenderEntityToCurrentPass(
Entity entity,
614 ApplyFramebufferBlend(entity);
616 VALIDATION_LOG <<
"Emulated advanced blends are currently unsupported.";
621 InlinePassContext::RenderPassResult result =
622 render_passes_.back().inline_pass_context->GetRenderPass(0);
630 entity.
Render(renderer_, *result.pass);
633 void ExperimentalCanvas::AddClipEntityToCurrentPass(Entity entity) {
652 if (current_clip_coverage.has_value()) {
655 current_clip_coverage =
656 current_clip_coverage->Shift(-GetGlobalPassPosition());
659 auto clip_coverage = entity.GetClipCoverage(current_clip_coverage);
660 if (clip_coverage.coverage.has_value()) {
661 clip_coverage.coverage =
662 clip_coverage.coverage->Shift(GetGlobalPassPosition());
665 EntityPassClipStack::ClipStateResult clip_state_result =
667 clip_coverage, entity, GetClipHeightFloor(), GetGlobalPassPosition());
669 if (clip_state_result.clip_did_change) {
673 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass,
674 GetGlobalPassPosition());
677 if (!clip_state_result.should_render) {
683 *render_passes_.back().inline_pass_context->GetRenderPass(0).pass);
686 bool ExperimentalCanvas::BlitToOnscreen() {
687 auto command_buffer = renderer_.
GetContext()->CreateCommandBuffer();
688 command_buffer->SetLabel(
"EntityPass Root Command Buffer");
689 auto offscreen_target = render_passes_.back()
690 .inline_pass_context->GetPassTarget()
695 ->SupportsTextureToTextureBlits()) {
696 auto blit_pass = command_buffer->CreateBlitPass();
697 blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
699 if (!blit_pass->EncodeCommands(
700 renderer_.
GetContext()->GetResourceAllocator())) {
706 ->Submit({command_buffer})
711 auto render_pass = command_buffer->CreateRenderPass(render_target_);
712 render_pass->SetLabel(
"EntityPass Root Render Pass");
715 auto size_rect =
Rect::MakeSize(offscreen_target.GetRenderTargetSize());
717 contents->SetTexture(offscreen_target.GetRenderTargetTexture());
718 contents->SetSourceRect(size_rect);
719 contents->SetLabel(
"Root pass blit");
722 entity.SetContents(contents);
725 if (!entity.Render(renderer_, *render_pass)) {
731 if (!render_pass->EncodeCommands()) {
737 ->Submit({command_buffer})
746 FML_DCHECK(render_passes_.size() == 1u);
747 render_passes_.back().inline_pass_context->EndPass();
752 if (requires_readback_) {
756 render_passes_.clear();