-
Notifications
You must be signed in to change notification settings - Fork 6k
Add texture support for macOS shell. #8507
Changes from 11 commits
5302cf8
2953e13
4b422b3
fa3f8b0
a222a4a
668e656
97f1e91
cd636b4
799e9c1
52b1417
e49c549
7589f46
2c60631
42b7502
dbcdf16
9b15427
e4ff652
ba2efa3
9c19bac
6ff0a76
ec8083a
ff49e14
ee09e69
0f06004
09156bf
235314a
650c00a
d4c0be8
cda947c
e78d2e1
eb3bf39
d622f01
ec70d4a
2871956
9b63c65
4962f91
b20be2c
067e8a1
27c6f94
5f6833f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This appears to be identical to FlutterTexture.h other than the prefixes; now that macOS is in the same repo as iOS the goal is to share code whenever possible (and move away from the FLE prefix). You can just add that file to the (If you want to add these comments to FlutterTexture.h, ideally as a separate PR, that would be great, since the existing file isn't commented at all.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @chinmaygarde @stuartmorgan There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should be able to specify that the texture target is GL_TEXTURE_RECTANGLE by specifying the target property of FlutterOpenGLTexture. All the copying ought to be unnecessarily inefficient. |
||
// 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 <CoreVideo/CoreVideo.h> | ||
#import <Foundation/Foundation.h> | ||
|
||
/** | ||
* Implement a texture object for the FLE plugin side. | ||
*/ | ||
@protocol FLETexture <NSObject> | ||
|
||
/** | ||
* When the texture on the platform side is ready, | ||
* the flutter engine will copy the texture buffer | ||
* using copyPixelBuffer. | ||
*/ | ||
- (nullable CVPixelBufferRef)copyPixelBuffer:(size_t)width height:(size_t)height; | ||
|
||
@end | ||
|
||
/** | ||
* The protocol for an object managing registration for texture. | ||
*/ | ||
@protocol FLETextureRegistrar <NSObject> | ||
|
||
/** | ||
* Register a |texture| object and return a textureID. | ||
*/ | ||
- (int64_t)registerTexture:(nonnull id<FLETexture>)texture; | ||
|
||
/** | ||
* Mark a texture buffer is ready. | ||
*/ | ||
- (void)textureFrameAvailable:(int64_t)textureID; | ||
|
||
/** | ||
* Unregister an existing Texture object. | ||
*/ | ||
- (void)unregisterTexture:(int64_t)textureID; | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// 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/macos/framework/Headers/FLETexture.h" | ||
#import "flutter/shell/platform/embedder/embedder.h" | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* Used to bridge FLETexture object and handle the texture copy request. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide more context in this comment:
Providing some high-level explanation of how this class fits into the overall flow of passing textures back and forth wit the engine would be very helpful. |
||
*/ | ||
@interface FLEExternalTextureGL : NSObject | ||
|
||
/** | ||
* Initializes a texture adapter with |texture| return a FLEExternalTextureGL. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm having trouble parsing this comment; what is returning an FLEExternalTextureGL here? |
||
*/ | ||
- (nonnull instancetype)initWithFLETexture:(nonnull id<FLETexture>)texture; | ||
|
||
/** | ||
* Accept texture buffer copy request from the flutter engine. | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add more explanation to this comment:
|
||
*/ | ||
- (BOOL)populateTextureWithWidth:(size_t)width | ||
height:(size_t)height | ||
texture:(nonnull FlutterOpenGLTexture*)texture; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The uses of the word "texture" in this class (header and implementation) need disambiguation. The class itself is a texture, and accepts two different objects that are also textures. In this method, kind of texture is the parameter? (The type provides the answer here, but not at a call site). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking more closely at the implementation, it looks like the texture being populated is the texture that is the last parameter; the current naming makes it sounds like some other internal texture is being populated from these arguments. As a general rule, you should never be naming the same parameter twice in the signature. So unless I'm misunderstanding, this should be |
||
|
||
/** | ||
* The texture ID. | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
- (int64_t)textureID; | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// 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/FLEExternalTextureGL.h" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're moving away from using FLE as a prefix, and this code isn't part of an unstable public API surface, you can use Flutter rather than FLE as the prefix for this class, so that it doesn't need to be renamed later. |
||
|
||
#import <AppKit/AppKit.h> | ||
#import <CoreVideo/CoreVideo.h> | ||
#import <OpenGL/gl.h> | ||
|
||
@implementation FLEExternalTextureGL { | ||
CVOpenGLTextureCacheRef _textureCache; | ||
CVPixelBufferRef _pixelBuffer; | ||
id<FLETexture> _texture; | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
- (instancetype)initWithFLETexture:(id<FLETexture>)texture { | ||
self = [super init]; | ||
if (self) { | ||
_texture = texture; | ||
_pixelBuffer = nil; | ||
_textureCache = nil; | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
return self; | ||
} | ||
|
||
static void OnGLTextureRelease(CVPixelBufferRef pixelBuffer) { | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
CVPixelBufferRelease(pixelBuffer); | ||
} | ||
|
||
- (int64_t)textureID { | ||
return reinterpret_cast<int64_t>(self); | ||
} | ||
|
||
- (BOOL)populateTextureWithWidth:(size_t)width | ||
height:(size_t)height | ||
texture:(FlutterOpenGLTexture*)texture { | ||
if (!_texture) { | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return NO; | ||
} | ||
|
||
// Copy image buffer from external texture. | ||
_pixelBuffer = [_texture copyPixelBuffer:width height:height]; | ||
|
||
if (!_pixelBuffer) { | ||
return NO; | ||
} | ||
|
||
// Create the texture cache if necessary. | ||
if (!_textureCache) { | ||
CGLContextObj context = [NSOpenGLContext currentContext].CGLContextObj; | ||
CGLPixelFormatObj format = CGLGetPixelFormat(context); | ||
if (CVOpenGLTextureCacheCreate(kCFAllocatorDefault, NULL, context, format, NULL, | ||
&_textureCache) != kCVReturnSuccess) { | ||
NSLog(@"Could not create texture cache."); | ||
CVPixelBufferRelease(_pixelBuffer); | ||
return NO; | ||
} | ||
} | ||
|
||
// Try to clear the cache of OpenGL textures to save memory. | ||
CVOpenGLTextureCacheFlush(_textureCache, 0); | ||
|
||
CVOpenGLTextureRef openGLTexture = NULL; | ||
if (CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, _pixelBuffer, | ||
NULL, &openGLTexture) != kCVReturnSuccess) { | ||
CVPixelBufferRelease(_pixelBuffer); | ||
return NO; | ||
} | ||
|
||
texture->target = static_cast<uint32_t>(CVOpenGLTextureGetTarget(openGLTexture)); | ||
texture->name = static_cast<uint32_t>(CVOpenGLTextureGetName(openGLTexture)); | ||
texture->format = static_cast<uint32_t>(GL_RGBA8); | ||
texture->destruction_callback = reinterpret_cast<VoidCallback>(&OnGLTextureRelease); | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
texture->user_data = openGLTexture; | ||
|
||
CVPixelBufferRelease(_pixelBuffer); | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return YES; | ||
} | ||
|
||
- (void)dealloc { | ||
CVOpenGLTextureCacheRelease(_textureCache); | ||
} | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterCodecs.h" | ||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FLEReshapeListener.h" | ||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FLEView.h" | ||
#import "flutter/shell/platform/darwin/macos/framework/Source/FLEExternalTextureGL.h" | ||
#import "flutter/shell/platform/darwin/macos/framework/Source/FLETextInputPlugin.h" | ||
#import "flutter/shell/platform/embedder/embedder.h" | ||
|
||
|
@@ -91,6 +92,14 @@ - (void)dispatchMouseEvent:(nonnull NSEvent*)event phase:(FlutterPointerPhase)ph | |
*/ | ||
- (void)dispatchKeyEvent:(NSEvent*)event ofType:(NSString*)type; | ||
|
||
/** | ||
* Forwarding texture copy request to the corresponding texture via |textureID|, | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* |width| and |height| may be used to get a specific sized texture in the future. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to comment on the meaning of width/height, since this is just forwarding. (Specifically it seems like this comment is talking about implementation details that are in a different class.) |
||
*/ | ||
- (BOOL)populateTextureWithIdentifier:(int64_t)textureID | ||
width:(size_t)width | ||
height:(size_t)height | ||
texture:(FlutterOpenGLTexture*)texture; | ||
@end | ||
|
||
#pragma mark - Static methods provided to engine configuration | ||
|
@@ -142,6 +151,20 @@ static bool OnMakeResourceCurrent(FLEViewController* controller) { | |
return true; | ||
} | ||
|
||
/** | ||
* Dispatching the texture copy request forward to the controller. | ||
*/ | ||
static bool OnAcquireExternalTexture(FLEViewController* controller, | ||
stuartmorgan-g marked this conversation as resolved.
Show resolved
Hide resolved
|
||
int64_t texture_identifier, | ||
size_t width, | ||
size_t height, | ||
FlutterOpenGLTexture* texture) { | ||
return [controller populateTextureWithIdentifier:texture_identifier | ||
width:width | ||
height:height | ||
texture:texture]; | ||
} | ||
|
||
#pragma mark Static methods provided for headless engine configuration | ||
|
||
static bool HeadlessOnMakeCurrent(FLEViewController* controller) { | ||
|
@@ -181,6 +204,9 @@ @implementation FLEViewController { | |
// A message channel for passing key events to the Flutter engine. This should be replaced with | ||
// an embedding API; see Issue #47. | ||
FlutterBasicMessageChannel* _keyEventChannel; | ||
|
||
// A mapping of textureID to internal FLEExternalTextureGL adapter. | ||
NSMutableDictionary<NSNumber*, FLEExternalTextureGL*>* _textures; | ||
} | ||
|
||
@dynamic view; | ||
|
@@ -191,6 +217,7 @@ @implementation FLEViewController { | |
static void CommonInit(FLEViewController* controller) { | ||
controller->_messageHandlers = [[NSMutableDictionary alloc] init]; | ||
controller->_additionalKeyResponders = [[NSMutableOrderedSet alloc] init]; | ||
controller->_textures = [[NSMutableDictionary alloc] init]; | ||
} | ||
|
||
- (instancetype)initWithCoder:(NSCoder*)coder { | ||
|
@@ -374,7 +401,9 @@ + (FlutterRendererConfig)createRenderConfigHeadless:(BOOL)headless { | |
.open_gl.clear_current = (BoolCallback)OnClearCurrent, | ||
.open_gl.present = (BoolCallback)OnPresent, | ||
.open_gl.fbo_callback = (UIntCallback)OnFBO, | ||
.open_gl.make_resource_current = (BoolCallback)OnMakeResourceCurrent}; | ||
.open_gl.make_resource_current = (BoolCallback)OnMakeResourceCurrent, | ||
.open_gl.gl_external_texture_frame_callback = | ||
(TextureFrameCallback)OnAcquireExternalTexture}; | ||
return config; | ||
} | ||
} | ||
|
@@ -389,6 +418,30 @@ - (void)makeResourceContextCurrent { | |
[_resourceContext makeCurrentContext]; | ||
} | ||
|
||
- (BOOL)populateTextureWithIdentifier:(int64_t)textureID | ||
cloudwebrtc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
width:(size_t)width | ||
height:(size_t)height | ||
texture:(FlutterOpenGLTexture*)texture { | ||
return [_textures[@(textureID)] populateTextureWithWidth:width height:height texture:texture]; | ||
} | ||
|
||
- (int64_t)registerTexture:(id<FLETexture>)texture { | ||
FLEExternalTextureGL* fleTexture = [[FLEExternalTextureGL alloc] initWithFLETexture:texture]; | ||
int64_t textureID = [fleTexture textureID]; | ||
FlutterEngineRegisterExternalTexture(_engine, textureID); | ||
_textures[@(textureID)] = fleTexture; | ||
return textureID; | ||
} | ||
|
||
- (void)textureFrameAvailable:(int64_t)textureID { | ||
FlutterEngineMarkExternalTextureFrameAvailable(_engine, textureID); | ||
} | ||
|
||
- (void)unregisterTexture:(int64_t)textureID { | ||
FlutterEngineUnregisterExternalTexture(_engine, textureID); | ||
[_textures removeObjectForKey:@(textureID)]; | ||
} | ||
|
||
- (void)handlePlatformMessage:(const FlutterPlatformMessage*)message { | ||
NSData* messageData = [NSData dataWithBytesNoCopy:(void*)message->message | ||
length:message->message_size | ||
|
@@ -522,6 +575,10 @@ - (void)setMessageHandlerOnChannel:(nonnull NSString*)channel | |
return self; | ||
} | ||
|
||
- (id<FLETextureRegistrar>)textures { | ||
return self; | ||
} | ||
|
||
- (void)addMethodCallDelegate:(nonnull id<FLEPlugin>)delegate | ||
channel:(nonnull FlutterMethodChannel*)channel { | ||
[channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { | ||
|
Uh oh!
There was an error while loading. Please reload this page.