| Flutter macOS Embedder |

FlutterSurface.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 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurface.h"
6
7 #import <CoreMedia/CoreMedia.h>
8 #import <Metal/Metal.h>
9
10 #import "flutter/fml/platform/darwin/cf_utils.h"
11
12 @interface FlutterSurface () {
13 CGSize _size;
14 fml::CFRef<IOSurfaceRef> _ioSurface;
15 id<MTLTexture> _texture;
16 // Used for testing.
17 BOOL _isInUseOverride;
18 // Whether this surface was created with wide gamut enabled.
19 BOOL _isWideGamut;
20 }
21 @end
22
23 @implementation FlutterSurface
24
25 - (IOSurfaceRef)ioSurface {
26 return _ioSurface;
27 }
28
29 - (CGSize)size {
30 return _size;
31 }
32
33 - (int64_t)textureId {
34 return reinterpret_cast<int64_t>(_texture);
35 }
36
37 - (BOOL)isInUse {
38 return _isInUseOverride || IOSurfaceIsInUse(_ioSurface);
39 }
40
41 - (BOOL)isWideGamut {
42 return _isWideGamut;
43 }
44
45 - (BOOL)isInUseOverride {
46 return _isInUseOverride;
47 }
48
49 - (void)setIsInUseOverride:(BOOL)isInUseOverride {
50 _isInUseOverride = isInUseOverride;
51 }
52
53 - (instancetype)initWithSize:(CGSize)size
54 device:(id<MTLDevice>)device
55 enableWideGamut:(BOOL)enableWideGamut {
56 if (self = [super init]) {
57 self->_size = size;
58 self->_isWideGamut = enableWideGamut;
59 self->_ioSurface.Reset([FlutterSurface createIOSurfaceWithSize:size
60 enableWideGamut:enableWideGamut]);
61 MTLPixelFormat pixelFormat =
62 enableWideGamut ? MTLPixelFormatBGRA10_XR : MTLPixelFormatBGRA8Unorm;
63 self->_texture = [FlutterSurface createTextureForIOSurface:_ioSurface
64 size:size
65 device:device
66 pixelFormat:pixelFormat];
67 }
68 return self;
69 }
70
71 - (FlutterMetalTexture)asFlutterMetalTexture {
72 return FlutterMetalTexture{
73 .struct_size = sizeof(FlutterMetalTexture),
74 .texture_id = self.textureId,
75 .texture = (__bridge void*)_texture,
76 // Retain for use in [FlutterSurface fromFlutterMetalTexture]. Released in
77 // destruction_callback.
78 .user_data = (__bridge_retained void*)self,
79 .destruction_callback =
80 [](void* user_data) {
81 // Balancing release for the retain when setting user_data above.
82 FlutterSurface* surface = (__bridge_transfer FlutterSurface*)user_data;
83 surface = nil;
84 },
85 };
86 }
87
88 + (FlutterSurface*)fromFlutterMetalTexture:(const FlutterMetalTexture*)texture {
89 return (__bridge FlutterSurface*)texture->user_data;
90 }
91
92 + (IOSurfaceRef)createIOSurfaceWithSize:(CGSize)size enableWideGamut:(BOOL)enableWideGamut {
93 unsigned pixelFormat;
94 unsigned bytesPerElement;
95 if (enableWideGamut) {
96 // 10-bit wide gamut format (same as iOS)
97 pixelFormat = kCVPixelFormatType_40ARGBLEWideGamut;
98 bytesPerElement = 8;
99 } else {
100 pixelFormat = kCVPixelFormatType_32BGRA;
101 bytesPerElement = 4;
102 }
103
104 size_t bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.width * bytesPerElement);
105 size_t totalBytes = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.height * bytesPerRow);
106 NSDictionary* options = @{
107 (id)kIOSurfaceWidth : @(size.width),
108 (id)kIOSurfaceHeight : @(size.height),
109 (id)kIOSurfacePixelFormat : @(pixelFormat),
110 (id)kIOSurfaceBytesPerElement : @(bytesPerElement),
111 (id)kIOSurfaceBytesPerRow : @(bytesPerRow),
112 (id)kIOSurfaceAllocSize : @(totalBytes),
113 };
114
115 IOSurfaceRef res = IOSurfaceCreate((CFDictionaryRef)options);
116 if (enableWideGamut) {
117 IOSurfaceSetValue(res, kIOSurfaceColorSpace, kCGColorSpaceExtendedSRGB);
118 } else {
119 IOSurfaceSetValue(res, kIOSurfaceColorSpace, kCGColorSpaceSRGB);
120 }
121 return res;
122 }
123
124 + (id<MTLTexture>)createTextureForIOSurface:(IOSurfaceRef)surface
125 size:(CGSize)size
126 device:(id<MTLDevice>)device
127 pixelFormat:(MTLPixelFormat)pixelFormat {
128 MTLTextureDescriptor* textureDescriptor =
129 [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat
130 width:size.width
131 height:size.height
132 mipmapped:NO];
133 textureDescriptor.usage =
134 MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget | MTLTextureUsageShaderWrite;
135 // plane = 0 for BGRA.
136 return [device newTextureWithDescriptor:textureDescriptor iosurface:surface plane:0];
137 }
138
139 @end
_texture
id< FlutterTexture > _texture
Definition: FlutterExternalTexture.mm:14
FlutterSurface.h
FlutterSurface()::_ioSurface
fml::CFRef< IOSurfaceRef > _ioSurface
Definition: FlutterSurface.mm:14
FlutterSurface()::_isWideGamut
BOOL _isWideGamut
Definition: FlutterSurface.mm:19
FlutterSurface()::_isInUseOverride
BOOL _isInUseOverride
Definition: FlutterSurface.mm:17
FlutterSurface()::_size
CGSize _size
Definition: FlutterSurface.mm:13
FlutterSurface()::_texture
id< MTLTexture > _texture
Definition: FlutterSurface.mm:15
FlutterSurface(Private)::ioSurface
IOSurfaceRef ioSurface
Definition: FlutterSurface.h:34
FlutterSurface(Private)::textureId
int64_t textureId
Definition: FlutterSurface.h:36
FlutterSurface(Private)::isInUse
BOOL isInUse
Definition: FlutterSurface.h:38
FlutterSurface(Private)::isWideGamut
BOOL isWideGamut
Definition: FlutterSurface.h:40
FlutterSurface(Private)::size
CGSize size
Definition: FlutterSurface.h:35
FlutterSurface(Testing)::isInUseOverride
BOOL isInUseOverride
Definition: FlutterSurface.h:45
FlutterSurface
Definition: FlutterSurface.h:17
-[FlutterSurface asFlutterMetalTexture]
FlutterMetalTexture asFlutterMetalTexture()
Definition: FlutterSurface.mm:71
user_data
void * user_data
Definition: texture_registrar_unittests.cc:27
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24