Flutter Engine
 
Loading...
Searching...
No Matches
compositor_opengl.cc
Go to the documentation of this file.
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
6
7#include "GLES3/gl3.h"
10
11namespace flutter {
12
13namespace {
14
15constexpr uint32_t kWindowFrameBufferId = 0;
16
17// The metadata for an OpenGL framebuffer backing store.
18struct FramebufferBackingStore {
20 uint32_t texture_id;
21};
22
23typedef const impeller::GLProc<decltype(glBlitFramebuffer)> BlitFramebufferProc;
24
25const BlitFramebufferProc& GetBlitFramebufferProc(
26 const impeller::ProcTableGLES& gl) {
27 if (gl.BlitFramebuffer.IsAvailable()) {
28 return gl.BlitFramebuffer;
29 } else if (gl.BlitFramebufferANGLE.IsAvailable()) {
30 return gl.BlitFramebufferANGLE;
31 }
32
33 // CompositorOpenGL::Initialize verifies that a blit procedure is available.
35}
36
37} // namespace
38
41 bool enable_impeller)
42 : engine_(engine), resolver_(resolver), enable_impeller_(enable_impeller) {}
43
45 const FlutterBackingStoreConfig& config,
46 FlutterBackingStore* result) {
47 if (!is_initialized_ && !Initialize()) {
48 return false;
49 }
50
51 auto store = std::make_unique<FramebufferBackingStore>();
52
53 gl_->GenTextures(1, &store->texture_id);
54 gl_->GenFramebuffers(1, &store->framebuffer_id);
55
56 gl_->BindFramebuffer(GL_FRAMEBUFFER, store->framebuffer_id);
57
58 gl_->BindTexture(GL_TEXTURE_2D, store->texture_id);
59 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
60 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
61 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
62 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
63 gl_->TexImage2D(GL_TEXTURE_2D, 0, format_.general_format, config.size.width,
64 config.size.height, 0, format_.general_format,
65 GL_UNSIGNED_BYTE, nullptr);
66 gl_->BindTexture(GL_TEXTURE_2D, 0);
67
68 if (enable_impeller_) {
69 // Impeller requries that its onscreen surface is Multisampled and already
70 // has depth/stencil attached in order for anti-aliasing to work.
71 gl_->FramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
72 GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
73 store->texture_id, 0, 4);
74
75 // Set up depth/stencil attachment for impeller renderer.
76 GLuint depth_stencil;
77 gl_->GenRenderbuffers(1, &depth_stencil);
78 gl_->BindRenderbuffer(GL_RENDERBUFFER, depth_stencil);
79 gl_->RenderbufferStorageMultisampleEXT(
80 GL_RENDERBUFFER, // target
81 4, // samples
82 GL_DEPTH24_STENCIL8, // internal format
83 config.size.width, // width
84 config.size.height // height
85 );
86 gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
87 GL_RENDERBUFFER, depth_stencil);
88 gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
89 GL_RENDERBUFFER, depth_stencil);
90
91 } else {
92 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
93 GL_TEXTURE_2D, store->texture_id, 0);
94 }
95
98 result->open_gl.framebuffer.name = store->framebuffer_id;
99 result->open_gl.framebuffer.target = format_.sized_format;
100 result->open_gl.framebuffer.user_data = store.release();
102 // Backing store destroyed in `CompositorOpenGL::CollectBackingStore`, set
103 // on FlutterCompositor.collect_backing_store_callback during engine start.
104 };
105 return true;
106}
107
109 FML_DCHECK(is_initialized_);
112
113 auto user_data = static_cast<FramebufferBackingStore*>(
115
116 gl_->DeleteFramebuffers(1, &user_data->framebuffer_id);
117 gl_->DeleteTextures(1, &user_data->texture_id);
118
119 delete user_data;
120 return true;
121}
122
124 const FlutterLayer** layers,
125 size_t layers_count) {
126 FML_DCHECK(view != nullptr);
127
128 // Clear the view if there are no layers to present.
129 if (layers_count == 0) {
130 // Normally the compositor is initialized when the first backing store is
131 // created. However, on an empty frame no backing stores are created and
132 // the present needs to initialize the compositor.
133 if (!is_initialized_ && !Initialize()) {
134 return false;
135 }
136
137 return Clear(view);
138 }
139
140 // TODO: Support compositing layers and platform views.
141 // See: https://github.com/flutter/flutter/issues/31713
142 FML_DCHECK(is_initialized_);
144 FML_DCHECK(layers[0]->offset.x == 0 && layers[0]->offset.y == 0);
147 FML_DCHECK(layers[0]->backing_store->open_gl.type ==
149
150 auto width = layers[0]->size.width;
151 auto height = layers[0]->size.height;
152
153 // Check if this frame can be presented. This resizes the surface if a resize
154 // is pending and |width| and |height| match the target size.
155 if (!view->OnFrameGenerated(width, height)) {
156 return false;
157 }
158
159 // |OnFrameGenerated| should return false if the surface isn't valid.
160 FML_DCHECK(view->surface() != nullptr);
161 FML_DCHECK(view->surface()->IsValid());
162
163 egl::WindowSurface* surface = view->surface();
164 if (!surface->MakeCurrent()) {
165 return false;
166 }
167
168 auto source_id = layers[0]->backing_store->open_gl.framebuffer.name;
169
170 // Disable the scissor test as it can affect blit operations.
171 // Prevents regressions like: https://github.com/flutter/flutter/issues/140828
172 // See OpenGL specification version 4.6, section 18.3.1.
173 gl_->Disable(GL_SCISSOR_TEST);
174 gl_->BindFramebuffer(GL_READ_FRAMEBUFFER, source_id);
175 gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, kWindowFrameBufferId);
176
177 auto blitFramebuffer = GetBlitFramebufferProc(*gl_);
178 blitFramebuffer(0, // srcX0
179 0, // srcY0
180 width, // srcX1
181 height, // srcY1
182 0, // dstX0
183 0, // dstY0
184 width, // dstX1
185 height, // dstY1
186 GL_COLOR_BUFFER_BIT, // mask
187 GL_NEAREST // filter
188 );
189
190 if (!surface->SwapBuffers()) {
191 return false;
192 }
193
194 view->OnFramePresented();
195 return true;
196}
197
198bool CompositorOpenGL::Initialize() {
199 FML_DCHECK(!is_initialized_);
200
201 egl::Manager* manager = engine_->egl_manager();
202 if (!manager) {
203 return false;
204 }
205
206 if (!manager->render_context()->MakeCurrent()) {
207 return false;
208 }
209
210 gl_ = std::make_unique<impeller::ProcTableGLES>(resolver_);
211 if (!gl_->IsValid()) {
212 gl_.reset();
213 return false;
214 }
215
216 if (gl_->GetDescription()->HasExtension("GL_EXT_texture_format_BGRA8888")) {
217 format_.sized_format = GL_BGRA8_EXT;
218 format_.general_format = GL_BGRA_EXT;
219 } else {
220 format_.sized_format = GL_RGBA8;
221 format_.general_format = GL_RGBA;
222 }
223
224 if (!gl_->BlitFramebuffer.IsAvailable() &&
225 !gl_->BlitFramebufferANGLE.IsAvailable()) {
226 FML_LOG(ERROR) << "Unable to find OpenGL blit framebuffer procedure.";
227 return false;
228 }
229
230 is_initialized_ = true;
231 return true;
232}
233
234bool CompositorOpenGL::Clear(FlutterWindowsView* view) {
235 FML_DCHECK(is_initialized_);
236
237 // Check if this frame can be presented. This resizes the surface if needed.
238 if (!view->OnEmptyFrameGenerated()) {
239 return false;
240 }
241
242 // |OnEmptyFrameGenerated| should return false if the surface isn't valid.
243 FML_DCHECK(view->surface() != nullptr);
244 FML_DCHECK(view->surface()->IsValid());
245
246 egl::WindowSurface* surface = view->surface();
247 if (!surface->MakeCurrent()) {
248 return false;
249 }
250
251 gl_->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
252 gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
253
254 if (!surface->SwapBuffers()) {
255 return false;
256 }
257
258 view->OnFramePresented();
259 return true;
260}
261
262} // namespace flutter
GLenum type
bool Present(FlutterWindowsView *view, const FlutterLayer **layers, size_t layers_count) override
|Compositor|
bool CreateBackingStore(const FlutterBackingStoreConfig &config, FlutterBackingStore *result) override
|Compositor|
bool CollectBackingStore(const FlutterBackingStore *store) override
|Compositor|
CompositorOpenGL(FlutterWindowsEngine *engine, impeller::ProcTableGLES::Resolver resolver, bool enable_impeller)
std::function< void *(const char *function_name)> Resolver
uint32_t framebuffer_id
@ kFlutterLayerContentTypeBackingStore
Definition embedder.h:2102
@ kFlutterOpenGLTargetTypeFramebuffer
Definition embedder.h:417
@ kFlutterBackingStoreTypeOpenGL
Definition embedder.h:2051
FlutterEngine engine
Definition main.cc:84
VkSurfaceKHR surface
Definition main.cc:65
FlView * view
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
#define FML_LOG(severity)
Definition logging.h:101
#define FML_UNREACHABLE()
Definition logging.h:128
#define FML_DCHECK(condition)
Definition logging.h:122
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font manager
int32_t height
int32_t width
FlutterSize size
The size of the render target the engine expects to render into.
Definition embedder.h:2093
FlutterBackingStoreType type
Specifies the type of backing store.
Definition embedder.h:2071
FlutterOpenGLBackingStore open_gl
The description of the OpenGL backing store.
Definition embedder.h:2077
FlutterPoint offset
Definition embedder.h:2145
FlutterLayerContentType type
Definition embedder.h:2134
const FlutterBackingStore * backing_store
Definition embedder.h:2138
FlutterSize size
The size of the layer (in physical pixels).
Definition embedder.h:2147
FlutterOpenGLTargetType type
Definition embedder.h:1914
FlutterOpenGLFramebuffer framebuffer
Definition embedder.h:1920
uint32_t name
The name of the framebuffer.
Definition embedder.h:544
VoidCallback destruction_callback
Definition embedder.h:551
void * user_data
User data to be returned on the invocation of the destruction callback.
Definition embedder.h:547
double height
Definition embedder.h:629
double width
Definition embedder.h:628
int64_t texture_id