| 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 {
47 return [self populateTextureFromRGBAPixelBuffer:pixelBuffer textureOut:textureOut];
48 }
49 }
50
51 - (BOOL)populateTextureFromYUVAPixelBuffer:(nonnull CVPixelBufferRef)pixelBuffer
52 textureOut:(nonnull FlutterMetalExternalTexture*)textureOut {
53 CVMetalTextureRef yCVMetalTexture = nullptr;
54 CVMetalTextureRef uvCVMetalTextureRef = nullptr;
55 SkISize textureSize =
56 SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
57
58 CVReturn yCVReturn = CVMetalTextureCacheCreateTextureFromImage(
59 /*allocator=*/kCFAllocatorDefault,
60 /*textureCache=*/_darwinMetalContext.textureCache,
61 /*sourceImage=*/pixelBuffer,
62 /*textureAttributes=*/nullptr,
63 /*pixelFormat=*/MTLPixelFormatR8Unorm,
64 /*width=*/CVPixelBufferGetWidthOfPlane(pixelBuffer, 0u),
65 /*height=*/CVPixelBufferGetHeightOfPlane(pixelBuffer, 0u),
66 /*planeIndex=*/0u,
67 /*texture=*/&yCVMetalTexture);
68
69 if (yCVReturn != kCVReturnSuccess) {
70 NSLog(@"Could not create Metal texture from pixel buffer: CVReturn %d", yCVReturn);
71 return NO;
72 }
73
74 CVReturn uvCVReturn = CVMetalTextureCacheCreateTextureFromImage(
75 /*allocator=*/kCFAllocatorDefault,
76 /*textureCache=*/_darwinMetalContext.textureCache,
77 /*sourceImage=*/pixelBuffer,
78 /*textureAttributes=*/nullptr,
79 /*pixelFormat=*/MTLPixelFormatRG8Unorm,
80 /*width=*/CVPixelBufferGetWidthOfPlane(pixelBuffer, 1u),
81 /*height=*/CVPixelBufferGetHeightOfPlane(pixelBuffer, 1u),
82 /*planeIndex=*/1u,
83 /*texture=*/&uvCVMetalTextureRef);
84
85 if (uvCVReturn != kCVReturnSuccess) {
86 CVBufferRelease(yCVMetalTexture);
87 NSLog(@"Could not create Metal texture from pixel buffer: CVReturn %d", uvCVReturn);
88 return NO;
89 }
90
91 _textures = {(__bridge FlutterMetalTextureHandle)CVMetalTextureGetTexture(yCVMetalTexture),
92 (__bridge FlutterMetalTextureHandle)CVMetalTextureGetTexture(uvCVMetalTextureRef)};
93 CVBufferRelease(yCVMetalTexture);
94 CVBufferRelease(uvCVMetalTextureRef);
95
96 textureOut->num_textures = 2;
97 textureOut->height = textureSize.height();
98 textureOut->width = textureSize.width();
99 textureOut->pixel_format = FlutterMetalExternalTexturePixelFormat::kYUVA;
100 textureOut->textures = _textures.data();
101 OSType pixel_format = CVPixelBufferGetPixelFormatType(pixelBuffer);
102 textureOut->yuv_color_space = pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
103 ? FlutterMetalExternalTextureYUVColorSpace::kBT601LimitedRange
104 : FlutterMetalExternalTextureYUVColorSpace::kBT601FullRange;
105
106 return YES;
107 }
108
109 - (BOOL)populateTextureFromRGBAPixelBuffer:(nonnull CVPixelBufferRef)pixelBuffer
110 textureOut:(nonnull FlutterMetalExternalTexture*)textureOut {
111 SkISize textureSize =
112 SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
113
114 CVMetalTextureRef cvMetalTexture = nullptr;
115 CVReturn cvReturn =
116 CVMetalTextureCacheCreateTextureFromImage(/*allocator=*/kCFAllocatorDefault,
117 /*textureCache=*/_darwinMetalContext.textureCache,
118 /*sourceImage=*/pixelBuffer,
119 /*textureAttributes=*/nullptr,
120 /*pixelFormat=*/MTLPixelFormatBGRA8Unorm,
121 /*width=*/textureSize.width(),
122 /*height=*/textureSize.height(),
123 /*planeIndex=*/0u,
124 /*texture=*/&cvMetalTexture);
125
126 if (cvReturn != kCVReturnSuccess) {
127 NSLog(@"Could not create Metal texture from pixel buffer: CVReturn %d", cvReturn);
128 return NO;
129 }
130
131 _textures = {(__bridge FlutterMetalTextureHandle)CVMetalTextureGetTexture(cvMetalTexture)};
132 CVBufferRelease(cvMetalTexture);
133
134 textureOut->num_textures = 1;
135 textureOut->height = textureSize.height();
136 textureOut->width = textureSize.width();
137 textureOut->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA;
138 textureOut->textures = _textures.data();
139
140 return YES;
141 }
142
143 @end
_textureID
int64_t _textureID
Definition: FlutterExternalTexture.mm:9
FlutterExternalTexture.h
FlutterExternalTexture
Definition: FlutterExternalTexture.h:15
_textures
std::vector< FlutterMetalTextureHandle > _textures
Definition: FlutterExternalTexture.mm:16
_texture
id< FlutterTexture > _texture
Definition: FlutterExternalTexture.mm:14
FlutterTexture-p
Definition: FlutterTexture.h:21