diff --git a/impeller/renderer/backend/metal/surface_mtl.h b/impeller/renderer/backend/metal/surface_mtl.h index c5dd5a61eeff6..bff5072f8fb8b 100644 --- a/impeller/renderer/backend/metal/surface_mtl.h +++ b/impeller/renderer/backend/metal/surface_mtl.h @@ -65,6 +65,9 @@ class SurfaceMTL final : public Surface { present_with_transaction_ = present_with_transaction; } + /// @brief Perform the final blit and trigger end of frame workloads. + bool PreparePresent(); + // |Surface| bool Present() const override; @@ -82,6 +85,7 @@ class SurfaceMTL final : public Surface { std::optional clip_rect_; bool frame_boundary_ = false; bool present_with_transaction_ = false; + bool prepared_ = false; static bool ShouldPerformPartialRepaint(std::optional damage_rect); diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index c94ad6cd4c0da..caa6804c8a42a 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -222,8 +222,7 @@ - (void)flutterPrepareForPresent:(nonnull id)commandBuffer; return IRect::MakeSize(resolve_texture_->GetSize()); } -// |Surface| -bool SurfaceMTL::Present() const { +bool SurfaceMTL::PreparePresent() { auto context = context_.lock(); if (!context) { return false; @@ -260,6 +259,17 @@ - (void)flutterPrepareForPresent:(nonnull id)commandBuffer; #ifdef IMPELLER_DEBUG ContextMTL::Cast(context.get())->GetGPUTracer()->MarkFrameEnd(); #endif // IMPELLER_DEBUG + prepared_ = true; + return true; +} + +// |Surface| +bool SurfaceMTL::Present() const { + FML_CHECK(prepared_); + auto context = context_.lock(); + if (!context) { + return false; + } if (drawable_) { id command_buffer = diff --git a/shell/gpu/gpu_surface_metal_impeller.mm b/shell/gpu/gpu_surface_metal_impeller.mm index 5041fc4092c11..f9cb5dd30b3e2 100644 --- a/shell/gpu/gpu_surface_metal_impeller.mm +++ b/shell/gpu/gpu_surface_metal_impeller.mm @@ -157,6 +157,9 @@ surface->PresentWithTransaction(surface_frame.submit_info().present_with_transaction); if (clip_rect && clip_rect->IsEmpty()) { + if (!surface->PreparePresent()) { + return false; + } surface_frame.set_user_data(std::move(surface)); return true; } @@ -167,7 +170,6 @@ const impeller::RenderTarget& render_target = surface->GetTargetRenderPassDescriptor(); surface->SetFrameBoundary(surface_frame.submit_info().frame_boundary); - surface_frame.set_user_data(std::move(surface)); #if EXPERIMENTAL_CANVAS impeller::TextFrameDispatcher collector(aiks_context->GetContentContext(), impeller::Matrix()); @@ -181,13 +183,25 @@ impeller_dispatcher.FinishRecording(); aiks_context->GetContentContext().GetTransientsBuffer().Reset(); aiks_context->GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames(); + + if (!surface->PreparePresent()) { + return false; + } + surface_frame.set_user_data(std::move(surface)); return true; #else impeller::DlDispatcher impeller_dispatcher(cull_rect); display_list->Dispatch(impeller_dispatcher, sk_cull_rect); auto picture = impeller_dispatcher.EndRecordingAsPicture(); const bool reset_host_buffer = surface_frame.submit_info().frame_boundary; - return aiks_context->Render(picture, render_target, reset_host_buffer); + + auto result = aiks_context->Render(picture, render_target, reset_host_buffer); + + if (!surface->PreparePresent()) { + return false; + } + surface_frame.set_user_data(std::move(surface)); + return result; #endif }); @@ -278,6 +292,9 @@ surface->PresentWithTransaction(surface_frame.submit_info().present_with_transaction); if (clip_rect && clip_rect->IsEmpty()) { + if (!surface->PreparePresent()) { + return false; + } return surface->Present(); } @@ -296,6 +313,9 @@ impeller_dispatcher.FinishRecording(); aiks_context->GetContentContext().GetTransientsBuffer().Reset(); aiks_context->GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames(); + if (!surface->PreparePresent()) { + return false; + } bool render_result = true; #else impeller::DlDispatcher impeller_dispatcher(cull_rect); @@ -310,8 +330,7 @@ FML_LOG(ERROR) << "Failed to render Impeller frame"; return false; } - - return true; + return surface->PreparePresent(); }); SurfaceFrame::SubmitCallback submit_callback =