Allow the default background color to be changed (flutter/engine#54575)

Fixes https://github.com/flutter/flutter/issues/149920
This commit is contained in:
Robert Ancell 2024-08-20 08:00:06 +12:00 committed by GitHub
parent 11288f546d
commit 2bbc3b4b41
7 changed files with 97 additions and 17 deletions

View File

@ -195,6 +195,9 @@ static void render_with_textures(FlRenderer* self, int width, int height) {
GLint saved_array_buffer_binding;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(priv->program);
for (guint i = 0; i < priv->framebuffers->len; i++) {
@ -236,6 +239,8 @@ static void render_with_textures(FlRenderer* self, int width, int height) {
glDeleteBuffers(1, &vertex_buffer);
}
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
glBindVertexArray(saved_vao_binding);
glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
@ -443,13 +448,17 @@ void fl_renderer_setup(FlRenderer* self) {
}
}
void fl_renderer_render(FlRenderer* self, int width, int height) {
void fl_renderer_render(FlRenderer* self,
int width,
int height,
const GdkRGBA* background_color) {
FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
fl_renderer_get_instance_private(self));
g_return_if_fail(FL_IS_RENDERER(self));
glClearColor(0.0, 0.0, 0.0, 1.0);
glClearColor(background_color->red, background_color->green,
background_color->blue, background_color->alpha);
glClear(GL_COLOR_BUFFER_BIT);
if (priv->has_gl_framebuffer_blit) {

View File

@ -209,10 +209,14 @@ void fl_renderer_setup(FlRenderer* renderer);
* @renderer: an #FlRenderer.
* @width: width of the window in pixels.
* @height: height of the window in pixels.
* @background_color: color to use for background.
*
* Performs OpenGL commands to render current Flutter view.
*/
void fl_renderer_render(FlRenderer* renderer, int width, int height);
void fl_renderer_render(FlRenderer* renderer,
int width,
int height,
const GdkRGBA* background_color);
/**
* fl_renderer_cleanup:

View File

@ -12,6 +12,36 @@
#include <epoxy/egl.h>
TEST(FlRendererTest, BackgroundColor) {
::testing::NiceMock<flutter::testing::MockEpoxy> epoxy;
ON_CALL(epoxy, epoxy_is_desktop_gl).WillByDefault(::testing::Return(true));
EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(30));
ON_CALL(epoxy, glGetString(GL_VENDOR))
.WillByDefault(
::testing::Return(reinterpret_cast<const GLubyte*>("Intel")));
EXPECT_CALL(epoxy, glClearColor(0.2, 0.3, 0.4, 0.5));
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
fl_renderer_setup(FL_RENDERER(renderer));
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
FlutterBackingStoreConfig config = {
.struct_size = sizeof(FlutterBackingStoreConfig),
.size = {.width = 1024, .height = 1024}};
FlutterBackingStore backing_store;
fl_renderer_create_backing_store(FL_RENDERER(renderer), &config,
&backing_store);
const FlutterLayer layer0 = {.struct_size = sizeof(FlutterLayer),
.type = kFlutterLayerContentTypeBackingStore,
.backing_store = &backing_store,
.size = {.width = 1024, .height = 1024}};
const FlutterLayer* layers[] = {&layer0};
fl_renderer_present_layers(FL_RENDERER(renderer), 0, layers, 1);
GdkRGBA background_color = {
.red = 0.2, .green = 0.3, .blue = 0.4, .alpha = 0.5};
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024, &background_color);
}
TEST(FlRendererTest, RestoresGLState) {
::testing::NiceMock<flutter::testing::MockEpoxy> epoxy;
@ -44,7 +74,9 @@ TEST(FlRendererTest, RestoresGLState) {
fl_renderer_present_layers(FL_RENDERER(renderer), 0, layers.data(),
layers.size());
fl_renderer_render(FL_RENDERER(renderer), kWidth, kHeight);
GdkRGBA background_color = {
.red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0};
fl_renderer_render(FL_RENDERER(renderer), kWidth, kHeight, &background_color);
GLuint texture_2d_binding;
glGetIntegerv(GL_TEXTURE_BINDING_2D,
@ -82,8 +114,7 @@ TEST(FlRendererTest, BlitFramebuffer) {
EXPECT_CALL(epoxy, glBlitFramebuffer);
g_autoptr(FlMockRenderer) renderer =
fl_mock_renderer_new(&renderer_get_refresh_rate);
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
fl_renderer_setup(FL_RENDERER(renderer));
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
FlutterBackingStoreConfig config = {
@ -98,7 +129,9 @@ TEST(FlRendererTest, BlitFramebuffer) {
.size = {.width = 1024, .height = 1024}};
const FlutterLayer* layers[] = {&layer0};
fl_renderer_present_layers(FL_RENDERER(renderer), 0, layers, 1);
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024);
GdkRGBA background_color = {
.red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0};
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024, &background_color);
}
TEST(FlRendererTest, BlitFramebufferExtension) {
@ -116,8 +149,7 @@ TEST(FlRendererTest, BlitFramebufferExtension) {
EXPECT_CALL(epoxy, glBlitFramebuffer);
g_autoptr(FlMockRenderer) renderer =
fl_mock_renderer_new(&renderer_get_refresh_rate);
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
fl_renderer_setup(FL_RENDERER(renderer));
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
FlutterBackingStoreConfig config = {
@ -132,7 +164,9 @@ TEST(FlRendererTest, BlitFramebufferExtension) {
.size = {.width = 1024, .height = 1024}};
const FlutterLayer* layers[] = {&layer0};
fl_renderer_present_layers(FL_RENDERER(renderer), 0, layers, 1);
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024);
GdkRGBA background_color = {
.red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0};
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024, &background_color);
}
TEST(FlRendererTest, NoBlitFramebuffer) {
@ -145,8 +179,7 @@ TEST(FlRendererTest, NoBlitFramebuffer) {
ON_CALL(epoxy, epoxy_is_desktop_gl).WillByDefault(::testing::Return(true));
EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(20));
g_autoptr(FlMockRenderer) renderer =
fl_mock_renderer_new(&renderer_get_refresh_rate);
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
fl_renderer_setup(FL_RENDERER(renderer));
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
FlutterBackingStoreConfig config = {
@ -161,7 +194,9 @@ TEST(FlRendererTest, NoBlitFramebuffer) {
.size = {.width = 1024, .height = 1024}};
const FlutterLayer* layers[] = {&layer0};
fl_renderer_present_layers(FL_RENDERER(renderer), 0, layers, 1);
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024);
GdkRGBA background_color = {
.red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0};
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024, &background_color);
}
TEST(FlRendererTest, BlitFramebufferNvidia) {
@ -175,8 +210,7 @@ TEST(FlRendererTest, BlitFramebufferNvidia) {
ON_CALL(epoxy, epoxy_is_desktop_gl).WillByDefault(::testing::Return(true));
EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(30));
g_autoptr(FlMockRenderer) renderer =
fl_mock_renderer_new(&renderer_get_refresh_rate);
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
fl_renderer_setup(FL_RENDERER(renderer));
fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024);
FlutterBackingStoreConfig config = {
@ -191,5 +225,7 @@ TEST(FlRendererTest, BlitFramebufferNvidia) {
.size = {.width = 1024, .height = 1024}};
const FlutterLayer* layers[] = {&layer0};
fl_renderer_present_layers(FL_RENDERER(renderer), 0, layers, 1);
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024);
GdkRGBA background_color = {
.red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0};
fl_renderer_render(FL_RENDERER(renderer), 1024, 1024, &background_color);
}

View File

@ -46,6 +46,9 @@ struct _FlView {
// Rendering output.
FlRendererGdk* renderer;
// Background color.
GdkRGBA* background_color;
// Pointer button state recorded for sending status updates.
int64_t button_state;
@ -607,7 +610,7 @@ static gboolean render_cb(FlView* self, GdkGLContext* context) {
int height = gtk_widget_get_allocated_height(GTK_WIDGET(self->gl_area));
gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(self->gl_area));
fl_renderer_render(FL_RENDERER(self->renderer), width * scale_factor,
height * scale_factor);
height * scale_factor, self->background_color);
return TRUE;
}
@ -654,6 +657,7 @@ static void fl_view_dispose(GObject* object) {
g_clear_object(&self->engine);
g_clear_object(&self->renderer);
g_clear_pointer(&self->background_color, gdk_rgba_free);
g_clear_object(&self->window_state_monitor);
g_clear_object(&self->scrolling_manager);
g_clear_object(&self->keyboard_handler);
@ -706,6 +710,10 @@ static void fl_view_init(FlView* self) {
// https://github.com/flutter/flutter/issues/138178
self->view_id = flutter::kFlutterImplicitViewId;
GdkRGBA default_background = {
.red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0};
self->background_color = gdk_rgba_copy(&default_background);
self->event_box = gtk_event_box_new();
gtk_widget_set_hexpand(self->event_box, TRUE);
gtk_widget_set_vexpand(self->event_box, TRUE);
@ -743,6 +751,7 @@ static void fl_view_init(FlView* self) {
self);
self->gl_area = GTK_GL_AREA(gtk_gl_area_new());
gtk_gl_area_set_has_alpha(self->gl_area, TRUE);
gtk_widget_show(GTK_WIDGET(self->gl_area));
gtk_container_add(GTK_CONTAINER(self->event_box), GTK_WIDGET(self->gl_area));
@ -785,6 +794,13 @@ G_MODULE_EXPORT FlEngine* fl_view_get_engine(FlView* self) {
return self->engine;
}
G_MODULE_EXPORT void fl_view_set_background_color(FlView* self,
const GdkRGBA* color) {
g_return_if_fail(FL_IS_VIEW(self));
gdk_rgba_free(self->background_color);
self->background_color = gdk_rgba_copy(color);
}
void fl_view_redraw(FlView* self) {
g_return_if_fail(FL_IS_VIEW(self));
gtk_widget_queue_draw(GTK_WIDGET(self->gl_area));

View File

@ -69,6 +69,15 @@ FlView* fl_view_new_for_engine(FlEngine* engine);
*/
FlEngine* fl_view_get_engine(FlView* view);
/**
* fl_view_set_background_color:
* @view: an #FlView.
* @color: a background color.
*
* Set the background color for Flutter (defaults to black).
*/
void fl_view_set_background_color(FlView* view, const GdkRGBA* color);
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_PUBLIC_FLUTTER_LINUX_FL_VIEW_H_

View File

@ -382,6 +382,10 @@ GLuint _glCreateProgram() {
void _glCompileShader(GLuint shader) {}
void _glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
mock->glClearColor(r, g, b, a);
}
GLuint _glCreateShader(GLenum shaderType) {
return 0;
}
@ -594,6 +598,7 @@ static void library_init() {
epoxy_glBindTexture = _glBindTexture;
epoxy_glBlitFramebuffer = _glBlitFramebuffer;
epoxy_glCompileShader = _glCompileShader;
epoxy_glClearColor = _glClearColor;
epoxy_glCreateProgram = _glCreateProgram;
epoxy_glCreateShader = _glCreateShader;
epoxy_glDeleteFramebuffers = _glDeleteFramebuffers;

View File

@ -20,6 +20,7 @@ class MockEpoxy {
MOCK_METHOD(bool, epoxy_has_gl_extension, (const char* extension));
MOCK_METHOD(bool, epoxy_is_desktop_gl, ());
MOCK_METHOD(int, epoxy_gl_version, ());
MOCK_METHOD(void, glClearColor, (GLfloat r, GLfloat g, GLfloat b, GLfloat a));
MOCK_METHOD(void,
glBlitFramebuffer,
(GLint srcX0,