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 if (requires_blit_) {
233 if (!(source_texture_ && destination_texture_)) {
237 auto blit_command_buffer = context->CreateCommandBuffer();
238 if (!blit_command_buffer) {
241 auto blit_pass = blit_command_buffer->CreateBlitPass();
242 if (!clip_rect_.has_value()) {
246 blit_pass->AddCopy(source_texture_, destination_texture_, std::nullopt,
247 clip_rect_->GetOrigin());
248 blit_pass->EncodeCommands(context->GetResourceAllocator());
249 if (!context->GetCommandQueue()->Submit({blit_command_buffer}).ok()) {
253 #ifdef IMPELLER_DEBUG
255 #endif // IMPELLER_DEBUG
258 id<MTLCommandBuffer> command_buffer =
262 id<CAMetalDrawable> metal_drawable =
263 reinterpret_cast<id<CAMetalDrawable>
>(drawable_);
266 flutterPrepareForPresent:command_buffer];
272 if ([[NSThread currentThread] isMainThread] ||
273 [[MTLCaptureManager sharedCaptureManager] isCapturing]) {
274 TRACE_EVENT0(
"flutter",
"waitUntilScheduled");
275 [command_buffer commit];
276 [command_buffer waitUntilScheduled];
281 id<CAMetalDrawable>
drawable = drawable_;
282 [command_buffer addScheduledHandler:^(id<MTLCommandBuffer> buffer) {
285 [command_buffer commit];
291 #pragma GCC diagnostic pop