mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
102 lines
4.0 KiB
C++
102 lines
4.0 KiB
C++
// 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 "fl_renderer_x11.h"
|
|
#include "flutter/shell/platform/linux/egl_utils.h"
|
|
|
|
struct _FlRendererX11 {
|
|
FlRenderer parent_instance;
|
|
|
|
GdkX11Window* window;
|
|
};
|
|
|
|
G_DEFINE_TYPE(FlRendererX11, fl_renderer_x11, fl_renderer_get_type())
|
|
|
|
static void fl_renderer_x11_dispose(GObject* object) {
|
|
FlRendererX11* self = FL_RENDERER_X11(object);
|
|
|
|
g_clear_object(&self->window);
|
|
|
|
G_OBJECT_CLASS(fl_renderer_x11_parent_class)->dispose(object);
|
|
}
|
|
|
|
// Implements FlRenderer::get_visual.
|
|
static GdkVisual* fl_renderer_x11_get_visual(FlRenderer* renderer,
|
|
GdkScreen* screen,
|
|
EGLint visual_id) {
|
|
return gdk_x11_screen_lookup_visual(GDK_X11_SCREEN(screen), visual_id);
|
|
}
|
|
|
|
// Implements FlRenderer::set_window.
|
|
static void fl_renderer_x11_set_window(FlRenderer* renderer,
|
|
GdkWindow* window) {
|
|
FlRendererX11* self = FL_RENDERER_X11(renderer);
|
|
g_return_if_fail(GDK_IS_X11_WINDOW(window));
|
|
g_assert_null(self->window);
|
|
self->window = GDK_X11_WINDOW(g_object_ref(window));
|
|
}
|
|
|
|
// Implements FlRenderer::create_display.
|
|
static EGLDisplay fl_renderer_x11_create_display(FlRenderer* renderer) {
|
|
// Note the use of EGL_DEFAULT_DISPLAY rather than sharing the existing
|
|
// display connection from GTK. This is because this EGL display is going to
|
|
// be accessed by a thread from Flutter. The GTK/X11 display connection is not
|
|
// thread safe and would cause a crash.
|
|
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
}
|
|
|
|
// Implements FlRenderer::create_surfaces.
|
|
static gboolean fl_renderer_x11_create_surfaces(FlRenderer* renderer,
|
|
EGLDisplay display,
|
|
EGLConfig config,
|
|
EGLSurface* visible,
|
|
EGLSurface* resource,
|
|
GError** error) {
|
|
FlRendererX11* self = FL_RENDERER_X11(renderer);
|
|
|
|
if (!self->window) {
|
|
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
|
|
"Can not create EGL surface: FlRendererX11::window not set");
|
|
return FALSE;
|
|
}
|
|
|
|
*visible = eglCreateWindowSurface(
|
|
display, config, gdk_x11_window_get_xid(self->window), nullptr);
|
|
if (*visible == EGL_NO_SURFACE) {
|
|
EGLint egl_error = eglGetError(); // Must be before egl_config_to_string().
|
|
g_autofree gchar* config_string = egl_config_to_string(display, config);
|
|
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
|
|
"Failed to create EGL surface using configuration (%s): %s",
|
|
config_string, egl_error_to_string(egl_error));
|
|
return FALSE;
|
|
}
|
|
|
|
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
|
*resource = eglCreatePbufferSurface(display, config, attribs);
|
|
if (*resource == EGL_NO_SURFACE) {
|
|
EGLint egl_error = eglGetError(); // Must be before egl_config_to_string().
|
|
g_autofree gchar* config_string = egl_config_to_string(display, config);
|
|
g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
|
|
"Failed to create EGL resource using configuration (%s): %s",
|
|
config_string, egl_error_to_string(egl_error));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void fl_renderer_x11_class_init(FlRendererX11Class* klass) {
|
|
G_OBJECT_CLASS(klass)->dispose = fl_renderer_x11_dispose;
|
|
FL_RENDERER_CLASS(klass)->get_visual = fl_renderer_x11_get_visual;
|
|
FL_RENDERER_CLASS(klass)->set_window = fl_renderer_x11_set_window;
|
|
FL_RENDERER_CLASS(klass)->create_display = fl_renderer_x11_create_display;
|
|
FL_RENDERER_CLASS(klass)->create_surfaces = fl_renderer_x11_create_surfaces;
|
|
}
|
|
|
|
static void fl_renderer_x11_init(FlRendererX11* self) {}
|
|
|
|
FlRendererX11* fl_renderer_x11_new() {
|
|
return FL_RENDERER_X11(g_object_new(fl_renderer_x11_get_type(), nullptr));
|
|
}
|