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

Commit 9065d23

Browse files
committed
Add additional state to manage frame status and CALayers to FlutterGLCompositor
1 parent aee3776 commit 9065d23

File tree

5 files changed

+121
-26
lines changed

5 files changed

+121
-26
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/FlutterEngine.mm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,8 @@ - (FlutterCompositor*)createFlutterCompositor {
405405
_macOSGLCompositor->SetPresentCallback(
406406
[weak_self]() { return [weak_self engineCallbackOnPresent]; });
407407

408+
_compositor.avoid_cache = true;
409+
408410
return &_compositor;
409411
}
410412

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: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,36 @@
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;
4859
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {
4960
if (user_data != nullptr) {
5061
CFRelease(user_data);
@@ -64,19 +75,33 @@
6475
FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
6576
switch (layer->type) {
6677
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.";
78+
if (backing_store->open_gl.framebuffer.user_data) {
79+
FlutterBackingStoreData* backing_store_data =
80+
(__bridge FlutterBackingStoreData*)backing_store->open_gl.framebuffer.user_data;
81+
82+
FlutterIOSurfaceHolder* io_surface_holder = [backing_store_data getIOSurfaceHolder];
83+
size_t layer_id = [backing_store_data getLayerId];
84+
85+
CALayer* content_layer = ca_layer_map_[layer_id];
86+
87+
FML_CHECK(content_layer) << "Unable to find a content layer with layer id " << layer_id;
88+
89+
content_layer.frame = content_layer.superlayer.bounds;
90+
content_layer.transform = CATransform3DMakeScale(1, -1, 1);
91+
IOSurfaceRef io_surface_contents = [io_surface_holder ioSurface];
92+
[content_layer setContents:(__bridge id)io_surface_contents];
7193
}
7294
break;
7395
}
7496
case kFlutterLayerContentTypePlatformView:
7597
// Add functionality in follow up PR.
76-
FML_CHECK(false) << "Presenting PlatformViews not yet supported";
98+
FML_LOG(WARNING) << "Presenting PlatformViews not yet supported";
7799
break;
78100
};
79101
}
102+
// The frame has been presented, prepare FlutterGLCompositor to
103+
// render a new frame.
104+
frame_started_ = false;
80105
return present_callback_();
81106
}
82107

@@ -85,4 +110,29 @@
85110
present_callback_ = present_callback;
86111
}
87112

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

0 commit comments

Comments
 (0)