7 #include "flutter/fml/trace_event.h"
17 - (void)flutterPrepareForPresent:(nonnull
id<MTLCommandBuffer>)commandBuffer;
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic ignored "-Wunguarded-availability-new"
26 const std::shared_ptr<Context>& context,
27 CAMetalLayer* layer) {
28 TRACE_EVENT0(
"impeller",
"SurfaceMTL::WrapCurrentMetalLayerDrawable");
30 if (context ==
nullptr || !context->IsValid() || layer == nil) {
34 id<CAMetalDrawable> current_drawable = nil;
36 TRACE_EVENT0(
"impeller",
"WaitForNextDrawable");
37 current_drawable = [layer nextDrawable];
40 if (!current_drawable) {
44 return current_drawable;
49 id<MTLTexture> texture,
51 std::optional<IRect> clip_rect) {
57 if (!clip_rect.has_value()) {
61 root_size =
ISize(clip_rect->GetWidth(), clip_rect->GetHeight());
63 root_size = {
static_cast<ISize::Type>(texture.width),
69 resolve_tex_desc.
size = root_size;
70 resolve_tex_desc.
usage =
81 std::shared_ptr<Texture> resolve_tex;
93 resolve_tex->SetLabel(
"ImpellerOnscreenResolve");
99 msaa_tex_desc.
format = resolve_tex->GetTextureDescriptor().format;
100 msaa_tex_desc.
size = resolve_tex->GetSize();
108 msaa_tex->SetLabel(
"ImpellerOnscreenColorMSAA");
117 auto render_target_desc = std::make_optional<RenderTarget>();
118 render_target_desc->SetColorAttachment(color0, 0u);
120 return render_target_desc;
124 const std::shared_ptr<Context>& context,
125 id<CAMetalDrawable> drawable,
126 std::optional<IRect> clip_rect) {
132 const std::shared_ptr<Context>& context,
133 id<MTLTexture> texture,
134 std::optional<IRect> clip_rect,
135 id<CAMetalDrawable> drawable) {
136 bool partial_repaint_blit_required = ShouldPerformPartialRepaint(clip_rect);
143 partial_repaint_blit_required, clip_rect);
144 if (!render_target) {
151 auto source_texture = partial_repaint_blit_required
152 ? render_target->GetRenderTargetTexture()
157 std::shared_ptr<Texture> destination_texture;
158 if (partial_repaint_blit_required) {
162 auto destination_descriptor =
163 render_target->GetRenderTargetTexture()->GetTextureDescriptor();
164 destination_descriptor.size = {
static_cast<ISize::Type>(texture.width),
170 destination_texture = render_target->GetRenderTargetTexture();
173 return std::unique_ptr<SurfaceMTL>(
new SurfaceMTL(
176 render_target->GetRenderTargetTexture(),
180 partial_repaint_blit_required,
185 SurfaceMTL::SurfaceMTL(
const std::weak_ptr<Context>& context,
187 std::shared_ptr<Texture> resolve_texture,
188 id<CAMetalDrawable> drawable,
189 std::shared_ptr<Texture> source_texture,
190 std::shared_ptr<Texture> destination_texture,
192 std::optional<IRect> clip_rect)
195 resolve_texture_(
std::move(resolve_texture)),
197 source_texture_(
std::move(source_texture)),
198 destination_texture_(
std::move(destination_texture)),
199 requires_blit_(requires_blit),
200 clip_rect_(clip_rect) {}
205 bool SurfaceMTL::ShouldPerformPartialRepaint(std::optional<IRect> damage_rect) {
209 if (!damage_rect.has_value()) {
214 if (damage_rect->IsEmpty()) {
227 auto context = context_.lock();
232 #ifdef IMPELLER_DEBUG
233 context->GetResourceAllocator()->DebugTraceMemoryStatistics();
234 #endif // IMPELLER_DEBUG
236 if (requires_blit_) {
237 if (!(source_texture_ && destination_texture_)) {
241 auto blit_command_buffer = context->CreateCommandBuffer();
242 if (!blit_command_buffer) {
245 auto blit_pass = blit_command_buffer->CreateBlitPass();
246 if (!clip_rect_.has_value()) {
250 blit_pass->AddCopy(source_texture_, destination_texture_, std::nullopt,
251 clip_rect_->GetOrigin());
252 blit_pass->EncodeCommands(context->GetResourceAllocator());
253 if (!context->GetCommandQueue()->Submit({blit_command_buffer}).ok()) {
257 #ifdef IMPELLER_DEBUG
259 #endif // IMPELLER_DEBUG
262 id<MTLCommandBuffer> command_buffer =
266 id<CAMetalDrawable> metal_drawable =
267 reinterpret_cast<id<CAMetalDrawable>
>(drawable_);
270 flutterPrepareForPresent:command_buffer];
277 #if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
278 constexpr
bool alwaysWaitForScheduling =
true;
280 constexpr
bool alwaysWaitForScheduling =
false;
281 #endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
286 if ([[NSThread currentThread] isMainThread] ||
287 [[MTLCaptureManager sharedCaptureManager] isCapturing] ||
288 alwaysWaitForScheduling) {
289 TRACE_EVENT0(
"flutter",
"waitUntilScheduled");
290 [command_buffer commit];
291 #if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
292 [command_buffer waitUntilCompleted];
294 [command_buffer waitUntilScheduled];
295 #endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
300 id<CAMetalDrawable>
drawable = drawable_;
301 [command_buffer addScheduledHandler:^(id<MTLCommandBuffer> buffer) {
304 [command_buffer commit];
310 #pragma GCC diagnostic pop