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 
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:18
_textures
std::vector< FlutterMetalTextureHandle > _textures
Definition: FlutterExternalTexture.mm:16
_texture
id< FlutterTexture > _texture
Definition: FlutterExternalTexture.mm:14
FlutterTexture-p
Definition: FlutterTexture.h:21