| Flutter macOS Embedder |

FlutterEmbedderExternalTextureTest.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 <Foundation/Foundation.h>
6 #import <Metal/Metal.h>
7
8 #include <memory>
9 #include <vector>
10
11 #include "flutter/display_list/display_list.h"
12 #include "flutter/display_list/dl_builder.h"
13 #import "flutter/display_list/skia/dl_sk_canvas.h"
14 #include "flutter/fml/synchronization/sync_switch.h"
15 #include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h"
16 #import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h"
17 #import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h"
18 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTexture.h"
19 #include "flutter/shell/platform/embedder/embedder.h"
20 #include "flutter/shell/platform/embedder/embedder_external_texture_metal.h"
21 #include "flutter/testing/autoreleasepool_test.h"
22 #include "flutter/testing/testing.h"
23 #include "impeller/display_list/aiks_context.h" // nogncheck
24 #include "impeller/entity/mtl/entity_shaders.h" // nogncheck
25 #include "impeller/entity/mtl/framebuffer_blend_shaders.h" // nogncheck
26 #include "impeller/entity/mtl/modern_shaders.h" // nogncheck
27 #include "impeller/renderer/backend/metal/context_mtl.h" // nogncheck
28 #include "third_party/googletest/googletest/include/gtest/gtest.h"
29 #include "third_party/skia/include/core/SkImage.h"
30 #include "third_party/skia/include/core/SkSamplingOptions.h"
31 #include "third_party/skia/include/core/SkSurface.h"
32 #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
33
34 static std::shared_ptr<impeller::ContextMTL> CreateImpellerContext() {
35 std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
36 std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_data,
37 impeller_entity_shaders_length),
38 std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_data,
39 impeller_modern_shaders_length),
40 std::make_shared<fml::NonOwnedMapping>(impeller_framebuffer_blend_shaders_data,
41 impeller_framebuffer_blend_shaders_length),
42 };
43 auto sync_switch = std::make_shared<fml::SyncSwitch>(false);
44 return impeller::ContextMTL::Create(impeller::Flags{}, shader_mappings, sync_switch,
45 "Impeller Library");
46 }
47
48 @interface TestExternalTexture : NSObject <FlutterTexture>
49
50 - (nonnull instancetype)initWidth:(size_t)width
51 height:(size_t)height
52 pixelFormatType:(OSType)pixelFormatType;
53
54 @end
55
56 @implementation TestExternalTexture {
57 size_t _width;
58 size_t _height;
59 OSType _pixelFormatType;
60 }
61
62 - (nonnull instancetype)initWidth:(size_t)width
63 height:(size_t)height
64 pixelFormatType:(OSType)pixelFormatType {
65 if (self = [super init]) {
66 _width = width;
67 _height = height;
68 _pixelFormatType = pixelFormatType;
69 }
70 return self;
71 }
72
73 - (CVPixelBufferRef)copyPixelBuffer {
74 return [self pixelBuffer];
75 }
76
77 - (CVPixelBufferRef)pixelBuffer {
78 NSDictionary* options = @{
79 // This key is required to generate SKPicture with CVPixelBufferRef in metal.
80 (NSString*)kCVPixelBufferMetalCompatibilityKey : @YES
81 };
82 CVPixelBufferRef pxbuffer = NULL;
83 CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, _width, _width, _pixelFormatType,
84 (__bridge CFDictionaryRef)options, &pxbuffer);
85 FML_CHECK(status == kCVReturnSuccess && pxbuffer != nullptr) << "Failed to create pixel buffer";
86 return pxbuffer;
87 }
88
89 @end
90
91 namespace flutter::testing {
92
93 // Test-specific name for AutoreleasePoolTest fixture.
94 using FlutterEmbedderExternalTextureTest = AutoreleasePoolTest;
95
96 TEST_F(FlutterEmbedderExternalTextureTest, TestTextureResolution) {
97 // Constants.
98 const size_t width = 100;
99 const size_t height = 100;
100 const int64_t texture_id = 1;
101
102 // Set up the surface.
103 FlutterDarwinContextMetalSkia* darwinContextMetal =
104 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
105 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
106 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
107 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
108
109 // Create a texture.
110 MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init];
111 textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
112 textureDescriptor.width = width;
113 textureDescriptor.height = height;
114 textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
115 id<MTLTexture> mtlTexture =
116 [darwinContextMetal.device newTextureWithDescriptor:textureDescriptor];
117 std::vector<FlutterMetalTextureHandle> textures = {
118 (__bridge FlutterMetalTextureHandle)mtlTexture,
119 };
120
121 // Callback to resolve the texture.
122 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
123 size_t h) {
124 EXPECT_TRUE(w == width);
125 EXPECT_TRUE(h == height);
126
127 auto texture = std::make_unique<FlutterMetalExternalTexture>();
128 texture->struct_size = sizeof(FlutterMetalExternalTexture);
129 texture->num_textures = 1;
130 texture->height = h;
131 texture->width = w;
132 texture->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA;
133 texture->textures = textures.data();
134 return texture;
135 };
136
137 // Render the texture.
138 std::unique_ptr<flutter::Texture> texture =
139 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
140 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
141 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
142 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
143 flutter::Texture::PaintContext context{
144 .canvas = &canvas,
145 .gr_context = grContext,
146 };
147 texture->Paint(context, bounds, /*freeze=*/false, sampling);
148
149 ASSERT_TRUE(mtlTexture != nil);
150
151 gpuSurface->makeImageSnapshot();
152 }
153
154 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateExternalTexture) {
155 // Constants.
156 const size_t width = 100;
157 const size_t height = 100;
158 const int64_t texture_id = 1;
159
160 // Set up the surface.
161 FlutterDarwinContextMetalSkia* darwinContextMetal =
162 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
163 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
164 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
165 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
166
167 // Create a texture.
168 TestExternalTexture* testExternalTexture =
169 [[TestExternalTexture alloc] initWidth:width
170 height:height
171 pixelFormatType:kCVPixelFormatType_32BGRA];
172 FlutterExternalTexture* textureHolder =
173 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
174 darwinMetalContext:darwinContextMetal];
175
176 // Callback to resolve the texture.
177 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
178 size_t h) {
179 EXPECT_TRUE(w == width);
180 EXPECT_TRUE(h == height);
181
182 auto texture = std::make_unique<FlutterMetalExternalTexture>();
183 [textureHolder populateTexture:texture.get()];
184
185 EXPECT_TRUE(texture->num_textures == 1);
186 EXPECT_TRUE(texture->textures != nullptr);
187 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kRGBA);
188 return texture;
189 };
190
191 // Render the texture.
192 std::unique_ptr<flutter::Texture> texture =
193 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
194 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
195 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
196 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
197 flutter::Texture::PaintContext context{
198 .canvas = &canvas,
199 .gr_context = grContext,
200 };
201 texture->Paint(context, bounds, /*freeze=*/false, sampling);
202
203 gpuSurface->makeImageSnapshot();
204 }
205
206 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateExternalTextureYUVA) {
207 // Constants.
208 const size_t width = 100;
209 const size_t height = 100;
210 const int64_t texture_id = 1;
211
212 // Set up the surface.
213 FlutterDarwinContextMetalSkia* darwinContextMetal =
214 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
215 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
216 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
217 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
218
219 // Create a texture.
220 TestExternalTexture* testExternalTexture =
221 [[TestExternalTexture alloc] initWidth:width
222 height:height
223 pixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];
224 FlutterExternalTexture* textureHolder =
225 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
226 darwinMetalContext:darwinContextMetal];
227
228 // Callback to resolve the texture.
229 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
230 size_t h) {
231 EXPECT_TRUE(w == width);
232 EXPECT_TRUE(h == height);
233
234 auto texture = std::make_unique<FlutterMetalExternalTexture>();
235 [textureHolder populateTexture:texture.get()];
236
237 EXPECT_TRUE(texture->num_textures == 2);
238 EXPECT_TRUE(texture->textures != nullptr);
239 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kYUVA);
240 EXPECT_TRUE(texture->yuv_color_space ==
241 FlutterMetalExternalTextureYUVColorSpace::kBT601LimitedRange);
242 return texture;
243 };
244
245 // Render the texture.
246 std::unique_ptr<flutter::Texture> texture =
247 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
248 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
249 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
250 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
251 flutter::Texture::PaintContext context{
252 .canvas = &canvas,
253 .gr_context = grContext,
254 };
255 texture->Paint(context, bounds, /*freeze=*/false, sampling);
256
257 gpuSurface->makeImageSnapshot();
258 }
259
260 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateExternalTextureYUVA2) {
261 // Constants.
262 const size_t width = 100;
263 const size_t height = 100;
264 const int64_t texture_id = 1;
265
266 // Set up the surface.
267 FlutterDarwinContextMetalSkia* darwinContextMetal =
268 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
269 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
270 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
271 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
272
273 // Create a texture.
274 TestExternalTexture* testExternalTexture =
275 [[TestExternalTexture alloc] initWidth:width
276 height:height
277 pixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];
278 FlutterExternalTexture* textureHolder =
279 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
280 darwinMetalContext:darwinContextMetal];
281
282 // Callback to resolve the texture.
283 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
284 size_t h) {
285 EXPECT_TRUE(w == width);
286 EXPECT_TRUE(h == height);
287
288 auto texture = std::make_unique<FlutterMetalExternalTexture>();
289 [textureHolder populateTexture:texture.get()];
290
291 EXPECT_TRUE(texture->num_textures == 2);
292 EXPECT_TRUE(texture->textures != nullptr);
293 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kYUVA);
294 EXPECT_TRUE(texture->yuv_color_space ==
295 FlutterMetalExternalTextureYUVColorSpace::kBT601FullRange);
296 return texture;
297 };
298
299 // Render the texture.
300 std::unique_ptr<flutter::Texture> texture =
301 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
302 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
303 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
304 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
305 flutter::Texture::PaintContext context{
306 .canvas = &canvas,
307 .gr_context = grContext,
308 };
309 texture->Paint(context, bounds, /*freeze=*/false, sampling);
310
311 gpuSurface->makeImageSnapshot();
312 }
313
314 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateUnsupportedExternalTexture) {
315 // Constants.
316 const size_t width = 100;
317 const size_t height = 100;
318 const int64_t texture_id = 1;
319
320 // Set up the surface.
321 FlutterDarwinContextMetalSkia* darwinContextMetal =
322 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
323 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
324 GrDirectContext* grContext = darwinContextMetal.mainContext.get();
325 sk_sp<SkSurface> gpuSurface(SkSurfaces::RenderTarget(grContext, skgpu::Budgeted::kNo, info));
326
327 // Create a texture.
328 TestExternalTexture* testExternalTexture =
329 [[TestExternalTexture alloc] initWidth:width
330 height:height
331 pixelFormatType:kCVPixelFormatType_420YpCbCr8PlanarFullRange];
332 FlutterExternalTexture* textureHolder =
333 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
334 darwinMetalContext:darwinContextMetal];
335
336 // Callback to resolve the texture.
337 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
338 size_t h) {
339 EXPECT_TRUE(w == width);
340 EXPECT_TRUE(h == height);
341
342 auto texture = std::make_unique<FlutterMetalExternalTexture>();
343 EXPECT_FALSE([textureHolder populateTexture:texture.get()]);
344 return nullptr;
345 };
346
347 // Render the texture.
348 std::unique_ptr<flutter::Texture> texture =
349 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
350 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
351 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
352 DlSkCanvasAdapter canvas(gpuSurface->getCanvas());
353 flutter::Texture::PaintContext context{
354 .canvas = &canvas,
355 .gr_context = grContext,
356 };
357 texture->Paint(context, bounds, /*freeze=*/false, sampling);
358 }
359
360 TEST_F(FlutterEmbedderExternalTextureTest, TestTextureResolutionImpeller) {
361 // Constants.
362 const size_t width = 100;
363 const size_t height = 100;
364 const int64_t texture_id = 1;
365
366 // Set up the surface.
367 auto device = ::MTLCreateSystemDefaultDevice();
368 impeller::AiksContext aiks_context(CreateImpellerContext(), nullptr);
369
370 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
371
372 // Create a texture.
373 MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init];
374 textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
375 textureDescriptor.width = width;
376 textureDescriptor.height = height;
377 textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
378 id<MTLTexture> mtlTexture = [device newTextureWithDescriptor:textureDescriptor];
379 std::vector<FlutterMetalTextureHandle> textures = {
380 (__bridge FlutterMetalTextureHandle)mtlTexture,
381 };
382
383 // Callback to resolve the texture.
384 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
385 size_t h) {
386 EXPECT_TRUE(w == width);
387 EXPECT_TRUE(h == height);
388
389 auto texture = std::make_unique<FlutterMetalExternalTexture>();
390 texture->struct_size = sizeof(FlutterMetalExternalTexture);
391 texture->num_textures = 1;
392 texture->height = h;
393 texture->width = w;
394 texture->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA;
395 texture->textures = textures.data();
396 return texture;
397 };
398
399 // Render the texture.
400 std::unique_ptr<flutter::Texture> texture =
401 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
402 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
403 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
404
405 DisplayListBuilder builder;
406 flutter::Texture::PaintContext context{
407 .canvas = &builder, .gr_context = nullptr, .aiks_context = &aiks_context};
408 texture->Paint(context, bounds, /*freeze=*/false, sampling);
409
410 ASSERT_TRUE(mtlTexture != nil);
411 }
412
413 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateExternalTextureImpeller) {
414 // Constants.
415 const size_t width = 100;
416 const size_t height = 100;
417 const int64_t texture_id = 1;
418
419 // Set up the surface.
420 FlutterDarwinContextMetalSkia* darwinContextMetal =
421 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
422 impeller::AiksContext aiks_context(CreateImpellerContext(), nullptr);
423 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
424
425 // Create a texture.
426 TestExternalTexture* testExternalTexture =
427 [[TestExternalTexture alloc] initWidth:width
428 height:height
429 pixelFormatType:kCVPixelFormatType_32BGRA];
430 FlutterExternalTexture* textureHolder =
431 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
432 darwinMetalContext:darwinContextMetal];
433
434 // Callback to resolve the texture.
435 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
436 size_t h) {
437 EXPECT_TRUE(w == width);
438 EXPECT_TRUE(h == height);
439
440 auto texture = std::make_unique<FlutterMetalExternalTexture>();
441 [textureHolder populateTexture:texture.get()];
442
443 EXPECT_TRUE(texture->num_textures == 1);
444 EXPECT_TRUE(texture->textures != nullptr);
445 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kRGBA);
446 return texture;
447 };
448
449 // Render the texture.
450 std::unique_ptr<flutter::Texture> texture =
451 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
452 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
453 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
454
455 DisplayListBuilder builder;
456 flutter::Texture::PaintContext context{
457 .canvas = &builder,
458 .gr_context = nullptr,
459 .aiks_context = &aiks_context,
460 };
461 texture->Paint(context, bounds, /*freeze=*/false, sampling);
462 }
463
464 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateExternalTextureYUVAImpeller) {
465 // Constants.
466 const size_t width = 100;
467 const size_t height = 100;
468 const int64_t texture_id = 1;
469
470 // Set up the surface.
471 FlutterDarwinContextMetalSkia* darwinContextMetal =
472 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
473 impeller::AiksContext aiks_context(CreateImpellerContext(), nullptr);
474 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
475
476 // Create a texture.
477 TestExternalTexture* testExternalTexture =
478 [[TestExternalTexture alloc] initWidth:width
479 height:height
480 pixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];
481 FlutterExternalTexture* textureHolder =
482 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
483 darwinMetalContext:darwinContextMetal];
484
485 // Callback to resolve the texture.
486 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
487 size_t h) {
488 EXPECT_TRUE(w == width);
489 EXPECT_TRUE(h == height);
490
491 auto texture = std::make_unique<FlutterMetalExternalTexture>();
492 [textureHolder populateTexture:texture.get()];
493
494 EXPECT_TRUE(texture->num_textures == 2);
495 EXPECT_TRUE(texture->textures != nullptr);
496 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kYUVA);
497 EXPECT_TRUE(texture->yuv_color_space ==
498 FlutterMetalExternalTextureYUVColorSpace::kBT601LimitedRange);
499 return texture;
500 };
501
502 // Render the texture.
503 std::unique_ptr<flutter::Texture> texture =
504 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
505 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
506 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
507
508 DisplayListBuilder builder;
509 flutter::Texture::PaintContext context{
510 .canvas = &builder, .gr_context = nullptr, .aiks_context = &aiks_context};
511 texture->Paint(context, bounds, /*freeze=*/false, sampling);
512 }
513
514 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateExternalTextureYUVA2Impeller) {
515 // Constants.
516 const size_t width = 100;
517 const size_t height = 100;
518 const int64_t texture_id = 1;
519
520 // Set up the surface.
521 FlutterDarwinContextMetalSkia* darwinContextMetal =
522 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
523 impeller::AiksContext aiks_context(CreateImpellerContext(), nullptr);
524 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
525
526 // Create a texture.
527 TestExternalTexture* testExternalTexture =
528 [[TestExternalTexture alloc] initWidth:width
529 height:height
530 pixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];
531 FlutterExternalTexture* textureHolder =
532 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
533 darwinMetalContext:darwinContextMetal];
534
535 // Callback to resolve the texture.
536 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
537 size_t h) {
538 EXPECT_TRUE(w == width);
539 EXPECT_TRUE(h == height);
540
541 auto texture = std::make_unique<FlutterMetalExternalTexture>();
542 [textureHolder populateTexture:texture.get()];
543
544 EXPECT_TRUE(texture->num_textures == 2);
545 EXPECT_TRUE(texture->textures != nullptr);
546 EXPECT_TRUE(texture->pixel_format == FlutterMetalExternalTexturePixelFormat::kYUVA);
547 EXPECT_TRUE(texture->yuv_color_space ==
548 FlutterMetalExternalTextureYUVColorSpace::kBT601FullRange);
549 return texture;
550 };
551
552 // Render the texture.
553 std::unique_ptr<flutter::Texture> texture =
554 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
555 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
556 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
557
558 DisplayListBuilder builder;
559 flutter::Texture::PaintContext context{
560 .canvas = &builder, .gr_context = nullptr, .aiks_context = &aiks_context};
561 texture->Paint(context, bounds, /*freeze=*/false, sampling);
562 }
563
564 TEST_F(FlutterEmbedderExternalTextureTest, TestPopulateUnsupportedExternalTextureImpeller) {
565 // Constants.
566 const size_t width = 100;
567 const size_t height = 100;
568 const int64_t texture_id = 1;
569
570 // Set up the surface.
571 FlutterDarwinContextMetalSkia* darwinContextMetal =
572 [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice];
573 impeller::AiksContext aiks_context(CreateImpellerContext(), nullptr);
574 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
575
576 // Create a texture.
577 TestExternalTexture* testExternalTexture =
578 [[TestExternalTexture alloc] initWidth:width
579 height:height
580 pixelFormatType:kCVPixelFormatType_420YpCbCr8PlanarFullRange];
581 FlutterExternalTexture* textureHolder =
582 [[FlutterExternalTexture alloc] initWithFlutterTexture:testExternalTexture
583 darwinMetalContext:darwinContextMetal];
584
585 // Callback to resolve the texture.
586 EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
587 size_t h) {
588 EXPECT_TRUE(w == width);
589 EXPECT_TRUE(h == height);
590
591 auto texture = std::make_unique<FlutterMetalExternalTexture>();
592 EXPECT_FALSE([textureHolder populateTexture:texture.get()]);
593 return nullptr;
594 };
595
596 // Render the texture.
597 std::unique_ptr<flutter::Texture> texture =
598 std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
599 DlRect bounds = DlRect::MakeWH(info.width(), info.height());
600 DlImageSampling sampling = DlImageSampling::kNearestNeighbor;
601
602 DisplayListBuilder builder;
603 flutter::Texture::PaintContext context{
604 .canvas = &builder, .gr_context = nullptr, .aiks_context = &aiks_context};
605 texture->Paint(context, bounds, /*freeze=*/false, sampling);
606 }
607
608 } // namespace flutter::testing
_height
size_t _height
Definition: FlutterEmbedderExternalTextureTest.mm:56
_pixelFormatType
OSType _pixelFormatType
Definition: FlutterEmbedderExternalTextureTest.mm:59
CreateImpellerContext
static std::shared_ptr< impeller::ContextMTL > CreateImpellerContext()
Definition: FlutterEmbedderExternalTextureTest.mm:34
FlutterExternalTexture.h
FlutterExternalTexture
Definition: FlutterExternalTexture.h:19
-[FlutterExternalTexture populateTexture:]
BOOL populateTexture:(nonnull FlutterMetalExternalTexture *metalTexture)
TestExternalTexture
Definition: FlutterEmbedderExternalTextureTest.mm:48
flutter::testing
Definition: AccessibilityBridgeMacTest.mm:13
flutter::testing::FlutterEmbedderExternalTextureTest
AutoreleasePoolTest FlutterEmbedderExternalTextureTest
Definition: FlutterEmbedderExternalTextureTest.mm:94
flutter::testing::TEST_F
TEST_F(AccessibilityBridgeMacWindowTest, SendsAccessibilityCreateNotificationFlutterViewWindow)
Definition: AccessibilityBridgeMacTest.mm:90
FlutterTexture-p
Definition: FlutterTexture.h:21
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24