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

Commit b19a17d

Browse files
Implement an EGL resource context for the Linux shell. (#18918)
Fixes flutter/flutter#54855
1 parent db7f226 commit b19a17d

File tree

4 files changed

+78
-6
lines changed

4 files changed

+78
-6
lines changed

shell/platform/linux/fl_engine.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ static bool fl_engine_gl_present(void* user_data) {
108108
return result;
109109
}
110110

111+
static bool fl_engine_gl_make_resource_current(void* user_data) {
112+
FlEngine* self = static_cast<FlEngine*>(user_data);
113+
g_autoptr(GError) error = nullptr;
114+
gboolean result = fl_renderer_make_resource_current(self->renderer, &error);
115+
if (!result)
116+
g_warning("%s", error->message);
117+
return result;
118+
}
119+
111120
// Called by the engine to determine if it is on the GTK thread.
112121
static bool fl_engine_runs_task_on_current_thread(void* user_data) {
113122
FlEngine* self = static_cast<FlEngine*>(user_data);
@@ -222,6 +231,7 @@ gboolean fl_engine_start(FlEngine* self, GError** error) {
222231
config.open_gl.clear_current = fl_engine_gl_clear_current;
223232
config.open_gl.fbo_callback = fl_engine_gl_get_fbo;
224233
config.open_gl.present = fl_engine_gl_present;
234+
config.open_gl.make_resource_current = fl_engine_gl_make_resource_current;
225235

226236
FlutterTaskRunnerDescription platform_task_runner = {};
227237
platform_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription);

shell/platform/linux/fl_renderer.cc

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ typedef struct {
1212
EGLDisplay egl_display;
1313
EGLSurface egl_surface;
1414
EGLContext egl_context;
15+
16+
EGLSurface resource_surface;
17+
EGLContext resource_context;
1518
} FlRendererPrivate;
1619

1720
G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
@@ -55,18 +58,38 @@ static const gchar* get_egl_error() {
5558
}
5659
}
5760

61+
// Creates a resource surface.
62+
static void create_resource_surface(FlRenderer* self, EGLConfig config) {
63+
FlRendererPrivate* priv =
64+
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
65+
66+
EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
67+
const EGLint resource_context_attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1,
68+
EGL_NONE};
69+
priv->resource_surface = eglCreatePbufferSurface(priv->egl_display, config,
70+
resource_context_attribs);
71+
if (priv->resource_surface != nullptr) {
72+
g_warning("Failed to create EGL resource surface: %s", get_egl_error());
73+
return;
74+
}
75+
76+
priv->resource_context = eglCreateContext(
77+
priv->egl_display, config, priv->egl_context, context_attributes);
78+
if (priv->resource_context == nullptr)
79+
g_warning("Failed to create EGL resource context: %s", get_egl_error());
80+
}
81+
5882
// Default implementation for the start virtual method.
5983
// Provided so subclasses can chain up to here.
6084
static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) {
6185
FlRendererPrivate* priv =
6286
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
6387

64-
// Note the use of EGL_DEFAULT_DISPLAY rather than sharing an existing display
65-
// connection (e.g. an X11 connection from GTK). This is because this EGL
66-
// display is going to be accessed by a thread from Flutter. In the case
67-
// of GTK/X11 the display connection is not thread safe and this would cause
68-
// a crash.
69-
//
88+
// Note the use of EGL_DEFAULT_DISPLAY rather than sharing an existing
89+
// display connection (e.g. an X11 connection from GTK). This is because
90+
// this EGL display is going to be accessed by a thread from Flutter. In the
91+
// case of GTK/X11 the display connection is not thread safe and this would
92+
// cause a crash.
7093
priv->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
7194

7295
if (!eglInitialize(priv->egl_display, nullptr, nullptr)) {
@@ -120,6 +143,9 @@ static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) {
120143
"Failed to create EGL context: %s", get_egl_error());
121144
return FALSE;
122145
}
146+
147+
create_resource_surface(self, egl_config);
148+
123149
EGLint value;
124150
eglQueryContext(priv->egl_display, priv->egl_context,
125151
EGL_CONTEXT_CLIENT_VERSION, &value);
@@ -155,6 +181,23 @@ gboolean fl_renderer_make_current(FlRenderer* self, GError** error) {
155181
return TRUE;
156182
}
157183

184+
gboolean fl_renderer_make_resource_current(FlRenderer* self, GError** error) {
185+
FlRendererPrivate* priv =
186+
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
187+
188+
if (priv->resource_surface == nullptr || priv->resource_context == nullptr)
189+
return FALSE;
190+
191+
if (!eglMakeCurrent(priv->egl_display, priv->resource_surface,
192+
priv->resource_surface, priv->resource_context)) {
193+
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
194+
"Failed to make EGL context current: %s", get_egl_error());
195+
return FALSE;
196+
}
197+
198+
return TRUE;
199+
}
200+
158201
gboolean fl_renderer_clear_current(FlRenderer* self, GError** error) {
159202
FlRendererPrivate* priv =
160203
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

shell/platform/linux/fl_renderer.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ void* fl_renderer_get_proc_address(FlRenderer* renderer, const char* name);
8080
*/
8181
gboolean fl_renderer_make_current(FlRenderer* renderer, GError** error);
8282

83+
/**
84+
* fl_renderer_make_resource_current:
85+
* @renderer: an #FlRenderer.
86+
* @error: (allow-none): #GError location to store the error occurring, or %NULL
87+
* to ignore.
88+
*
89+
* Makes the resource rendering context current.
90+
*
91+
* Returns %TRUE if successful.
92+
*/
93+
gboolean fl_renderer_make_resource_current(FlRenderer* renderer,
94+
GError** error);
95+
8396
/**
8497
* fl_renderer_clear_current:
8598
* @renderer: an #FlRenderer.

shell/platform/linux/testing/mock_egl.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ EGLContext eglCreateContext(EGLDisplay dpy,
2323
return nullptr;
2424
}
2525

26+
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy,
27+
EGLConfig config,
28+
const EGLint* attrib_list) {
29+
return nullptr;
30+
}
31+
2632
EGLSurface eglCreateWindowSurface(EGLDisplay dpy,
2733
EGLConfig config,
2834
EGLNativeWindowType win,

0 commit comments

Comments
 (0)