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

Commit 191a305

Browse files
committed
Add additional state to manage frame status and CALayers to FlutterGLCompositor
1 parent 7c09d8a commit 191a305

9 files changed

+133
-43
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,35 @@
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>
9+
#import <Foundation/Foundation.h>
610

711
/**
812
* FlutterBackingStoreData holds data to be stored in the
913
* BackingStore's user_data.
1014
*/
1115
@interface FlutterBackingStoreData : NSObject
1216

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

15-
- (bool)isRootView;
21+
/**
22+
* layerId is the layer's key value in FlutterGLCompositor's ca_layer_map_.
23+
*/
24+
@property(nonatomic, readonly) size_t layerId;
25+
26+
/**
27+
* frameBufferProvider used to provide the fbo for rendering the layer.
28+
*/
29+
@property(nonnull, nonatomic, readonly) FlutterFrameBufferProvider* frameBufferProvider;
30+
31+
/**
32+
* ioSurfaceHolder contains the IOSurfaceRef with the layer contents.
33+
*/
34+
@property(nonnull, nonatomic, readonly) FlutterIOSurfaceHolder* ioSurfaceHolder;
1635

1736
@end

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

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,22 @@
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

9-
@interface FlutterBackingStoreData () {
10-
bool _isRootView;
11-
}
12-
@end
13-
1411
@implementation FlutterBackingStoreData
1512

16-
- (nullable instancetype)initWithIsRootView:(bool)isRootView {
13+
- (nullable instancetype)initWithLayerId:(size_t)layerId
14+
fbProvider:(nonnull FlutterFrameBufferProvider*)fbProvider
15+
ioSurfaceHolder:(nonnull FlutterIOSurfaceHolder*)ioSurfaceHolder {
1716
if (self = [super init]) {
18-
_isRootView = isRootView;
17+
_layerId = layerId;
18+
_frameBufferProvider = fbProvider;
19+
_ioSurfaceHolder = ioSurfaceHolder;
1920
}
2021
return self;
2122
}
2223

23-
- (bool)isRootView {
24-
return _isRootView;
25-
}
26-
2724
@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/FlutterFrameBufferProvider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
@interface FlutterFrameBufferProvider : NSObject
1111

12-
- (nullable instancetype)initWithOpenGLContext:(nonnull NSOpenGLContext*)opengLContext;
12+
- (nullable instancetype)initWithOpenGLContext:(nonnull const NSOpenGLContext*)opengLContext;
1313

1414
/**
1515
* Returns the id of the framebuffer.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ @interface FlutterFrameBufferProvider () {
1515
@end
1616

1717
@implementation FlutterFrameBufferProvider
18-
- (instancetype)initWithOpenGLContext:(NSOpenGLContext*)openGLContext {
18+
- (instancetype)initWithOpenGLContext:(const NSOpenGLContext*)openGLContext {
1919
if (self = [super init]) {
2020
MacOSGLContextSwitch context_switch(openGLContext);
2121

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

Lines changed: 26 additions & 3 deletions
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()>;
@@ -46,9 +47,31 @@ class FlutterGLCompositor {
4647
void SetPresentCallback(const PresentCallback& present_callback);
4748

4849
private:
49-
FlutterViewController* view_controller_;
50+
const FlutterViewController* view_controller_;
51+
const NSOpenGLContext* open_gl_context_;
5052
PresentCallback present_callback_;
51-
NSOpenGLContext* open_gl_context_;
53+
54+
// Count for how many CALayers have been created for a frame.
55+
// Resets when a frame is finished.
56+
// ca_layer_count_ is also used as a layerId.
57+
size_t ca_layer_count_ = 0;
58+
59+
// Maps a layer_id (size_t) to a CALayer.
60+
// The layer_id starts at 0 for a given frame
61+
// and increments by 1 for each new CALayer.
62+
std::map<size_t, CALayer*> ca_layer_map_;
63+
64+
// frame_started_ keeps track of if a layer has been
65+
// created for the frame.
66+
bool frame_started_ = false;
67+
68+
// Set frame_started_ to true and reset all layer state.
69+
void StartFrame();
70+
71+
// Creates a CALayer and adds it to ca_layer_map_ and increments
72+
// ca_layer_count_; Returns the key value (size_t) for the layer in
73+
// ca_layer_map_.
74+
size_t CreateCALayer();
5275

5376
FML_DISALLOW_COPY_AND_ASSIGN(FlutterGLCompositor);
5477
};

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

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

55
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.h"
6-
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h"
7-
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h"
8-
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h"
96

107
#import <OpenGL/gl.h>
8+
119
#import "flutter/fml/logging.h"
1210
#import "flutter/fml/platform/darwin/cf_utils.h"
11+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h"
12+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h"
13+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h"
1314
#import "third_party/skia/include/core/SkCanvas.h"
1415
#import "third_party/skia/include/core/SkSurface.h"
1516
#import "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
1617
#import "third_party/skia/include/utils/mac/SkCGUtils.h"
1718

18-
#include <unistd.h>
19-
2019
namespace flutter {
2120

2221
FlutterGLCompositor::FlutterGLCompositor(FlutterViewController* view_controller)
@@ -26,25 +25,36 @@
2625
bool FlutterGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
2726
FlutterBackingStore* backing_store_out) {
2827
CGSize size = CGSizeMake(config->size.width, config->size.height);
29-
FlutterBackingStoreData* data =
30-
[[FlutterBackingStoreData alloc] initWithIsRootView:config->is_root_view];
3128

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;
29+
if (!frame_started_) {
30+
StartFrame();
31+
// If the backing store is for the first layer, return the fbo for the
32+
// FlutterView.
4133
auto fbo = [view_controller_.flutterView frameBufferIDForSize:size];
4234
backing_store_out->open_gl.framebuffer.name = fbo;
4335
} else {
44-
FML_CHECK(false) << "Compositor only supports creating a backing store for the root view";
36+
FlutterFrameBufferProvider* fb_provider =
37+
[[FlutterFrameBufferProvider alloc] initWithOpenGLContext:open_gl_context_];
38+
FlutterIOSurfaceHolder* io_surface_holder = [FlutterIOSurfaceHolder alloc];
39+
40+
GLuint fbo = [fb_provider glFrameBufferId];
41+
GLuint texture = [fb_provider glTextureId];
42+
43+
size_t layer_id = CreateCALayer();
44+
45+
[io_surface_holder bindSurfaceToTexture:texture fbo:fbo size:size];
46+
FlutterBackingStoreData* data =
47+
[[FlutterBackingStoreData alloc] initWithLayerId:layer_id
48+
fbProvider:fb_provider
49+
ioSurfaceHolder:io_surface_holder];
50+
51+
backing_store_out->open_gl.framebuffer.name = fbo;
52+
backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data;
4553
}
4654

47-
backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data;
55+
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
56+
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
57+
backing_store_out->open_gl.framebuffer.target = GL_RGBA8;
4858
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {
4959
if (user_data != nullptr) {
5060
CFRelease(user_data);
@@ -64,19 +74,33 @@
6474
FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
6575
switch (layer->type) {
6676
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.";
77+
if (backing_store->open_gl.framebuffer.user_data) {
78+
FlutterBackingStoreData* backing_store_data =
79+
(__bridge FlutterBackingStoreData*)backing_store->open_gl.framebuffer.user_data;
80+
81+
FlutterIOSurfaceHolder* io_surface_holder = [backing_store_data ioSurfaceHolder];
82+
size_t layer_id = [backing_store_data layerId];
83+
84+
CALayer* content_layer = ca_layer_map_[layer_id];
85+
86+
FML_CHECK(content_layer) << "Unable to find a content layer with layer id " << layer_id;
87+
88+
content_layer.frame = content_layer.superlayer.bounds;
89+
content_layer.transform = CATransform3DMakeScale(1, -1, 1);
90+
IOSurfaceRef io_surface_contents = [io_surface_holder ioSurface];
91+
[content_layer setContents:(__bridge id)io_surface_contents];
7192
}
7293
break;
7394
}
7495
case kFlutterLayerContentTypePlatformView:
7596
// Add functionality in follow up PR.
76-
FML_CHECK(false) << "Presenting PlatformViews not yet supported";
97+
FML_LOG(WARNING) << "Presenting PlatformViews not yet supported";
7798
break;
7899
};
79100
}
101+
// The frame has been presented, prepare FlutterGLCompositor to
102+
// render a new frame.
103+
frame_started_ = false;
80104
return present_callback_();
81105
}
82106

@@ -85,4 +109,29 @@
85109
present_callback_ = present_callback;
86110
}
87111

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
class MacOSGLContextSwitch {
1212
public:
13-
explicit MacOSGLContextSwitch(NSOpenGLContext* context);
13+
explicit MacOSGLContextSwitch(const NSOpenGLContext* context);
1414
~MacOSGLContextSwitch();
1515

1616
MacOSGLContextSwitch(const MacOSGLContextSwitch&) = delete;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#import "flutter/shell/platform/darwin/macos/framework/Source/MacOSGLContextSwitch.h"
66

7-
MacOSGLContextSwitch::MacOSGLContextSwitch(NSOpenGLContext* context) {
7+
MacOSGLContextSwitch::MacOSGLContextSwitch(const NSOpenGLContext* context) {
88
previous_ = [NSOpenGLContext currentContext];
99
[context makeCurrentContext];
1010
}

0 commit comments

Comments
 (0)