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

Commit bbe63af

Browse files
Save and restore OpenGL bindings that are changed by fl_renderer_render (#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.
1 parent 16b0cfd commit bbe63af

File tree

5 files changed

+95
-1
lines changed

5 files changed

+95
-1
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41986,6 +41986,7 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.cc + ../../../flut
4198641986
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h + ../../../flutter/LICENSE
4198741987
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc + ../../../flutter/LICENSE
4198841988
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.h + ../../../flutter/LICENSE
41989+
ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_test.cc + ../../../flutter/LICENSE
4198941990
ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc + ../../../flutter/LICENSE
4199041991
ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h + ../../../flutter/LICENSE
4199141992
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
4489744898
FILE: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h
4489844899
FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc
4489944900
FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.h
44901+
FILE: ../../../flutter/shell/platform/linux/fl_renderer_test.cc
4490044902
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc
4490144903
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h
4490244904
FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager_test.cc

shell/platform/linux/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ executable("flutter_linux_unittests") {
213213
"fl_pixel_buffer_texture_test.cc",
214214
"fl_platform_plugin_test.cc",
215215
"fl_plugin_registrar_test.cc",
216+
"fl_renderer_test.cc",
216217
"fl_scrolling_manager_test.cc",
217218
"fl_settings_plugin_test.cc",
218219
"fl_settings_portal_test.cc",

shell/platform/linux/fl_renderer.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,16 @@ void fl_renderer_render(FlRenderer* self, int width, int height) {
314314

315315
g_return_if_fail(FL_IS_RENDERER(self));
316316

317+
// Save bindings that are set by this function. All bindings must be restored
318+
// to their original values because Skia expects that its bindings have not
319+
// been altered.
320+
GLint saved_texture_binding;
321+
glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
322+
GLint saved_vao_binding;
323+
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
324+
GLint saved_array_buffer_binding;
325+
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
326+
317327
glClearColor(0.0, 0.0, 0.0, 1.0);
318328
glClear(GL_COLOR_BUFFER_BIT);
319329

@@ -364,6 +374,10 @@ void fl_renderer_render(FlRenderer* self, int width, int height) {
364374
}
365375

366376
glFlush();
377+
378+
glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
379+
glBindVertexArray(saved_vao_binding);
380+
glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
367381
}
368382

369383
void fl_renderer_cleanup(FlRenderer* self) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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 "gtest/gtest.h"
6+
7+
#include <epoxy/egl.h>
8+
9+
#include "flutter/fml/logging.h"
10+
#include "flutter/shell/platform/linux/fl_backing_store_provider.h"
11+
#include "flutter/shell/platform/linux/testing/fl_test_gtk_logs.h"
12+
#include "flutter/shell/platform/linux/testing/mock_renderer.h"
13+
14+
TEST(FlRendererTest, RestoresGLState) {
15+
constexpr int kWidth = 100;
16+
constexpr int kHeight = 100;
17+
18+
flutter::testing::fl_ensure_gtk_init();
19+
g_autoptr(FlDartProject) project = fl_dart_project_new();
20+
g_autoptr(FlView) view = fl_view_new(project);
21+
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
22+
g_autoptr(FlBackingStoreProvider) backing_store_provider =
23+
fl_backing_store_provider_new(kWidth, kHeight);
24+
25+
fl_renderer_start(FL_RENDERER(renderer), view);
26+
fl_renderer_wait_for_frame(FL_RENDERER(renderer), kWidth, kHeight);
27+
28+
FlutterBackingStore backing_store;
29+
backing_store.type = kFlutterBackingStoreTypeOpenGL;
30+
backing_store.open_gl.framebuffer.user_data = backing_store_provider;
31+
32+
FlutterLayer layer;
33+
layer.type = kFlutterLayerContentTypeBackingStore;
34+
layer.backing_store = &backing_store;
35+
layer.offset = {0, 0};
36+
layer.size = {kWidth, kHeight};
37+
38+
std::array<const FlutterLayer*, 1> layers = {&layer};
39+
40+
constexpr GLuint kFakeTextureName = 123;
41+
glBindTexture(GL_TEXTURE_2D, kFakeTextureName);
42+
43+
fl_renderer_present_layers(FL_RENDERER(renderer), layers.data(),
44+
layers.size());
45+
fl_renderer_render(FL_RENDERER(renderer), kWidth, kHeight);
46+
47+
GLuint texture_2d_binding;
48+
glGetIntegerv(GL_TEXTURE_BINDING_2D,
49+
reinterpret_cast<GLint*>(&texture_2d_binding));
50+
EXPECT_EQ(texture_2d_binding, kFakeTextureName);
51+
52+
g_object_ref_sink(view);
53+
}

shell/platform/linux/testing/mock_epoxy.cc

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,16 @@ EGLBoolean _eglMakeCurrent(EGLDisplay dpy,
325325

326326
return bool_success();
327327
}
328+
EGLBoolean _eglQueryContext(EGLDisplay display,
329+
EGLContext context,
330+
EGLint attribute,
331+
EGLint* value) {
332+
if (attribute == EGL_CONTEXT_CLIENT_TYPE) {
333+
*value = EGL_OPENGL_API;
334+
return EGL_TRUE;
335+
}
336+
return EGL_FALSE;
337+
}
328338

329339
EGLBoolean _eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
330340
if (!check_display(dpy) || !check_initialized(dpy)) {
@@ -334,9 +344,15 @@ EGLBoolean _eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
334344
return bool_success();
335345
}
336346

347+
static GLuint bound_texture_2d;
348+
337349
static void _glBindFramebuffer(GLenum target, GLuint framebuffer) {}
338350

339-
static void _glBindTexture(GLenum target, GLuint texture) {}
351+
static void _glBindTexture(GLenum target, GLuint texture) {
352+
if (target == GL_TEXTURE_2D) {
353+
bound_texture_2d = texture;
354+
}
355+
}
340356

341357
void _glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {}
342358

@@ -360,6 +376,12 @@ static void _glGenFramebuffers(GLsizei n, GLuint* framebuffers) {
360376
}
361377
}
362378

379+
static void _glGetIntegerv(GLenum pname, GLint* data) {
380+
if (pname == GL_TEXTURE_BINDING_2D) {
381+
*data = bound_texture_2d;
382+
}
383+
}
384+
363385
static void _glTexParameterf(GLenum target, GLenum pname, GLfloat param) {}
364386

365387
static void _glTexParameteri(GLenum target, GLenum pname, GLint param) {}
@@ -477,6 +499,7 @@ static void library_init() {
477499
epoxy_eglGetProcAddress = _eglGetProcAddress;
478500
epoxy_eglInitialize = _eglInitialize;
479501
epoxy_eglMakeCurrent = _eglMakeCurrent;
502+
epoxy_eglQueryContext = _eglQueryContext;
480503
epoxy_eglSwapBuffers = _eglSwapBuffers;
481504

482505
epoxy_glBindFramebuffer = _glBindFramebuffer;
@@ -486,6 +509,7 @@ static void library_init() {
486509
epoxy_glFramebufferTexture2D = _glFramebufferTexture2D;
487510
epoxy_glGenFramebuffers = _glGenFramebuffers;
488511
epoxy_glGenTextures = _glGenTextures;
512+
epoxy_glGetIntegerv = _glGetIntegerv;
489513
epoxy_glTexParameterf = _glTexParameterf;
490514
epoxy_glTexParameteri = _glTexParameteri;
491515
epoxy_glTexImage2D = _glTexImage2D;

0 commit comments

Comments
 (0)