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