Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 47 additions & 51 deletions engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <epoxy/egl.h>
#include <gdk/gdkwayland.h>
#include <gdk/gdkx.h>

#include "flutter/shell/platform/linux/fl_opengl_manager.h"

struct _FlOpenGLManager {
GObject parent_instance;

// OpenGL rendering context used by GDK.
GdkGLContext* gdk_context;
// Display being rendered to.
EGLDisplay display;

// Main OpenGL rendering context used by Flutter.
GdkGLContext* main_context;
// Context used by Flutter to render.
EGLContext render_context;

// OpenGL rendering context used by a Flutter background thread for
// asynchronous texture uploads.
GdkGLContext* resource_context;
// Context used by Flutter to share resources.
EGLContext resource_context;
};

G_DEFINE_TYPE(FlOpenGLManager, fl_opengl_manager, G_TYPE_OBJECT)

static void fl_opengl_manager_dispose(GObject* object) {
FlOpenGLManager* self = FL_OPENGL_MANAGER(object);

g_clear_object(&self->gdk_context);
g_clear_object(&self->main_context);
g_clear_object(&self->resource_context);
eglDestroyContext(self->display, self->render_context);
eglDestroyContext(self->display, self->resource_context);
eglTerminate(self->display);

G_OBJECT_CLASS(fl_opengl_manager_parent_class)->dispose(object);
}
Expand All @@ -34,59 +37,52 @@ static void fl_opengl_manager_class_init(FlOpenGLManagerClass* klass) {
G_OBJECT_CLASS(klass)->dispose = fl_opengl_manager_dispose;
}

static void fl_opengl_manager_init(FlOpenGLManager* self) {}
static void fl_opengl_manager_init(FlOpenGLManager* self) {
GdkDisplay* display = gdk_display_get_default();
if (GDK_IS_WAYLAND_DISPLAY(display)) {
self->display = eglGetPlatformDisplayEXT(
EGL_PLATFORM_WAYLAND_EXT, gdk_wayland_display_get_wl_display(display),
NULL);
} else if (GDK_IS_X11_DISPLAY(display)) {
self->display = eglGetPlatformDisplayEXT(
EGL_PLATFORM_X11_EXT, gdk_x11_display_get_xdisplay(display), NULL);
} else {
g_critical("Unsupported GDK backend, unable to get EGL display");
}

eglInitialize(self->display, nullptr, nullptr);

const EGLint config_attributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
EGL_NONE};
EGLConfig config = nullptr;
EGLint num_config = 0;
eglChooseConfig(self->display, config_attributes, &config, 1, &num_config);

const EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
self->render_context = eglCreateContext(self->display, config, EGL_NO_CONTEXT,
context_attributes);
self->resource_context = eglCreateContext(
self->display, config, self->render_context, context_attributes);
}

FlOpenGLManager* fl_opengl_manager_new() {
FlOpenGLManager* self =
FL_OPENGL_MANAGER(g_object_new(fl_opengl_manager_get_type(), nullptr));
return self;
}

gboolean fl_opengl_manager_create_contexts(FlOpenGLManager* self,
GdkWindow* window,
GError** error) {
g_return_val_if_fail(FL_IS_OPENGL_MANAGER(self), FALSE);

self->gdk_context = gdk_window_create_gl_context(window, error);
if (self->gdk_context == nullptr) {
return FALSE;
}
if (!gdk_gl_context_realize(self->gdk_context, error)) {
return FALSE;
}

self->main_context = gdk_window_create_gl_context(window, error);
if (self->main_context == nullptr) {
return FALSE;
}
if (!gdk_gl_context_realize(self->main_context, error)) {
return FALSE;
}

self->resource_context = gdk_window_create_gl_context(window, error);
if (self->resource_context == nullptr) {
return FALSE;
}
if (!gdk_gl_context_realize(self->resource_context, error)) {
return FALSE;
}

return TRUE;
}

GdkGLContext* fl_opengl_manager_get_context(FlOpenGLManager* self) {
g_return_val_if_fail(FL_IS_OPENGL_MANAGER(self), nullptr);
return self->gdk_context;
}

void fl_opengl_manager_make_current(FlOpenGLManager* self) {
gdk_gl_context_make_current(self->main_context);
eglMakeCurrent(self->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
self->render_context);
}

void fl_opengl_manager_make_resource_current(FlOpenGLManager* self) {
gdk_gl_context_make_current(self->resource_context);
eglMakeCurrent(self->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
self->resource_context);
}

void fl_opengl_manager_clear_current(FlOpenGLManager* self) {
gdk_gl_context_clear_current();
eglMakeCurrent(self->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
25 changes: 1 addition & 24 deletions engine/src/flutter/shell/platform/linux/fl_opengl_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_OPENGL_MANAGER_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_OPENGL_MANAGER_H_

#include <gtk/gtk.h>
#include <glib-object.h>

G_BEGIN_DECLS

Expand All @@ -24,29 +24,6 @@ G_DECLARE_FINAL_TYPE(FlOpenGLManager,
*/
FlOpenGLManager* fl_opengl_manager_new();

/**
* fl_opengl_manager_create_contexts:
* @manager: an #FlOpenGLManager.
* @window: the window that is being rendered on.
* @error: (allow-none): #GError location to store the error occurring, or
* %NULL to ignore.
*
* Create rendering contexts.
*
* Returns: %TRUE if contexts were created, %FALSE if there was an error.
*/
gboolean fl_opengl_manager_create_contexts(FlOpenGLManager* manager,
GdkWindow* window,
GError** error);

/**
* fl_opengl_manager_get_context:
* @manager: an #FlOpenGLManager.
*
* Returns: the main context used for rendering.
*/
GdkGLContext* fl_opengl_manager_get_context(FlOpenGLManager* manager);

/**
* fl_opengl_manager_make_current:
* @manager: an #FlOpenGLManager.
Expand Down
20 changes: 0 additions & 20 deletions engine/src/flutter/shell/platform/linux/fl_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -429,24 +429,6 @@ static void gesture_zoom_end_cb(FlView* self) {
fl_scrolling_manager_handle_zoom_end(self->scrolling_manager);
}

static GdkGLContext* create_context_cb(FlView* self) {
if (self->view_id != flutter::kFlutterImplicitViewId) {
return nullptr;
}

FlOpenGLManager* opengl_manager = fl_engine_get_opengl_manager(self->engine);
g_autoptr(GError) error = nullptr;
if (!fl_opengl_manager_create_contexts(
opengl_manager, gtk_widget_get_parent_window(GTK_WIDGET(self)),
&error)) {
gtk_gl_area_set_error(GTK_GL_AREA(self->render_area), error);
return nullptr;
}

return GDK_GL_CONTEXT(
g_object_ref(fl_opengl_manager_get_context(opengl_manager)));
}

static void realize_cb(FlView* self) {
FlutterRendererType renderer_type = fl_engine_get_renderer_type(self->engine);
gboolean shareable;
Expand Down Expand Up @@ -712,8 +694,6 @@ static void setup_engine(FlView* self) {
G_CALLBACK(opengl_draw_cb), self);
g_signal_connect_swapped(self->render_area, "render",
G_CALLBACK(render_cb), self);
g_signal_connect_swapped(self->render_area, "create-context",
G_CALLBACK(create_context_cb), self);
g_signal_connect_swapped(self->render_area, "unrealize",
G_CALLBACK(unrealize_cb), self);
break;
Expand Down
10 changes: 10 additions & 0 deletions engine/src/flutter/shell/platform/linux/testing/mock_epoxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,12 @@ EGLDisplay _eglGetCurrentDisplay() {
return &mock_display;
}

EGLDisplay _eglGetPlatformDisplayEXT(EGLenum platform,
void* native_display,
const EGLint* attrib_list) {
return &mock_display;
}

EGLint _eglGetError() {
EGLint error = mock_error;
mock_error = EGL_SUCCESS;
Expand Down Expand Up @@ -612,6 +618,9 @@ EGLBoolean (*epoxy_eglGetConfigAttrib)(EGLDisplay dpy,
EGLint attribute,
EGLint* value);
EGLDisplay (*epoxy_eglGetDisplay)(EGLNativeDisplayType display_id);
EGLDisplay (*epoxy_eglGetPlatformDisplayEXT)(EGLenum platform,
void* native_display,
const EGLint* attrib_list);
EGLint (*epoxy_eglGetError)();
void (*(*epoxy_eglGetProcAddress)(const char* procname))(void);
EGLBoolean (*epoxy_eglInitialize)(EGLDisplay dpy, EGLint* major, EGLint* minor);
Expand Down Expand Up @@ -693,6 +702,7 @@ static void library_init() {
epoxy_eglGetConfigAttrib = _eglGetConfigAttrib;
epoxy_eglGetDisplay = _eglGetDisplay;
epoxy_eglGetCurrentDisplay = _eglGetCurrentDisplay;
epoxy_eglGetPlatformDisplayEXT = _eglGetPlatformDisplayEXT;
epoxy_eglGetError = _eglGetError;
epoxy_eglGetProcAddress = _eglGetProcAddress;
epoxy_eglInitialize = _eglInitialize;
Expand Down
9 changes: 3 additions & 6 deletions engine/src/flutter/shell/platform/linux/testing/mock_gtk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

#include <dlfcn.h>
#include <gdk/gdkwayland.h>

#include "flutter/shell/platform/linux/testing/mock_gtk.h"

Expand Down Expand Up @@ -47,7 +48,7 @@ guint gdk_keymap_lookup_key(GdkKeymap* keymap, const GdkKeymapKey* key) {
}

GdkDisplay* gdk_display_get_default() {
return GDK_DISPLAY(g_object_new(gdk_display_get_type(), nullptr));
return GDK_DISPLAY(g_object_new(gdk_wayland_display_get_type(), nullptr));
}

void gdk_display_beep(GdkDisplay* display) {}
Expand All @@ -57,7 +58,7 @@ GdkWindowState gdk_window_get_state(GdkWindow* window) {
}

GdkDisplay* gdk_window_get_display(GdkWindow* window) {
return GDK_DISPLAY(g_object_new(gdk_display_get_type(), nullptr));
return GDK_DISPLAY(g_object_new(gdk_wayland_display_get_type(), nullptr));
}

int gdk_display_get_n_monitors(GdkDisplay* display) {
Expand All @@ -79,10 +80,6 @@ GdkCursor* gdk_cursor_new_from_name(GdkDisplay* display, const gchar* name) {

void gdk_window_set_cursor(GdkWindow* window, GdkCursor* cursor) {}

void gdk_gl_context_make_current(GdkGLContext* context) {}

void gdk_gl_context_clear_current() {}

GtkWidget* gtk_window_new(GtkWindowType type) {
GtkWindow* window = GTK_WINDOW(g_object_new(gtk_window_get_type(), nullptr));
mock->gtk_window_new(window, type);
Expand Down