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 // 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 
39  impeller::ProcTableGLES::Resolver resolver)
40  : engine_(engine), resolver_(resolver) {}
41 
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 
96  const FlutterLayer** layers,
97  size_t layers_count) {
98  FML_DCHECK(view != nullptr);
99 
100  // Clear the view if there are no layers to present.
101  if (layers_count == 0) {
102  // Normally the compositor is initialized when the first backing store is
103  // created. However, on an empty frame no backing stores are created and
104  // the present needs to initialize the compositor.
105  if (!is_initialized_ && !Initialize()) {
106  return false;
107  }
108 
109  return Clear(view);
110  }
111 
112  // TODO: Support compositing layers and platform views.
113  // See: https://github.com/flutter/flutter/issues/31713
114  FML_DCHECK(is_initialized_);
115  FML_DCHECK(layers_count == 1);
116  FML_DCHECK(layers[0]->offset.x == 0 && layers[0]->offset.y == 0);
117  FML_DCHECK(layers[0]->type == kFlutterLayerContentTypeBackingStore);
118  FML_DCHECK(layers[0]->backing_store->type == kFlutterBackingStoreTypeOpenGL);
119  FML_DCHECK(layers[0]->backing_store->open_gl.type ==
120  kFlutterOpenGLTargetTypeFramebuffer);
121 
122  auto width = layers[0]->size.width;
123  auto height = layers[0]->size.height;
124 
125  // Check if this frame can be presented. This resizes the surface if a resize
126  // is pending and |width| and |height| match the target size.
127  if (!view->OnFrameGenerated(width, height)) {
128  return false;
129  }
130 
131  // |OnFrameGenerated| should return false if the surface isn't valid.
132  FML_DCHECK(view->surface() != nullptr);
133  FML_DCHECK(view->surface()->IsValid());
134 
135  egl::WindowSurface* surface = view->surface();
136  if (!surface->MakeCurrent()) {
137  return false;
138  }
139 
140  auto source_id = layers[0]->backing_store->open_gl.framebuffer.name;
141 
142  // Disable the scissor test as it can affect blit operations.
143  // Prevents regressions like: https://github.com/flutter/flutter/issues/140828
144  // See OpenGL specification version 4.6, section 18.3.1.
145  gl_->Disable(GL_SCISSOR_TEST);
146 
147  gl_->BindFramebuffer(GL_READ_FRAMEBUFFER, source_id);
148  gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, kWindowFrameBufferId);
149 
150  gl_->BlitFramebuffer(0, // srcX0
151  0, // srcY0
152  width, // srcX1
153  height, // srcY1
154  0, // dstX0
155  0, // dstY0
156  width, // dstX1
157  height, // dstY1
158  GL_COLOR_BUFFER_BIT, // mask
159  GL_NEAREST // filter
160  );
161 
162  if (!surface->SwapBuffers()) {
163  return false;
164  }
165 
166  view->OnFramePresented();
167  return true;
168 }
169 
170 bool CompositorOpenGL::Initialize() {
171  FML_DCHECK(!is_initialized_);
172 
173  egl::Manager* manager = engine_->egl_manager();
174  if (!manager) {
175  return false;
176  }
177 
178  if (!manager->render_context()->MakeCurrent()) {
179  return false;
180  }
181 
182  gl_ = std::make_unique<impeller::ProcTableGLES>(resolver_);
183  if (!gl_->IsValid()) {
184  gl_.reset();
185  return false;
186  }
187 
188  format_ = GetSupportedTextureFormat(gl_->GetDescription());
189  is_initialized_ = true;
190  return true;
191 }
192 
193 bool CompositorOpenGL::Clear(FlutterWindowsView* view) {
194  FML_DCHECK(is_initialized_);
195 
196  // Check if this frame can be presented. This resizes the surface if needed.
197  if (!view->OnEmptyFrameGenerated()) {
198  return false;
199  }
200 
201  // |OnEmptyFrameGenerated| should return false if the surface isn't valid.
202  FML_DCHECK(view->surface() != nullptr);
203  FML_DCHECK(view->surface()->IsValid());
204 
205  egl::WindowSurface* surface = view->surface();
206  if (!surface->MakeCurrent()) {
207  return false;
208  }
209 
210  gl_->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
211  gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
212 
213  if (!surface->SwapBuffers()) {
214  return false;
215  }
216 
217  view->OnFramePresented();
218  return true;
219 }
220 
221 } // namespace flutter
flutter::egl::Manager::render_context
virtual Context * render_context() const
Definition: manager.cc:318
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::CompositorOpenGL::CompositorOpenGL
CompositorOpenGL(FlutterWindowsEngine *engine, impeller::ProcTableGLES::Resolver resolver)
Definition: compositor_opengl.cc:38
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: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::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:95
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