未验证 提交 b19a17d5 编写于 作者: R Robert Ancell 提交者: GitHub

Implement an EGL resource context for the Linux shell. (#18918)

Fixes https://github.com/flutter/flutter/issues/54855
上级 db7f226c
......@@ -108,6 +108,15 @@ static bool fl_engine_gl_present(void* user_data) {
return result;
}
static bool fl_engine_gl_make_resource_current(void* user_data) {
FlEngine* self = static_cast<FlEngine*>(user_data);
g_autoptr(GError) error = nullptr;
gboolean result = fl_renderer_make_resource_current(self->renderer, &error);
if (!result)
g_warning("%s", error->message);
return result;
}
// Called by the engine to determine if it is on the GTK thread.
static bool fl_engine_runs_task_on_current_thread(void* user_data) {
FlEngine* self = static_cast<FlEngine*>(user_data);
......@@ -222,6 +231,7 @@ gboolean fl_engine_start(FlEngine* self, GError** error) {
config.open_gl.clear_current = fl_engine_gl_clear_current;
config.open_gl.fbo_callback = fl_engine_gl_get_fbo;
config.open_gl.present = fl_engine_gl_present;
config.open_gl.make_resource_current = fl_engine_gl_make_resource_current;
FlutterTaskRunnerDescription platform_task_runner = {};
platform_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription);
......
......@@ -12,6 +12,9 @@ typedef struct {
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLContext egl_context;
EGLSurface resource_surface;
EGLContext resource_context;
} FlRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
......@@ -55,18 +58,38 @@ static const gchar* get_egl_error() {
}
}
// Creates a resource surface.
static void create_resource_surface(FlRenderer* self, EGLConfig config) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
const EGLint resource_context_attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1,
EGL_NONE};
priv->resource_surface = eglCreatePbufferSurface(priv->egl_display, config,
resource_context_attribs);
if (priv->resource_surface != nullptr) {
g_warning("Failed to create EGL resource surface: %s", get_egl_error());
return;
}
priv->resource_context = eglCreateContext(
priv->egl_display, config, priv->egl_context, context_attributes);
if (priv->resource_context == nullptr)
g_warning("Failed to create EGL resource context: %s", get_egl_error());
}
// Default implementation for the start virtual method.
// Provided so subclasses can chain up to here.
static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
// Note the use of EGL_DEFAULT_DISPLAY rather than sharing an existing display
// connection (e.g. an X11 connection from GTK). This is because this EGL
// display is going to be accessed by a thread from Flutter. In the case
// of GTK/X11 the display connection is not thread safe and this would cause
// a crash.
//
// Note the use of EGL_DEFAULT_DISPLAY rather than sharing an existing
// display connection (e.g. an X11 connection from GTK). This is because
// this EGL display is going to be accessed by a thread from Flutter. In the
// case of GTK/X11 the display connection is not thread safe and this would
// cause a crash.
priv->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!eglInitialize(priv->egl_display, nullptr, nullptr)) {
......@@ -120,6 +143,9 @@ static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) {
"Failed to create EGL context: %s", get_egl_error());
return FALSE;
}
create_resource_surface(self, egl_config);
EGLint value;
eglQueryContext(priv->egl_display, priv->egl_context,
EGL_CONTEXT_CLIENT_VERSION, &value);
......@@ -155,6 +181,23 @@ gboolean fl_renderer_make_current(FlRenderer* self, GError** error) {
return TRUE;
}
gboolean fl_renderer_make_resource_current(FlRenderer* self, GError** error) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
if (priv->resource_surface == nullptr || priv->resource_context == nullptr)
return FALSE;
if (!eglMakeCurrent(priv->egl_display, priv->resource_surface,
priv->resource_surface, priv->resource_context)) {
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
"Failed to make EGL context current: %s", get_egl_error());
return FALSE;
}
return TRUE;
}
gboolean fl_renderer_clear_current(FlRenderer* self, GError** error) {
FlRendererPrivate* priv =
static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
......
......@@ -80,6 +80,19 @@ void* fl_renderer_get_proc_address(FlRenderer* renderer, const char* name);
*/
gboolean fl_renderer_make_current(FlRenderer* renderer, GError** error);
/**
* fl_renderer_make_resource_current:
* @renderer: an #FlRenderer.
* @error: (allow-none): #GError location to store the error occurring, or %NULL
* to ignore.
*
* Makes the resource rendering context current.
*
* Returns %TRUE if successful.
*/
gboolean fl_renderer_make_resource_current(FlRenderer* renderer,
GError** error);
/**
* fl_renderer_clear_current:
* @renderer: an #FlRenderer.
......
......@@ -23,6 +23,12 @@ EGLContext eglCreateContext(EGLDisplay dpy,
return nullptr;
}
EGLSurface eglCreatePbufferSurface(EGLDisplay dpy,
EGLConfig config,
const EGLint* attrib_list) {
return nullptr;
}
EGLSurface eglCreateWindowSurface(EGLDisplay dpy,
EGLConfig config,
EGLNativeWindowType win,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册