| Flutter macOS Embedder |

FlutterExternalTexture.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/FlutterExternalTexture.h"
6
7 #include "flutter/fml/platform/darwin/cf_utils.h"
8
9 @implementation FlutterExternalTexture {
10 FlutterDarwinContextMetalSkia* _darwinMetalContext;
11
12 int64_t _textureID;
13
14 id<FlutterTexture> _texture;
15
16 std::vector<FlutterMetalTextureHandle> _textures;
17 }
18
19 - (instancetype)initWithFlutterTexture:(id<FlutterTexture>)texture
20 darwinMetalContext:(FlutterDarwinContextMetalSkia*)context {
21 self = [super init];
22 if (self) {
23 _texture = texture;
24 _textureID = reinterpret_cast<int64_t>(_texture);
25 _darwinMetalContext = context;
26 }
27 return self;
28 }
29
30 - (int64_t)textureID {
31 return _textureID;
32 }
33
34 - (BOOL)populateTexture:(FlutterMetalExternalTexture*)textureOut {
35 // Copy the pixel buffer from the FlutterTexture instance implemented on the user side.
36 fml::CFRef<CVPixelBufferRef> pixelBuffer([_texture copyPixelBuffer]);
37
38 if (!pixelBuffer) {
39 return NO;
40 }
41
42 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixelBuffer);
43 if (pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
44 pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
45 return [self populateTextureFromYUVAPixelBuffer:pixelBuffer textureOut:textureOut];
46 } else if (pixel_format == kCVPixelFormatType_32BGRA) {
47 return [self populateTextureFromRGBAPixelBuffer:pixelBuffer textureOut:textureOut];
48 } else {
49 NSLog(@"Unsupported pixel format: %d", pixel_format);
50 return NO;
51 }
52 }
53
54 - (BOOL)populateTextureFromYUVAPixelBuffer:(nonnull CVPixelBufferRef)pixelBuffer
55 textureOut:(nonnull FlutterMetalExternalTexture*)textureOut {
56 CVMetalTextureRef yCVMetalTexture = nullptr;
57 CVMetalTextureRef uvCVMetalTextureRef = nullptr;
58 SkISize textureSize =
59 SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
60
61 CVReturn yCVReturn = CVMetalTextureCacheCreateTextureFromImage(
62 /*allocator=*/kCFAllocatorDefault,
63 /*textureCache=*/_darwinMetalContext.textureCache,
64 /*sourceImage=*/pixelBuffer,
65 /*textureAttributes=*/nullptr,
66 /*pixelFormat=*/MTLPixelFormatR8Unorm,
67 /*width=*/CVPixelBufferGetWidthOfPlane(pixelBuffer, 0u),
68 /*height=*/CVPixelBufferGetHeightOfPlane(pixelBuffer, 0u),
69 /*planeIndex=*/0u,
70 /*texture=*/&yCVMetalTexture);
71
72 if (yCVReturn != kCVReturnSuccess) {
73 NSLog(@"Could not create Metal texture from pixel buffer: CVReturn %d", yCVReturn);
74 return NO;
75 }
76
77 CVReturn uvCVReturn = CVMetalTextureCacheCreateTextureFromImage(
78 /*allocator=*/kCFAllocatorDefault,
79 /*textureCache=*/_darwinMetalContext.textureCache,
80 /*sourceImage=*/pixelBuffer,
81 /*textureAttributes=*/nullptr,
82 /*pixelFormat=*/MTLPixelFormatRG8Unorm,
83 /*width=*/CVPixelBufferGetWidthOfPlane(pixelBuffer, 1u),
84 /*height=*/CVPixelBufferGetHeightOfPlane(pixelBuffer, 1u),
85 /*planeIndex=*/1u,
86 /*texture=*/&uvCVMetalTextureRef);
87
88 if (uvCVReturn != kCVReturnSuccess) {
89 CVBufferRelease(yCVMetalTexture);
90 NSLog(@"Could not create Metal texture from pixel buffer: CVReturn %d", uvCVReturn);
91 return NO;
92 }
93
94 _textures = {(__bridge FlutterMetalTextureHandle)CVMetalTextureGetTexture(yCVMetalTexture),
95 (__bridge FlutterMetalTextureHandle)CVMetalTextureGetTexture(uvCVMetalTextureRef)};
96 CVBufferRelease(yCVMetalTexture);
97 CVBufferRelease(uvCVMetalTextureRef);
98
99 textureOut->num_textures = 2;
100 textureOut->height = textureSize.height();
101 textureOut->width = textureSize.width();
102 textureOut->pixel_format = FlutterMetalExternalTexturePixelFormat::kYUVA;
103 textureOut->textures = _textures.data();
104 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixelBuffer);
105 textureOut->yuv_color_space = pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
106 ? FlutterMetalExternalTextureYUVColorSpace::kBT601LimitedRange
107 : FlutterMetalExternalTextureYUVColorSpace::kBT601FullRange;
108
109 return YES;
110 }
111
112 - (BOOL)populateTextureFromRGBAPixelBuffer:(nonnull CVPixelBufferRef)pixelBuffer
113 textureOut:(nonnull FlutterMetalExternalTexture*)textureOut {
114 SkISize textureSize =
115 SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
116
117 CVMetalTextureRef cvMetalTexture = nullptr;
118 CVReturn cvReturn =
119 CVMetalTextureCacheCreateTextureFromImage(/*allocator=*/kCFAllocatorDefault,
120 /*textureCache=*/_darwinMetalContext.textureCache,
121 /*sourceImage=*/pixelBuffer,
122 /*textureAttributes=*/nullptr,
123 /*pixelFormat=*/MTLPixelFormatBGRA8Unorm,
124 /*width=*/textureSize.width(),
125 /*height=*/textureSize.height(),
126 /*planeIndex=*/0u,
127 /*texture=*/&cvMetalTexture);
128
129 if (cvReturn != kCVReturnSuccess) {
130 NSLog(@"Could not create Metal texture from pixel buffer: CVReturn %d", cvReturn);
131 return NO;
132 }
133
134 _textures = {(__bridge FlutterMetalTextureHandle)CVMetalTextureGetTexture(cvMetalTexture)};
135 CVBufferRelease(cvMetalTexture);
136
137 textureOut->num_textures = 1;
138 textureOut->height = textureSize.height();
139 textureOut->width = textureSize.width();
140 textureOut->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA;
141 textureOut->textures = _textures.data();
142
143 return YES;
144 }
145
146 @end
FlutterExternalTexture.h
_textures
std::vector< FlutterMetalTextureHandle > _textures
Definition: FlutterExternalTexture.mm:16
_texture
id< FlutterTexture > _texture
Definition: FlutterExternalTexture.mm:14
_textureID
int64_t _textureID
Definition: FlutterExternalTexture.mm:9
FlutterExternalTexture
Definition: FlutterExternalTexture.h:19
FlutterTexture-p
Definition: FlutterTexture.h:21