Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External Texture support for macOS Metal #24523

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngin
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.h
Expand All @@ -1118,6 +1120,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSur
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterIntermediateKeyResponder.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterIntermediateKeyResponder.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSExternalTexture.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRendererTest.mm
Expand All @@ -1138,6 +1141,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextI
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputModel.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextureRegistrar.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextureRegistrar.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
Expand Down
7 changes: 7 additions & 0 deletions shell/platform/darwin/macos/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterEngine_Internal.h",
"framework/Source/FlutterExternalTextureGL.h",
"framework/Source/FlutterExternalTextureGL.mm",
"framework/Source/FlutterExternalTextureMetal.h",
"framework/Source/FlutterExternalTextureMetal.mm",
"framework/Source/FlutterFrameBufferProvider.h",
"framework/Source/FlutterFrameBufferProvider.mm",
"framework/Source/FlutterGLCompositor.h",
Expand All @@ -71,6 +73,8 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterIOSurfaceHolder.mm",
"framework/Source/FlutterIntermediateKeyResponder.h",
"framework/Source/FlutterIntermediateKeyResponder.mm",
"framework/Source/FlutterMacOSExternalTexture.h",
"framework/Source/FlutterMacOSExternalTexture.h",
"framework/Source/FlutterMetalRenderer.h",
"framework/Source/FlutterMetalRenderer.mm",
"framework/Source/FlutterMouseCursorPlugin.h",
Expand All @@ -88,6 +92,8 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterTextInputModel.mm",
"framework/Source/FlutterTextInputPlugin.h",
"framework/Source/FlutterTextInputPlugin.mm",
"framework/Source/FlutterTextureRegistrar.h",
"framework/Source/FlutterTextureRegistrar.mm",
"framework/Source/FlutterView.h",
"framework/Source/FlutterView.mm",
"framework/Source/FlutterViewController.mm",
Expand All @@ -104,6 +110,7 @@ source_set("flutter_framework_source") {
"//flutter/fml",
"//flutter/shell/platform/common:common_cpp_switches",
"//flutter/shell/platform/darwin/common:framework_shared",
"//flutter/shell/platform/darwin/graphics:graphics",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
"//third_party/skia",
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@

#import <Foundation/Foundation.h>

#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
#import "flutter/shell/platform/embedder/embedder.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSExternalTexture.h"

/**
* Used to bridge FlutterTexture object and handle the texture copy request the
* Flutter engine.
*/
@interface FlutterExternalTextureGL : NSObject
@interface FlutterExternalTextureGL : NSObject <FlutterMacOSExternalTexture>

/**
* Initializes a texture adapter with |texture| return a instance.
* Initializes a texture adapter with |texture|.
*/
- (nonnull instancetype)initWithFlutterTexture:(nonnull id<FlutterTexture>)texture;

Expand All @@ -26,9 +25,4 @@
*/
- (BOOL)populateTexture:(nonnull FlutterOpenGLTexture*)openGLTexture;

/**
* Returns the ID for the FlutterTexture instance.
*/
- (int64_t)textureID;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <Foundation/Foundation.h>

#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSExternalTexture.h"

/**
* Used to bridge FlutterTexture object and handle the texture copy request the
* Flutter engine.
*/
@interface FlutterExternalTextureMetal : NSObject <FlutterMacOSExternalTexture>

/**
* Initializes a texture adapter with |texture|.
*/
- (nonnull instancetype)initWithFlutterTexture:(nonnull id<FlutterTexture>)texture
darwinMetalContext:(nonnull FlutterDarwinContextMetal*)context;

/**
* Accepts texture buffer copy request from the Flutter engine.
* When the user side marks the textureID as available, the Flutter engine will
* callback to this method and ask for populate the |metalTexture| object,
* such as the texture type and the format of the pixel buffer and the texture object.
*/
- (BOOL)populateTexture:(nonnull FlutterMetalExternalTexture*)metalTexture;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h"

@implementation FlutterExternalTextureMetal {
FlutterDarwinContextMetal* _darwinMetalContext;

int64_t _textureID;

id<FlutterTexture> _texture;

id<MTLTexture> _mtlTexture;
}

- (instancetype)initWithFlutterTexture:(id<FlutterTexture>)texture
darwinMetalContext:(FlutterDarwinContextMetal*)context {
self = [super init];
if (self) {
_texture = texture;
_textureID = reinterpret_cast<int64_t>(_texture);
_darwinMetalContext = context;
}
return self;
}

- (int64_t)textureID {
return _textureID;
}

- (BOOL)populateTexture:(FlutterMetalExternalTexture*)textureOut {
// Copy the pixel buffer from the FlutterTexture instance implemented on the user side.
CVPixelBufferRef pixelBuffer = [_texture copyPixelBuffer];

if (!pixelBuffer) {
return NO;
}

SkISize textureSize =
SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));

CVMetalTextureRef cvMetalTexture = nullptr;
CVReturn cvReturn =
CVMetalTextureCacheCreateTextureFromImage(/*allocator=*/kCFAllocatorDefault,
/*textureCache=*/_darwinMetalContext.textureCache,
/*sourceImage=*/pixelBuffer,
/*textureAttributes=*/nullptr,
/*pixelFormat=*/MTLPixelFormatBGRA8Unorm,
/*width=*/textureSize.width(),
/*height=*/textureSize.height(),
/*planeIndex=*/0u,
/*texture=*/&cvMetalTexture);

if (cvReturn != kCVReturnSuccess) {
NSLog(@"Could not create Metal texture from pixel buffer: CVReturn %d", cvReturn);
return NO;
}

_mtlTexture = CVMetalTextureGetTexture(cvMetalTexture);
CVBufferRelease(cvMetalTexture);

std::vector<FlutterMetalTextureHandle> textures = {
(__bridge FlutterMetalTextureHandle)_mtlTexture};

textureOut->num_textures = 1;
textureOut->height = textureSize.height();
textureOut->width = textureSize.width();
textureOut->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA;
textureOut->textures = textures.data();

return YES;
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <Foundation/Foundation.h>

#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
#import "flutter/shell/platform/embedder/embedder.h"

/*
* Embedding side texture wrappers for GL and Metal external textures.
*/
@protocol FlutterMacOSExternalTexture

/**
* Returns the ID for the FlutterTexture instance.
*/
- (int64_t)textureID;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* FlutterEngine creation and then attached to the FlutterView once the FlutterViewController is
* initialized.
*/
@interface FlutterMetalRenderer : NSObject <FlutterRenderer>
@interface FlutterMetalRenderer : FlutterTextureRegistrar <FlutterRenderer>

/**
* Interface to the system GPU. Used to issue all the rendering commands.
Expand All @@ -34,4 +34,10 @@
*/
- (BOOL)present:(int64_t)textureID;

/**
* Populates the texture registry with the provided metalTexture.
*/
- (BOOL)populateTextureWithIdentifier:(int64_t)textureID
metalTexture:(nonnull FlutterMetalExternalTexture*)metalTexture;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.h"

#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
#include "flutter/shell/platform/embedder/embedder.h"

Expand All @@ -23,16 +24,27 @@ static bool OnPresentDrawable(FlutterEngine* engine, const FlutterMetalTexture*
return [metalRenderer present:texture->texture_id];
}

static bool OnAcquireExternalTexture(FlutterEngine* engine,
int64_t textureIdentifier,
size_t width,
size_t height,
FlutterMetalExternalTexture* metalTexture) {
FlutterMetalRenderer* metalRenderer = reinterpret_cast<FlutterMetalRenderer*>(engine.renderer);
return [metalRenderer populateTextureWithIdentifier:textureIdentifier metalTexture:metalTexture];
}

#pragma mark - FlutterMetalRenderer implementation

@implementation FlutterMetalRenderer {
__weak FlutterEngine* _engine;

FlutterView* _flutterView;

FlutterDarwinContextMetal* _darwinMetalContext;
}

- (instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine {
self = [super init];
self = [super initWithDelegate:self engine:flutterEngine];
if (self) {
_engine = flutterEngine;

Expand All @@ -47,6 +59,9 @@ - (instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine {
NSLog(@"Could not create Metal command queue.");
return nil;
}

_darwinMetalContext = [[FlutterDarwinContextMetal alloc] initWithMTLDevice:_device
commandQueue:_commandQueue];
}
return self;
}
Expand All @@ -65,6 +80,8 @@ - (FlutterRendererConfig)createRendererConfig {
reinterpret_cast<FlutterMetalTextureCallback>(OnGetNextDrawable),
.metal.present_drawable_callback =
reinterpret_cast<FlutterMetalPresentCallback>(OnPresentDrawable),
.metal.external_texture_frame_callback =
reinterpret_cast<FlutterMetalTextureFrameCallback>(OnAcquireExternalTexture),
};
return config;
}
Expand Down Expand Up @@ -92,20 +109,17 @@ - (BOOL)present:(int64_t)textureID {

#pragma mark - FlutterTextureRegistrar methods.

- (int64_t)registerTexture:(id<FlutterTexture>)texture {
NSAssert(NO, @"External textures aren't yet supported when using Metal on macOS."
" See: https://github.com/flutter/flutter/issues/73826");
return 0;
}

- (void)textureFrameAvailable:(int64_t)textureID {
NSAssert(NO, @"External textures aren't yet supported when using Metal on macOS."
" See: https://github.com/flutter/flutter/issues/73826");
- (BOOL)populateTextureWithIdentifier:(int64_t)textureID
metalTexture:(FlutterMetalExternalTexture*)textureOut {
id<FlutterMacOSExternalTexture> texture = [self getTextureWithID:textureID];
FlutterExternalTextureMetal* metalTexture =
reinterpret_cast<FlutterExternalTextureMetal*>(texture);
return [metalTexture populateTexture:textureOut];
}

- (void)unregisterTexture:(int64_t)textureID {
NSAssert(NO, @"External textures aren't yet supported when using Metal on macOS."
" See: https://github.com/flutter/flutter/issues/73826");
- (id<FlutterMacOSExternalTexture>)onRegisterTexture:(id<FlutterTexture>)texture {
return [[FlutterExternalTextureMetal alloc] initWithFlutterTexture:texture
darwinMetalContext:_darwinMetalContext];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* texture management. This is initialized during FlutterEngine creation and then attached to the
* FlutterView once the FlutterViewController is initializer.
*/
@interface FlutterOpenGLRenderer : NSObject <FlutterRenderer>
@interface FlutterOpenGLRenderer : FlutterTextureRegistrar <FlutterRenderer>

/**
* The resource context used by the engine for texture uploads. FlutterViews associated with this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,13 @@ @implementation FlutterOpenGLRenderer {
// The context provided to the Flutter engine for resource loading.
NSOpenGLContext* _resourceContext;

// A mapping of textureID to internal FlutterExternalTextureGL adapter.
NSMutableDictionary<NSNumber*, FlutterExternalTextureGL*>* _textures;

__weak FlutterEngine* _flutterEngine;
}

- (instancetype)initWithFlutterEngine:(FlutterEngine*)flutterEngine {
self = [super init];
self = [super initWithDelegate:self engine:flutterEngine];
if (self) {
_flutterEngine = flutterEngine;
_textures = [[NSMutableDictionary alloc] init];
}
return self;
}
Expand Down Expand Up @@ -136,37 +132,13 @@ - (BOOL)makeResourceCurrent {

- (BOOL)populateTextureWithIdentifier:(int64_t)textureID
openGLTexture:(FlutterOpenGLTexture*)openGLTexture {
return [_textures[@(textureID)] populateTexture:openGLTexture];
}

- (int64_t)registerTexture:(id<FlutterTexture>)texture {
FlutterExternalTextureGL* externalTexture =
[[FlutterExternalTextureGL alloc] initWithFlutterTexture:texture];
int64_t textureID = [externalTexture textureID];
BOOL success = [_flutterEngine registerTextureWithID:textureID];
if (success) {
_textures[@(textureID)] = externalTexture;
return textureID;
} else {
NSLog(@"Unable to register the texture with id: %lld.", textureID);
return 0;
}
}

- (void)textureFrameAvailable:(int64_t)textureID {
BOOL success = [_flutterEngine markTextureFrameAvailable:textureID];
if (!success) {
NSLog(@"Unable to mark texture with id %lld as available.", textureID);
}
id<FlutterMacOSExternalTexture> texture = [self getTextureWithID:textureID];
FlutterExternalTextureGL* glTexture = reinterpret_cast<FlutterExternalTextureGL*>(texture);
return [glTexture populateTexture:openGLTexture];
}

- (void)unregisterTexture:(int64_t)textureID {
bool success = [_flutterEngine unregisterTextureWithID:textureID];
if (success) {
[_textures removeObjectForKey:@(textureID)];
} else {
NSLog(@"Unable to unregister texture with id: %lld.", textureID);
}
- (id<FlutterMacOSExternalTexture>)onRegisterTexture:(id<FlutterTexture>)texture {
return [[FlutterExternalTextureGL alloc] initWithFlutterTexture:texture];
}

- (FlutterRendererConfig)createRendererConfig {
Expand Down
Loading