forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFlutterGLCompositor.mm
More file actions
178 lines (145 loc) · 7.01 KB
/
FlutterGLCompositor.mm
File metadata and controls
178 lines (145 loc) · 7.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.h"
#import <OpenGL/gl.h>
#include "flutter/fml/logging.h"
#include "flutter/fml/platform/darwin/cf_utils.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStore.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterBackingStoreData.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterFrameBufferProvider.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
namespace flutter {
FlutterGLCompositor::FlutterGLCompositor(FlutterViewController* view_controller,
NSOpenGLContext* opengl_context)
: open_gl_context_(opengl_context) {
FML_CHECK(view_controller != nullptr) << "FlutterViewController* cannot be nullptr";
FML_CHECK(platform_view_controller != nullptr)
<< "FlutterPlatformViewController* cannot be nullptr";
view_controller_ = view_controller;
platform_view_controller_ = platform_view_controller;
}
bool FlutterGLCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
FlutterBackingStore* backing_store_out) {
CGSize size = CGSizeMake(config->size.width, config->size.height);
if (!frame_started_) {
StartFrame();
// If the backing store is for the first layer, return the fbo for the
// FlutterView.
FlutterOpenGLRenderBackingStore* backingStore =
reinterpret_cast<FlutterOpenGLRenderBackingStore*>(
[view_controller_.flutterView backingStoreForSize:size]);
backing_store_out->open_gl.framebuffer.name = backingStore.frameBufferID;
} else {
FlutterFrameBufferProvider* fb_provider =
[[FlutterFrameBufferProvider alloc] initWithOpenGLContext:open_gl_context_];
FlutterIOSurfaceHolder* io_surface_holder = [FlutterIOSurfaceHolder alloc];
GLuint fbo = [fb_provider glFrameBufferId];
GLuint texture = [fb_provider glTextureId];
size_t layer_id = CreateCALayer();
[io_surface_holder bindSurfaceToTexture:texture fbo:fbo size:size];
FlutterBackingStoreData* data =
[[FlutterBackingStoreData alloc] initWithLayerId:layer_id
fbProvider:fb_provider
ioSurfaceHolder:io_surface_holder];
backing_store_out->open_gl.framebuffer.name = fbo;
backing_store_out->open_gl.framebuffer.user_data = (__bridge_retained void*)data;
}
backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
backing_store_out->open_gl.framebuffer.target = GL_RGBA8;
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* user_data) {
if (user_data != nullptr) {
CFRelease(user_data);
}
};
return true;
}
bool FlutterGLCompositor::CollectBackingStore(const FlutterBackingStore* backing_store) {
return true;
}
bool FlutterGLCompositor::Present(const FlutterLayer** layers, size_t layers_count) {
[platform_view_controller_ disposePlatformViews];
for (size_t i = 0; i < layers_count; ++i) {
const auto* layer = layers[i];
FlutterBackingStore* backing_store = const_cast<FlutterBackingStore*>(layer->backing_store);
switch (layer->type) {
case kFlutterLayerContentTypeBackingStore: {
if (backing_store->open_gl.framebuffer.user_data) {
FlutterBackingStoreData* flutter_backing_store_data =
(__bridge FlutterBackingStoreData*)backing_store->open_gl.framebuffer.user_data;
PresentBackingStoreContent(flutter_backing_store_data, i);
}
break;
}
case kFlutterLayerContentTypePlatformView:
PresentPlatformView(layer, i);
break;
};
}
// The frame has been presented, prepare FlutterGLCompositor to
// render a new frame.
frame_started_ = false;
return present_callback_();
}
void FlutterGLCompositor::PresentBackingStoreContent(
FlutterBackingStoreData* flutter_backing_store_data,
size_t layer_position) {
FML_DCHECK([[NSThread currentThread] isMainThread])
<< "Must be on the main thread to update CALayer contents";
FlutterIOSurfaceHolder* io_surface_holder = [flutter_backing_store_data ioSurfaceHolder];
size_t layer_id = [flutter_backing_store_data layerId];
CALayer* content_layer = ca_layer_map_[layer_id];
FML_DCHECK(content_layer) << "Unable to find a content layer with layer id " << layer_id;
content_layer.frame = content_layer.superlayer.bounds;
content_layer.zPosition = layer_position;
// The surface is an OpenGL texture, which means it has origin in bottom left corner
// and needs to be flipped vertically
content_layer.transform = CATransform3DMakeScale(1, -1, 1);
IOSurfaceRef io_surface_contents = [io_surface_holder ioSurface];
[content_layer setContents:(__bridge id)io_surface_contents];
}
void FlutterGLCompositor::PresentPlatformView(const FlutterLayer* layer, size_t layer_position) {
FML_DCHECK([[NSThread currentThread] isMainThread])
<< "Must be on the main thread to handle presenting platform views";
FML_DCHECK(platform_view_controller_.platformViews.count(layer->platform_view->identifier))
<< "Platform view not found for id: " << layer->platform_view->identifier;
NSView* platform_view = platform_view_controller_.platformViews[layer->platform_view->identifier];
CGFloat scale = [[NSScreen mainScreen] backingScaleFactor];
platform_view.frame = CGRectMake(layer->offset.x / scale, layer->offset.y / scale,
layer->size.width / scale, layer->size.height / scale);
if (platform_view.superview == nil) {
[view_controller_.flutterView addSubview:platform_view];
} else {
platform_view.layer.zPosition = layer_position;
}
}
void FlutterGLCompositor::SetPresentCallback(
const FlutterGLCompositor::PresentCallback& present_callback) {
present_callback_ = present_callback;
}
void FlutterGLCompositor::StartFrame() {
// First reset all the state.
ca_layer_count_ = 0;
// First remove all CALayers from the superlayer.
for (auto const& ca_layer_kvp : ca_layer_map_) {
[ca_layer_kvp.second removeFromSuperlayer];
}
// Reset layer map.
ca_layer_map_.clear();
frame_started_ = true;
}
size_t FlutterGLCompositor::CreateCALayer() {
// FlutterGLCompositor manages the lifecycle of content layers.
// The id for a CALayer starts at 0 and increments by 1 for
// any given frame.
CALayer* content_layer = [[CALayer alloc] init];
[view_controller_.flutterView.layer addSublayer:content_layer];
ca_layer_map_[ca_layer_count_] = content_layer;
return ca_layer_count_++;
}
} // namespace flutter