Flutter iOS Embedder
ios_surface_metal_skia.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #if !SLIMPELLER
6 
8 
9 #include "flutter/shell/gpu/gpu_surface_metal_delegate.h"
10 #include "flutter/shell/gpu/gpu_surface_metal_skia.h"
12 
14 
15 @protocol FlutterMetalDrawable <MTLDrawable>
16 - (void)flutterPrepareForPresent:(nonnull id<MTLCommandBuffer>)commandBuffer;
17 @end
18 
19 namespace flutter {
20 
21 static IOSContextMetalSkia* CastToMetalContext(const std::shared_ptr<IOSContext>& context)
22  __attribute__((cf_audited_transfer)) {
23  return (IOSContextMetalSkia*)context.get();
24 }
25 
26 IOSSurfaceMetalSkia::IOSSurfaceMetalSkia(const fml::scoped_nsobject<CAMetalLayer>& layer,
27  std::shared_ptr<IOSContext> context)
28  : IOSSurface(std::move(context)),
29  GPUSurfaceMetalDelegate(MTLRenderTargetType::kCAMetalLayer),
30  layer_(layer) {
31  is_valid_ = layer_;
32  auto metal_context = CastToMetalContext(GetContext());
33  auto darwin_context = metal_context->GetDarwinContext().get();
34  command_queue_ = darwin_context.commandQueue;
35  device_ = darwin_context.device;
36 }
37 
38 // |IOSSurface|
40 
41 // |IOSSurface|
42 bool IOSSurfaceMetalSkia::IsValid() const {
43  return is_valid_;
44 }
45 
46 // |IOSSurface|
47 void IOSSurfaceMetalSkia::UpdateStorageSizeIfNecessary() {
48  // Nothing to do.
49 }
50 
51 // |IOSSurface|
52 std::unique_ptr<Surface> IOSSurfaceMetalSkia::CreateGPUSurface(GrDirectContext* context) {
53  FML_DCHECK(context);
54  return std::make_unique<GPUSurfaceMetalSkia>(this, // delegate
55  sk_ref_sp(context) // context
56  );
57 }
58 
59 // |GPUSurfaceMetalDelegate|
60 GPUCAMetalLayerHandle IOSSurfaceMetalSkia::GetCAMetalLayer(const SkISize& frame_info) const {
61  CAMetalLayer* layer = layer_.get();
62  layer.device = device_;
63 
64  layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
65  // Flutter needs to read from the color attachment in cases where there are effects such as
66  // backdrop filters. Flutter plugins that create platform views may also read from the layer.
67  layer.framebufferOnly = NO;
68 
69  const auto drawable_size = CGSizeMake(frame_info.width(), frame_info.height());
70  if (!CGSizeEqualToSize(drawable_size, layer.drawableSize)) {
71  layer.drawableSize = drawable_size;
72  }
73 
74  // When there are platform views in the scene, the drawable needs to be presented in the same
75  // transaction as the one created for platform views. When the drawable are being presented from
76  // the raster thread, there is no such transaction.
77  layer.presentsWithTransaction = [[NSThread currentThread] isMainThread];
78 
79  return (__bridge GPUCAMetalLayerHandle)layer;
80 }
81 
82 // |GPUSurfaceMetalDelegate|
83 bool IOSSurfaceMetalSkia::PreparePresent(GrMTLHandle drawable) const {
84  id<MTLCommandBuffer> command_buffer = [command_queue_ commandBuffer];
85  id<CAMetalDrawable> metal_drawable = (__bridge id<CAMetalDrawable>)drawable;
86  if ([metal_drawable conformsToProtocol:@protocol(FlutterMetalDrawable)]) {
87  [(id<FlutterMetalDrawable>)metal_drawable flutterPrepareForPresent:command_buffer];
88  }
89  [command_buffer commit];
90  [command_buffer waitUntilScheduled];
91  return true;
92 }
93 
94 // |GPUSurfaceMetalDelegate|
95 bool IOSSurfaceMetalSkia::PresentDrawable(GrMTLHandle drawable) const {
96  if (drawable == nullptr) {
97  FML_DLOG(ERROR) << "Could not acquire next Metal drawable from the SkSurface.";
98  return false;
99  }
100 
101  id<CAMetalDrawable> metal_drawable = (__bridge id<CAMetalDrawable>)drawable;
102  [metal_drawable present];
103  return true;
104 }
105 
106 // |GPUSurfaceMetalDelegate|
107 GPUMTLTextureInfo IOSSurfaceMetalSkia::GetMTLTexture(const SkISize& frame_info) const {
108  FML_CHECK(false) << "render to texture not supported on ios";
109  return {.texture_id = -1, .texture = nullptr};
110 }
111 
112 // |GPUSurfaceMetalDelegate|
113 bool IOSSurfaceMetalSkia::PresentTexture(GPUMTLTextureInfo texture) const {
114  FML_CHECK(false) << "render to texture not supported on ios";
115  return false;
116 }
117 
118 // |GPUSurfaceMetalDelegate|
119 bool IOSSurfaceMetalSkia::AllowsDrawingWhenGpuDisabled() const {
120  return false;
121 }
122 
123 } // namespace flutter
124 
125 #endif // !SLIMPELLER
ios_surface_metal_skia.h
flutter::IOSSurfaceMetalSkia::~IOSSurfaceMetalSkia
~IOSSurfaceMetalSkia()
flutter::IOSSurface
Definition: ios_surface.h:21
FlutterMetalDrawable-p
Definition: FlutterMetalLayer.h:33
ios_context_metal_skia.h
flutter::IOSContextMetalSkia
Definition: ios_context_metal_skia.h:21
flutter
Definition: accessibility_bridge.h:28
flutter::CastToMetalContext
static IOSContextMetalSkia * CastToMetalContext(const std::shared_ptr< IOSContext > &context) __attribute__((cf_audited_transfer))
Definition: ios_surface_metal_skia.mm:21
flutter::IOSSurfaceMetalSkia::IOSSurfaceMetalSkia
IOSSurfaceMetalSkia(const fml::scoped_nsobject< CAMetalLayer > &layer, std::shared_ptr< IOSContext > context)
Definition: ios_surface_metal_skia.mm:26
flutter::IOSSurface::GetContext
std::shared_ptr< IOSContext > GetContext() const
Definition: ios_surface.mm:62
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13