Save and restore OpenGL bindings that are changed by fl_renderer_render (flutter/engine#51887)

fl_renderer_render uses the raster thread GL context that is also used by Skia.  Skia expects that its bindings have not been changed elsewhere.
This commit is contained in:
Jason Simmons 2024-04-11 12:39:03 -07:00 committed by GitHub
parent b1030afadd
commit e5d0cae6cd
5 changed files with 95 additions and 1 deletions

View File

@ -41986,6 +41986,7 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.cc + ../../../flut
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_test.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager_test.cc + ../../../flutter/LICENSE
@ -44897,6 +44898,7 @@ FILE: ../../../flutter/shell/platform/linux/fl_renderer_gdk.cc
FILE: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h
FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc
FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.h
FILE: ../../../flutter/shell/platform/linux/fl_renderer_test.cc
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager_test.cc

View File

@ -213,6 +213,7 @@ executable("flutter_linux_unittests") {
"fl_pixel_buffer_texture_test.cc",
"fl_platform_plugin_test.cc",
"fl_plugin_registrar_test.cc",
"fl_renderer_test.cc",
"fl_scrolling_manager_test.cc",
"fl_settings_plugin_test.cc",
"fl_settings_portal_test.cc",

View File

@ -314,6 +314,16 @@ void fl_renderer_render(FlRenderer* self, int width, int height) {
g_return_if_fail(FL_IS_RENDERER(self));
// Save bindings that are set by this function. All bindings must be restored
// to their original values because Skia expects that its bindings have not
// been altered.
GLint saved_texture_binding;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
GLint saved_vao_binding;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
GLint saved_array_buffer_binding;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
@ -364,6 +374,10 @@ void fl_renderer_render(FlRenderer* self, int width, int height) {
}
glFlush();
glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
glBindVertexArray(saved_vao_binding);
glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
}
void fl_renderer_cleanup(FlRenderer* self) {

View File

@ -0,0 +1,53 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gtest/gtest.h"
#include <epoxy/egl.h>
#include "flutter/fml/logging.h"
#include "flutter/shell/platform/linux/fl_backing_store_provider.h"
#include "flutter/shell/platform/linux/testing/fl_test_gtk_logs.h"
#include "flutter/shell/platform/linux/testing/mock_renderer.h"
TEST(FlRendererTest, RestoresGLState) {
constexpr int kWidth = 100;
constexpr int kHeight = 100;
flutter::testing::fl_ensure_gtk_init();
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(FlBackingStoreProvider) backing_store_provider =
fl_backing_store_provider_new(kWidth, kHeight);
fl_renderer_start(FL_RENDERER(renderer), view);
fl_renderer_wait_for_frame(FL_RENDERER(renderer), kWidth, kHeight);
FlutterBackingStore backing_store;
backing_store.type = kFlutterBackingStoreTypeOpenGL;
backing_store.open_gl.framebuffer.user_data = backing_store_provider;
FlutterLayer layer;
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = &backing_store;
layer.offset = {0, 0};
layer.size = {kWidth, kHeight};
std::array<const FlutterLayer*, 1> layers = {&layer};
constexpr GLuint kFakeTextureName = 123;
glBindTexture(GL_TEXTURE_2D, kFakeTextureName);
fl_renderer_present_layers(FL_RENDERER(renderer), layers.data(),
layers.size());
fl_renderer_render(FL_RENDERER(renderer), kWidth, kHeight);
GLuint texture_2d_binding;
glGetIntegerv(GL_TEXTURE_BINDING_2D,
reinterpret_cast<GLint*>(&texture_2d_binding));
EXPECT_EQ(texture_2d_binding, kFakeTextureName);
g_object_ref_sink(view);
}

View File

@ -325,6 +325,16 @@ EGLBoolean _eglMakeCurrent(EGLDisplay dpy,
return bool_success();
}
EGLBoolean _eglQueryContext(EGLDisplay display,
EGLContext context,
EGLint attribute,
EGLint* value) {
if (attribute == EGL_CONTEXT_CLIENT_TYPE) {
*value = EGL_OPENGL_API;
return EGL_TRUE;
}
return EGL_FALSE;
}
EGLBoolean _eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
if (!check_display(dpy) || !check_initialized(dpy)) {
@ -334,9 +344,15 @@ EGLBoolean _eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
return bool_success();
}
static GLuint bound_texture_2d;
static void _glBindFramebuffer(GLenum target, GLuint framebuffer) {}
static void _glBindTexture(GLenum target, GLuint texture) {}
static void _glBindTexture(GLenum target, GLuint texture) {
if (target == GL_TEXTURE_2D) {
bound_texture_2d = texture;
}
}
void _glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {}
@ -360,6 +376,12 @@ static void _glGenFramebuffers(GLsizei n, GLuint* framebuffers) {
}
}
static void _glGetIntegerv(GLenum pname, GLint* data) {
if (pname == GL_TEXTURE_BINDING_2D) {
*data = bound_texture_2d;
}
}
static void _glTexParameterf(GLenum target, GLenum pname, GLfloat param) {}
static void _glTexParameteri(GLenum target, GLenum pname, GLint param) {}
@ -477,6 +499,7 @@ static void library_init() {
epoxy_eglGetProcAddress = _eglGetProcAddress;
epoxy_eglInitialize = _eglInitialize;
epoxy_eglMakeCurrent = _eglMakeCurrent;
epoxy_eglQueryContext = _eglQueryContext;
epoxy_eglSwapBuffers = _eglSwapBuffers;
epoxy_glBindFramebuffer = _glBindFramebuffer;
@ -486,6 +509,7 @@ static void library_init() {
epoxy_glFramebufferTexture2D = _glFramebufferTexture2D;
epoxy_glGenFramebuffers = _glGenFramebuffers;
epoxy_glGenTextures = _glGenTextures;
epoxy_glGetIntegerv = _glGetIntegerv;
epoxy_glTexParameterf = _glTexParameterf;
epoxy_glTexParameteri = _glTexParameteri;
epoxy_glTexImage2D = _glTexImage2D;