Skip to content

[macOS] Add FLETexture and FLETextureRegistrar. #263

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

Closed
wants to merge 19 commits into from
Closed
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
46 changes: 46 additions & 0 deletions library/macos/FLEExternalTexture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import <Foundation/Foundation.h>
#import <FlutterEmbedder/FlutterEmbedder.h>

#import "FLETexture.h"

/**
* Used to bridge external FLETexture objects,
* so the implementer only needs to return the CVPixelBufferRef object,
* which will make the interface consistent with the FlutterTexture.
*/
@interface FLEExternalTexture : NSObject

/**
*
*/
- (nonnull instancetype)initWithExternalTexture:(nonnull id<FLETexture>)external_texture;

/**
* Accept texture rendering notifications from the flutter engine.
*/
- (BOOL)populateTextureWidth:(size_t)width
height:(size_t)height
texture:(FlutterOpenGLTexture *)texture;

/**
*
*/
- (int64_t)textureId;

@property(nullable, weak) id<FLETexture> external_texture;

@end
96 changes: 96 additions & 0 deletions library/macos/FLEExternalTexture.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import "FLEExternalTexture.h"

#import <AppKit/NSOpenGL.h>
#import <CoreVideo/CVOpenGLBuffer.h>
#import <CoreVideo/CVOpenGLTextureCache.h>
#import <OpenGL/gl.h>

@implementation FLEExternalTexture {
CVOpenGLTextureCacheRef _textureCache;
CVPixelBufferRef _pixelBuffer;
}

@synthesize external_texture;

- (instancetype)initWithExternalTexture:(id<FLETexture>)external_texture {
self = [super init];

if (self) {
self.external_texture = external_texture;
}

return self;
}

static void OnGLTextureRelease(CVPixelBufferRef pixelBuffer) {
CVPixelBufferRelease(pixelBuffer);
}

- (int64_t)textureId {
return (NSInteger)(self);
}

- (BOOL)populateTextureWidth:(size_t)width
height:(size_t)height
texture:(FlutterOpenGLTexture *)texture {

if(external_texture == NULL) {
return NO;
}

// Copy image buffer from external texture.
_pixelBuffer = [external_texture copyPixelBuffer];

if(_pixelBuffer == NULL) {
return NO;
}

// Create the texture cache if necessary.
if (_textureCache == NULL) {
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 = CVOpenGLTextureGetTarget(openGLTexture);
texture->name = CVOpenGLTextureGetName(openGLTexture);
texture->format = GL_RGBA8;
texture->destruction_callback = (VoidCallback)&OnGLTextureRelease;
texture->user_data = openGLTexture;

CVPixelBufferRelease(_pixelBuffer);
return YES;
}

- (void)dealloc {
CVOpenGLTextureCacheRelease(_textureCache);
}

@end
6 changes: 6 additions & 0 deletions library/macos/FLEPluginRegistrar.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#import "FLEBinaryMessenger.h"
#import "FLEMethodChannel.h"
#import "FLETexture.h"

/**
* The protocol for an object managing registration for a plugin. It provides access to application
Expand All @@ -31,6 +32,11 @@
*/
@property(nonnull, readonly) id<FLEBinaryMessenger> messenger;

/**
* Returns a `FLETextureRegistry` for registering textures provided by the plugin.
*/
@property(nonnull, readonly) id<FLETextureRegistrar> textures;

/**
* The view displaying Flutter content.
*
Expand Down
52 changes: 52 additions & 0 deletions library/macos/FLETexture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import <Foundation/Foundation.h>
#import <CoreVideo/CVPixelBuffer.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;

@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
3 changes: 2 additions & 1 deletion library/macos/FLEViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#import "FLEPlugin.h"
#import "FLEPluginRegistrar.h"
#import "FLEReshapeListener.h"
#import "FLETexture.h"

/**
* Controls embedder plugins and communication with the underlying Flutter engine, managing a view
Expand All @@ -29,7 +30,7 @@
* Flutter engine in non-interactive mode, or with a drawable Flutter canvas.
*/
@interface FLEViewController
: NSViewController <FLEBinaryMessenger, FLEPluginRegistrar, FLEReshapeListener>
: NSViewController <FLEBinaryMessenger, FLEPluginRegistrar, FLEReshapeListener, FLETextureRegistrar>

/**
* The view this controller manages when launched in interactive mode (headless set to false). Must
Expand Down
48 changes: 47 additions & 1 deletion library/macos/FLEViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#import "FLEReshapeListener.h"
#import "FLETextInputPlugin.h"
#import "FLEView.h"
#import "FLEExternalTexture.h"

static NSString *const kXcodeExtraArgumentOne = @"-NSDocumentRevisionsDebugMode";
static NSString *const kXcodeExtraArgumentTwo = @"YES";
Expand Down Expand Up @@ -95,6 +96,10 @@ - (void)dispatchMouseEvent:(nonnull NSEvent *)event phase:(FlutterPointerPhase)p
*/
- (void)dispatchKeyEvent:(NSEvent *)event ofType:(NSString *)type;

-(BOOL) populateTextureWithIdentifier:(int64_t)texture_identifier
width:(size_t)width
height:(size_t)height
texture:(FlutterOpenGLTexture *)texture;
@end

#pragma mark - Static methods provided to engine configuration
Expand Down Expand Up @@ -144,6 +149,14 @@ static bool OnMakeResourceCurrent(FLEViewController *controller) {
return true;
}

static bool OnAcquireExternalTexture(FLEViewController *controller,
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) { return false; }
Expand Down Expand Up @@ -173,6 +186,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.
FLEBasicMessageChannel *_keyEventChannel;

// A mapping of external textures.
NSMutableDictionary<NSNumber *, FLEExternalTexture *> *_textures;
}

@dynamic view;
Expand All @@ -183,6 +199,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 {
Expand Down Expand Up @@ -327,7 +344,8 @@ + (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;
}
}
Expand All @@ -342,6 +360,30 @@ - (void)makeResourceContextCurrent {
[_resourceContext makeCurrentContext];
}

- (BOOL)populateTextureWithIdentifier:(int64_t)textureId
width:(size_t)width
height:(size_t) height
texture:(FlutterOpenGLTexture *)texture {
return [_textures[@(textureId)] populateTextureWidth:width height:height texture:texture];
}

- (int64_t)registerTexture:(id<FLETexture>)texture {
FLEExternalTexture *fleTexture = [[FLEExternalTexture alloc] initWithExternalTexture: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
Expand Down Expand Up @@ -440,6 +482,10 @@ - (void)setMessageHandlerOnChannel:(nonnull NSString *)channel
return self;
}

- (id<FLETextureRegistrar>)textures {
return self;
}

- (void)addMethodCallDelegate:(nonnull id<FLEPlugin>)delegate
channel:(nonnull FLEMethodChannel *)channel {
[channel setMethodCallHandler:^(FLEMethodCall *call, FLEMethodResult result) {
Expand Down
1 change: 1 addition & 0 deletions library/macos/FlutterEmbedderMac.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@
#import "FLEPlugin.h"
#import "FLEPluginRegistrar.h"
#import "FLEReshapeListener.h"
#import "FLETexture.h"
#import "FLEView.h"
#import "FLEViewController.h"
Loading