| Flutter Windows Embedder |

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
5 #include "flutter/shell/platform/windows/compositor_opengl.h"
6
7 #include "GLES3/gl3.h"
8 #include "flutter/shell/platform/windows/flutter_windows_engine.h"
9 #include "flutter/shell/platform/windows/flutter_windows_view.h"
10
11 namespace flutter {
12
13 namespace {
14
15 constexpr uint32_t kWindowFrameBufferId = 0;
16
17 // The metadata for an OpenGL framebuffer backing store.
18 struct FramebufferBackingStore {
19 uint32_t framebuffer_id;
20 uint32_t texture_id;
21 };
22
23 typedef const impeller::GLProc<decltype(glBlitFramebuffer)> BlitFramebufferProc;
24
25 const 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.
34 FML_UNREACHABLE();
35 }
36
37 } // namespace
38
39 CompositorOpenGL::CompositorOpenGL(FlutterWindowsEngine* engine,
40 impeller::ProcTableGLES::Resolver resolver,
41 bool enable_impeller)
42 : engine_(engine), resolver_(resolver), enable_impeller_(enable_impeller) {}
43
44 bool CompositorOpenGL::CreateBackingStore(
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
96 result->type = kFlutterBackingStoreTypeOpenGL;
97 result->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
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();
101 result->open_gl.framebuffer.destruction_callback = [](void* user_data) {
102 // Backing store destroyed in `CompositorOpenGL::CollectBackingStore`, set
103 // on FlutterCompositor.collect_backing_store_callback during engine start.
104 };
105 return true;
106 }
107
108 bool CompositorOpenGL::CollectBackingStore(const FlutterBackingStore* store) {
109 FML_DCHECK(is_initialized_);
110 FML_DCHECK(store->type == kFlutterBackingStoreTypeOpenGL);
111 FML_DCHECK(store->open_gl.type == kFlutterOpenGLTargetTypeFramebuffer);
112
113 auto user_data = static_cast<FramebufferBackingStore*>(
114 store->open_gl.framebuffer.user_data);
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
123 bool CompositorOpenGL::Present(FlutterWindowsView* view,
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_);
143 FML_DCHECK(layers_count == 1);
144 FML_DCHECK(layers[0]->offset.x == 0 && layers[0]->offset.y == 0);
145 FML_DCHECK(layers[0]->type == kFlutterLayerContentTypeBackingStore);
146 FML_DCHECK(layers[0]->backing_store->type == kFlutterBackingStoreTypeOpenGL);
147 FML_DCHECK(layers[0]->backing_store->open_gl.type ==
148 kFlutterOpenGLTargetTypeFramebuffer);
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
198 bool 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
234 bool 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
flutter::CompositorOpenGL::Present
bool Present(FlutterWindowsView *view, const FlutterLayer **layers, size_t layers_count) override
|Compositor|
Definition: compositor_opengl.cc:123
flutter::CompositorOpenGL::CreateBackingStore
bool CreateBackingStore(const FlutterBackingStoreConfig &config, FlutterBackingStore *result) override
|Compositor|
Definition: compositor_opengl.cc:44
flutter::CompositorOpenGL::CollectBackingStore
bool CollectBackingStore(const FlutterBackingStore *store) override
|Compositor|
Definition: compositor_opengl.cc:108
flutter::CompositorOpenGL::CompositorOpenGL
CompositorOpenGL(FlutterWindowsEngine *engine, impeller::ProcTableGLES::Resolver resolver, bool enable_impeller)
Definition: compositor_opengl.cc:39
flutter::FlutterWindowsEngine
Definition: flutter_windows_engine.h:92
flutter::FlutterWindowsEngine::egl_manager
egl::Manager * egl_manager() const
Definition: flutter_windows_engine.h:183
flutter::FlutterWindowsView
Definition: flutter_windows_view.h:46
flutter::FlutterWindowsView::OnFramePresented
virtual void OnFramePresented()
Definition: flutter_windows_view.cc:709
flutter::FlutterWindowsView::surface
egl::WindowSurface * surface() const
Definition: flutter_windows_view.cc:814
flutter::FlutterWindowsView::OnFrameGenerated
bool OnFrameGenerated(size_t width, size_t height)
Definition: flutter_windows_view.cc:159
flutter::egl::Context::MakeCurrent
virtual bool MakeCurrent() const
Definition: context.cc:29
flutter::egl::Manager
Definition: manager.h:40
flutter::egl::Manager::render_context
virtual Context * render_context() const
Definition: manager.cc:335
flutter::egl::Surface::SwapBuffers
virtual bool SwapBuffers() const
Definition: surface.cc:59
flutter::egl::Surface::IsValid
virtual bool IsValid() const
Definition: surface.cc:19
flutter::egl::Surface::MakeCurrent
virtual bool MakeCurrent() const
Definition: surface.cc:50
flutter::egl::WindowSurface
Definition: window_surface.h:19
texture_id
uint32_t texture_id
Definition: compositor_opengl.cc:20
framebuffer_id
uint32_t framebuffer_id
Definition: compositor_opengl.cc:19
compositor_opengl.h
flutter_windows_engine.h
flutter_windows_view.h
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
type
enum flutter::testing::@100::KeyboardChange::Type type
flutter
Definition: accessibility_bridge_windows.cc:11