16#include "third_party/skia/include/core/SkColorSpace.h"
17#include "third_party/skia/include/core/SkImage.h"
18#include "third_party/skia/include/core/SkYUVAInfo.h"
19#include "third_party/skia/include/gpu/GpuTypes.h"
20#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
21#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
22#include "third_party/skia/include/gpu/ganesh/GrYUVABackendTextures.h"
23#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
24#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlBackendSurface.h"
25#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlTypes.h"
26#include "third_party/skia/include/ports/SkCFObject.h"
40- (instancetype)initWithTextureCache:(nonnull CVMetalTextureCacheRef)textureCache
41 textureID:(int64_t)textureID
43 enableImpeller:(
BOOL)enableImpeller {
44 if (
self = [super init]) {
45 _textureCache.Retain(textureCache);
57 CVMetalTextureCacheFlush(_textureCache, 0);
61- (void)paintContext:(
flutter::Texture::PaintContext&)context
62 bounds:(const SkRect&)bounds
67 if (needsUpdatedTexture) {
68 [
self onNeedsUpdatedTexture:context];
72 context.canvas->DrawImageRect(
83- (void)onNeedsUpdatedTexture:(
flutter::Texture::PaintContext&)context {
84 CVPixelBufferRef pixelBuffer = [_externalTexture copyPixelBuffer];
93 sk_sp<flutter::DlImage>
image = [
self wrapExternalPixelBuffer:_lastPixelBuffer context:context];
100- (void)onGrContextCreated {
106- (void)onGrContextDestroyed {
113 CVMetalTextureCacheFlush(_textureCache, 0);
117- (void)markNewFrameAvailable {
121- (void)onTextureUnregistered {
122 if ([
_externalTexture respondsToSelector:@selector(onTextureUnregistered:)]) {
123 [_externalTexture onTextureUnregistered:_externalTexture];
127#pragma mark - External texture skia wrapper methods.
129- (sk_sp<
flutter::DlImage>)wrapExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
130 context:(
flutter::Texture::PaintContext&)context {
135 sk_sp<flutter::DlImage>
image =
nullptr;
136 if (
_pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
137 _pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
138 image = [
self wrapNV12ExternalPixelBuffer:pixelBuffer context:context];
140 image = [
self wrapBGRAExternalPixelBuffer:pixelBuffer context:context];
147 FML_DLOG(ERROR) <<
"Could not wrap Metal texture as a display list image.";
153- (sk_sp<
flutter::DlImage>)wrapNV12ExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
154 context:(
flutter::Texture::PaintContext&)context {
155 SkISize textureSize =
156 SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
157 CVMetalTextureRef yMetalTexture =
nullptr;
160 CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
164 MTLPixelFormatR8Unorm,
166 textureSize.height(),
170 if (cvReturn != kCVReturnSuccess) {
171 FML_DLOG(ERROR) <<
"Could not create Metal texture from pixel buffer: CVReturn " << cvReturn;
176 CVMetalTextureRef uvMetalTexture =
nullptr;
179 CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
183 MTLPixelFormatRG8Unorm,
184 textureSize.width() / 2,
185 textureSize.height() / 2,
189 if (cvReturn != kCVReturnSuccess) {
190 FML_DLOG(ERROR) <<
"Could not create Metal texture from pixel buffer: CVReturn " << cvReturn;
195 id<MTLTexture> yTex = CVMetalTextureGetTexture(yMetalTexture);
196 CVBufferRelease(yMetalTexture);
198 id<MTLTexture> uvTex = CVMetalTextureGetTexture(uvMetalTexture);
199 CVBufferRelease(uvMetalTexture);
203 _pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
212 SkYUVColorSpace colorSpace =
_pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
213 ? kRec601_Limited_SkYUVColorSpace
214 : kJPEG_Full_SkYUVColorSpace;
219 width:textureSize.width()
220 height:textureSize.height()];
229- (sk_sp<
flutter::DlImage>)wrapBGRAExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
230 context:(
flutter::Texture::PaintContext&)context {
231 SkISize textureSize =
232 SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
233 CVMetalTextureRef metalTexture =
nullptr;
235 CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
239 MTLPixelFormatBGRA8Unorm,
241 textureSize.height(),
245 if (cvReturn != kCVReturnSuccess) {
246 FML_DLOG(ERROR) <<
"Could not create Metal texture from pixel buffer: CVReturn " << cvReturn;
250 id<MTLTexture> rgbaTex = CVMetalTextureGetTexture(metalTexture);
251 CVBufferRelease(metalTexture);
260 width:textureSize.width()
261 height:textureSize.height()];
274+ (sk_sp<SkImage>)wrapYUVATexture:(
id<MTLTexture>)yTex
275 UVTex:(
id<MTLTexture>)uvTex
276 YUVColorSpace:(SkYUVColorSpace)colorSpace
277 grContext:(nonnull GrDirectContext*)grContext
279 height:(
size_t)height {
283 GrMtlTextureInfo ySkiaTextureInfo;
284 ySkiaTextureInfo.fTexture.retain((__bridge GrMTLHandle)yTex);
286 GrBackendTexture skiaBackendTextures[2];
287 skiaBackendTextures[0] =
288 GrBackendTextures::MakeMtl(
width,
height, skgpu::Mipmapped::kNo, ySkiaTextureInfo);
290 GrMtlTextureInfo uvSkiaTextureInfo;
291 uvSkiaTextureInfo.fTexture.retain((__bridge GrMTLHandle)uvTex);
293 skiaBackendTextures[1] =
294 GrBackendTextures::MakeMtl(
width,
height, skgpu::Mipmapped::kNo, uvSkiaTextureInfo);
295 SkYUVAInfo yuvaInfo(skiaBackendTextures[0].dimensions(), SkYUVAInfo::PlaneConfig::kY_UV,
296 SkYUVAInfo::Subsampling::k444, colorSpace);
297 GrYUVABackendTextures yuvaBackendTextures(yuvaInfo, skiaBackendTextures,
298 kTopLeft_GrSurfaceOrigin);
300 return SkImages::TextureFromYUVATextures(grContext, yuvaBackendTextures,
306+ (sk_sp<SkImage>)wrapRGBATexture:(
id<MTLTexture>)rgbaTex
307 grContext:(nonnull GrDirectContext*)grContext
309 height:(
size_t)height {
314 GrMtlTextureInfo skiaTextureInfo;
315 skiaTextureInfo.fTexture.retain((__bridge GrMTLHandle)rgbaTex);
317 GrBackendTexture skiaBackendTexture =
318 GrBackendTextures::MakeMtl(
width,
height, skgpu::Mipmapped ::kNo, skiaTextureInfo);
320 return SkImages::BorrowTextureFrom(grContext, skiaBackendTexture, kTopLeft_GrSurfaceOrigin,
321 kBGRA_8888_SkColorType, kPremul_SkAlphaType,
330+ (sk_sp<
flutter::DlImage>)wrapYUVATexture:(
id<MTLTexture>)yTex
331 UVTex:(
id<MTLTexture>)uvTex
333 aiksContext:(nonnull
impeller::AiksContext*)aiks_context {
355+ (sk_sp<
flutter::DlImage>)wrapRGBATexture:(
id<MTLTexture>)rgbaTex
356 aiksContext:(nonnull
impeller::AiksContext*)aiks_context {
sk_sp< flutter::DlImage > _externalImage
NSObject< FlutterTexture > * _externalTexture
CVPixelBufferRef _lastPixelBuffer
BOOL _textureFrameAvailable
static sk_sp< DlImage > Make(const SkImage *image)
static sk_sp< DlImageImpeller > MakeFromYUVTextures(AiksContext *aiks_context, std::shared_ptr< Texture > y_texture, std::shared_ptr< Texture > uv_texture, YUVColorSpace yuv_color_space)
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
static std::shared_ptr< TextureMTL > Wrapper(TextureDescriptor desc, id< MTLTexture > texture, std::function< void()> deletion_proc=nullptr)
FlutterVulkanImage * image
#define FML_DLOG(severity)
#define FML_LOG(severity)
sk_sp< flutter::DlImage > wrapRGBATexture:aiksContext:(nonnull id< MTLTexture > rgbaTex,[aiksContext] nonnull impeller::AiksContext *aiks_context)
sk_sp< flutter::DlImage > wrapYUVATexture:UVTex:YUVColorSpace:aiksContext:(nonnull id< MTLTexture > yTex,[UVTex] nonnull id< MTLTexture > uvTex,[YUVColorSpace] impeller::YUVColorSpace colorSpace,[aiksContext] nonnull impeller::AiksContext *aiksContext)
sk_sp< SkImage > wrapRGBATexture:grContext:width:height:(nonnull id< MTLTexture > rgbaTex,[grContext] nonnull GrDirectContext *grContext,[width] size_t width,[height] size_t height)
sk_sp< SkImage > wrapYUVATexture:UVTex:YUVColorSpace:grContext:width:height:(nonnull id< MTLTexture > yTex,[UVTex] nonnull id< MTLTexture > uvTex,[YUVColorSpace] SkYUVColorSpace colorSpace,[grContext] nonnull GrDirectContext *grContext,[width] size_t width,[height] size_t height)
const DlRect & ToDlRect(const SkRect &rect)
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...