5 #import <Foundation/Foundation.h>
6 #import <Metal/Metal.h>
11 #import "flutter/display_list/skia/dl_sk_canvas.h"
12 #import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h"
13 #import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h"
15 #include "flutter/shell/platform/embedder/embedder.h"
16 #include "flutter/shell/platform/embedder/embedder_external_texture_metal.h"
17 #include "flutter/testing/autoreleasepool_test.h"
18 #include "flutter/testing/testing.h"
19 #include "third_party/googletest/googletest/include/gtest/gtest.h"
20 #include "third_party/skia/include/core/SkImage.h"
21 #include "third_party/skia/include/core/SkSamplingOptions.h"
22 #include "third_party/skia/include/core/SkSurface.h"
23 #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
27 - (nonnull instancetype)initWidth:(
size_t)width
29 pixelFormatType:(OSType)pixelFormatType;
39 - (nonnull instancetype)initWidth:(
size_t)width
41 pixelFormatType:(OSType)pixelFormatType {
42 if (
self = [super init]) {
50 - (CVPixelBufferRef)copyPixelBuffer {
51 return [
self pixelBuffer];
54 - (CVPixelBufferRef)pixelBuffer {
55 NSDictionary* options = @{
57 (NSString*)kCVPixelBufferMetalCompatibilityKey : @YES
59 CVPixelBufferRef pxbuffer = NULL;
60 CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, _width, _width,
_pixelFormatType,
61 (__bridge CFDictionaryRef)options, &pxbuffer);
62 FML_CHECK(status == kCVReturnSuccess && pxbuffer !=
nullptr) <<
"Failed to create pixel buffer";
75 const size_t width = 100;
76 const size_t height = 100;
80 FlutterDarwinContextMetalSkia* darwinContextMetal =
81 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
82 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
83 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
84 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
87 MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init];
88 textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
89 textureDescriptor.width = width;
90 textureDescriptor.height = height;
91 textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
92 id<MTLTexture> mtlTexture =
93 [darwinContextMetal.device newTextureWithDescriptor:textureDescriptor];
94 std::vector<FlutterMetalTextureHandle> textures = {
95 (__bridge FlutterMetalTextureHandle)mtlTexture,
99 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t
texture_id,
size_t w,
101 EXPECT_TRUE(w == width);
102 EXPECT_TRUE(h == height);
104 auto texture = std::make_unique<FlutterMetalExternalTexture>();
105 texture->struct_size =
sizeof(FlutterMetalExternalTexture);
106 texture->num_textures = 1;
109 texture->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA;
110 texture->textures = textures.data();
115 std::unique_ptr<flutter::Texture> texture =
116 std::make_unique<EmbedderExternalTextureMetal>(
texture_id, callback);
117 SkRect bounds = SkRect::MakeWH(info.width(), info.height());
118 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
119 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
120 flutter::Texture::PaintContext context{
122 .gr_context = grContext,
124 texture->Paint(context, bounds,
false, sampling);
126 ASSERT_TRUE(mtlTexture != nil);
128 gpuSurface->makeImageSnapshot();
133 const size_t width = 100;
134 const size_t height = 100;
138 FlutterDarwinContextMetalSkia* darwinContextMetal =
139 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
140 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
141 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
142 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
148 pixelFormatType:kCVPixelFormatType_32BGRA];
151 darwinMetalContext:darwinContextMetal];
154 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t
texture_id,
size_t w,
156 EXPECT_TRUE(w == width);
157 EXPECT_TRUE(h == height);
159 auto texture = std::make_unique<FlutterMetalExternalTexture>();
162 EXPECT_TRUE(texture->num_textures == 1);
163 EXPECT_TRUE(texture->textures !=
nullptr);
164 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kRGBA);
169 std::unique_ptr<flutter::Texture> texture =
170 std::make_unique<EmbedderExternalTextureMetal>(
texture_id, callback);
171 SkRect bounds = SkRect::MakeWH(info.width(), info.height());
172 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
173 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
174 flutter::Texture::PaintContext context{
176 .gr_context = grContext,
178 texture->Paint(context, bounds,
false, sampling);
180 gpuSurface->makeImageSnapshot();
185 const size_t width = 100;
186 const size_t height = 100;
190 FlutterDarwinContextMetalSkia* darwinContextMetal =
191 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
192 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
193 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
194 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
200 pixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];
203 darwinMetalContext:darwinContextMetal];
206 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t
texture_id,
size_t w,
208 EXPECT_TRUE(w == width);
209 EXPECT_TRUE(h == height);
211 auto texture = std::make_unique<FlutterMetalExternalTexture>();
214 EXPECT_TRUE(texture->num_textures == 2);
215 EXPECT_TRUE(texture->textures !=
nullptr);
216 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kYUVA);
217 EXPECT_TRUE(texture->yuv_color_space ==
218 FlutterMetalExternalTextureYUVColorSpace::kBT601LimitedRange);
223 std::unique_ptr<flutter::Texture> texture =
224 std::make_unique<EmbedderExternalTextureMetal>(
texture_id, callback);
225 SkRect bounds = SkRect::MakeWH(info.width(), info.height());
226 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
227 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
228 flutter::Texture::PaintContext context{
230 .gr_context = grContext,
232 texture->Paint(context, bounds,
false, sampling);
234 gpuSurface->makeImageSnapshot();
239 const size_t width = 100;
240 const size_t height = 100;
244 FlutterDarwinContextMetalSkia* darwinContextMetal =
245 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
246 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
247 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
248 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
254 pixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];
257 darwinMetalContext:darwinContextMetal];
260 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t
texture_id,
size_t w,
262 EXPECT_TRUE(w == width);
263 EXPECT_TRUE(h == height);
265 auto texture = std::make_unique<FlutterMetalExternalTexture>();
268 EXPECT_TRUE(texture->num_textures == 2);
269 EXPECT_TRUE(texture->textures !=
nullptr);
270 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kYUVA);
271 EXPECT_TRUE(texture->yuv_color_space ==
272 FlutterMetalExternalTextureYUVColorSpace::kBT601FullRange);
277 std::unique_ptr<flutter::Texture> texture =
278 std::make_unique<EmbedderExternalTextureMetal>(
texture_id, callback);
279 SkRect bounds = SkRect::MakeWH(info.width(), info.height());
280 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
281 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
282 flutter::Texture::PaintContext context{
284 .gr_context = grContext,
286 texture->Paint(context, bounds,
false, sampling);
288 gpuSurface->makeImageSnapshot();
293 const size_t width = 100;
294 const size_t height = 100;
298 FlutterDarwinContextMetalSkia* darwinContextMetal =
299 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
300 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
301 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
302 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
308 pixelFormatType:kCVPixelFormatType_420YpCbCr8PlanarFullRange];
311 darwinMetalContext:darwinContextMetal];
314 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t
texture_id,
size_t w,
316 EXPECT_TRUE(w == width);
317 EXPECT_TRUE(h == height);
319 auto texture = std::make_unique<FlutterMetalExternalTexture>();
320 EXPECT_FALSE([textureHolder populateTexture:texture.get()]);
325 std::unique_ptr<flutter::Texture> texture =
326 std::make_unique<EmbedderExternalTextureMetal>(
texture_id, callback);
327 SkRect bounds = SkRect::MakeWH(info.width(), info.height());
328 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
329 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
330 flutter::Texture::PaintContext context{
332 .gr_context = grContext,
334 texture->Paint(context, bounds,
false, sampling);