Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 9525c1a

Browse files
authored
Reland "[Windows] Move to FlutterCompositor for rendering" (#49726)
## Original pull request description This migrates the Windows embedder to `FlutterCompositor` so that the engine renders off-screen to a framebuffer instead of directly onto the window's surface. This will allow us to support platform views and multiple views on Windows. Addresses flutter/flutter#128904 ## Reland (again) #49262 was reverted as it regressed [`package:material_floating_search_bar_2`](https://pub.dev/packages/material_floating_search_bar_2/versions/0.5.0). See: flutter/flutter#140828 This pull request is split into the following commits: 1. d337378 is the previous reland pull request, unchanged 2. e866af0 disables the scissor test before blitting the framebuffer, allowing us to "force" copy the framebuffer's contents by ignoring scissoring values [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 041ae35 commit 9525c1a

23 files changed

+940
-44
lines changed

ci/licenses_golden/excluded_files

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,8 @@
375375
../../../flutter/shell/platform/windows/client_wrapper/flutter_view_unittests.cc
376376
../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc
377377
../../../flutter/shell/platform/windows/client_wrapper/testing
378+
../../../flutter/shell/platform/windows/compositor_opengl_unittests.cc
379+
../../../flutter/shell/platform/windows/compositor_software_unittests.cc
378380
../../../flutter/shell/platform/windows/cursor_handler_unittests.cc
379381
../../../flutter/shell/platform/windows/direct_manipulation_unittests.cc
380382
../../../flutter/shell/platform/windows/dpi_utils_unittests.cc

ci/licenses_golden/licenses_flutter

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7219,6 +7219,11 @@ ORIGIN: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/f
72197219
ORIGIN: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h + ../../../flutter/LICENSE
72207220
ORIGIN: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h + ../../../flutter/LICENSE
72217221
ORIGIN: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h + ../../../flutter/LICENSE
7222+
ORIGIN: ../../../flutter/shell/platform/windows/compositor.h + ../../../flutter/LICENSE
7223+
ORIGIN: ../../../flutter/shell/platform/windows/compositor_opengl.cc + ../../../flutter/LICENSE
7224+
ORIGIN: ../../../flutter/shell/platform/windows/compositor_opengl.h + ../../../flutter/LICENSE
7225+
ORIGIN: ../../../flutter/shell/platform/windows/compositor_software.cc + ../../../flutter/LICENSE
7226+
ORIGIN: ../../../flutter/shell/platform/windows/compositor_software.h + ../../../flutter/LICENSE
72227227
ORIGIN: ../../../flutter/shell/platform/windows/cursor_handler.cc + ../../../flutter/LICENSE
72237228
ORIGIN: ../../../flutter/shell/platform/windows/cursor_handler.h + ../../../flutter/LICENSE
72247229
ORIGIN: ../../../flutter/shell/platform/windows/direct_manipulation.cc + ../../../flutter/LICENSE
@@ -10079,6 +10084,11 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flu
1007910084
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h
1008010085
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h
1008110086
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h
10087+
FILE: ../../../flutter/shell/platform/windows/compositor.h
10088+
FILE: ../../../flutter/shell/platform/windows/compositor_opengl.cc
10089+
FILE: ../../../flutter/shell/platform/windows/compositor_opengl.h
10090+
FILE: ../../../flutter/shell/platform/windows/compositor_software.cc
10091+
FILE: ../../../flutter/shell/platform/windows/compositor_software.h
1008210092
FILE: ../../../flutter/shell/platform/windows/cursor_handler.cc
1008310093
FILE: ../../../flutter/shell/platform/windows/cursor_handler.h
1008410094
FILE: ../../../flutter/shell/platform/windows/direct_manipulation.cc

impeller/renderer/backend/gles/blit_command_gles.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static std::optional<GLuint> ConfigureFBO(
4848
}
4949

5050
if (gl.CheckFramebufferStatus(fbo_type) != GL_FRAMEBUFFER_COMPLETE) {
51-
VALIDATION_LOG << "Could not create a complete frambuffer.";
51+
VALIDATION_LOG << "Could not create a complete framebuffer.";
5252
DeleteFBO(gl, fbo, fbo_type);
5353
return std::nullopt;
5454
}

impeller/renderer/backend/gles/description_gles.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ std::string DescriptionGLES::GetString() const {
156156
return stream.str();
157157
}
158158

159+
Version DescriptionGLES::GetGlVersion() const {
160+
return gl_version_;
161+
}
162+
159163
bool DescriptionGLES::IsES() const {
160164
return is_es_;
161165
}

impeller/renderer/backend/gles/description_gles.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class DescriptionGLES {
2727

2828
std::string GetString() const;
2929

30+
Version GetGlVersion() const;
31+
3032
bool HasExtension(const std::string& ext) const;
3133

3234
/// @brief Returns whether GLES includes the debug extension.

shell/platform/linux/fl_backing_store_provider.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ uint32_t fl_backing_store_provider_get_gl_format(FlBackingStoreProvider* self) {
8282
// In Linux kN32_SkColorType is assumed to be kBGRA_8888_SkColorType.
8383
// So we must choose a valid gl format to be compatible with surface format
8484
// BGRA8.
85-
// Following logics are copied from Skia GrGLCaps.cpp.
85+
// Following logic is copied from Skia GrGLCaps.cpp:
86+
// https://github.com/google/skia/blob/4738ed711e03212aceec3cd502a4adb545f38e63/src/gpu/ganesh/gl/GrGLCaps.cpp#L1963-L2116
8687

8788
if (epoxy_is_desktop_gl()) {
8889
// For OpenGL.

shell/platform/windows/BUILD.gn

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ source_set("flutter_windows_source") {
4242
"accessibility_bridge_windows.h",
4343
"angle_surface_manager.cc",
4444
"angle_surface_manager.h",
45+
"compositor.h",
46+
"compositor_opengl.cc",
47+
"compositor_opengl.h",
48+
"compositor_software.cc",
49+
"compositor_software.h",
4550
"cursor_handler.cc",
4651
"cursor_handler.h",
4752
"direct_manipulation.cc",
@@ -134,6 +139,7 @@ source_set("flutter_windows_source") {
134139
deps = [
135140
":flutter_windows_headers",
136141
"//flutter/fml:fml",
142+
"//flutter/impeller/renderer/backend/gles",
137143
"//flutter/shell/platform/common:common_cpp",
138144
"//flutter/shell/platform/common:common_cpp_input",
139145
"//flutter/shell/platform/common:common_cpp_switches",
@@ -175,6 +181,8 @@ executable("flutter_windows_unittests") {
175181
# Common Windows test sources.
176182
sources = [
177183
"accessibility_bridge_windows_unittests.cc",
184+
"compositor_opengl_unittests.cc",
185+
"compositor_software_unittests.cc",
178186
"cursor_handler_unittests.cc",
179187
"direct_manipulation_unittests.cc",
180188
"dpi_utils_unittests.cc",
@@ -235,6 +243,7 @@ executable("flutter_windows_unittests") {
235243
":flutter_windows_fixtures",
236244
":flutter_windows_headers",
237245
":flutter_windows_source",
246+
"//flutter/impeller/renderer/backend/gles",
238247
"//flutter/shell/platform/common:common_cpp",
239248
"//flutter/shell/platform/common/client_wrapper:client_wrapper",
240249
"//flutter/shell/platform/embedder:embedder_as_internal_library",

shell/platform/windows/compositor.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_COMPOSITOR_H_
6+
#define FLUTTER_SHELL_PLATFORM_WINDOWS_COMPOSITOR_H_
7+
8+
#include "flutter/shell/platform/embedder/embedder.h"
9+
10+
namespace flutter {
11+
12+
// Enables the Flutter engine to render content on Windows.
13+
//
14+
// The engine uses this to:
15+
//
16+
// 1. Create backing stores used for rendering Flutter content
17+
// 2. Composite and present Flutter content and platform views onto a view
18+
//
19+
// Platform views are not yet supported.
20+
class Compositor {
21+
public:
22+
virtual ~Compositor() = default;
23+
24+
// Creates a backing store used for rendering Flutter content.
25+
//
26+
// The backing store's configuration is stored in |backing_store_out|.
27+
virtual bool CreateBackingStore(const FlutterBackingStoreConfig& config,
28+
FlutterBackingStore* backing_store_out) = 0;
29+
30+
// Destroys a backing store and releases its resources.
31+
virtual bool CollectBackingStore(const FlutterBackingStore* store) = 0;
32+
33+
// Present Flutter content and platform views onto the view.
34+
virtual bool Present(const FlutterLayer** layers, size_t layers_count) = 0;
35+
};
36+
37+
} // namespace flutter
38+
39+
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_COMPOSITOR_H_
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
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_view.h"
9+
10+
namespace flutter {
11+
12+
namespace {
13+
14+
constexpr uint32_t kWindowFrameBufferId = 0;
15+
16+
// The metadata for an OpenGL framebuffer backing store.
17+
struct FramebufferBackingStore {
18+
uint32_t framebuffer_id;
19+
uint32_t texture_id;
20+
};
21+
22+
// Based off Skia's logic:
23+
// https://github.com/google/skia/blob/4738ed711e03212aceec3cd502a4adb545f38e63/src/gpu/ganesh/gl/GrGLCaps.cpp#L1963-L2116
24+
int GetSupportedTextureFormat(const impeller::DescriptionGLES* description) {
25+
if (description->HasExtension("GL_EXT_texture_format_BGRA8888")) {
26+
return GL_BGRA8_EXT;
27+
} else if (description->HasExtension("GL_APPLE_texture_format_BGRA8888") &&
28+
description->GetGlVersion().IsAtLeast(impeller::Version(3, 0))) {
29+
return GL_BGRA8_EXT;
30+
} else {
31+
return GL_RGBA8;
32+
}
33+
}
34+
35+
} // namespace
36+
37+
CompositorOpenGL::CompositorOpenGL(FlutterWindowsEngine* engine,
38+
impeller::ProcTableGLES::Resolver resolver)
39+
: engine_(engine), resolver_(resolver) {}
40+
41+
bool CompositorOpenGL::CreateBackingStore(
42+
const FlutterBackingStoreConfig& config,
43+
FlutterBackingStore* result) {
44+
if (!is_initialized_ && !Initialize()) {
45+
return false;
46+
}
47+
48+
auto store = std::make_unique<FramebufferBackingStore>();
49+
50+
gl_->GenTextures(1, &store->texture_id);
51+
gl_->GenFramebuffers(1, &store->framebuffer_id);
52+
53+
gl_->BindFramebuffer(GL_FRAMEBUFFER, store->framebuffer_id);
54+
55+
gl_->BindTexture(GL_TEXTURE_2D, store->texture_id);
56+
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
57+
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
58+
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
59+
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
60+
gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, config.size.width,
61+
config.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
62+
gl_->BindTexture(GL_TEXTURE_2D, 0);
63+
64+
gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT,
65+
GL_TEXTURE_2D, store->texture_id, 0);
66+
67+
result->type = kFlutterBackingStoreTypeOpenGL;
68+
result->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
69+
result->open_gl.framebuffer.name = store->framebuffer_id;
70+
result->open_gl.framebuffer.target = format_;
71+
result->open_gl.framebuffer.user_data = store.release();
72+
result->open_gl.framebuffer.destruction_callback = [](void* user_data) {
73+
// Backing store destroyed in `CompositorOpenGL::CollectBackingStore`, set
74+
// on FlutterCompositor.collect_backing_store_callback during engine start.
75+
};
76+
return true;
77+
}
78+
79+
bool CompositorOpenGL::CollectBackingStore(const FlutterBackingStore* store) {
80+
FML_DCHECK(is_initialized_);
81+
FML_DCHECK(store->type == kFlutterBackingStoreTypeOpenGL);
82+
FML_DCHECK(store->open_gl.type == kFlutterOpenGLTargetTypeFramebuffer);
83+
84+
auto user_data = static_cast<FramebufferBackingStore*>(
85+
store->open_gl.framebuffer.user_data);
86+
87+
gl_->DeleteFramebuffers(1, &user_data->framebuffer_id);
88+
gl_->DeleteTextures(1, &user_data->texture_id);
89+
90+
delete user_data;
91+
return true;
92+
}
93+
94+
bool CompositorOpenGL::Present(const FlutterLayer** layers,
95+
size_t layers_count) {
96+
if (!engine_->view()) {
97+
return false;
98+
}
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 ClearSurface();
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 (!engine_->view()->OnFrameGenerated(width, height)) {
128+
return false;
129+
}
130+
131+
if (!engine_->surface_manager()->MakeCurrent()) {
132+
return false;
133+
}
134+
135+
auto source_id = layers[0]->backing_store->open_gl.framebuffer.name;
136+
137+
// Disable the scissor test as it can affect blit operations.
138+
// Prevents regressions like: https://github.com/flutter/flutter/issues/140828
139+
// See OpenGL specification version 4.6, section 18.3.1.
140+
gl_->Disable(GL_SCISSOR_TEST);
141+
142+
gl_->BindFramebuffer(GL_READ_FRAMEBUFFER, source_id);
143+
gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, kWindowFrameBufferId);
144+
145+
gl_->BlitFramebuffer(0, // srcX0
146+
0, // srcY0
147+
width, // srcX1
148+
height, // srcY1
149+
0, // dstX0
150+
0, // dstY0
151+
width, // dstX1
152+
height, // dstY1
153+
GL_COLOR_BUFFER_BIT, // mask
154+
GL_NEAREST // filter
155+
);
156+
157+
return engine_->view()->SwapBuffers();
158+
}
159+
160+
bool CompositorOpenGL::Initialize() {
161+
FML_DCHECK(!is_initialized_);
162+
163+
if (!engine_->surface_manager()->MakeCurrent()) {
164+
return false;
165+
}
166+
167+
gl_ = std::make_unique<impeller::ProcTableGLES>(resolver_);
168+
if (!gl_->IsValid()) {
169+
gl_.reset();
170+
return false;
171+
}
172+
173+
format_ = GetSupportedTextureFormat(gl_->GetDescription());
174+
is_initialized_ = true;
175+
return true;
176+
}
177+
178+
bool CompositorOpenGL::ClearSurface() {
179+
FML_DCHECK(is_initialized_);
180+
181+
// Resize the surface if needed.
182+
engine_->view()->OnEmptyFrameGenerated();
183+
184+
if (!engine_->surface_manager()->MakeCurrent()) {
185+
return false;
186+
}
187+
188+
gl_->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
189+
gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
190+
191+
return engine_->view()->SwapBuffers();
192+
}
193+
194+
} // namespace flutter

0 commit comments

Comments
 (0)