diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index b2a91424b1af5..44d4905aaec6b 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1054,6 +1054,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExter FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.mm +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h diff --git a/shell/platform/darwin/common/framework/Headers/FlutterTexture.h b/shell/platform/darwin/common/framework/Headers/FlutterTexture.h index 54ab0623be22b..db0b0bdd0c1b0 100644 --- a/shell/platform/darwin/common/framework/Headers/FlutterTexture.h +++ b/shell/platform/darwin/common/framework/Headers/FlutterTexture.h @@ -39,7 +39,7 @@ FLUTTER_EXPORT /** * Registers a `FlutterTexture` for usage in Flutter and returns an id that can be used to reference * that texture when calling into Flutter with channels. Textures must be registered on the - * platform thread. + * platform thread. On success returns the pointer to the registered texture, else returns 0. */ - (int64_t)registerTexture:(NSObject*)texture; /** diff --git a/shell/platform/darwin/macos/BUILD.gn b/shell/platform/darwin/macos/BUILD.gn index 4c345a008c19c..58ecdc3d14860 100644 --- a/shell/platform/darwin/macos/BUILD.gn +++ b/shell/platform/darwin/macos/BUILD.gn @@ -54,6 +54,8 @@ source_set("flutter_framework_source") { "framework/Source/FlutterExternalTextureGL.mm", "framework/Source/FlutterMouseCursorPlugin.h", "framework/Source/FlutterMouseCursorPlugin.mm", + "framework/Source/FlutterOpenGLRenderer.h", + "framework/Source/FlutterOpenGLRenderer.mm", "framework/Source/FlutterResizeSynchronizer.h", "framework/Source/FlutterResizeSynchronizer.mm", "framework/Source/FlutterSurfaceManager.h", diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h b/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h index 3ebbd16fdceff..78b0dec13b05f 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h @@ -21,7 +21,7 @@ * Coordinates a single instance of execution of a Flutter engine. */ FLUTTER_EXPORT -@interface FlutterEngine : NSObject +@interface FlutterEngine : NSObject /** * Initializes an engine with the given viewController. diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index d9ebd55f0d7ec..8c6496499aafc 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -10,6 +10,7 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/embedder/embedder.h" @@ -37,42 +38,11 @@ @interface FlutterEngine () */ - (void)sendUserLocales; -/** - * Called by the engine to make the context the engine should draw into current. - */ -- (bool)engineCallbackOnMakeCurrent; - -/** - * Called by the engine to clear the context the engine should draw into. - */ -- (bool)engineCallbackOnClearCurrent; - -/** - * Called by the engine when the context's buffers should be swapped. - */ -- (bool)engineCallbackOnPresent; - -/** - * Called by the engine when framebuffer object ID is requested. - */ -- (uint32_t)engineCallbackOnFBO:(const FlutterFrameInfo*)info; - -/** - * Makes the resource context the current context. - */ -- (bool)engineCallbackOnMakeResourceCurrent; - /** * Handles a platform message from the engine. */ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message; -/** - * Forwards texture copy request to the corresponding texture via |textureID|. - */ -- (BOOL)populateTextureWithIdentifier:(int64_t)textureID - openGLTexture:(FlutterOpenGLTexture*)openGLTexture; - /** * Requests that the task be posted back the to the Flutter engine at the target time. The target * time is in the clock used by the Flutter engine. @@ -119,7 +89,7 @@ - (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine } - (id)textures { - return _flutterEngine; + return _flutterEngine.openGLRenderer; } - (NSView*)view { @@ -138,38 +108,10 @@ - (void)addMethodCallDelegate:(nonnull id)delegate // Callbacks provided to the engine. See the called methods for documentation. #pragma mark - Static methods provided to engine configuration -static bool OnMakeCurrent(FlutterEngine* engine) { - return [engine engineCallbackOnMakeCurrent]; -} - -static bool OnClearCurrent(FlutterEngine* engine) { - return [engine engineCallbackOnClearCurrent]; -} - -static bool OnPresent(FlutterEngine* engine) { - return [engine engineCallbackOnPresent]; -} - -static uint32_t OnFBO(FlutterEngine* engine, const FlutterFrameInfo* info) { - return [engine engineCallbackOnFBO:info]; -} - -static bool OnMakeResourceCurrent(FlutterEngine* engine) { - return [engine engineCallbackOnMakeResourceCurrent]; -} - static void OnPlatformMessage(const FlutterPlatformMessage* message, FlutterEngine* engine) { [engine engineCallbackOnPlatformMessage:message]; } -static bool OnAcquireExternalTexture(FlutterEngine* engine, - int64_t texture_identifier, - size_t width, - size_t height, - FlutterOpenGLTexture* open_gl_texture) { - return [engine populateTextureWithIdentifier:texture_identifier openGLTexture:open_gl_texture]; -} - #pragma mark - @implementation FlutterEngine { @@ -179,22 +121,12 @@ @implementation FlutterEngine { // The project being run by this engine. FlutterDartProject* _project; - // The context provided to the Flutter engine for resource loading. - NSOpenGLContext* _resourceContext; - - // The context that is owned by the currently displayed FlutterView. This is stashed in the engine - // so that the view doesn't need to be accessed from a background thread. - NSOpenGLContext* _mainOpenGLContext; - // A mapping of channel names to the registered handlers for those channels. NSMutableDictionary* _messageHandlers; // Whether the engine can continue running after the view controller is removed. BOOL _allowHeadlessExecution; - // A mapping of textureID to internal FlutterExternalTextureGL adapter. - NSMutableDictionary* _textures; - // Pointer to the Dart AOT snapshot and instruction data. _FlutterEngineAOTData* _aotData; } @@ -211,10 +143,10 @@ - (instancetype)initWithName:(NSString*)labelPrefix _project = project ?: [[FlutterDartProject alloc] init]; _messageHandlers = [[NSMutableDictionary alloc] init]; - _textures = [[NSMutableDictionary alloc] init]; _allowHeadlessExecution = allowHeadlessExecution; _embedderAPI.struct_size = sizeof(FlutterEngineProcTable); FlutterEngineGetProcAddresses(&_embedderAPI); + _openGLRenderer = [[FlutterOpenGLRenderer alloc] initWithFlutterEngine:_engine]; NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self @@ -242,17 +174,8 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { return NO; } - const FlutterRendererConfig rendererConfig = { - .type = kOpenGL, - .open_gl.struct_size = sizeof(FlutterOpenGLRendererConfig), - .open_gl.make_current = (BoolCallback)OnMakeCurrent, - .open_gl.clear_current = (BoolCallback)OnClearCurrent, - .open_gl.present = (BoolCallback)OnPresent, - .open_gl.fbo_with_frame_info_callback = (UIntFrameInfoCallback)OnFBO, - .open_gl.fbo_reset_after_present = true, - .open_gl.make_resource_current = (BoolCallback)OnMakeResourceCurrent, - .open_gl.gl_external_texture_frame_callback = (TextureFrameCallback)OnAcquireExternalTexture, - }; + [_openGLRenderer attachToFlutterView:_viewController.flutterView]; + const FlutterRendererConfig rendererConfig = [_openGLRenderer createRendererConfig]; // TODO(stuartmorgan): Move internal channel registration from FlutterViewController to here. @@ -351,15 +274,6 @@ - (void)loadAOTData:(NSString*)assetsDir { } } -- (void)setViewController:(FlutterViewController*)controller { - _viewController = controller; - _mainOpenGLContext = controller.flutterView.openGLContext; - if (!controller && !_allowHeadlessExecution) { - [self shutDownEngine]; - _resourceContext = nil; - } -} - - (id)binaryMessenger { // TODO(stuartmorgan): Switch to FlutterBinaryMessengerRelay to avoid plugins // keeping the engine alive. @@ -372,17 +286,6 @@ - (BOOL)running { return _engine != nullptr; } -- (NSOpenGLContext*)resourceContext { - if (!_resourceContext) { - NSOpenGLPixelFormatAttribute attributes[] = { - NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, 0, - }; - NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - _resourceContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; - } - return _resourceContext; -} - - (void)updateDisplayConfig { if (!_engine) { return; @@ -461,37 +364,6 @@ - (void)sendUserLocales { _embedderAPI.UpdateLocales(_engine, flutterLocaleList.data(), flutterLocaleList.size()); } -- (bool)engineCallbackOnMakeCurrent { - if (!_mainOpenGLContext) { - return false; - } - [_mainOpenGLContext makeCurrentContext]; - return true; -} - -- (uint32_t)engineCallbackOnFBO:(const FlutterFrameInfo*)info { - CGSize size = CGSizeMake(info->size.width, info->size.height); - return [_viewController.flutterView frameBufferIDForSize:size]; -} - -- (bool)engineCallbackOnClearCurrent { - [NSOpenGLContext clearCurrentContext]; - return true; -} - -- (bool)engineCallbackOnPresent { - if (!_mainOpenGLContext) { - return false; - } - [self.viewController.flutterView present]; - return true; -} - -- (bool)engineCallbackOnMakeResourceCurrent { - [self.resourceContext makeCurrentContext]; - return true; -} - - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message { NSData* messageData = [NSData dataWithBytesNoCopy:(void*)message->message length:message->message_size @@ -618,31 +490,6 @@ - (void)cleanupConnection:(FlutterBinaryMessengerConnection)connection { return [[FlutterEngineRegistrar alloc] initWithPlugin:pluginName flutterEngine:self]; } -#pragma mark - FlutterTextureRegistrar - -- (BOOL)populateTextureWithIdentifier:(int64_t)textureID - openGLTexture:(FlutterOpenGLTexture*)openGLTexture { - return [_textures[@(textureID)] populateTexture:openGLTexture]; -} - -- (int64_t)registerTexture:(id)texture { - FlutterExternalTextureGL* FlutterTexture = - [[FlutterExternalTextureGL alloc] initWithFlutterTexture:texture]; - int64_t textureID = [FlutterTexture textureID]; - _embedderAPI.RegisterExternalTexture(_engine, textureID); - _textures[@(textureID)] = FlutterTexture; - return textureID; -} - -- (void)textureFrameAvailable:(int64_t)textureID { - _embedderAPI.MarkExternalTextureFrameAvailable(_engine, textureID); -} - -- (void)unregisterTexture:(int64_t)textureID { - _embedderAPI.UnregisterExternalTexture(_engine, textureID); - [_textures removeObjectForKey:@(textureID)]; -} - #pragma mark - Task runner integration - (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)targetTime { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h b/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h index 48a27da52c5c7..f7ccb9a8cfc22 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h @@ -6,6 +6,7 @@ #import +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h" #include "flutter/shell/platform/embedder/embedder.h" @interface FlutterEngine () @@ -16,10 +17,10 @@ @property(nonatomic, readonly) BOOL running; /** - * The resource context used by the engine for texture uploads. FlutterViews associated with this - * engine should be created to share with this context. + * Provides the renderer config needed to initialize the engine and also handles external texture + * management. */ -@property(nonatomic, readonly, nullable) NSOpenGLContext* resourceContext; +@property(nonatomic, readonly, nonnull) FlutterOpenGLRenderer* openGLRenderer; /** * Function pointers for interacting with the embedder.h API. diff --git a/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h b/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h new file mode 100644 index 0000000000000..7d9c19e522b36 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h @@ -0,0 +1,80 @@ +// 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 + +#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h" +#import "flutter/shell/platform/embedder/embedder.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides the renderer config needed to initialize the embedder engine and also handles external + * texture management. This is initialized during FlutterEngine creation and then attached to the + * FlutterView once the FlutterViewController is initializer. + */ +@interface FlutterOpenGLRenderer : NSObject + +/** + * The resource context used by the engine for texture uploads. FlutterViews associated with this + * engine should be created to share with this context. + */ +@property(nonatomic, readonly, nullable) NSOpenGLContext* resourceContext; + +/** + * Intializes the renderer with the given FlutterEngine. + */ +- (instancetype)initWithFlutterEngine:(FLUTTER_API_SYMBOL(FlutterEngine))engine; + +/** + * Attaches to the FlutterView and sets up the renderers main OpenGL context. + */ +- (void)attachToFlutterView:(FlutterView*)view; + +/** + * Called by the engine to make the context the engine should draw into current. + */ +- (bool)makeCurrent; + +/** + * Called by the engine to clear the context the engine should draw into. + */ +- (bool)clearCurrent; + +/** + * Called by the engine when the context's buffers should be swapped. + */ +- (bool)present; + +/** + * Called by the engine when framebuffer object ID is requested. + */ +- (uint32_t)getFBO:(const FlutterFrameInfo*)info; + +/** + * Makes the resource context the current context. + */ +- (bool)makeResourceCurrent; + +/** + * Called by the engine to unset the resource context. + */ +- (void)clearResourceContext; + +/** + * Populates the texture registry with the provided openGLTexture. + */ +- (BOOL)populateTextureWithIdentifier:(int64_t)textureID + openGLTexture:(FlutterOpenGLTexture*)openGLTexture; + +/** + * Creates a FlutterRendererConfig that renders using OpenGL context(s) held + * by this class. + */ +- (FlutterRendererConfig)createRendererConfig; + +@end + +NS_ASSUME_NONNULL_END diff --git a/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.mm b/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.mm new file mode 100644 index 0000000000000..8ae9a2f98d977 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.mm @@ -0,0 +1,179 @@ +// 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/FlutterOpenGLRenderer.h" +#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h" +#include "flutter/shell/platform/embedder/embedder.h" + +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h" + +#pragma mark - Static methods for openGL callbacks that require the engine. + +static bool OnMakeCurrent(FlutterEngine* engine) { + return [engine.openGLRenderer makeCurrent]; +} + +static bool OnClearCurrent(FlutterEngine* engine) { + return [engine.openGLRenderer clearCurrent]; +} + +static bool OnPresent(FlutterEngine* engine) { + return [engine.openGLRenderer present]; +} + +static uint32_t OnFBO(FlutterEngine* engine, const FlutterFrameInfo* info) { + return [engine.openGLRenderer getFBO:info]; +} + +static bool OnMakeResourceCurrent(FlutterEngine* engine) { + return [engine.openGLRenderer makeResourceCurrent]; +} + +static bool OnAcquireExternalTexture(FlutterEngine* engine, + int64_t textureIdentifier, + size_t width, + size_t height, + FlutterOpenGLTexture* openGlTexture) { + return [engine.openGLRenderer populateTextureWithIdentifier:textureIdentifier + openGLTexture:openGlTexture]; +} + +#pragma mark - FlutterOpenGLRenderer implementation. + +@implementation FlutterOpenGLRenderer { + // The embedding-API-level engine object. + FLUTTER_API_SYMBOL(FlutterEngine) _engine; + + FlutterView* _flutterView; + + // The context that is owned by the currently displayed FlutterView. This is stashed + // in the renderer so that the view doesn't need to be accessed from a background thread. + NSOpenGLContext* _openGLContext; + + // The context provided to the Flutter engine for resource loading. + NSOpenGLContext* _resourceContext; + + // A mapping of textureID to internal FlutterExternalTextureGL adapter. + NSMutableDictionary* _textures; + + FlutterEngineProcTable _embedderAPI; +} + +- (instancetype)initWithFlutterEngine:(FLUTTER_API_SYMBOL(FlutterEngine))engine { + self = [super init]; + if (self) { + _engine = engine; + _textures = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)attachToFlutterView:(FlutterView*)view { + _flutterView = view; + _openGLContext = view.openGLContext; +} + +- (bool)makeCurrent { + if (!_openGLContext) { + return false; + } + [_openGLContext makeCurrentContext]; + return true; +} + +- (bool)clearCurrent { + [NSOpenGLContext clearCurrentContext]; + return true; +} + +- (bool)present { + if (!_openGLContext) { + return false; + } + [_flutterView present]; + return true; +} + +- (uint32_t)getFBO:(const FlutterFrameInfo*)info { + CGSize size = CGSizeMake(info->size.width, info->size.height); + return [_flutterView frameBufferIDForSize:size]; +} + +- (NSOpenGLContext*)resourceContext { + if (!_resourceContext) { + NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, 0, + }; + NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + _resourceContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; + } + return _resourceContext; +} + +- (bool)makeResourceCurrent { + [self.resourceContext makeCurrentContext]; + return true; +} + +- (void)clearResourceContext { + _resourceContext = nil; +} + +#pragma mark - FlutterTextureRegistrar + +- (BOOL)populateTextureWithIdentifier:(int64_t)textureID + openGLTexture:(FlutterOpenGLTexture*)openGLTexture { + return [_textures[@(textureID)] populateTexture:openGLTexture]; +} + +- (int64_t)registerTexture:(id)texture { + FlutterExternalTextureGL* FlutterTexture = + [[FlutterExternalTextureGL alloc] initWithFlutterTexture:texture]; + int64_t textureID = [FlutterTexture textureID]; + auto success = _embedderAPI.RegisterExternalTexture(_engine, textureID); + if (success == FlutterEngineResult::kSuccess) { + _textures[@(textureID)] = FlutterTexture; + return textureID; + } else { + NSLog(@"Unable to register the texture with id: %lld.", textureID); + return 0; + } +} + +- (void)textureFrameAvailable:(int64_t)textureID { + auto success = _embedderAPI.MarkExternalTextureFrameAvailable(_engine, textureID); + if (success != FlutterEngineResult::kSuccess) { + NSLog(@"Unable to mark texture with id %lld as available.", textureID); + } +} + +- (void)unregisterTexture:(int64_t)textureID { + auto success = _embedderAPI.UnregisterExternalTexture(_engine, textureID); + if (success == FlutterEngineResult::kSuccess) { + [_textures removeObjectForKey:@(textureID)]; + } else { + NSLog(@"Unable to unregister texture with id: %lld.", textureID); + } +} + +#pragma mark - Helper methods to create rendering config for embedder. + +- (FlutterRendererConfig)createRendererConfig { + const FlutterRendererConfig rendererConfig = { + .type = kOpenGL, + .open_gl.struct_size = sizeof(FlutterOpenGLRendererConfig), + .open_gl.make_current = reinterpret_cast(OnMakeCurrent), + .open_gl.clear_current = reinterpret_cast(OnClearCurrent), + .open_gl.present = reinterpret_cast(OnPresent), + .open_gl.fbo_with_frame_info_callback = reinterpret_cast(OnFBO), + .open_gl.fbo_reset_after_present = true, + .open_gl.make_resource_current = reinterpret_cast(OnMakeResourceCurrent), + .open_gl.gl_external_texture_frame_callback = + reinterpret_cast(OnAcquireExternalTexture), + }; + return rendererConfig; +} + +@end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index cc5eaba49bf39..8fce6403c754e 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -239,7 +239,7 @@ - (instancetype)initWithProject:(nullable FlutterDartProject*)project { } - (void)loadView { - NSOpenGLContext* resourceContext = _engine.resourceContext; + NSOpenGLContext* resourceContext = _engine.openGLRenderer.resourceContext; if (!resourceContext) { NSLog(@"Unable to create FlutterView; no resource context available."); return;