Flutter macOS Embedder
FlutterRenderer.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 
6 
11 #include "flutter/shell/platform/embedder/embedder.h"
12 
13 #pragma mark - Static callbacks that require the engine.
14 
15 static FlutterMetalTexture OnGetNextDrawable(void* user_data, const FlutterFrameInfo* frameInfo) {
16  NSCAssert(NO, @"The renderer config should not be used to get the next drawable.");
17  return FlutterMetalTexture{};
18 }
19 
20 static bool OnPresentDrawable(void* user_data, const FlutterMetalTexture* texture) {
21  NSCAssert(NO, @"The renderer config should not be used to present drawable.");
22  return false;
23 }
24 
26  int64_t textureIdentifier,
27  size_t width,
28  size_t height,
29  FlutterMetalExternalTexture* metalTexture) {
30  FlutterEngine* engine = (__bridge FlutterEngine*)user_data;
31  return [engine.renderer populateTextureWithIdentifier:textureIdentifier
32  metalTexture:metalTexture];
33 }
34 
35 #pragma mark - FlutterRenderer implementation
36 
37 @implementation FlutterRenderer {
38  FlutterDarwinContextMetalSkia* _darwinMetalContext;
39 }
40 
41 namespace {
42 
43 // Attempts to find the integrated GPU backed metal device.
44 //
45 // See also: https://developer.apple.com/documentation/metal/multi-gpu-systems?language=objc
46 id<MTLDevice> SelectMetalDevice() {
47  NSArray<id<MTLDevice>>* devices = MTLCopyAllDevices();
48  for (id<MTLDevice> device in devices) {
49  if (@available(macOS 10.15, *)) {
50  if (device.hasUnifiedMemory) {
51  return device;
52  }
53  }
54  }
55  return MTLCreateSystemDefaultDevice();
56 }
57 } // namespace
58 
59 - (instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine {
60  self = [super initWithDelegate:self engine:flutterEngine];
61  if (self) {
62  _device = SelectMetalDevice();
63  if (!_device) {
64  NSLog(@"Could not acquire Metal device.");
65  return nil;
66  }
67 
68  _commandQueue = [_device newCommandQueue];
69  if (!_commandQueue) {
70  NSLog(@"Could not create Metal command queue.");
71  return nil;
72  }
73 
74  _darwinMetalContext = [[FlutterDarwinContextMetalSkia alloc] initWithMTLDevice:_device
75  commandQueue:_commandQueue];
76  }
77  return self;
78 }
79 
80 - (FlutterRendererConfig)createRendererConfig {
81  FlutterRendererConfig config = {
82  .type = FlutterRendererType::kMetal,
83  .metal = {
84  .struct_size = sizeof(FlutterMetalRendererConfig),
85  .device = (__bridge FlutterMetalDeviceHandle)_device,
86  .present_command_queue = (__bridge FlutterMetalCommandQueueHandle)_commandQueue,
87  .get_next_drawable_callback =
88  reinterpret_cast<FlutterMetalTextureCallback>(OnGetNextDrawable),
89  .present_drawable_callback =
90  reinterpret_cast<FlutterMetalPresentCallback>(OnPresentDrawable),
91  .external_texture_frame_callback =
92  reinterpret_cast<FlutterMetalTextureFrameCallback>(OnAcquireExternalTexture),
93  }};
94  return config;
95 }
96 
97 #pragma mark - Embedder callback implementations.
98 
99 - (BOOL)populateTextureWithIdentifier:(int64_t)textureID
100  metalTexture:(FlutterMetalExternalTexture*)textureOut {
101  FlutterExternalTexture* texture = [self getTextureWithID:textureID];
102  return [texture populateTexture:textureOut];
103 }
104 
105 #pragma mark - FlutterTextureRegistrar methods.
106 
107 - (FlutterExternalTexture*)onRegisterTexture:(id<FlutterTexture>)texture {
108  return [[FlutterExternalTexture alloc] initWithFlutterTexture:texture
109  darwinMetalContext:_darwinMetalContext];
110 }
111 
112 @end
static bool OnAcquireExternalTexture(void *user_data, int64_t textureIdentifier, size_t width, size_t height, FlutterMetalExternalTexture *metalTexture)
static FlutterMetalTexture OnGetNextDrawable(void *user_data, const FlutterFrameInfo *frameInfo)
static bool OnPresentDrawable(void *user_data, const FlutterMetalTexture *texture)
BOOL populateTexture:(nonnull FlutterMetalExternalTexture *metalTexture)
void * user_data