1010
1111#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
1212#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h"
13- #import " flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h"
1413#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
1514#import " flutter/shell/platform/embedder/embedder.h"
1615
@@ -38,11 +37,42 @@ @interface FlutterEngine () <FlutterBinaryMessenger>
3837 */
3938- (void )sendUserLocales ;
4039
40+ /* *
41+ * Called by the engine to make the context the engine should draw into current.
42+ */
43+ - (bool )engineCallbackOnMakeCurrent ;
44+
45+ /* *
46+ * Called by the engine to clear the context the engine should draw into.
47+ */
48+ - (bool )engineCallbackOnClearCurrent ;
49+
50+ /* *
51+ * Called by the engine when the context's buffers should be swapped.
52+ */
53+ - (bool )engineCallbackOnPresent ;
54+
55+ /* *
56+ * Called by the engine when framebuffer object ID is requested.
57+ */
58+ - (uint32_t )engineCallbackOnFBO : (const FlutterFrameInfo*)info ;
59+
60+ /* *
61+ * Makes the resource context the current context.
62+ */
63+ - (bool )engineCallbackOnMakeResourceCurrent ;
64+
4165/* *
4266 * Handles a platform message from the engine.
4367 */
4468- (void )engineCallbackOnPlatformMessage : (const FlutterPlatformMessage*)message ;
4569
70+ /* *
71+ * Forwards texture copy request to the corresponding texture via |textureID|.
72+ */
73+ - (BOOL )populateTextureWithIdentifier : (int64_t )textureID
74+ openGLTexture : (FlutterOpenGLTexture*)openGLTexture ;
75+
4676/* *
4777 * Requests that the task be posted back the to the Flutter engine at the target time. The target
4878 * time is in the clock used by the Flutter engine.
@@ -89,7 +119,7 @@ - (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine
89119}
90120
91121- (id <FlutterTextureRegistry>)textures {
92- return _flutterEngine. openGLRenderer ;
122+ return _flutterEngine;
93123}
94124
95125- (NSView *)view {
@@ -108,10 +138,38 @@ - (void)addMethodCallDelegate:(nonnull id<FlutterPlugin>)delegate
108138// Callbacks provided to the engine. See the called methods for documentation.
109139#pragma mark - Static methods provided to engine configuration
110140
141+ static bool OnMakeCurrent (FlutterEngine* engine) {
142+ return [engine engineCallbackOnMakeCurrent ];
143+ }
144+
145+ static bool OnClearCurrent (FlutterEngine* engine) {
146+ return [engine engineCallbackOnClearCurrent ];
147+ }
148+
149+ static bool OnPresent (FlutterEngine* engine) {
150+ return [engine engineCallbackOnPresent ];
151+ }
152+
153+ static uint32_t OnFBO (FlutterEngine* engine, const FlutterFrameInfo* info) {
154+ return [engine engineCallbackOnFBO: info];
155+ }
156+
157+ static bool OnMakeResourceCurrent (FlutterEngine* engine) {
158+ return [engine engineCallbackOnMakeResourceCurrent ];
159+ }
160+
111161static void OnPlatformMessage (const FlutterPlatformMessage* message, FlutterEngine* engine) {
112162 [engine engineCallbackOnPlatformMessage: message];
113163}
114164
165+ static bool OnAcquireExternalTexture (FlutterEngine* engine,
166+ int64_t texture_identifier,
167+ size_t width,
168+ size_t height,
169+ FlutterOpenGLTexture* open_gl_texture) {
170+ return [engine populateTextureWithIdentifier: texture_identifier openGLTexture: open_gl_texture];
171+ }
172+
115173#pragma mark -
116174
117175@implementation FlutterEngine {
@@ -121,12 +179,22 @@ @implementation FlutterEngine {
121179 // The project being run by this engine.
122180 FlutterDartProject* _project;
123181
182+ // The context provided to the Flutter engine for resource loading.
183+ NSOpenGLContext * _resourceContext;
184+
185+ // The context that is owned by the currently displayed FlutterView. This is stashed in the engine
186+ // so that the view doesn't need to be accessed from a background thread.
187+ NSOpenGLContext * _mainOpenGLContext;
188+
124189 // A mapping of channel names to the registered handlers for those channels.
125190 NSMutableDictionary <NSString *, FlutterBinaryMessageHandler>* _messageHandlers;
126191
127192 // Whether the engine can continue running after the view controller is removed.
128193 BOOL _allowHeadlessExecution;
129194
195+ // A mapping of textureID to internal FlutterExternalTextureGL adapter.
196+ NSMutableDictionary <NSNumber *, FlutterExternalTextureGL*>* _textures;
197+
130198 // Pointer to the Dart AOT snapshot and instruction data.
131199 _FlutterEngineAOTData* _aotData;
132200}
@@ -143,10 +211,10 @@ - (instancetype)initWithName:(NSString*)labelPrefix
143211
144212 _project = project ?: [[FlutterDartProject alloc ] init ];
145213 _messageHandlers = [[NSMutableDictionary alloc ] init ];
214+ _textures = [[NSMutableDictionary alloc ] init ];
146215 _allowHeadlessExecution = allowHeadlessExecution;
147216 _embedderAPI.struct_size = sizeof (FlutterEngineProcTable);
148217 FlutterEngineGetProcAddresses (&_embedderAPI);
149- _openGLRenderer = [[FlutterOpenGLRenderer alloc ] initWithFlutterEngine: _engine];
150218
151219 NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter ];
152220 [notificationCenter addObserver: self
@@ -174,8 +242,17 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
174242 return NO ;
175243 }
176244
177- [_openGLRenderer attachToFlutterView: _viewController.flutterView];
178- const FlutterRendererConfig rendererConfig = [_openGLRenderer createRendererConfig ];
245+ const FlutterRendererConfig rendererConfig = {
246+ .type = kOpenGL ,
247+ .open_gl .struct_size = sizeof (FlutterOpenGLRendererConfig),
248+ .open_gl .make_current = (BoolCallback)OnMakeCurrent,
249+ .open_gl .clear_current = (BoolCallback)OnClearCurrent,
250+ .open_gl .present = (BoolCallback)OnPresent,
251+ .open_gl .fbo_with_frame_info_callback = (UIntFrameInfoCallback)OnFBO,
252+ .open_gl .fbo_reset_after_present = true ,
253+ .open_gl .make_resource_current = (BoolCallback)OnMakeResourceCurrent,
254+ .open_gl .gl_external_texture_frame_callback = (TextureFrameCallback)OnAcquireExternalTexture,
255+ };
179256
180257 // TODO(stuartmorgan): Move internal channel registration from FlutterViewController to here.
181258
@@ -274,6 +351,15 @@ - (void)loadAOTData:(NSString*)assetsDir {
274351 }
275352}
276353
354+ - (void )setViewController : (FlutterViewController*)controller {
355+ _viewController = controller;
356+ _mainOpenGLContext = controller.flutterView .openGLContext ;
357+ if (!controller && !_allowHeadlessExecution) {
358+ [self shutDownEngine ];
359+ _resourceContext = nil ;
360+ }
361+ }
362+
277363- (id <FlutterBinaryMessenger>)binaryMessenger {
278364 // TODO(stuartmorgan): Switch to FlutterBinaryMessengerRelay to avoid plugins
279365 // keeping the engine alive.
@@ -286,6 +372,17 @@ - (BOOL)running {
286372 return _engine != nullptr ;
287373}
288374
375+ - (NSOpenGLContext *)resourceContext {
376+ if (!_resourceContext) {
377+ NSOpenGLPixelFormatAttribute attributes[] = {
378+ NSOpenGLPFAColorSize , 24 , NSOpenGLPFAAlphaSize , 8 , 0 ,
379+ };
380+ NSOpenGLPixelFormat * pixelFormat = [[NSOpenGLPixelFormat alloc ] initWithAttributes: attributes];
381+ _resourceContext = [[NSOpenGLContext alloc ] initWithFormat: pixelFormat shareContext: nil ];
382+ }
383+ return _resourceContext;
384+ }
385+
289386- (void )updateDisplayConfig {
290387 if (!_engine) {
291388 return ;
@@ -364,6 +461,37 @@ - (void)sendUserLocales {
364461 _embedderAPI.UpdateLocales (_engine, flutterLocaleList.data (), flutterLocaleList.size ());
365462}
366463
464+ - (bool )engineCallbackOnMakeCurrent {
465+ if (!_mainOpenGLContext) {
466+ return false ;
467+ }
468+ [_mainOpenGLContext makeCurrentContext ];
469+ return true ;
470+ }
471+
472+ - (uint32_t )engineCallbackOnFBO : (const FlutterFrameInfo*)info {
473+ CGSize size = CGSizeMake (info->size .width , info->size .height );
474+ return [_viewController.flutterView frameBufferIDForSize: size];
475+ }
476+
477+ - (bool )engineCallbackOnClearCurrent {
478+ [NSOpenGLContext clearCurrentContext ];
479+ return true ;
480+ }
481+
482+ - (bool )engineCallbackOnPresent {
483+ if (!_mainOpenGLContext) {
484+ return false ;
485+ }
486+ [self .viewController.flutterView present ];
487+ return true ;
488+ }
489+
490+ - (bool )engineCallbackOnMakeResourceCurrent {
491+ [self .resourceContext makeCurrentContext ];
492+ return true ;
493+ }
494+
367495- (void )engineCallbackOnPlatformMessage : (const FlutterPlatformMessage*)message {
368496 NSData * messageData = [NSData dataWithBytesNoCopy: (void *)message->message
369497 length: message->message_size
@@ -490,6 +618,31 @@ - (void)cleanupConnection:(FlutterBinaryMessengerConnection)connection {
490618 return [[FlutterEngineRegistrar alloc ] initWithPlugin: pluginName flutterEngine: self ];
491619}
492620
621+ #pragma mark - FlutterTextureRegistrar
622+
623+ - (BOOL )populateTextureWithIdentifier : (int64_t )textureID
624+ openGLTexture : (FlutterOpenGLTexture*)openGLTexture {
625+ return [_textures[@(textureID)] populateTexture: openGLTexture];
626+ }
627+
628+ - (int64_t )registerTexture : (id <FlutterTexture>)texture {
629+ FlutterExternalTextureGL* FlutterTexture =
630+ [[FlutterExternalTextureGL alloc ] initWithFlutterTexture: texture];
631+ int64_t textureID = [FlutterTexture textureID ];
632+ _embedderAPI.RegisterExternalTexture (_engine, textureID);
633+ _textures[@(textureID)] = FlutterTexture;
634+ return textureID;
635+ }
636+
637+ - (void )textureFrameAvailable : (int64_t )textureID {
638+ _embedderAPI.MarkExternalTextureFrameAvailable (_engine, textureID);
639+ }
640+
641+ - (void )unregisterTexture : (int64_t )textureID {
642+ _embedderAPI.UnregisterExternalTexture (_engine, textureID);
643+ [_textures removeObjectForKey: @(textureID)];
644+ }
645+
493646#pragma mark - Task runner integration
494647
495648- (void )postMainThreadTask : (FlutterTask)task targetTimeInNanoseconds : (uint64_t )targetTime {
0 commit comments