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

Commit 9aaea5a

Browse files
Match Windows logic for picking RGB/BGR textures. (#55121)
The existing code had a lot of additional checks that didn't seem to need to be there. BGR could be passed back to Flutter, but this was never used in creating the texture. There has been a report of a Flutter app on Linux with swapped red and blue color channels, so this seems like it is likely not working on some drivers. The original logic was introduced in f104bad
1 parent fe22a19 commit 9aaea5a

File tree

4 files changed

+48
-47
lines changed

4 files changed

+48
-47
lines changed

shell/platform/linux/fl_framebuffer.cc

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static void fl_framebuffer_class_init(FlFramebufferClass* klass) {
3939

4040
static void fl_framebuffer_init(FlFramebuffer* self) {}
4141

42-
FlFramebuffer* fl_framebuffer_new(size_t width, size_t height) {
42+
FlFramebuffer* fl_framebuffer_new(GLint format, size_t width, size_t height) {
4343
FlFramebuffer* provider =
4444
FL_FRAMEBUFFER(g_object_new(fl_framebuffer_get_type(), nullptr));
4545

@@ -56,12 +56,12 @@ FlFramebuffer* fl_framebuffer_new(size_t width, size_t height) {
5656
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5757
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5858
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
59-
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA,
59+
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
6060
GL_UNSIGNED_BYTE, NULL);
6161
glBindTexture(GL_TEXTURE_2D, 0);
6262

63-
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
64-
GL_TEXTURE_2D, provider->texture_id, 0);
63+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
64+
provider->texture_id, 0);
6565

6666
return provider;
6767
}
@@ -78,31 +78,6 @@ GLenum fl_framebuffer_get_target(FlFramebuffer* self) {
7878
return GL_TEXTURE_2D;
7979
}
8080

81-
GLenum fl_framebuffer_get_format(FlFramebuffer* self) {
82-
// Flutter defines SK_R32_SHIFT=16, so SK_PMCOLOR_BYTE_ORDER should be BGRA.
83-
// In Linux kN32_SkColorType is assumed to be kBGRA_8888_SkColorType.
84-
// So we must choose a valid gl format to be compatible with surface format
85-
// BGRA8.
86-
// Following logic is copied from Skia GrGLCaps.cpp:
87-
// https://github.com/google/skia/blob/4738ed711e03212aceec3cd502a4adb545f38e63/src/gpu/ganesh/gl/GrGLCaps.cpp#L1963-L2116
88-
89-
if (epoxy_is_desktop_gl()) {
90-
// For OpenGL.
91-
if (epoxy_gl_version() >= 12 || epoxy_has_gl_extension("GL_EXT_bgra")) {
92-
return GL_RGBA8;
93-
}
94-
} else {
95-
// For OpenGL ES.
96-
if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888") ||
97-
(epoxy_has_gl_extension("GL_APPLE_texture_format_BGRA8888") &&
98-
epoxy_gl_version() >= 30)) {
99-
return GL_BGRA8_EXT;
100-
}
101-
}
102-
g_critical("Failed to determine valid GL format for Flutter rendering");
103-
return GL_RGBA8;
104-
}
105-
10681
size_t fl_framebuffer_get_width(FlFramebuffer* self) {
10782
return self->width;
10883
}

shell/platform/linux/fl_framebuffer.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ G_DECLARE_FINAL_TYPE(FlFramebuffer, fl_framebuffer, FL, FRAMEBUFFER, GObject)
2121

2222
/**
2323
* fl_framebuffer_new:
24+
* @format: format, e.g. GL_RGB, GL_BGR
2425
* @width: width of texture.
2526
* @height: height of texture.
2627
*
2728
* Creates a new frame buffer. Requires a valid OpenGL context to create.
2829
*
2930
* Returns: a new #FlFramebuffer.
3031
*/
31-
FlFramebuffer* fl_framebuffer_new(size_t width, size_t height);
32+
FlFramebuffer* fl_framebuffer_new(GLint format, size_t width, size_t height);
3233

3334
/**
3435
* fl_framebuffer_get_id:
@@ -60,16 +61,6 @@ GLuint fl_framebuffer_get_texture_id(FlFramebuffer* framebuffer);
6061
*/
6162
GLenum fl_framebuffer_get_target(FlFramebuffer* framebuffer);
6263

63-
/**
64-
* fl_framebuffer_get_format:
65-
* @framebuffer: an #FlFramebuffer.
66-
*
67-
* Gets format of texture backing the framebuffer (example GL_RGBA8).
68-
*
69-
* Returns: texture format.
70-
*/
71-
GLenum fl_framebuffer_get_format(FlFramebuffer* framebuffer);
72-
7364
/**
7465
* fl_framebuffer_get_width:
7566
* @framebuffer: an #FlFramebuffer.

shell/platform/linux/fl_renderer.cc

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ typedef struct {
4242
// Engine we are rendering.
4343
GWeakRef engine;
4444

45+
// Flag to track lazy initialization.
46+
gboolean initialized;
47+
48+
// The pixel format passed to the engine.
49+
GLint sized_format;
50+
51+
// The format used to create textures.
52+
GLint general_format;
53+
4554
// Views being rendered.
4655
GHashTable* views;
4756

@@ -105,6 +114,25 @@ static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels) {
105114
return (2.0 * position / pixels) - 1.0;
106115
}
107116

117+
// Perform single run OpenGL initialization.
118+
static void initialize(FlRenderer* self) {
119+
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
120+
fl_renderer_get_instance_private(self));
121+
122+
if (priv->initialized) {
123+
return;
124+
}
125+
priv->initialized = TRUE;
126+
127+
if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
128+
priv->sized_format = GL_BGRA8_EXT;
129+
priv->general_format = GL_BGRA_EXT;
130+
} else {
131+
priv->sized_format = GL_RGBA8;
132+
priv->general_format = GL_RGBA;
133+
}
134+
}
135+
108136
static void fl_renderer_unblock_main_thread(FlRenderer* self) {
109137
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
110138
fl_renderer_get_instance_private(self));
@@ -328,13 +356,18 @@ guint32 fl_renderer_get_fbo(FlRenderer* self) {
328356
}
329357

330358
gboolean fl_renderer_create_backing_store(
331-
FlRenderer* renderer,
359+
FlRenderer* self,
332360
const FlutterBackingStoreConfig* config,
333361
FlutterBackingStore* backing_store_out) {
334-
fl_renderer_make_current(renderer);
362+
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
363+
fl_renderer_get_instance_private(self));
364+
365+
fl_renderer_make_current(self);
366+
367+
initialize(self);
335368

336-
FlFramebuffer* framebuffer =
337-
fl_framebuffer_new(config->size.width, config->size.height);
369+
FlFramebuffer* framebuffer = fl_framebuffer_new(
370+
priv->general_format, config->size.width, config->size.height);
338371
if (!framebuffer) {
339372
g_warning("Failed to create backing store");
340373
return FALSE;
@@ -345,8 +378,7 @@ gboolean fl_renderer_create_backing_store(
345378
backing_store_out->open_gl.framebuffer.user_data = framebuffer;
346379
backing_store_out->open_gl.framebuffer.name =
347380
fl_framebuffer_get_id(framebuffer);
348-
backing_store_out->open_gl.framebuffer.target =
349-
fl_framebuffer_get_format(framebuffer);
381+
backing_store_out->open_gl.framebuffer.target = priv->sized_format;
350382
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) {
351383
// Backing store destroyed in fl_renderer_collect_backing_store(), set
352384
// on FlutterCompositor.collect_backing_store_callback during engine start.

shell/platform/linux/fl_renderer_test.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ TEST(FlRendererTest, RestoresGLState) {
5252
g_autoptr(FlDartProject) project = fl_dart_project_new();
5353
g_autoptr(FlView) view = fl_view_new(project);
5454
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
55-
g_autoptr(FlFramebuffer) framebuffer = fl_framebuffer_new(kWidth, kHeight);
55+
g_autoptr(FlFramebuffer) framebuffer =
56+
fl_framebuffer_new(GL_RGB, kWidth, kHeight);
5657

5758
fl_renderer_add_view(FL_RENDERER(renderer), 0, view);
5859
fl_renderer_wait_for_frame(FL_RENDERER(renderer), kWidth, kHeight);
@@ -144,6 +145,8 @@ TEST(FlRendererTest, BlitFramebufferExtension) {
144145
::testing::Return(reinterpret_cast<const GLubyte*>("Intel")));
145146
ON_CALL(epoxy, epoxy_is_desktop_gl).WillByDefault(::testing::Return(true));
146147
EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(20));
148+
EXPECT_CALL(epoxy, epoxy_has_gl_extension(::testing::_))
149+
.WillRepeatedly(::testing::Return(false));
147150
EXPECT_CALL(epoxy, epoxy_has_gl_extension(
148151
::testing::StrEq("GL_EXT_framebuffer_blit")))
149152
.WillRepeatedly(::testing::Return(true));

0 commit comments

Comments
 (0)