Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1696d63

Browse files
committed
Refactor MacOS to use FlutterMacOSCompositor for creating backing stores using
FlutterSurfaceManager.
1 parent 0ce1137 commit 1696d63

11 files changed

+388
-64
lines changed

shell/platform/darwin/macos/BUILD.gn

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ source_set("flutter_framework_source") {
5252
"framework/Source/FlutterEngine_Internal.h",
5353
"framework/Source/FlutterExternalTextureGL.h",
5454
"framework/Source/FlutterExternalTextureGL.mm",
55+
"framework/Source/FlutterMacOSGLCompositor.h",
56+
"framework/Source/FlutterMacOSGLCompositor.mm",
5557
"framework/Source/FlutterMouseCursorPlugin.h",
5658
"framework/Source/FlutterMouseCursorPlugin.mm",
5759
"framework/Source/FlutterResizeSynchronizer.h",
@@ -73,9 +75,13 @@ source_set("flutter_framework_source") {
7375
sources += _flutter_framework_headers
7476

7577
deps = [
78+
"//flutter/flow:flow",
79+
"//flutter/fml",
80+
"//flutter/fml:fml",
7681
"//flutter/shell/platform/common/cpp:common_cpp_switches",
7782
"//flutter/shell/platform/darwin/common:framework_shared",
7883
"//flutter/shell/platform/embedder:embedder_as_internal_library",
84+
"//third_party/skia",
7985
]
8086

8187
public_configs = [ "//flutter:config" ]
@@ -115,7 +121,10 @@ executable("flutter_desktop_darwin_unittests") {
115121

116122
sources = [
117123
"framework/Source/FlutterEngineTest.mm",
124+
"framework/Source/FlutterMacOSGLCompositorUnittests.mm",
118125
"framework/Source/FlutterViewControllerTest.mm",
126+
"framework/Source/FlutterViewControllerTestsUtils.h",
127+
"framework/Source/FlutterViewControllerTestsUtils.mm",
119128
]
120129

121130
cflags_objcc = [ "-fobjc-arc" ]

shell/platform/darwin/macos/framework/Source/FlutterEngine.mm

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
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/FlutterViewController_Internal.h"
13+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h"
1414
#import "flutter/shell/platform/embedder/embedder.h"
1515

1616
/**
@@ -197,6 +197,11 @@ @implementation FlutterEngine {
197197

198198
// Pointer to the Dart AOT snapshot and instruction data.
199199
_FlutterEngineAOTData* _aotData;
200+
201+
// FlutterMacOSGLCompositor is created by the engine.
202+
// This is only created when the engine has a FlutterViewController
203+
// and used to support platform views.
204+
std::unique_ptr<flutter::FlutterMacOSGLCompositor> _macOSCompositor;
200205
}
201206

202207
- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project {
@@ -306,6 +311,15 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
306311
flutterArguments.aot_data = _aotData;
307312
}
308313

314+
// Only create a Compositor if we have a ViewController.
315+
if (_viewController) {
316+
// Engine does not need to manage the life cycle of compositor
317+
// since compositor is captured and copied in embedder.cc.
318+
FlutterCompositor compositor = {};
319+
[self setupCompositor:&compositor];
320+
flutterArguments.compositor = &compositor;
321+
}
322+
309323
FlutterEngineResult result = _embedderAPI.Initialize(
310324
FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine);
311325
if (result != kSuccess) {
@@ -360,6 +374,41 @@ - (void)setViewController:(FlutterViewController*)controller {
360374
}
361375
}
362376

377+
- (void)setupCompositor:(FlutterCompositor*)compositor {
378+
[_mainOpenGLContext makeCurrentContext];
379+
380+
_macOSCompositor =
381+
std::make_unique<flutter::FlutterMacOSGLCompositor>(_viewController, _resourceContext);
382+
383+
compositor->struct_size = sizeof(FlutterCompositor);
384+
compositor->user_data = _macOSCompositor.get();
385+
386+
compositor->create_backing_store_callback = [](const FlutterBackingStoreConfig* config, //
387+
FlutterBackingStore* backing_store_out, //
388+
void* user_data //
389+
) {
390+
return reinterpret_cast<flutter::FlutterMacOSGLCompositor*>(user_data)->CreateBackingStore(
391+
config, backing_store_out);
392+
};
393+
394+
compositor->collect_backing_store_callback = [](const FlutterBackingStore* backing_store, //
395+
void* user_data //
396+
) {
397+
return reinterpret_cast<flutter::FlutterMacOSGLCompositor*>(user_data)->CollectBackingStore(
398+
backing_store);
399+
};
400+
401+
compositor->present_layers_callback = [](const FlutterLayer** layers, //
402+
size_t layers_count, //
403+
void* user_data //
404+
) {
405+
return reinterpret_cast<flutter::FlutterMacOSGLCompositor*>(user_data)->Present(layers,
406+
layers_count);
407+
};
408+
409+
_macOSCompositor->SetPresentCallback([self]() { return [self engineCallbackOnPresent]; });
410+
}
411+
363412
- (id<FlutterBinaryMessenger>)binaryMessenger {
364413
// TODO(stuartmorgan): Switch to FlutterBinaryMessengerRelay to avoid plugins
365414
// keeping the engine alive.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include <vector>
6+
7+
#include "flutter/fml/macros.h"
8+
#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h"
9+
#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
10+
#include "flutter/shell/platform/embedder/embedder.h"
11+
#include "third_party/skia/include/gpu/GrDirectContext.h"
12+
13+
namespace flutter {
14+
15+
/**
16+
* FlutterMacOSGLCompositor creates and manages backing stores used for
17+
* rendering Flutter content and presents Flutter content and Platform views.
18+
*/
19+
class FlutterMacOSGLCompositor {
20+
public:
21+
FlutterMacOSGLCompositor(FlutterViewController* view_controller,
22+
NSOpenGLContext* open_gl_context);
23+
24+
virtual ~FlutterMacOSGLCompositor();
25+
26+
// Creates a backing store according to FlutterBackingStoreConfig
27+
// by modifying backing_store_out.
28+
bool CreateBackingStore(const FlutterBackingStoreConfig* config,
29+
FlutterBackingStore* backing_store_out);
30+
31+
// Releases the memory for any state used by the backing store.
32+
bool CollectBackingStore(const FlutterBackingStore* backing_store);
33+
34+
// Presents the FlutterLayers by updating FlutterView(s) using the
35+
// layer content.
36+
bool Present(const FlutterLayer** layers, size_t layers_count);
37+
38+
using PresentCallback = std::function<bool()>;
39+
40+
// PresentCallback is called at the end of the Present function.
41+
void SetPresentCallback(const PresentCallback& present_callback);
42+
43+
protected:
44+
FlutterViewController* view_controller_;
45+
PresentCallback present_callback_;
46+
NSOpenGLContext* open_gl_context_;
47+
48+
// Creates a FlutterSurfaceManager and uses the FlutterSurfaceManager's
49+
// underlying FBO and texture in the backing store.
50+
bool CreateBackingStoreUsingSurfaceManager(
51+
const FlutterBackingStoreConfig* config,
52+
FlutterBackingStore* backing_store_out);
53+
54+
FML_DISALLOW_COPY_AND_ASSIGN(FlutterMacOSGLCompositor);
55+
};
56+
57+
} // namespace flutter
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h"
6+
7+
#import <OpenGL/gl.h>
8+
#import "flutter/fml/logging.h"
9+
#import "flutter/fml/platform/darwin/cf_utils.h"
10+
#import "third_party/skia/include/core/SkCanvas.h"
11+
#import "third_party/skia/include/core/SkSurface.h"
12+
#import "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
13+
#import "third_party/skia/include/utils/mac/SkCGUtils.h"
14+
15+
#include <unistd.h>
16+
17+
namespace flutter {
18+
19+
FlutterMacOSGLCompositor::FlutterMacOSGLCompositor(FlutterViewController* view_controller,
20+
NSOpenGLContext* open_gl_context)
21+
: view_controller_(view_controller), open_gl_context_(open_gl_context) {}
22+
23+
FlutterMacOSGLCompositor::~FlutterMacOSGLCompositor() = default;
24+
25+
bool FlutterMacOSGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
26+
FlutterBackingStore* backing_store_out) {
27+
return CreateBackingStoreUsingSurfaceManager(config, backing_store_out);
28+
}
29+
30+
bool FlutterMacOSGLCompositor::CollectBackingStore(const FlutterBackingStore* backing_store) {
31+
// Currently no memory has to be released.
32+
return true;
33+
}
34+
35+
bool FlutterMacOSGLCompositor::Present(const FlutterLayer** layers, size_t layers_count) {
36+
for (size_t i = 0; i < layers_count; ++i) {
37+
const auto* layer = layers[i];
38+
FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
39+
switch (layer->type) {
40+
case kFlutterLayerContentTypeBackingStore: {
41+
FlutterSurfaceManager* surfaceManager =
42+
(__bridge FlutterSurfaceManager*)backing_store->user_data;
43+
44+
CGSize size = CGSizeMake(layer->size.width, layer->size.height);
45+
[view_controller_.flutterView frameBufferIDForSize:size];
46+
[surfaceManager setLayerContentWithIOSurface:[surfaceManager getIOSurface]];
47+
break;
48+
}
49+
case kFlutterLayerContentTypePlatformView:
50+
// Add functionality in follow up PR.
51+
FML_CHECK(false) << "Presenting PlatformViews not yet supported";
52+
break;
53+
};
54+
}
55+
return present_callback_();
56+
}
57+
58+
bool FlutterMacOSGLCompositor::CreateBackingStoreUsingSurfaceManager(
59+
const FlutterBackingStoreConfig* config,
60+
FlutterBackingStore* backing_store_out) {
61+
FlutterSurfaceManager* surfaceManager =
62+
[[FlutterSurfaceManager alloc] initWithLayer:view_controller_.flutterView.layer
63+
openGLContext:open_gl_context_];
64+
65+
GLuint fbo = [surfaceManager getFramebuffer];
66+
GLuint texture = [surfaceManager getTexture];
67+
IOSurfaceRef* io_surface_ref = [surfaceManager getIOSurface];
68+
69+
CGSize size = CGSizeMake(config->size.width, config->size.height);
70+
71+
[surfaceManager backTextureWithIOSurface:io_surface_ref size:size backingTexture:texture fbo:fbo];
72+
73+
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
74+
backing_store_out->user_data = (__bridge_retained void*)surfaceManager;
75+
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
76+
backing_store_out->open_gl.framebuffer.target = GL_RGBA8;
77+
backing_store_out->open_gl.framebuffer.name = fbo;
78+
// surfaceManager is managed by ARC. Nothing to be done in destruction callback.
79+
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {};
80+
81+
return true;
82+
}
83+
84+
void FlutterMacOSGLCompositor::SetPresentCallback(
85+
const FlutterMacOSGLCompositor::PresentCallback& present_callback) {
86+
present_callback_ = present_callback;
87+
}
88+
89+
} // namespace flutter
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import <Foundation/Foundation.h>
6+
7+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSGLCompositor.h"
8+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestsUtils.h"
9+
#import "flutter/testing/testing.h"
10+
11+
namespace flutter::testing {
12+
13+
TEST(FlutterMacOSGLCompositorTest, TestPresent) {
14+
id mockViewController = CreateMockViewController(nil);
15+
16+
std::unique_ptr<flutter::FlutterMacOSGLCompositor> macos_compositor =
17+
std::make_unique<FlutterMacOSGLCompositor>(mockViewController, nil);
18+
19+
bool flag = false;
20+
macos_compositor->SetPresentCallback([f = &flag]() {
21+
*f = true;
22+
return true;
23+
});
24+
25+
ASSERT_TRUE(macos_compositor->Present(nil, 0));
26+
ASSERT_TRUE(flag);
27+
}
28+
29+
} // flutter::testing
Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,60 @@
1-
// Copyright 2013 The Flutter Authors. All rights reserved.
2-
// Use of this source code is governed by a BSD-style license that can be
3-
// found in the LICENSE file.
4-
51
#import <Cocoa/Cocoa.h>
62

73
// Manages the IOSurfaces for FlutterView
84
@interface FlutterSurfaceManager : NSObject
95

10-
- (nullable instancetype)initWithLayer:(nonnull CALayer*)containingLayer
11-
openGLContext:(nonnull NSOpenGLContext*)opengLContext;
6+
- (instancetype)initWithLayer:(CALayer*)layer openGLContext:(NSOpenGLContext*)opengLContext;
127

138
- (void)ensureSurfaceSize:(CGSize)size;
149
- (void)swapBuffers;
1510

1611
- (uint32_t)glFrameBufferId;
1712

13+
/**
14+
* Sets the CALayer content to the content of _ioSurface[kBack].
15+
*/
16+
- (void)setLayerContent;
17+
18+
/**
19+
* Sets the CALayer content to the content of the provided ioSurface.
20+
*/
21+
- (void)setLayerContentWithIOSurface:(IOSurfaceRef*)ioSurface;
22+
23+
/**
24+
* Binds the IOSurface to the provided texture/framebuffer.
25+
*/
26+
- (void)backTextureWithIOSurface:(IOSurfaceRef*)ioSurface
27+
size:(CGSize)size
28+
backingTexture:(GLuint)texture
29+
fbo:(GLuint)fbo;
30+
31+
// Methods used by FlutterMacOSCompositor to render Flutter content
32+
// using a single Framebuffer/Texture/IOSurface.
33+
34+
/**
35+
* Returns the kFront framebuffer.
36+
* The framebuffer is used by FlutterMacOSCompositor to create a backing store.
37+
* The framebuffer is collected when the backing store that uses the
38+
* framebuffer is collected.
39+
*/
40+
- (uint32_t)getFramebuffer;
41+
42+
/**
43+
* Returns the kFront texture.
44+
* The texture is used by FlutterMacOSCompositor to create a backing store.
45+
* The texture is collected when the backing store that uses the
46+
* texture is collected.
47+
*/
48+
- (uint32_t)getTexture;
49+
50+
/**
51+
* Returns the kFront IOSurfaceRef.
52+
* The IOSurface is backed by the FBO provided by getFramebuffer
53+
* and texture provided by getTexture. The IOSurface is used
54+
* in FlutterMacOSCompositor's Present call.
55+
* The IOSurface is collected when the backing store that uses the
56+
* IOSurface is collected.
57+
*/
58+
- (IOSurfaceRef*)getIOSurface;
59+
1860
@end

0 commit comments

Comments
 (0)