| 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 // Based off Skia's logic:
24 // https://github.com/google/skia/blob/4738ed711e03212aceec3cd502a4adb545f38e63/src/gpu/ganesh/gl/GrGLCaps.cpp#L1963-L2116
25 int GetSupportedTextureFormat(const impeller::DescriptionGLES* description) {
26 if (description->HasExtension("GL_EXT_texture_format_BGRA8888")) {
27 return GL_BGRA8_EXT;
28 } else if (description->HasExtension("GL_APPLE_texture_format_BGRA8888") &&
29 description->GetGlVersion().IsAtLeast(impeller::Version(3, 0))) {
30 return GL_BGRA8_EXT;
31 } else {
32 return GL_RGBA8;
33 }
34 }
35
36 } // namespace
37
38 CompositorOpenGL::CompositorOpenGL(FlutterWindowsEngine* engine,
39 impeller::ProcTableGLES::Resolver resolver)
40 : engine_(engine), resolver_(resolver) {}
41
42 bool CompositorOpenGL::CreateBackingStore(
43 const FlutterBackingStoreConfig& config,
44 FlutterBackingStore* result) {
45 if (!is_initialized_ && !Initialize()) {
46 return false;
47 }
48
49 auto store = std::make_unique<FramebufferBackingStore>();
50
51 gl_->GenTextures(1, &store->texture_id);
52 gl_->GenFramebuffers(1, &store->framebuffer_id);
53
54 gl_->BindFramebuffer(GL_FRAMEBUFFER, store->framebuffer_id);
55
56 gl_->BindTexture(GL_TEXTURE_2D, store->texture_id);
57 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
58 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
59 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
60 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
61 gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, config.size.width,
62 config.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
63 gl_->BindTexture(GL_TEXTURE_2D, 0);
64
65 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT,
66 GL_TEXTURE_2D, store->texture_id, 0);
67
68 result->type = kFlutterBackingStoreTypeOpenGL;
69 result->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
70 result->open_gl.framebuffer.name = store->framebuffer_id;
71 result->open_gl.framebuffer.target = format_;
72 result->open_gl.framebuffer.user_data = store.release();
73 result->open_gl.framebuffer.destruction_callback = [](void* user_data) {
74 // Backing store destroyed in `CompositorOpenGL::CollectBackingStore`, set
75 // on FlutterCompositor.collect_backing_store_callback during engine start.
76 };
77 return true;
78 }
79
80 bool CompositorOpenGL::CollectBackingStore(const FlutterBackingStore* store) {
81 FML_DCHECK(is_initialized_);
82 FML_DCHECK(store->type == kFlutterBackingStoreTypeOpenGL);
83 FML_DCHECK(store->open_gl.type == kFlutterOpenGLTargetTypeFramebuffer);
84
85 auto user_data = static_cast<FramebufferBackingStore*>(
86 store->open_gl.framebuffer.user_data);
87
88 gl_->DeleteFramebuffers(1, &user_data->framebuffer_id);
89 gl_->DeleteTextures(1, &user_data->texture_id);
90
91 delete user_data;
92 return true;
93 }
94
95 bool CompositorOpenGL::Present(FlutterViewId view_id,
96 const FlutterLayer** layers,
97 size_t layers_count) {
98 FlutterWindowsView* view = engine_->view(view_id);
99 if (!view) {
100 return false;
101 }
102
103 // Clear the view if there are no layers to present.
104 if (layers_count == 0) {
105 // Normally the compositor is initialized when the first backing store is
106 // created. However, on an empty frame no backing stores are created and
107 // the present needs to initialize the compositor.
108 if (!is_initialized_ && !Initialize()) {
109 return false;
110 }
111
112 return Clear(view);
113 }
114
115 // TODO: Support compositing layers and platform views.
116 // See: https://github.com/flutter/flutter/issues/31713
117 FML_DCHECK(is_initialized_);
118 FML_DCHECK(layers_count == 1);
119 FML_DCHECK(layers[0]->offset.x == 0 && layers[0]->offset.y == 0);
120 FML_DCHECK(layers[0]->type == kFlutterLayerContentTypeBackingStore);
121 FML_DCHECK(layers[0]->backing_store->type == kFlutterBackingStoreTypeOpenGL);
122 FML_DCHECK(layers[0]->backing_store->open_gl.type ==
123 kFlutterOpenGLTargetTypeFramebuffer);
124
125 auto width = layers[0]->size.width;
126 auto height = layers[0]->size.height;
127
128 // Check if this frame can be presented. This resizes the surface if a resize
129 // is pending and |width| and |height| match the target size.
130 if (!view->OnFrameGenerated(width, height)) {
131 return false;
132 }
133
134 // |OnFrameGenerated| should return false if the surface isn't valid.
135 FML_DCHECK(view->surface() != nullptr);
136 FML_DCHECK(view->surface()->IsValid());
137
138 egl::WindowSurface* surface = view->surface();
139 if (!surface->MakeCurrent()) {
140 return false;
141 }
142
143 auto source_id = layers[0]->backing_store->open_gl.framebuffer.name;
144
145 // Disable the scissor test as it can affect blit operations.
146 // Prevents regressions like: https://github.com/flutter/flutter/issues/140828
147 // See OpenGL specification version 4.6, section 18.3.1.
148 gl_->Disable(GL_SCISSOR_TEST);
149
150 gl_->BindFramebuffer(GL_READ_FRAMEBUFFER, source_id);
151 gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, kWindowFrameBufferId);
152
153 gl_->BlitFramebuffer(0, // srcX0
154 0, // srcY0
155 width, // srcX1
156 height, // srcY1
157 0, // dstX0
158 0, // dstY0
159 width, // dstX1
160 height, // dstY1
161 GL_COLOR_BUFFER_BIT, // mask
162 GL_NEAREST // filter
163 );
164
165 if (!surface->SwapBuffers()) {
166 return false;
167 }
168
169 view->OnFramePresented();
170 return true;
171 }
172
173 bool CompositorOpenGL::Initialize() {
174 FML_DCHECK(!is_initialized_);
175
176 egl::Manager* manager = engine_->egl_manager();
177 if (!manager) {
178 return false;
179 }
180
181 if (!manager->render_context()->MakeCurrent()) {
182 return false;
183 }
184
185 gl_ = std::make_unique<impeller::ProcTableGLES>(resolver_);
186 if (!gl_->IsValid()) {
187 gl_.reset();
188 return false;
189 }
190
191 format_ = GetSupportedTextureFormat(gl_->GetDescription());
192 is_initialized_ = true;
193 return true;
194 }
195
196 bool CompositorOpenGL::Clear(FlutterWindowsView* view) {
197 FML_DCHECK(is_initialized_);
198
199 // Check if this frame can be presented. This resizes the surface if needed.
200 if (!view->OnEmptyFrameGenerated()) {
201 return false;
202 }
203
204 // |OnEmptyFrameGenerated| should return false if the surface isn't valid.
205 FML_DCHECK(view->surface() != nullptr);
206 FML_DCHECK(view->surface()->IsValid());
207
208 egl::WindowSurface* surface = view->surface();
209 if (!surface->MakeCurrent()) {
210 return false;
211 }
212
213 gl_->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
214 gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
215
216 if (!surface->SwapBuffers()) {
217 return false;
218 }
219
220 view->OnFramePresented();
221 return true;
222 }
223
224 } // namespace flutter
flutter::egl::Manager::render_context
virtual Context * render_context() const
Definition: manager.cc:318
flutter::FlutterWindowsEngine::view
FlutterWindowsView * view(FlutterViewId view_id) const
Definition: flutter_windows_engine.cc:533
flutter::FlutterWindowsView
Definition: flutter_windows_view.h:34
flutter::FlutterWindowsView::surface
egl::WindowSurface * surface() const
Definition: flutter_windows_view.cc:719
flutter::egl::WindowSurface
Definition: window_surface.h:19
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:52
flutter::CompositorOpenGL::CompositorOpenGL
CompositorOpenGL(FlutterWindowsEngine *engine, impeller::ProcTableGLES::Resolver resolver)
Definition: compositor_opengl.cc:38
flutter::FlutterWindowsEngine
Definition: flutter_windows_engine.h:89
type
enum flutter::testing::@87::KeyboardChange::Type type
flutter::egl::Context::MakeCurrent
virtual bool MakeCurrent() const
Definition: context.cc:29
flutter::CompositorOpenGL::CreateBackingStore
bool CreateBackingStore(const FlutterBackingStoreConfig &config, FlutterBackingStore *result) override
|Compositor|
Definition: compositor_opengl.cc:42
framebuffer_id
uint32_t framebuffer_id
Definition: compositor_opengl.cc:19
flutter_windows_view.h
flutter::egl::Surface::IsValid
virtual bool IsValid() const
Definition: surface.cc:19
flutter::CompositorOpenGL::CollectBackingStore
bool CollectBackingStore(const FlutterBackingStore *store) override
|Compositor|
Definition: compositor_opengl.cc:80
flutter::egl::Surface::MakeCurrent
virtual bool MakeCurrent() const
Definition: surface.cc:50
compositor_opengl.h
flutter::FlutterViewId
int64_t FlutterViewId
Definition: flutter_view.h:13
flutter::FlutterWindowsView::OnFrameGenerated
bool OnFrameGenerated(size_t width, size_t height)
Definition: flutter_windows_view.cc:137
flutter::egl::Surface::SwapBuffers
virtual bool SwapBuffers() const
Definition: surface.cc:59
flutter::CompositorOpenGL::Present
bool Present(FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count) override
|Compositor|
Definition: compositor_opengl.cc:95
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::egl::Manager
Definition: manager.h:31
flutter_windows_engine.h
flutter::FlutterWindowsEngine::egl_manager
egl::Manager * egl_manager() const
Definition: flutter_windows_engine.h:159
texture_id
uint32_t texture_id
Definition: compositor_opengl.cc:20
flutter::FlutterWindowsView::OnFramePresented
virtual void OnFramePresented()
Definition: flutter_windows_view.cc:613