Move the context clear to the correct layer
diff --git a/engine/src/flutter/shell/platform/linux/fl_compositor_opengl_test.cc b/engine/src/flutter/shell/platform/linux/fl_compositor_opengl_test.cc index b28cb94..c83f073 100644 --- a/engine/src/flutter/shell/platform/linux/fl_compositor_opengl_test.cc +++ b/engine/src/flutter/shell/platform/linux/fl_compositor_opengl_test.cc
@@ -349,9 +349,3 @@ const FlutterLayer* layers[1] = {&layer}; EXPECT_EQ(fl_compositor_opengl_get_frame_format(layers, 1), GL_RGBA); } - -TEST_F(FlCompositorOpenGLTest, ClearsGdkGLContextBeforePlatformContext) { - ::testing::NiceMock<flutter::testing::MockGtk> mock_gtk; - EXPECT_CALL(mock_gtk, gdk_gl_context_clear_current()).Times(2); - compositor = fl_compositor_opengl_new(opengl_manager); -}
diff --git a/engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc b/engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc index c83f22f..32d29c8 100644 --- a/engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc +++ b/engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc
@@ -109,14 +109,6 @@ } gboolean fl_opengl_manager_make_platform_current(FlOpenGLManager* self) { - // Under libglvnd, calling eglMakeCurrent on the GTK main thread while a GLX - // context (GdkGLContext) is active causes eglMakeCurrent to fail with - // EGL_BAD_ACCESS ("Another window API already has a current context"). - // Because EGL does not unbind foreign APIs, the GLX context must be - // explicitly unbound first via gdk_gl_context_clear_current() so that an - // X_GLXMakeContextCurrent(None) request is dispatched to the X server, - // preventing client-server state desynchronization. - gdk_gl_context_clear_current(); return eglMakeCurrent(self->display, EGL_NO_SURFACE, EGL_NO_SURFACE, self->platform_context) == EGL_TRUE; }
diff --git a/engine/src/flutter/shell/platform/linux/fl_view_renderer_opengl.cc b/engine/src/flutter/shell/platform/linux/fl_view_renderer_opengl.cc index f0c973d..859b182 100644 --- a/engine/src/flutter/shell/platform/linux/fl_view_renderer_opengl.cc +++ b/engine/src/flutter/shell/platform/linux/fl_view_renderer_opengl.cc
@@ -136,6 +136,14 @@ self->frame = fl_opengl_frame_new(); self->task_runner = FL_TASK_RUNNER(g_object_ref(fl_engine_get_task_runner(self->engine))); + // Creating the compositor makes an EGL context current on this thread. GDK + // leaves its OpenGL context current after drawing (see + // fl_view_renderer_opengl_draw()). On X11 this is a GLX context, and under + // libglvnd eglMakeCurrent fails with EGL_BAD_ACCESS while a context from + // another window API is current. EGL doesn't release it, so it must be + // released through GDK, which also keeps GDK's view of the current context in + // sync with the X server. + gdk_gl_context_clear_current(); self->compositor = fl_compositor_opengl_new(fl_engine_get_opengl_manager(self->engine)); @@ -236,6 +244,12 @@ // reference is dropped. This keeps it alive for the raster thread, which // holds a strong reference on the view (and thus this renderer) while // presenting. + // + // Releasing the compositor makes an EGL context current, so release GDK's + // context first (see fl_view_renderer_opengl_realize()). + if (self->compositor != nullptr) { + gdk_gl_context_clear_current(); + } g_clear_object(&self->compositor); g_clear_object(&self->frame);