Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c902a16

Browse files
authored
[embedder] [metal] Embedder API can support externally composited Metal textures (#24327)
1 parent 4956ad9 commit c902a16

23 files changed

+796
-206
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterBacki
10991099
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.mm
11001100
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject.mm
11011101
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h
1102+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm
11021103
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
11031104
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm
11041105
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h
@@ -1152,6 +1153,10 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_engine.cc
11521153
FILE: ../../../flutter/shell/platform/embedder/embedder_engine.h
11531154
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.cc
11541155
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.h
1156+
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_metal.h
1157+
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_metal.mm
1158+
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_resolver.cc
1159+
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_resolver.h
11551160
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view.cc
11561161
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view.h
11571162
FILE: ../../../flutter/shell/platform/embedder/embedder_external_view_embedder.cc
@@ -1187,6 +1192,7 @@ FILE: ../../../flutter/shell/platform/embedder/fixtures/compositor_with_platform
11871192
FILE: ../../../flutter/shell/platform/embedder/fixtures/compositor_with_root_layer_only.png
11881193
FILE: ../../../flutter/shell/platform/embedder/fixtures/dpr_noxform.png
11891194
FILE: ../../../flutter/shell/platform/embedder/fixtures/dpr_xform.png
1195+
FILE: ../../../flutter/shell/platform/embedder/fixtures/external_texture_metal.png
11901196
FILE: ../../../flutter/shell/platform/embedder/fixtures/gradient.png
11911197
FILE: ../../../flutter/shell/platform/embedder/fixtures/gradient_metal.png
11921198
FILE: ../../../flutter/shell/platform/embedder/fixtures/gradient_xform.png

shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,22 @@
77

88
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
99
#include "third_party/skia/include/core/SkCanvas.h"
10-
#include "third_party/skia/include/gpu/GrDirectContext.h"
10+
#include "third_party/skia/include/core/SkImage.h"
11+
12+
@interface FlutterDarwinExternalTextureSkImageWrapper : NSObject
13+
14+
+ (sk_sp<SkImage>)wrapYUVATexture:(nonnull id<MTLTexture>)yTex
15+
UVTex:(nonnull id<MTLTexture>)uvTex
16+
grContext:(nonnull GrDirectContext*)grContext
17+
width:(size_t)width
18+
height:(size_t)height;
19+
20+
+ (sk_sp<SkImage>)wrapRGBATexture:(nonnull id<MTLTexture>)rgbaTex
21+
grContext:(nonnull GrDirectContext*)grContext
22+
width:(size_t)width
23+
height:(size_t)height;
24+
25+
@end
1126

1227
@interface FlutterDarwinExternalTextureMetal : NSObject
1328

shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm

Lines changed: 63 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,6 @@
1414

1515
FLUTTER_ASSERT_ARC
1616

17-
namespace {
18-
19-
static sk_cf_obj<const void*> SkiaTextureFromCVMetalTexture(CVMetalTextureRef cvMetalTexture) {
20-
id<MTLTexture> texture = CVMetalTextureGetTexture(cvMetalTexture);
21-
// CVMetal texture can be released as soon as we can the MTLTexture from it.
22-
CVPixelBufferRelease(cvMetalTexture);
23-
return sk_cf_obj<const void*>{(__bridge_retained const void*)texture};
24-
}
25-
26-
}
27-
2817
@implementation FlutterDarwinExternalTextureMetal {
2918
CVMetalTextureCacheRef _textureCache;
3019
NSObject<FlutterTexture>* _externalTexture;
@@ -185,31 +174,17 @@ - (void)onTextureUnregistered {
185174
}
186175
}
187176

188-
GrMtlTextureInfo ySkiaTextureInfo;
189-
ySkiaTextureInfo.fTexture = SkiaTextureFromCVMetalTexture(yMetalTexture);
177+
id<MTLTexture> yTex = CVMetalTextureGetTexture(yMetalTexture);
178+
CVBufferRelease(yMetalTexture);
190179

191-
GrBackendTexture skiaBackendTextures[2];
192-
skiaBackendTextures[0] = GrBackendTexture(/*width=*/textureSize.width(),
193-
/*height=*/textureSize.height(),
194-
/*mipMapped=*/GrMipMapped ::kNo,
195-
/*textureInfo=*/ySkiaTextureInfo);
180+
id<MTLTexture> uvTex = CVMetalTextureGetTexture(uvMetalTexture);
181+
CVBufferRelease(uvMetalTexture);
196182

197-
GrMtlTextureInfo uvSkiaTextureInfo;
198-
uvSkiaTextureInfo.fTexture = SkiaTextureFromCVMetalTexture(uvMetalTexture);
199-
200-
skiaBackendTextures[1] = GrBackendTexture(/*width=*/textureSize.width(),
201-
/*height=*/textureSize.height(),
202-
/*mipMapped=*/GrMipMapped ::kNo,
203-
/*textureInfo=*/uvSkiaTextureInfo);
204-
SkYUVAInfo yuvaInfo(skiaBackendTextures[0].dimensions(), SkYUVAInfo::PlaneConfig::kY_UV,
205-
SkYUVAInfo::Subsampling::k444, kRec601_SkYUVColorSpace);
206-
GrYUVABackendTextures yuvaBackendTextures(yuvaInfo, skiaBackendTextures,
207-
kTopLeft_GrSurfaceOrigin);
208-
209-
sk_sp<SkImage> image =
210-
SkImage::MakeFromYUVATextures(grContext, yuvaBackendTextures, /*imageColorSpace=*/nullptr,
211-
/*releaseProc*/ nullptr, /*releaseContext*/ nullptr);
212-
return image;
183+
return [FlutterDarwinExternalTextureSkImageWrapper wrapYUVATexture:yTex
184+
UVTex:uvTex
185+
grContext:grContext
186+
width:textureSize.width()
187+
height:textureSize.height()];
213188
}
214189

215190
- (sk_sp<SkImage>)wrapRGBAExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
@@ -233,22 +208,64 @@ GrYUVABackendTextures yuvaBackendTextures(yuvaInfo, skiaBackendTextures,
233208
return nullptr;
234209
}
235210

211+
id<MTLTexture> rgbaTex = CVMetalTextureGetTexture(metalTexture);
212+
CVBufferRelease(metalTexture);
213+
214+
return [FlutterDarwinExternalTextureSkImageWrapper wrapRGBATexture:rgbaTex
215+
grContext:grContext
216+
width:textureSize.width()
217+
height:textureSize.height()];
218+
}
219+
220+
@end
221+
222+
@implementation FlutterDarwinExternalTextureSkImageWrapper
223+
224+
+ (sk_sp<SkImage>)wrapYUVATexture:(id<MTLTexture>)yTex
225+
UVTex:(id<MTLTexture>)uvTex
226+
grContext:(nonnull GrDirectContext*)grContext
227+
width:(size_t)width
228+
height:(size_t)height {
229+
GrMtlTextureInfo ySkiaTextureInfo;
230+
ySkiaTextureInfo.fTexture = sk_cf_obj<const void*>{(__bridge_retained const void*)yTex};
231+
232+
GrBackendTexture skiaBackendTextures[2];
233+
skiaBackendTextures[0] = GrBackendTexture(/*width=*/width,
234+
/*height=*/height,
235+
/*mipMapped=*/GrMipMapped::kNo,
236+
/*textureInfo=*/ySkiaTextureInfo);
237+
238+
GrMtlTextureInfo uvSkiaTextureInfo;
239+
uvSkiaTextureInfo.fTexture = sk_cf_obj<const void*>{(__bridge_retained const void*)uvTex};
240+
241+
skiaBackendTextures[1] = GrBackendTexture(/*width=*/width,
242+
/*height=*/height,
243+
/*mipMapped=*/GrMipMapped::kNo,
244+
/*textureInfo=*/uvSkiaTextureInfo);
245+
SkYUVAInfo yuvaInfo(skiaBackendTextures[0].dimensions(), SkYUVAInfo::PlaneConfig::kY_UV,
246+
SkYUVAInfo::Subsampling::k444, kRec601_SkYUVColorSpace);
247+
GrYUVABackendTextures yuvaBackendTextures(yuvaInfo, skiaBackendTextures,
248+
kTopLeft_GrSurfaceOrigin);
249+
250+
return SkImage::MakeFromYUVATextures(grContext, yuvaBackendTextures, /*imageColorSpace=*/nullptr,
251+
/*releaseProc*/ nullptr, /*releaseContext*/ nullptr);
252+
}
253+
254+
+ (sk_sp<SkImage>)wrapRGBATexture:(id<MTLTexture>)rgbaTex
255+
grContext:(nonnull GrDirectContext*)grContext
256+
width:(size_t)width
257+
height:(size_t)height {
236258
GrMtlTextureInfo skiaTextureInfo;
237-
skiaTextureInfo.fTexture = SkiaTextureFromCVMetalTexture(metalTexture);
259+
skiaTextureInfo.fTexture = sk_cf_obj<const void*>{(__bridge_retained const void*)rgbaTex};
238260

239-
GrBackendTexture skiaBackendTexture(/*width=*/textureSize.width(),
240-
/*height=*/textureSize.height(),
261+
GrBackendTexture skiaBackendTexture(/*width=*/width,
262+
/*height=*/height,
241263
/*mipMapped=*/GrMipMapped ::kNo,
242264
/*textureInfo=*/skiaTextureInfo);
243265

244-
sk_sp<SkImage> image =
245-
SkImage::MakeFromTexture(grContext, skiaBackendTexture, kTopLeft_GrSurfaceOrigin,
246-
kBGRA_8888_SkColorType, kPremul_SkAlphaType,
247-
/*imageColorSpace=*/nullptr, /*releaseProc*/ nullptr,
248-
/*releaseContext*/ nullptr
249-
250-
);
251-
return image;
266+
return SkImage::MakeFromTexture(grContext, skiaBackendTexture, kTopLeft_GrSurfaceOrigin,
267+
kBGRA_8888_SkColorType, kPremul_SkAlphaType,
268+
/*imageColorSpace=*/nullptr, /*releaseProc*/ nullptr,
269+
/*releaseContext*/ nullptr);
252270
}
253-
254271
@end

shell/platform/darwin/macos/BUILD.gn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ executable("flutter_desktop_darwin_unittests") {
154154

155155
if (shell_enable_metal) {
156156
sources += [
157+
"framework/Source/FlutterEmbedderExternalTextureUnittests.mm",
157158
"framework/Source/FlutterMetalRendererTest.mm",
158159
"framework/Source/FlutterMetalSurfaceManagerTest.mm",
159160
]
@@ -177,6 +178,10 @@ executable("flutter_desktop_darwin_unittests") {
177178
"//flutter/testing:testing_lib",
178179
"//third_party/ocmock:ocmock",
179180
]
181+
182+
if (shell_enable_metal) {
183+
deps += [ "//flutter/shell/platform/darwin/graphics" ]
184+
}
180185
}
181186

182187
copy("copy_dylib") {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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+
#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h"
12+
#import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h"
13+
#include "flutter/shell/platform/embedder/embedder.h"
14+
#include "flutter/shell/platform/embedder/embedder_external_texture_metal.h"
15+
#import "flutter/testing/testing.h"
16+
#include "third_party/googletest/googletest/include/gtest/gtest.h"
17+
#include "third_party/skia/include/core/SkImage.h"
18+
#include "third_party/skia/include/core/SkSamplingOptions.h"
19+
#include "third_party/skia/include/core/SkSurface.h"
20+
21+
namespace flutter::testing {
22+
23+
TEST(FlutterEmbedderExternalTextureUnittests, TestTextureResolution) {
24+
// constants.
25+
const size_t width = 100;
26+
const size_t height = 100;
27+
const int64_t texture_id = 1;
28+
29+
// setup the surface.
30+
FlutterDarwinContextMetal* darwinContextMetal =
31+
[[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice];
32+
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
33+
GrDirectContext* grContext = darwinContextMetal.mainContext.get();
34+
sk_sp<SkSurface> gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info));
35+
36+
// create a texture.
37+
MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init];
38+
textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
39+
textureDescriptor.width = width;
40+
textureDescriptor.height = height;
41+
textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
42+
id<MTLTexture> mtlTexture =
43+
[darwinContextMetal.device newTextureWithDescriptor:textureDescriptor];
44+
45+
// callback to resolve the texture.
46+
EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w,
47+
size_t h) {
48+
EXPECT_TRUE(w == width);
49+
EXPECT_TRUE(h == height);
50+
51+
FlutterMetalExternalTexture* texture = new FlutterMetalExternalTexture();
52+
texture->struct_size = sizeof(FlutterMetalExternalTexture);
53+
texture->num_textures = 1;
54+
texture->height = h;
55+
texture->width = w;
56+
texture->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA;
57+
58+
std::vector<FlutterMetalTextureHandle> textures = {
59+
(__bridge FlutterMetalTextureHandle)mtlTexture,
60+
};
61+
62+
texture->textures = textures.data();
63+
64+
return std::unique_ptr<FlutterMetalExternalTexture>(texture);
65+
};
66+
67+
// render the texture.
68+
std::unique_ptr<flutter::Texture> texture =
69+
std::make_unique<EmbedderExternalTextureMetal>(texture_id, callback);
70+
SkRect bounds = SkRect::MakeWH(info.width(), info.height());
71+
SkSamplingOptions sampling = SkSamplingOptions(SkFilterMode::kNearest);
72+
texture->Paint(*gpuSurface->getCanvas(), bounds, /*freeze=*/false, grContext, sampling);
73+
74+
ASSERT_TRUE(mtlTexture != nil);
75+
76+
gpuSurface->makeImageSnapshot();
77+
}
78+
79+
} // namespace flutter::testing

shell/platform/embedder/BUILD.gn

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ template("embedder_source_set") {
3434
"embedder.cc",
3535
"embedder_engine.cc",
3636
"embedder_engine.h",
37+
"embedder_external_texture_resolver.cc",
38+
"embedder_external_texture_resolver.h",
3739
"embedder_external_view.cc",
3840
"embedder_external_view.h",
3941
"embedder_external_view_embedder.cc",
@@ -90,6 +92,8 @@ template("embedder_source_set") {
9092

9193
if (embedder_enable_metal) {
9294
sources += [
95+
"embedder_external_texture_metal.h",
96+
"embedder_external_texture_metal.mm",
9397
"embedder_surface_metal.h",
9498
"embedder_surface_metal.mm",
9599
]
@@ -156,6 +160,7 @@ test_fixtures("fixtures") {
156160
"fixtures/dpr_xform.png",
157161
"fixtures/gradient.png",
158162
"fixtures/gradient_metal.png",
163+
"fixtures/external_texture_metal.png",
159164
"fixtures/gradient_xform.png",
160165
"fixtures/scene_without_custom_compositor.png",
161166
"fixtures/scene_without_custom_compositor_with_xform.png",
@@ -226,7 +231,7 @@ if (enable_unittests) {
226231
sources += [
227232
"tests/embedder_test_context_metal.cc",
228233
"tests/embedder_test_context_metal.h",
229-
"tests/embedder_unittests_metal.cc",
234+
"tests/embedder_unittests_metal.mm",
230235
]
231236

232237
deps += [ "//flutter/testing:metal" ]

0 commit comments

Comments
 (0)