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

Commit 62c9c79

Browse files
committed
Add additional state to manage frame status and CALayers to FlutterGLCompositor
1 parent 791731b commit 62c9c79

File tree

5 files changed

+120
-31
lines changed

5 files changed

+120
-31
lines changed

shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h"
6+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h"
7+
58
#import <Cocoa/Cocoa.h>
69

710
/**
@@ -10,8 +13,12 @@
1013
*/
1114
@interface FlutterBackingStoreData : NSObject
1215

13-
- (nullable instancetype)initWithIsRootView:(bool)isRootView;
16+
- (nullable instancetype)initWithLayerId:(size_t)layerId
17+
fbProvider:(nonnull FlutterFrameBufferProvider*)fbProvider
18+
ioSurfaceHolder:(nonnull FlutterIOSurfaceHolder*)ioSurfaceHolder;
1419

15-
- (bool)isRootView;
20+
- (size_t)getLayerId;
21+
- (nonnull FlutterFrameBufferProvider*)getFrameBufferProvider;
22+
- (nonnull FlutterIOSurfaceHolder*)getIOSurfaceHolder;
1623

1724
@end

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,40 @@
33
// found in the LICENSE file.
44

55
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h"
6+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h"
7+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h"
68

79
#include <OpenGL/gl.h>
810

911
@interface FlutterBackingStoreData () {
10-
bool _isRootView;
12+
size_t _layerId;
13+
FlutterFrameBufferProvider* _fbProvider;
14+
FlutterIOSurfaceHolder* _ioSurfaceHolder;
1115
}
1216
@end
1317

1418
@implementation FlutterBackingStoreData
1519

16-
- (nullable instancetype)initWithIsRootView:(bool)isRootView {
20+
- (nullable instancetype)initWithLayerId:(size_t)layerId
21+
fbProvider:(nonnull FlutterFrameBufferProvider*)fbProvider
22+
ioSurfaceHolder:(nonnull FlutterIOSurfaceHolder*)ioSurfaceHolder {
1723
if (self = [super init]) {
18-
_isRootView = isRootView;
24+
_layerId = layerId;
25+
_fbProvider = fbProvider;
26+
_ioSurfaceHolder = ioSurfaceHolder;
1927
}
2028
return self;
2129
}
2230

23-
- (bool)isRootView {
24-
return _isRootView;
31+
- (size_t)getLayerId {
32+
return _layerId;
33+
}
34+
35+
- (nonnull FlutterFrameBufferProvider*)getFrameBufferProvider {
36+
return _fbProvider;
37+
}
38+
- (nonnull FlutterIOSurfaceHolder*)getIOSurfaceHolder {
39+
return _ioSurfaceHolder;
2540
}
2641

2742
@end

shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#include <vector>
5+
#include <map>
66

77
#include "flutter/fml/macros.h"
88
#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h"
@@ -38,6 +38,7 @@ class FlutterGLCompositor {
3838

3939
// Presents the FlutterLayers by updating FlutterView(s) using the
4040
// layer content.
41+
// Present sets frame_started_ to false.
4142
bool Present(const FlutterLayer** layers, size_t layers_count);
4243

4344
using PresentCallback = std::function<bool()>;
@@ -50,6 +51,26 @@ class FlutterGLCompositor {
5051
PresentCallback present_callback_;
5152
NSOpenGLContext* open_gl_context_;
5253

54+
// State to manage CALayers for rendering content.
55+
size_t ca_layer_count_ = 0;
56+
57+
// Maps a layer_id (size_t) to a CALayer.
58+
// The layer_id starts at 0 for a given frame
59+
// and increments by 1 for each new CALayer.
60+
std::map<size_t, CALayer*> ca_layer_map_;
61+
62+
// frame_started_ keeps track of if a layer has been
63+
// created for the frame.
64+
bool frame_started_ = false;
65+
66+
// Set frame_started_ to true and reset all layer state.
67+
void StartFrame();
68+
69+
// Creates a CALayer and adds it to ca_layer_map_ and increments
70+
// ca_layer_count_; Returns the key value (size_t) for the layer in
71+
// ca_layer_map_.
72+
size_t CreateCALayer();
73+
5374
FML_DISALLOW_COPY_AND_ASSIGN(FlutterGLCompositor);
5475
};
5576

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

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,37 @@
2626
bool FlutterGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
2727
FlutterBackingStore* backing_store_out) {
2828
CGSize size = CGSizeMake(config->size.width, config->size.height);
29-
FlutterBackingStoreData* data =
30-
[[FlutterBackingStoreData alloc] initWithIsRootView:config->is_root_view];
3129

32-
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
33-
backing_store_out->is_cacheable = true;
34-
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
35-
backing_store_out->open_gl.framebuffer.target = GL_RGBA8;
36-
37-
if (config->is_root_view) {
38-
// The root view uses FlutterSurfaceManager and is not cacheable since
39-
// the fbo id changes on every present.
40-
backing_store_out->is_cacheable = false;
30+
if (!frame_started_) {
31+
StartFrame();
32+
// If the backing store is for the first layer, return the fbo for the
33+
// FlutterView.
4134
auto fbo = [view_controller_.flutterView frameBufferIDForSize:size];
4235
backing_store_out->open_gl.framebuffer.name = fbo;
4336
} else {
44-
FML_CHECK(false) << "Compositor only supports creating a backing store for the root view";
37+
FlutterFrameBufferProvider* fb_provider =
38+
[[FlutterFrameBufferProvider alloc] initWithOpenGLContext:open_gl_context_];
39+
FlutterIOSurfaceHolder* io_surface_holder = [FlutterIOSurfaceHolder alloc];
40+
41+
GLuint fbo = [fb_provider glFrameBufferId];
42+
GLuint texture = [fb_provider glTextureId];
43+
44+
size_t layer_id = CreateCALayer();
45+
46+
[io_surface_holder bindSurfaceToTexture:texture fbo:fbo size:size];
47+
FlutterBackingStoreData* data =
48+
[[FlutterBackingStoreData alloc] initWithLayerId:layer_id
49+
fbProvider:fb_provider
50+
ioSurfaceHolder:io_surface_holder];
51+
52+
backing_store_out->open_gl.framebuffer.name = fbo;
53+
backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data;
4554
}
4655

47-
backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data;
56+
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
57+
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
58+
backing_store_out->open_gl.framebuffer.target = GL_RGBA8;
59+
backing_store_out->is_cacheable = false;
4860
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {
4961
if (user_data != nullptr) {
5062
CFRelease(user_data);
@@ -64,19 +76,30 @@
6476
FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
6577
switch (layer->type) {
6678
case kFlutterLayerContentTypeBackingStore: {
67-
FlutterBackingStoreData* data =
68-
(__bridge FlutterBackingStoreData*)(backing_store->open_gl.framebuffer.user_data);
69-
if (![data isRootView]) {
70-
FML_CHECK(false) << "Compositor only supports presenting the root view.";
79+
if (backing_store->open_gl.framebuffer.user_data) {
80+
FlutterBackingStoreData* backing_store_data =
81+
(__bridge FlutterBackingStoreData*)backing_store->open_gl.framebuffer.user_data;
82+
83+
FlutterIOSurfaceHolder* io_surface_holder = [backing_store_data getIOSurfaceHolder];
84+
size_t layer_id = [backing_store_data getLayerId];
85+
86+
CALayer* content_layer = ca_layer_map_[layer_id];
87+
content_layer.frame = CGRectMake(0, 0, layer->size.width, layer->size.height);
88+
content_layer.transform = CATransform3DMakeScale(1, -1, 1);
89+
IOSurfaceRef io_surface_contents = [io_surface_holder ioSurface];
90+
[content_layer setContents:(__bridge id)io_surface_contents];
7191
}
7292
break;
7393
}
7494
case kFlutterLayerContentTypePlatformView:
7595
// Add functionality in follow up PR.
76-
FML_CHECK(false) << "Presenting PlatformViews not yet supported";
96+
FML_LOG(WARNING) << "Presenting PlatformViews not yet supported";
7797
break;
7898
};
7999
}
100+
// The frame has been presented, prepare FlutterGLCompositor to
101+
// render a new frame.
102+
frame_started_ = false;
80103
return present_callback_();
81104
}
82105

@@ -85,4 +108,29 @@
85108
present_callback_ = present_callback;
86109
}
87110

111+
void FlutterGLCompositor::StartFrame() {
112+
// First reset all the state.
113+
ca_layer_count_ = 0;
114+
115+
// First remove all CALayers from the superlayer.
116+
for (auto const& x : ca_layer_map_) {
117+
[x.second removeFromSuperlayer];
118+
}
119+
120+
// Reset layer map.
121+
ca_layer_map_.clear();
122+
123+
frame_started_ = true;
124+
}
125+
126+
size_t FlutterGLCompositor::CreateCALayer() {
127+
// FlutterGLCompositor manages the lifecycle of content layers.
128+
// The id for a CALayer starts at 0 and increments by 1 for
129+
// any given frame.
130+
CALayer* content_layer = [[CALayer alloc] init];
131+
[view_controller_.flutterView.layer addSublayer:content_layer];
132+
ca_layer_map_[ca_layer_count_] = content_layer;
133+
return ca_layer_count_++;
134+
}
135+
88136
} // namespace flutter

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,17 +394,15 @@ - (void)addInternalPlugins {
394394
[weakSelf handleMethodCall:call result:result];
395395
}];
396396

397-
[_platformViewsChannel
398-
setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
397+
[_platformViewsChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
399398
// This is hardcoded to create an NSTextView.
400399
NSDictionary<NSString*, id>* args = [call arguments];
401400
long viewId = [args[@"id"] longValue];
402401

403402
MockFlutterPlatformFactory* factory = [MockFlutterPlatformFactory new];
404403

405-
NSObject<FlutterPlatformView>* embedded_view = [factory createWithFrame:CGRectMake(500, 0, 300, 300)
406-
viewIdentifier:viewId
407-
arguments:nil];
404+
NSObject<FlutterPlatformView>* embedded_view =
405+
[factory createWithFrame:CGRectMake(500, 0, 300, 300) viewIdentifier:viewId arguments:nil];
408406

409407
// Hard coded right now to store one platform view in the map.
410408
self->_view_map[1] = [embedded_view view];

0 commit comments

Comments
 (0)