From 441767147c92847af3c634961f4a1ba4a026ccfb Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 1 Jul 2020 09:42:10 +1200 Subject: [PATCH 1/3] Use the X visual from the EGL configuration when making an FlView. --- shell/platform/linux/fl_renderer.cc | 65 +++++++++++++------ shell/platform/linux/fl_renderer.h | 40 ++++++++++-- shell/platform/linux/fl_renderer_x11.cc | 27 ++++++-- shell/platform/linux/fl_renderer_x11.h | 6 +- shell/platform/linux/fl_view.cc | 12 ++-- shell/platform/linux/testing/mock_egl.cc | 7 ++ shell/platform/linux/testing/mock_renderer.cc | 9 +-- 7 files changed, 122 insertions(+), 44 deletions(-) diff --git a/shell/platform/linux/fl_renderer.cc b/shell/platform/linux/fl_renderer.cc index 6f8d4b61fe99a..17c59d4bdd80a 100644 --- a/shell/platform/linux/fl_renderer.cc +++ b/shell/platform/linux/fl_renderer.cc @@ -10,6 +10,7 @@ G_DEFINE_QUARK(fl_renderer_error_quark, fl_renderer_error) typedef struct { EGLDisplay egl_display; + EGLConfig egl_config; EGLSurface egl_surface; EGLContext egl_context; @@ -79,9 +80,11 @@ static void create_resource_surface(FlRenderer* self, EGLConfig config) { 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) { +static void fl_renderer_class_init(FlRendererClass* klass) {} + +static void fl_renderer_init(FlRenderer* self) {} + +gboolean fl_renderer_setup(FlRenderer* self, GError** error) { FlRendererPrivate* priv = static_cast(fl_renderer_get_instance_private(self)); @@ -109,34 +112,68 @@ static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) { EGL_ALPHA_SIZE, 8, EGL_NONE}; - EGLConfig egl_config; EGLint n_config; - if (!eglChooseConfig(priv->egl_display, attributes, &egl_config, 1, + if (!eglChooseConfig(priv->egl_display, attributes, &priv->egl_config, 1, &n_config)) { g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, "Failed to choose EGL config: %s", get_egl_error()); return FALSE; } + if (n_config == 0) { g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, - "Failed to find appropriate EGL config: %s", get_egl_error()); + "Failed to find appropriate EGL config"); return FALSE; } + if (!eglBindAPI(EGL_OPENGL_ES_API)) { g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, "Failed to bind EGL OpenGL ES API: %s", get_egl_error()); return FALSE; } + return TRUE; +} + +GdkVisual* fl_renderer_get_visual(FlRenderer* self, + GdkScreen* screen, + GError** error) { + FlRendererPrivate* priv = + static_cast(fl_renderer_get_instance_private(self)); + + EGLint visual_id; + if (!eglGetConfigAttrib(priv->egl_display, priv->egl_config, + EGL_NATIVE_VISUAL_ID, &visual_id)) { + g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, + "Failed to determine EGL configuration visual"); + return nullptr; + } + + GdkVisual* visual = + FL_RENDERER_GET_CLASS(self)->get_visual(self, screen, visual_id); + if (visual == nullptr) { + g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, + "Failed to find visual 0x%x", visual_id); + return nullptr; + } + + return visual; +} + +gboolean fl_renderer_start(FlRenderer* self, GError** error) { + FlRendererPrivate* priv = + static_cast(fl_renderer_get_instance_private(self)); + priv->egl_surface = FL_RENDERER_GET_CLASS(self)->create_surface( - self, priv->egl_display, egl_config); + self, priv->egl_display, priv->egl_config); if (priv->egl_surface == nullptr) { g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, "Failed to create EGL surface: %s", get_egl_error()); return FALSE; } + EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - priv->egl_context = eglCreateContext(priv->egl_display, egl_config, + priv->egl_context = eglCreateContext(priv->egl_display, priv->egl_config, EGL_NO_CONTEXT, context_attributes); if (priv->egl_context == nullptr) { g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, @@ -144,7 +181,7 @@ static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) { return FALSE; } - create_resource_surface(self, egl_config); + create_resource_surface(self, priv->egl_config); EGLint value; eglQueryContext(priv->egl_display, priv->egl_context, @@ -153,16 +190,6 @@ static gboolean fl_renderer_real_start(FlRenderer* self, GError** error) { return TRUE; } -static void fl_renderer_class_init(FlRendererClass* klass) { - klass->start = fl_renderer_real_start; -} - -static void fl_renderer_init(FlRenderer* self) {} - -gboolean fl_renderer_start(FlRenderer* self, GError** error) { - return FL_RENDERER_GET_CLASS(self)->start(self, error); -} - void* fl_renderer_get_proc_address(FlRenderer* self, const char* name) { return reinterpret_cast(eglGetProcAddress(name)); } diff --git a/shell/platform/linux/fl_renderer.h b/shell/platform/linux/fl_renderer.h index edfafeadc6a24..94a6ef432ae78 100644 --- a/shell/platform/linux/fl_renderer.h +++ b/shell/platform/linux/fl_renderer.h @@ -7,7 +7,7 @@ #include -#include +#include #include "flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h" @@ -35,23 +35,51 @@ G_DECLARE_DERIVABLE_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject) struct _FlRendererClass { GObjectClass parent_class; - // Virtual method called when Flutter has set up EGL and is ready for the - // renderer to start. - gboolean (*start)(FlRenderer* renderer, GError** error); + // Virtual method called to get the visual that matches the given ID. + GdkVisual* (*get_visual)(FlRenderer* renderer, + GdkScreen* screen, + EGLint visual_id); - // Virtual method called when flutter needs a surface to render to. + // Virtual method called when Flutter needs a surface to render to. EGLSurface (*create_surface)(FlRenderer* renderer, EGLDisplay display, EGLConfig config); }; +/** + * fl_renderer_setup: + * @renderer: an #FlRenderer. + * @error: (allow-none): #GError location to store the error occurring, or %NULL + * to ignore. + * + * Setup the renderer. + * + * Returns: %TRUE if successfully setup. + */ +gboolean fl_renderer_setup(FlRenderer* self, GError** error); + +/** + * fl_renderer_get_visual: + * @renderer: an #FlRenderer. + * @screen: the screen being rendered on. + * @error: (allow-none): #GError location to store the error occurring, or %NULL + * to ignore. + * + * Gets the visual required to render on. + * + * Returns: a #GdkVisual. + */ +GdkVisual* fl_renderer_get_visual(FlRenderer* self, + GdkScreen* screen, + GError** error); + /** * fl_renderer_start: * @renderer: an #FlRenderer. * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * - * Start the renderer. EGL must be set up before this call. + * Start the renderer. * * Returns: %TRUE if successfully started. */ diff --git a/shell/platform/linux/fl_renderer_x11.cc b/shell/platform/linux/fl_renderer_x11.cc index 9f9108cefce4f..f4e8dfdfc3ca2 100644 --- a/shell/platform/linux/fl_renderer_x11.cc +++ b/shell/platform/linux/fl_renderer_x11.cc @@ -7,19 +7,38 @@ struct _FlRendererX11 { FlRenderer parent_instance; - Window xid; + 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); +} + +// Implments 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); +} + +// Implments FlRenderer::create_surface. static EGLSurface fl_renderer_x11_create_surface(FlRenderer* renderer, EGLDisplay display, EGLConfig config) { FlRendererX11* self = FL_RENDERER_X11(renderer); - return eglCreateWindowSurface(display, config, self->xid, nullptr); + return eglCreateWindowSurface(display, config, + gdk_x11_window_get_xid(self->window), nullptr); } 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)->create_surface = fl_renderer_x11_create_surface; } @@ -29,7 +48,7 @@ FlRendererX11* fl_renderer_x11_new() { return FL_RENDERER_X11(g_object_new(fl_renderer_x11_get_type(), nullptr)); } -void fl_renderer_x11_set_xid(FlRendererX11* self, Window xid) { +void fl_renderer_x11_set_window(FlRendererX11* self, GdkX11Window* window) { g_return_if_fail(FL_IS_RENDERER_X11(self)); - self->xid = xid; + self->window = GDK_X11_WINDOW(g_object_ref(window)); } diff --git a/shell/platform/linux/fl_renderer_x11.h b/shell/platform/linux/fl_renderer_x11.h index 14b19e57f043c..92d808591da70 100644 --- a/shell/platform/linux/fl_renderer_x11.h +++ b/shell/platform/linux/fl_renderer_x11.h @@ -34,13 +34,13 @@ G_DECLARE_FINAL_TYPE(FlRendererX11, FlRendererX11* fl_renderer_x11_new(); /** - * fl_renderer_x11_set_xid: + * fl_renderer_x11_set_window: * @renderer: an #FlRendererX11. - * @xid: The X window being rendered to. + * @window: the X window being rendered to. * * Sets the X11 window that is being rendered to. */ -void fl_renderer_x11_set_xid(FlRendererX11* renderer, Window xid); +void fl_renderer_x11_set_window(FlRendererX11* renderer, GdkX11Window* window); G_END_DECLS diff --git a/shell/platform/linux/fl_view.cc b/shell/platform/linux/fl_view.cc index c46919da3bff7..6b6fac67d46a8 100644 --- a/shell/platform/linux/fl_view.cc +++ b/shell/platform/linux/fl_view.cc @@ -202,6 +202,10 @@ static void fl_view_realize(GtkWidget* widget) { gtk_widget_set_realized(widget, TRUE); + g_autoptr(GError) error = nullptr; + if (!fl_renderer_setup(FL_RENDERER(self->renderer), &error)) + g_warning("Failed to setup renderer: %s", error->message); + GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); @@ -212,7 +216,8 @@ static void fl_view_realize(GtkWidget* widget) { window_attributes.width = allocation.width; window_attributes.height = allocation.height; window_attributes.wclass = GDK_INPUT_OUTPUT; - window_attributes.visual = gtk_widget_get_visual(widget); + window_attributes.visual = fl_renderer_get_visual( + FL_RENDERER(self->renderer), gtk_widget_get_screen(widget), nullptr); window_attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | @@ -227,10 +232,9 @@ static void fl_view_realize(GtkWidget* widget) { gtk_widget_register_window(widget, window); gtk_widget_set_window(widget, window); - Window xid = gdk_x11_window_get_xid(gtk_widget_get_window(GTK_WIDGET(self))); - fl_renderer_x11_set_xid(self->renderer, xid); + fl_renderer_x11_set_window( + self->renderer, GDK_X11_WINDOW(gtk_widget_get_window(GTK_WIDGET(self)))); - g_autoptr(GError) error = nullptr; if (!fl_engine_start(self->engine, &error)) g_warning("Failed to start Flutter engine: %s", error->message); } diff --git a/shell/platform/linux/testing/mock_egl.cc b/shell/platform/linux/testing/mock_egl.cc index ab28fc9068492..b5b4079e7517d 100644 --- a/shell/platform/linux/testing/mock_egl.cc +++ b/shell/platform/linux/testing/mock_egl.cc @@ -36,6 +36,13 @@ EGLSurface eglCreateWindowSurface(EGLDisplay dpy, return nullptr; } +EGLBoolean eglGetConfigAttrib(EGLDisplay display, + EGLConfig config, + EGLint attribute, + EGLint* value) { + return EGL_FALSE; +} + EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) { return nullptr; } diff --git a/shell/platform/linux/testing/mock_renderer.cc b/shell/platform/linux/testing/mock_renderer.cc index 03ab5482d9e72..0ca16079325ea 100644 --- a/shell/platform/linux/testing/mock_renderer.cc +++ b/shell/platform/linux/testing/mock_renderer.cc @@ -10,14 +10,7 @@ struct _FlMockRenderer { G_DEFINE_TYPE(FlMockRenderer, fl_mock_renderer, fl_renderer_get_type()) -// Implements FlRenderer::start -static gboolean fl_mock_renderer_start(FlRenderer* renderer, GError** error) { - return TRUE; -} - -static void fl_mock_renderer_class_init(FlMockRendererClass* klass) { - FL_RENDERER_CLASS(klass)->start = fl_mock_renderer_start; -} +static void fl_mock_renderer_class_init(FlMockRendererClass* klass) {} static void fl_mock_renderer_init(FlMockRenderer* self) {} From d80f993a9c37a64ffd8e375e55504ff7bdb3b0b6 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 2 Jul 2020 10:07:18 +1200 Subject: [PATCH 2/3] Grammar --- shell/platform/linux/fl_renderer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/linux/fl_renderer.h b/shell/platform/linux/fl_renderer.h index 94a6ef432ae78..25042f9666986 100644 --- a/shell/platform/linux/fl_renderer.h +++ b/shell/platform/linux/fl_renderer.h @@ -52,7 +52,7 @@ struct _FlRendererClass { * @error: (allow-none): #GError location to store the error occurring, or %NULL * to ignore. * - * Setup the renderer. + * Set up the renderer. * * Returns: %TRUE if successfully setup. */ From 73a52a0f245b626f30c99b243f3eedc7db7eaa03 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 2 Jul 2020 12:07:27 +1200 Subject: [PATCH 3/3] Fix tests --- shell/platform/linux/egl_utils_test.cc | 8 +- .../linux/fl_basic_message_channel_test.cc | 9 +- .../linux/fl_binary_messenger_test.cc | 9 +- .../platform/linux/fl_method_channel_test.cc | 9 +- shell/platform/linux/fl_renderer.cc | 15 +-- shell/platform/linux/testing/mock_egl.cc | 117 +++++++++--------- shell/platform/linux/testing/mock_renderer.cc | 19 ++- 7 files changed, 106 insertions(+), 80 deletions(-) diff --git a/shell/platform/linux/egl_utils_test.cc b/shell/platform/linux/egl_utils_test.cc index ba6ae8e7b1286..3be967d98b296 100644 --- a/shell/platform/linux/egl_utils_test.cc +++ b/shell/platform/linux/egl_utils_test.cc @@ -23,9 +23,9 @@ TEST(EGLUtils, ErrorToStringNegative) { TEST(EGLUtils, ConfigToString) { EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(display, nullptr, nullptr); + EXPECT_TRUE(eglInitialize(display, nullptr, nullptr)); EGLConfig config; - eglChooseConfig(display, nullptr, &config, 1, nullptr); + EXPECT_TRUE(eglChooseConfig(display, nullptr, &config, 1, nullptr)); g_autofree gchar* config_string = egl_config_to_string(display, config); EXPECT_STREQ( config_string, @@ -46,9 +46,9 @@ TEST(EGLUtils, ConfigToString) { TEST(EGLUtils, ConfigToStringNullptr) { EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(display, nullptr, nullptr); + EXPECT_TRUE(eglInitialize(display, nullptr, nullptr)); EGLConfig config; - eglChooseConfig(display, nullptr, &config, 1, nullptr); + EXPECT_TRUE(eglChooseConfig(display, nullptr, &config, 1, nullptr)); g_autofree gchar* config_string1 = egl_config_to_string(nullptr, config); EXPECT_STREQ(config_string1, ""); g_autofree gchar* config_string2 = egl_config_to_string(display, nullptr); diff --git a/shell/platform/linux/fl_basic_message_channel_test.cc b/shell/platform/linux/fl_basic_message_channel_test.cc index aa922303f164b..cbd45d80a05a0 100644 --- a/shell/platform/linux/fl_basic_message_channel_test.cc +++ b/shell/platform/linux/fl_basic_message_channel_test.cc @@ -15,10 +15,13 @@ static FlEngine* make_mock_engine() { g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(GError) renderer_error = nullptr; + EXPECT_TRUE(fl_renderer_setup(FL_RENDERER(renderer), &renderer_error)); + EXPECT_EQ(renderer_error, nullptr); g_autoptr(FlEngine) engine = fl_engine_new(project, FL_RENDERER(renderer)); - g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_engine_start(engine, &error)); - EXPECT_EQ(error, nullptr); + g_autoptr(GError) engine_error = nullptr; + EXPECT_TRUE(fl_engine_start(engine, &engine_error)); + EXPECT_EQ(engine_error, nullptr); return static_cast(g_object_ref(engine)); } diff --git a/shell/platform/linux/fl_binary_messenger_test.cc b/shell/platform/linux/fl_binary_messenger_test.cc index dcc48394ba98a..475111e305b25 100644 --- a/shell/platform/linux/fl_binary_messenger_test.cc +++ b/shell/platform/linux/fl_binary_messenger_test.cc @@ -14,10 +14,13 @@ static FlEngine* make_mock_engine() { g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(GError) renderer_error = nullptr; + EXPECT_TRUE(fl_renderer_setup(FL_RENDERER(renderer), &renderer_error)); + EXPECT_EQ(renderer_error, nullptr); g_autoptr(FlEngine) engine = fl_engine_new(project, FL_RENDERER(renderer)); - g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_engine_start(engine, &error)); - EXPECT_EQ(error, nullptr); + g_autoptr(GError) engine_error = nullptr; + EXPECT_TRUE(fl_engine_start(engine, &engine_error)); + EXPECT_EQ(engine_error, nullptr); return static_cast(g_object_ref(engine)); } diff --git a/shell/platform/linux/fl_method_channel_test.cc b/shell/platform/linux/fl_method_channel_test.cc index efbc03732e7b6..b23eeff697648 100644 --- a/shell/platform/linux/fl_method_channel_test.cc +++ b/shell/platform/linux/fl_method_channel_test.cc @@ -17,10 +17,13 @@ static FlEngine* make_mock_engine() { g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(GError) renderer_error = nullptr; + EXPECT_TRUE(fl_renderer_setup(FL_RENDERER(renderer), &renderer_error)); + EXPECT_EQ(renderer_error, nullptr); g_autoptr(FlEngine) engine = fl_engine_new(project, FL_RENDERER(renderer)); - g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_engine_start(engine, &error)); - EXPECT_EQ(error, nullptr); + g_autoptr(GError) engine_error = nullptr; + EXPECT_TRUE(fl_engine_start(engine, &engine_error)); + EXPECT_EQ(engine_error, nullptr); return static_cast(g_object_ref(engine)); } diff --git a/shell/platform/linux/fl_renderer.cc b/shell/platform/linux/fl_renderer.cc index a2b2542e22ce8..595f2d733f260 100644 --- a/shell/platform/linux/fl_renderer.cc +++ b/shell/platform/linux/fl_renderer.cc @@ -31,7 +31,7 @@ static void create_resource_surface(FlRenderer* self, EGLConfig config) { EGL_NONE}; priv->resource_surface = eglCreatePbufferSurface(priv->egl_display, config, resource_context_attribs); - if (priv->resource_surface == nullptr) { + if (priv->resource_surface == EGL_NO_SURFACE) { g_warning("Failed to create EGL resource surface: %s", egl_error_to_string(eglGetError())); return; @@ -39,7 +39,7 @@ static void create_resource_surface(FlRenderer* self, EGLConfig config) { priv->resource_context = eglCreateContext( priv->egl_display, config, priv->egl_context, context_attributes); - if (priv->resource_context == nullptr) + if (priv->resource_context == EGL_NO_CONTEXT) g_warning("Failed to create EGL resource context: %s", egl_error_to_string(eglGetError())); } @@ -135,7 +135,7 @@ gboolean fl_renderer_start(FlRenderer* self, GError** error) { priv->egl_surface = FL_RENDERER_GET_CLASS(self)->create_surface( self, priv->egl_display, priv->egl_config); - if (priv->egl_surface == nullptr) { + if (priv->egl_surface == EGL_NO_SURFACE) { g_autofree gchar* config_string = egl_config_to_string(priv->egl_display, priv->egl_config); g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, @@ -147,7 +147,7 @@ gboolean fl_renderer_start(FlRenderer* self, GError** error) { EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; priv->egl_context = eglCreateContext(priv->egl_display, priv->egl_config, EGL_NO_CONTEXT, context_attributes); - if (priv->egl_context == nullptr) { + if (priv->egl_context == EGL_NO_CONTEXT) { g_autofree gchar* config_string = egl_config_to_string(priv->egl_display, priv->egl_config); g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED, @@ -158,10 +158,6 @@ gboolean fl_renderer_start(FlRenderer* self, GError** error) { create_resource_surface(self, priv->egl_config); - EGLint value; - eglQueryContext(priv->egl_display, priv->egl_context, - EGL_CONTEXT_CLIENT_VERSION, &value); - return TRUE; } @@ -188,7 +184,8 @@ gboolean fl_renderer_make_resource_current(FlRenderer* self, GError** error) { FlRendererPrivate* priv = static_cast(fl_renderer_get_instance_private(self)); - if (priv->resource_surface == nullptr || priv->resource_context == nullptr) + if (priv->resource_surface == EGL_NO_SURFACE || + priv->resource_context == EGL_NO_CONTEXT) return FALSE; if (!eglMakeCurrent(priv->egl_display, priv->resource_surface, diff --git a/shell/platform/linux/testing/mock_egl.cc b/shell/platform/linux/testing/mock_egl.cc index 555a3af61f5e7..8790aff19ef8c 100644 --- a/shell/platform/linux/testing/mock_egl.cc +++ b/shell/platform/linux/testing/mock_egl.cc @@ -35,11 +35,19 @@ typedef struct { } MockConfig; typedef struct { - bool initialized; - MockConfig config; } MockDisplay; +typedef struct { +} MockContext; + +typedef struct { +} MockSurface; + +static bool display_initialized = false; static MockDisplay mock_display; +static MockConfig mock_config; +static MockContext mock_context; +static MockSurface mock_surface; static EGLint mock_error = EGL_SUCCESS; @@ -49,8 +57,11 @@ static bool check_display(EGLDisplay dpy) { return false; } - MockDisplay* display = static_cast(dpy); - if (!display->initialized) { + return true; +} + +static bool check_initialized(EGLDisplay dpy) { + if (!display_initialized) { mock_error = EGL_NOT_INITIALIZED; return false; } @@ -86,7 +97,8 @@ EGLBoolean eglChooseConfig(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) { - MockDisplay* display = static_cast(dpy); + if (!check_display(dpy) || !check_initialized(dpy)) + return EGL_FALSE; if (configs == nullptr) { if (num_config != nullptr) @@ -96,7 +108,8 @@ EGLBoolean eglChooseConfig(EGLDisplay dpy, EGLint n_returned = 0; if (config_size >= 1) { - configs[0] = &display->config; + configs[0] = &mock_config; + n_returned++; } if (num_config != nullptr) @@ -109,39 +122,39 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list) { - if (!check_display(dpy) || !check_config(config)) + if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) return EGL_NO_CONTEXT; mock_error = EGL_SUCCESS; - return EGL_NO_CONTEXT; + return &mock_context; } EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) { - if (!check_display(dpy) || !check_config(config)) + if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) return EGL_NO_SURFACE; mock_error = EGL_SUCCESS; - return EGL_NO_SURFACE; + return &mock_surface; } EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list) { - if (!check_display(dpy) || !check_config(config)) + if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) return EGL_NO_SURFACE; mock_error = EGL_SUCCESS; - return EGL_NO_SURFACE; + return &mock_surface; } EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) { - if (!check_display(dpy) || !check_config(config)) + if (!check_display(dpy) || !check_initialized(dpy) || !check_config(config)) return EGL_FALSE; MockConfig* c = static_cast(config); @@ -248,38 +261,38 @@ void (*eglGetProcAddress(const char* procname))(void) { } EGLBoolean eglInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) { - MockDisplay* display = static_cast(dpy); - - if (!display->initialized) { - MockConfig* c = &display->config; - c->config_id = 1; - c->buffer_size = 32; - c->color_buffer_type = EGL_RGB_BUFFER; - c->transparent_type = EGL_NONE; - c->level = 1; - c->red_size = 8; - c->green_size = 8; - c->blue_size = 8; - c->alpha_size = 0; - c->depth_size = 0; - c->stencil_size = 0; - c->samples = 0; - c->sample_buffers = 0; - c->native_visual_id = 1; - c->native_visual_type = 0; - c->native_renderable = EGL_TRUE; - c->config_caveat = EGL_NONE; - c->bind_to_texture_rgb = EGL_TRUE; - c->bind_to_texture_rgba = EGL_FALSE; - c->renderable_type = EGL_OPENGL_ES2_BIT; - c->conformant = EGL_OPENGL_ES2_BIT; - c->surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; - c->max_pbuffer_width = 1024; - c->max_pbuffer_height = 1024; - c->max_pbuffer_pixels = 1024 * 1024; - c->min_swap_interval = 0; - c->max_swap_interval = 1000; - display->initialized = true; + if (!check_display(dpy)) + return EGL_FALSE; + + if (!display_initialized) { + mock_config.config_id = 1; + mock_config.buffer_size = 32; + mock_config.color_buffer_type = EGL_RGB_BUFFER; + mock_config.transparent_type = EGL_NONE; + mock_config.level = 1; + mock_config.red_size = 8; + mock_config.green_size = 8; + mock_config.blue_size = 8; + mock_config.alpha_size = 0; + mock_config.depth_size = 0; + mock_config.stencil_size = 0; + mock_config.samples = 0; + mock_config.sample_buffers = 0; + mock_config.native_visual_id = 1; + mock_config.native_visual_type = 0; + mock_config.native_renderable = EGL_TRUE; + mock_config.config_caveat = EGL_NONE; + mock_config.bind_to_texture_rgb = EGL_TRUE; + mock_config.bind_to_texture_rgba = EGL_FALSE; + mock_config.renderable_type = EGL_OPENGL_ES2_BIT; + mock_config.conformant = EGL_OPENGL_ES2_BIT; + mock_config.surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; + mock_config.max_pbuffer_width = 1024; + mock_config.max_pbuffer_height = 1024; + mock_config.max_pbuffer_pixels = 1024 * 1024; + mock_config.min_swap_interval = 0; + mock_config.max_swap_interval = 1000; + display_initialized = true; } if (major != nullptr) @@ -294,24 +307,14 @@ EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { - if (!check_display(dpy)) - return EGL_FALSE; - - return bool_success(); -} - -EGLBoolean eglQueryContext(EGLDisplay dpy, - EGLContext ctx, - EGLint attribute, - EGLint* value) { - if (!check_display(dpy)) + if (!check_display(dpy) || !check_initialized(dpy)) return EGL_FALSE; return bool_success(); } EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { - if (!check_display(dpy)) + if (!check_display(dpy) || !check_initialized(dpy)) return EGL_FALSE; return bool_success(); diff --git a/shell/platform/linux/testing/mock_renderer.cc b/shell/platform/linux/testing/mock_renderer.cc index 0ca16079325ea..0112c38faa9bc 100644 --- a/shell/platform/linux/testing/mock_renderer.cc +++ b/shell/platform/linux/testing/mock_renderer.cc @@ -10,7 +10,24 @@ struct _FlMockRenderer { G_DEFINE_TYPE(FlMockRenderer, fl_mock_renderer, fl_renderer_get_type()) -static void fl_mock_renderer_class_init(FlMockRendererClass* klass) {} +// Implements FlRenderer::get_visual. +static GdkVisual* fl_mock_renderer_get_visual(FlRenderer* renderer, + GdkScreen* screen, + EGLint visual_id) { + return static_cast(g_object_new(GDK_TYPE_VISUAL, nullptr)); +} + +// Implements FlRenderer::create_surface. +static EGLSurface fl_mock_renderer_create_surface(FlRenderer* renderer, + EGLDisplay display, + EGLConfig config) { + return eglCreateWindowSurface(display, config, 0, nullptr); +} + +static void fl_mock_renderer_class_init(FlMockRendererClass* klass) { + FL_RENDERER_CLASS(klass)->get_visual = fl_mock_renderer_get_visual; + FL_RENDERER_CLASS(klass)->create_surface = fl_mock_renderer_create_surface; +} static void fl_mock_renderer_init(FlMockRenderer* self) {}