mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Match Windows logic for picking RGB/BGR textures. (flutter/engine#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 87509d8518cea0e90912cc30b08192b1dd4da760
This commit is contained in:
parent
5d553bb416
commit
e3f49a5875
@ -39,7 +39,7 @@ static void fl_framebuffer_class_init(FlFramebufferClass* klass) {
|
||||
|
||||
static void fl_framebuffer_init(FlFramebuffer* self) {}
|
||||
|
||||
FlFramebuffer* fl_framebuffer_new(size_t width, size_t height) {
|
||||
FlFramebuffer* fl_framebuffer_new(GLint format, size_t width, size_t height) {
|
||||
FlFramebuffer* provider =
|
||||
FL_FRAMEBUFFER(g_object_new(fl_framebuffer_get_type(), nullptr));
|
||||
|
||||
@ -56,12 +56,12 @@ FlFramebuffer* fl_framebuffer_new(size_t width, size_t height) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA,
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D, provider->texture_id, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
provider->texture_id, 0);
|
||||
|
||||
return provider;
|
||||
}
|
||||
@ -78,31 +78,6 @@ GLenum fl_framebuffer_get_target(FlFramebuffer* self) {
|
||||
return GL_TEXTURE_2D;
|
||||
}
|
||||
|
||||
GLenum fl_framebuffer_get_format(FlFramebuffer* self) {
|
||||
// Flutter defines SK_R32_SHIFT=16, so SK_PMCOLOR_BYTE_ORDER should be BGRA.
|
||||
// In Linux kN32_SkColorType is assumed to be kBGRA_8888_SkColorType.
|
||||
// So we must choose a valid gl format to be compatible with surface format
|
||||
// BGRA8.
|
||||
// Following logic is copied from Skia GrGLCaps.cpp:
|
||||
// https://github.com/google/skia/blob/4738ed711e03212aceec3cd502a4adb545f38e63/src/gpu/ganesh/gl/GrGLCaps.cpp#L1963-L2116
|
||||
|
||||
if (epoxy_is_desktop_gl()) {
|
||||
// For OpenGL.
|
||||
if (epoxy_gl_version() >= 12 || epoxy_has_gl_extension("GL_EXT_bgra")) {
|
||||
return GL_RGBA8;
|
||||
}
|
||||
} else {
|
||||
// For OpenGL ES.
|
||||
if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888") ||
|
||||
(epoxy_has_gl_extension("GL_APPLE_texture_format_BGRA8888") &&
|
||||
epoxy_gl_version() >= 30)) {
|
||||
return GL_BGRA8_EXT;
|
||||
}
|
||||
}
|
||||
g_critical("Failed to determine valid GL format for Flutter rendering");
|
||||
return GL_RGBA8;
|
||||
}
|
||||
|
||||
size_t fl_framebuffer_get_width(FlFramebuffer* self) {
|
||||
return self->width;
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ G_DECLARE_FINAL_TYPE(FlFramebuffer, fl_framebuffer, FL, FRAMEBUFFER, GObject)
|
||||
|
||||
/**
|
||||
* fl_framebuffer_new:
|
||||
* @format: format, e.g. GL_RGB, GL_BGR
|
||||
* @width: width of texture.
|
||||
* @height: height of texture.
|
||||
*
|
||||
@ -28,7 +29,7 @@ G_DECLARE_FINAL_TYPE(FlFramebuffer, fl_framebuffer, FL, FRAMEBUFFER, GObject)
|
||||
*
|
||||
* Returns: a new #FlFramebuffer.
|
||||
*/
|
||||
FlFramebuffer* fl_framebuffer_new(size_t width, size_t height);
|
||||
FlFramebuffer* fl_framebuffer_new(GLint format, size_t width, size_t height);
|
||||
|
||||
/**
|
||||
* fl_framebuffer_get_id:
|
||||
@ -60,16 +61,6 @@ GLuint fl_framebuffer_get_texture_id(FlFramebuffer* framebuffer);
|
||||
*/
|
||||
GLenum fl_framebuffer_get_target(FlFramebuffer* framebuffer);
|
||||
|
||||
/**
|
||||
* fl_framebuffer_get_format:
|
||||
* @framebuffer: an #FlFramebuffer.
|
||||
*
|
||||
* Gets format of texture backing the framebuffer (example GL_RGBA8).
|
||||
*
|
||||
* Returns: texture format.
|
||||
*/
|
||||
GLenum fl_framebuffer_get_format(FlFramebuffer* framebuffer);
|
||||
|
||||
/**
|
||||
* fl_framebuffer_get_width:
|
||||
* @framebuffer: an #FlFramebuffer.
|
||||
|
||||
@ -42,6 +42,15 @@ typedef struct {
|
||||
// Engine we are rendering.
|
||||
GWeakRef engine;
|
||||
|
||||
// Flag to track lazy initialization.
|
||||
gboolean initialized;
|
||||
|
||||
// The pixel format passed to the engine.
|
||||
GLint sized_format;
|
||||
|
||||
// The format used to create textures.
|
||||
GLint general_format;
|
||||
|
||||
// Views being rendered.
|
||||
GHashTable* views;
|
||||
|
||||
@ -105,6 +114,25 @@ static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels) {
|
||||
return (2.0 * position / pixels) - 1.0;
|
||||
}
|
||||
|
||||
// Perform single run OpenGL initialization.
|
||||
static void initialize(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
if (priv->initialized) {
|
||||
return;
|
||||
}
|
||||
priv->initialized = TRUE;
|
||||
|
||||
if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
|
||||
priv->sized_format = GL_BGRA8_EXT;
|
||||
priv->general_format = GL_BGRA_EXT;
|
||||
} else {
|
||||
priv->sized_format = GL_RGBA8;
|
||||
priv->general_format = GL_RGBA;
|
||||
}
|
||||
}
|
||||
|
||||
static void fl_renderer_unblock_main_thread(FlRenderer* self) {
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
@ -328,13 +356,18 @@ guint32 fl_renderer_get_fbo(FlRenderer* self) {
|
||||
}
|
||||
|
||||
gboolean fl_renderer_create_backing_store(
|
||||
FlRenderer* renderer,
|
||||
FlRenderer* self,
|
||||
const FlutterBackingStoreConfig* config,
|
||||
FlutterBackingStore* backing_store_out) {
|
||||
fl_renderer_make_current(renderer);
|
||||
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
|
||||
fl_renderer_get_instance_private(self));
|
||||
|
||||
FlFramebuffer* framebuffer =
|
||||
fl_framebuffer_new(config->size.width, config->size.height);
|
||||
fl_renderer_make_current(self);
|
||||
|
||||
initialize(self);
|
||||
|
||||
FlFramebuffer* framebuffer = fl_framebuffer_new(
|
||||
priv->general_format, config->size.width, config->size.height);
|
||||
if (!framebuffer) {
|
||||
g_warning("Failed to create backing store");
|
||||
return FALSE;
|
||||
@ -345,8 +378,7 @@ gboolean fl_renderer_create_backing_store(
|
||||
backing_store_out->open_gl.framebuffer.user_data = framebuffer;
|
||||
backing_store_out->open_gl.framebuffer.name =
|
||||
fl_framebuffer_get_id(framebuffer);
|
||||
backing_store_out->open_gl.framebuffer.target =
|
||||
fl_framebuffer_get_format(framebuffer);
|
||||
backing_store_out->open_gl.framebuffer.target = priv->sized_format;
|
||||
backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) {
|
||||
// Backing store destroyed in fl_renderer_collect_backing_store(), set
|
||||
// on FlutterCompositor.collect_backing_store_callback during engine start.
|
||||
|
||||
@ -52,7 +52,8 @@ TEST(FlRendererTest, RestoresGLState) {
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
g_autoptr(FlView) view = fl_view_new(project);
|
||||
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
|
||||
g_autoptr(FlFramebuffer) framebuffer = fl_framebuffer_new(kWidth, kHeight);
|
||||
g_autoptr(FlFramebuffer) framebuffer =
|
||||
fl_framebuffer_new(GL_RGB, kWidth, kHeight);
|
||||
|
||||
fl_renderer_add_view(FL_RENDERER(renderer), 0, view);
|
||||
fl_renderer_wait_for_frame(FL_RENDERER(renderer), kWidth, kHeight);
|
||||
@ -144,6 +145,8 @@ TEST(FlRendererTest, BlitFramebufferExtension) {
|
||||
::testing::Return(reinterpret_cast<const GLubyte*>("Intel")));
|
||||
ON_CALL(epoxy, epoxy_is_desktop_gl).WillByDefault(::testing::Return(true));
|
||||
EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(20));
|
||||
EXPECT_CALL(epoxy, epoxy_has_gl_extension(::testing::_))
|
||||
.WillRepeatedly(::testing::Return(false));
|
||||
EXPECT_CALL(epoxy, epoxy_has_gl_extension(
|
||||
::testing::StrEq("GL_EXT_framebuffer_blit")))
|
||||
.WillRepeatedly(::testing::Return(true));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user