From bfe95d3819c60daaf4079842bc63f9a11c246713 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Fri, 28 Mar 2025 13:37:05 +1300 Subject: [PATCH] Move OpenGL context management to FlOpenGLManager (#166025) This helps to make a non-OpenGL FlRenderer --- .../ci/licenses_golden/licenses_flutter | 12 +- .../src/flutter/shell/platform/linux/BUILD.gn | 5 +- .../flutter/shell/platform/linux/fl_engine.cc | 50 ++-- .../shell/platform/linux/fl_engine_private.h | 23 +- .../shell/platform/linux/fl_engine_test.cc | 2 +- .../shell/platform/linux/fl_opengl_manager.cc | 92 ++++++++ .../shell/platform/linux/fl_opengl_manager.h | 76 +++++++ .../shell/platform/linux/fl_renderer.cc | 214 +++++++----------- .../shell/platform/linux/fl_renderer.h | 80 +------ .../shell/platform/linux/fl_renderer_gdk.cc | 109 --------- .../shell/platform/linux/fl_renderer_gdk.h | 66 ------ .../platform/linux/fl_renderer_headless.cc | 34 --- .../platform/linux/fl_renderer_headless.h | 36 --- .../shell/platform/linux/fl_renderer_test.cc | 23 +- .../flutter/shell/platform/linux/fl_view.cc | 36 ++- .../shell/platform/linux/testing/fl_test.cc | 2 +- .../shell/platform/linux/testing/mock_gtk.cc | 4 + .../{mock_renderer.cc => mock_renderable.cc} | 33 +-- .../{mock_renderer.h => mock_renderable.h} | 17 +- 19 files changed, 322 insertions(+), 592 deletions(-) create mode 100644 engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc create mode 100644 engine/src/flutter/shell/platform/linux/fl_opengl_manager.h delete mode 100644 engine/src/flutter/shell/platform/linux/fl_renderer_gdk.cc delete mode 100644 engine/src/flutter/shell/platform/linux/fl_renderer_gdk.h delete mode 100644 engine/src/flutter/shell/platform/linux/fl_renderer_headless.cc delete mode 100644 engine/src/flutter/shell/platform/linux/fl_renderer_headless.h rename engine/src/flutter/shell/platform/linux/testing/{mock_renderer.cc => mock_renderable.cc} (56%) rename engine/src/flutter/shell/platform/linux/testing/{mock_renderer.h => mock_renderable.h} (50%) diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index 78919cf0fb..7925630d9a 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -53264,6 +53264,8 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.cc + ../.. ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/linux/fl_opengl_manager.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/linux/fl_opengl_manager.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc + ../../../flutter/LICENSE @@ -53284,10 +53286,6 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_renderable.cc + ../../../flutte ORIGIN: ../../../flutter/shell/platform/linux/fl_renderable.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_headless.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_renderer_test.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h + ../../../flutter/LICENSE @@ -56281,6 +56279,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_channel.h FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.cc FILE: ../../../flutter/shell/platform/linux/fl_mouse_cursor_handler.h +FILE: ../../../flutter/shell/platform/linux/fl_opengl_manager.cc +FILE: ../../../flutter/shell/platform/linux/fl_opengl_manager.h FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture.cc FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc @@ -56301,10 +56301,6 @@ FILE: ../../../flutter/shell/platform/linux/fl_renderable.cc FILE: ../../../flutter/shell/platform/linux/fl_renderable.h FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc FILE: ../../../flutter/shell/platform/linux/fl_renderer.h -FILE: ../../../flutter/shell/platform/linux/fl_renderer_gdk.cc -FILE: ../../../flutter/shell/platform/linux/fl_renderer_gdk.h -FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.cc -FILE: ../../../flutter/shell/platform/linux/fl_renderer_headless.h FILE: ../../../flutter/shell/platform/linux/fl_renderer_test.cc FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.cc FILE: ../../../flutter/shell/platform/linux/fl_scrolling_manager.h diff --git a/engine/src/flutter/shell/platform/linux/BUILD.gn b/engine/src/flutter/shell/platform/linux/BUILD.gn index 31b4d8e0f8..dfae597ef8 100644 --- a/engine/src/flutter/shell/platform/linux/BUILD.gn +++ b/engine/src/flutter/shell/platform/linux/BUILD.gn @@ -128,6 +128,7 @@ source_set("flutter_linux_sources") { "fl_method_response.cc", "fl_mouse_cursor_channel.cc", "fl_mouse_cursor_handler.cc", + "fl_opengl_manager.cc", "fl_pixel_buffer_texture.cc", "fl_platform_channel.cc", "fl_platform_handler.cc", @@ -136,8 +137,6 @@ source_set("flutter_linux_sources") { "fl_pointer_manager.cc", "fl_renderable.cc", "fl_renderer.cc", - "fl_renderer_gdk.cc", - "fl_renderer_headless.cc", "fl_scrolling_manager.cc", "fl_settings.cc", "fl_settings_channel.cc", @@ -261,7 +260,7 @@ executable("flutter_linux_unittests") { "testing/mock_epoxy.cc", "testing/mock_gtk.cc", "testing/mock_plugin_registrar.cc", - "testing/mock_renderer.cc", + "testing/mock_renderable.cc", "testing/mock_settings.cc", "testing/mock_signal_handler.cc", "testing/mock_texture_registrar.cc", diff --git a/engine/src/flutter/shell/platform/linux/fl_engine.cc b/engine/src/flutter/shell/platform/linux/fl_engine.cc index 66e0fd29a8..a2bbb209f0 100644 --- a/engine/src/flutter/shell/platform/linux/fl_engine.cc +++ b/engine/src/flutter/shell/platform/linux/fl_engine.cc @@ -4,6 +4,7 @@ #include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h" +#include #include #include @@ -16,12 +17,11 @@ #include "flutter/shell/platform/linux/fl_display_monitor.h" #include "flutter/shell/platform/linux/fl_engine_private.h" #include "flutter/shell/platform/linux/fl_keyboard_handler.h" +#include "flutter/shell/platform/linux/fl_opengl_manager.h" #include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h" #include "flutter/shell/platform/linux/fl_platform_handler.h" #include "flutter/shell/platform/linux/fl_plugin_registrar_private.h" #include "flutter/shell/platform/linux/fl_renderer.h" -#include "flutter/shell/platform/linux/fl_renderer_gdk.h" -#include "flutter/shell/platform/linux/fl_renderer_headless.h" #include "flutter/shell/platform/linux/fl_settings_handler.h" #include "flutter/shell/platform/linux/fl_texture_gl_private.h" #include "flutter/shell/platform/linux/fl_texture_registrar_private.h" @@ -51,6 +51,9 @@ struct _FlEngine { // Renders the Flutter app. FlRenderer* renderer; + // Manages OpenGL contexts. + FlOpenGLManager* opengl_manager; + // Messenger used to send and receive platform messages. FlBinaryMessenger* binary_messenger; @@ -274,25 +277,24 @@ static bool compositor_present_view_callback( // Flutter engine rendering callbacks. static void* fl_engine_gl_proc_resolver(void* user_data, const char* name) { - FlEngine* self = static_cast(user_data); - return fl_renderer_get_proc_address(self->renderer, name); + return reinterpret_cast(eglGetProcAddress(name)); } static bool fl_engine_gl_make_current(void* user_data) { FlEngine* self = static_cast(user_data); - fl_renderer_make_current(self->renderer); + fl_opengl_manager_make_current(self->opengl_manager); return true; } static bool fl_engine_gl_clear_current(void* user_data) { FlEngine* self = static_cast(user_data); - fl_renderer_clear_current(self->renderer); + fl_opengl_manager_clear_current(self->opengl_manager); return true; } static uint32_t fl_engine_gl_get_fbo(void* user_data) { - FlEngine* self = static_cast(user_data); - return fl_renderer_get_fbo(self->renderer); + // There is only one frame buffer object - always return that. + return 0; } static bool fl_engine_gl_present(void* user_data) { @@ -303,7 +305,7 @@ static bool fl_engine_gl_present(void* user_data) { static bool fl_engine_gl_make_resource_current(void* user_data) { FlEngine* self = static_cast(user_data); - fl_renderer_make_resource_current(self->renderer); + fl_opengl_manager_make_resource_current(self->opengl_manager); return true; } @@ -483,6 +485,7 @@ static void fl_engine_dispose(GObject* object) { g_clear_object(&self->project); g_clear_object(&self->display_monitor); g_clear_object(&self->renderer); + g_clear_object(&self->opengl_manager); g_clear_object(&self->texture_registrar); g_clear_object(&self->binary_messenger); g_clear_object(&self->settings_handler); @@ -533,6 +536,8 @@ static void fl_engine_init(FlEngine* self) { g_warning("Failed get get engine function pointers"); } + self->opengl_manager = fl_opengl_manager_new(); + self->display_monitor = fl_display_monitor_new(self, gdk_display_get_default()); self->task_runner = fl_task_runner_new(self); @@ -550,15 +555,13 @@ static void fl_engine_init(FlEngine* self) { } static FlEngine* fl_engine_new_full(FlDartProject* project, - FlRenderer* renderer, FlBinaryMessenger* binary_messenger) { g_return_val_if_fail(FL_IS_DART_PROJECT(project), nullptr); - g_return_val_if_fail(FL_IS_RENDERER(renderer), nullptr); FlEngine* self = FL_ENGINE(g_object_new(fl_engine_get_type(), nullptr)); self->project = FL_DART_PROJECT(g_object_ref(project)); - self->renderer = FL_RENDERER(g_object_ref(renderer)); + self->renderer = fl_renderer_new(self); if (binary_messenger != nullptr) { self->binary_messenger = FL_BINARY_MESSENGER(g_object_ref(binary_messenger)); @@ -570,8 +573,6 @@ static FlEngine* fl_engine_new_full(FlDartProject* project, fl_mouse_cursor_handler_new(self->binary_messenger); self->windowing_handler = fl_windowing_handler_new(self); - fl_renderer_set_engine(self->renderer, self); - return self; } @@ -581,28 +582,18 @@ FlEngine* fl_engine_for_id(int64_t id) { return FL_ENGINE(engine); } -FlEngine* fl_engine_new_with_renderer(FlDartProject* project, - FlRenderer* renderer) { - g_return_val_if_fail(FL_IS_DART_PROJECT(project), nullptr); - g_return_val_if_fail(FL_IS_RENDERER(renderer), nullptr); - return fl_engine_new_full(project, renderer, nullptr); -} - G_MODULE_EXPORT FlEngine* fl_engine_new(FlDartProject* project) { - g_autoptr(FlRendererGdk) renderer = fl_renderer_gdk_new(); - return fl_engine_new_with_renderer(project, FL_RENDERER(renderer)); + return fl_engine_new_full(project, nullptr); } FlEngine* fl_engine_new_with_binary_messenger( FlBinaryMessenger* binary_messenger) { g_autoptr(FlDartProject) project = fl_dart_project_new(); - g_autoptr(FlRendererGdk) renderer = fl_renderer_gdk_new(); - return fl_engine_new_full(project, FL_RENDERER(renderer), binary_messenger); + return fl_engine_new_full(project, binary_messenger); } G_MODULE_EXPORT FlEngine* fl_engine_new_headless(FlDartProject* project) { - g_autoptr(FlRendererHeadless) renderer = fl_renderer_headless_new(); - return fl_engine_new_with_renderer(project, FL_RENDERER(renderer)); + return fl_engine_new(project); } FlRenderer* fl_engine_get_renderer(FlEngine* self) { @@ -610,6 +601,11 @@ FlRenderer* fl_engine_get_renderer(FlEngine* self) { return self->renderer; } +FlOpenGLManager* fl_engine_get_opengl_manager(FlEngine* self) { + g_return_val_if_fail(FL_IS_ENGINE(self), nullptr); + return self->opengl_manager; +} + FlDisplayMonitor* fl_engine_get_display_monitor(FlEngine* self) { g_return_val_if_fail(FL_IS_ENGINE(self), nullptr); return self->display_monitor; diff --git a/engine/src/flutter/shell/platform/linux/fl_engine_private.h b/engine/src/flutter/shell/platform/linux/fl_engine_private.h index bceabf0b0e..3be38cf8ff 100644 --- a/engine/src/flutter/shell/platform/linux/fl_engine_private.h +++ b/engine/src/flutter/shell/platform/linux/fl_engine_private.h @@ -11,6 +11,7 @@ #include "flutter/shell/platform/linux/fl_display_monitor.h" #include "flutter/shell/platform/linux/fl_keyboard_manager.h" #include "flutter/shell/platform/linux/fl_mouse_cursor_handler.h" +#include "flutter/shell/platform/linux/fl_opengl_manager.h" #include "flutter/shell/platform/linux/fl_renderable.h" #include "flutter/shell/platform/linux/fl_renderer.h" #include "flutter/shell/platform/linux/fl_task_runner.h" @@ -62,18 +63,6 @@ typedef gboolean (*FlEnginePlatformMessageHandler)( FlEngine* fl_engine_new_with_binary_messenger( FlBinaryMessenger* binary_messenger); -/** - * fl_engine_new_with_renderer: - * @project: an #FlDartProject. - * @renderer: an #FlRenderer. - * - * Creates new Flutter engine. - * - * Returns: a new #FlEngine. - */ -FlEngine* fl_engine_new_with_renderer(FlDartProject* project, - FlRenderer* renderer); - /** * fl_engine_get_renderer: * @engine: an #FlEngine. @@ -84,6 +73,16 @@ FlEngine* fl_engine_new_with_renderer(FlDartProject* project, */ FlRenderer* fl_engine_get_renderer(FlEngine* engine); +/** + * fl_engine_get_opengl_manager: + * @engine: an #FlEngine. + * + * Gets the OpenGL manager used by this engine. + * + * Returns: an #FlOpenGLManager. + */ +FlOpenGLManager* fl_engine_get_opengl_manager(FlEngine* engine); + /** * fl_engine_get_display_monitor: * @engine: an #FlEngine. diff --git a/engine/src/flutter/shell/platform/linux/fl_engine_test.cc b/engine/src/flutter/shell/platform/linux/fl_engine_test.cc index 25c67b3c3f..c2cff862be 100644 --- a/engine/src/flutter/shell/platform/linux/fl_engine_test.cc +++ b/engine/src/flutter/shell/platform/linux/fl_engine_test.cc @@ -10,7 +10,7 @@ #include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h" -#include "flutter/shell/platform/linux/testing/mock_renderer.h" +#include "flutter/shell/platform/linux/testing/mock_renderable.h" // MOCK_ENGINE_PROC is leaky by design // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape) diff --git a/engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc b/engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc new file mode 100644 index 0000000000..177d1629ed --- /dev/null +++ b/engine/src/flutter/shell/platform/linux/fl_opengl_manager.cc @@ -0,0 +1,92 @@ +// 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 "flutter/shell/platform/linux/fl_opengl_manager.h" + +struct _FlOpenGLManager { + GObject parent_instance; + + // OpenGL rendering context used by GDK. + GdkGLContext* gdk_context; + + // Main OpenGL rendering context used by Flutter. + GdkGLContext* main_context; + + // OpenGL rendering context used by a Flutter background thread for + // asynchronous texture uploads. + GdkGLContext* 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); + + G_OBJECT_CLASS(fl_opengl_manager_parent_class)->dispose(object); +} + +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) {} + +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); +} + +void fl_opengl_manager_make_resource_current(FlOpenGLManager* self) { + gdk_gl_context_make_current(self->resource_context); +} + +void fl_opengl_manager_clear_current(FlOpenGLManager* self) { + gdk_gl_context_clear_current(); +} diff --git a/engine/src/flutter/shell/platform/linux/fl_opengl_manager.h b/engine/src/flutter/shell/platform/linux/fl_opengl_manager.h new file mode 100644 index 0000000000..6f01c64eb3 --- /dev/null +++ b/engine/src/flutter/shell/platform/linux/fl_opengl_manager.h @@ -0,0 +1,76 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_OPENGL_MANAGER_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_OPENGL_MANAGER_H_ + +#include + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE(FlOpenGLManager, + fl_opengl_manager, + FL, + OPENGL_MANAGER, + GObject) + +/** + * fl_opengl_manager_new: + * + * Creates an object that allows Flutter to render by OpenGL ES. + * + * Returns: a new #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. + * + * Makes the rendering context current. + */ +void fl_opengl_manager_make_current(FlOpenGLManager* manager); + +/** + * fl_opengl_manager_make_resource_current: + * @manager: an #FlOpenGLManager. + * + * Makes the resource rendering context current. + */ +void fl_opengl_manager_make_resource_current(FlOpenGLManager* manager); + +/** + * fl_opengl_manager_clear_current: + * @manager: an #FlOpenGLManager. + * + * Clears the current rendering context. + */ +void fl_opengl_manager_clear_current(FlOpenGLManager* manager); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_OPENGL_MANAGER_H_ diff --git a/engine/src/flutter/shell/platform/linux/fl_renderer.cc b/engine/src/flutter/shell/platform/linux/fl_renderer.cc index b86dc066bf..a1362e974f 100644 --- a/engine/src/flutter/shell/platform/linux/fl_renderer.cc +++ b/engine/src/flutter/shell/platform/linux/fl_renderer.cc @@ -38,10 +38,15 @@ static const char* fragment_shader_src = G_DEFINE_QUARK(fl_renderer_error_quark, fl_renderer_error) -typedef struct { +struct _FlRenderer { + GObject parent_instance; + // Engine we are rendering. GWeakRef engine; + // OpenGL contexts. + FlOpenGLManager* opengl_manager; + // Flag to track lazy initialization. gboolean initialized; @@ -78,9 +83,9 @@ typedef struct { // Condition to unblock the raster thread after task is completed on platform // thread. GCond present_condition; -} FlRendererPrivate; +}; -G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT) +G_DEFINE_TYPE(FlRenderer, fl_renderer, G_TYPE_OBJECT) // Check if running on an NVIDIA driver. static gboolean is_nvidia() { @@ -127,30 +132,25 @@ static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels) { // Perform single run OpenGL initialization. static void initialize(FlRenderer* self) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - - if (priv->initialized) { + if (self->initialized) { return; } - priv->initialized = TRUE; + self->initialized = TRUE; if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) { - priv->sized_format = GL_BGRA8_EXT; - priv->general_format = GL_BGRA_EXT; + self->sized_format = GL_BGRA8_EXT; + self->general_format = GL_BGRA_EXT; } else { - priv->sized_format = GL_RGBA8; - priv->general_format = GL_RGBA; + self->sized_format = GL_RGBA8; + self->general_format = GL_RGBA; } } static void fl_renderer_unblock_main_thread(FlRenderer* self) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - if (priv->blocking_main_thread) { - priv->blocking_main_thread = false; + if (self->blocking_main_thread) { + self->blocking_main_thread = false; - g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine)); + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); if (engine != nullptr) { fl_task_runner_release_main_thread(fl_engine_get_task_runner(engine)); } @@ -158,9 +158,6 @@ static void fl_renderer_unblock_main_thread(FlRenderer* self) { } static void setup_shader(FlRenderer* self) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex_shader, 1, &vertex_shader_src, nullptr); glCompileShader(vertex_shader); @@ -181,15 +178,15 @@ static void setup_shader(FlRenderer* self) { g_warning("Failed to compile fragment shader: %s", shader_log); } - priv->program = glCreateProgram(); - glAttachShader(priv->program, vertex_shader); - glAttachShader(priv->program, fragment_shader); - glLinkProgram(priv->program); + self->program = glCreateProgram(); + glAttachShader(self->program, vertex_shader); + glAttachShader(self->program, fragment_shader); + glLinkProgram(self->program); GLint link_status; - glGetProgramiv(priv->program, GL_LINK_STATUS, &link_status); + glGetProgramiv(self->program, GL_LINK_STATUS, &link_status); if (link_status == GL_FALSE) { - g_autofree gchar* program_log = get_program_log(priv->program); + g_autofree gchar* program_log = get_program_log(self->program); g_warning("Failed to link program: %s", program_log); } @@ -221,9 +218,6 @@ static void render_with_textures(FlRenderer* self, GPtrArray* framebuffers, int width, int height) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - // Save bindings that are set by this function. All bindings must be restored // to their original values because Skia expects that its bindings have not // been altered. @@ -237,7 +231,7 @@ static void render_with_textures(FlRenderer* self, glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glUseProgram(priv->program); + glUseProgram(self->program); for (guint i = 0; i < framebuffers->len; i++) { FlFramebuffer* framebuffer = @@ -263,11 +257,11 @@ static void render_with_textures(FlRenderer* self, glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - GLint position_index = glGetAttribLocation(priv->program, "position"); + GLint position_index = glGetAttribLocation(self->program, "position"); glEnableVertexAttribArray(position_index); glVertexAttribPointer(position_index, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); - GLint texcoord_index = glGetAttribLocation(priv->program, "in_texcoord"); + GLint texcoord_index = glGetAttribLocation(self->program, "in_texcoord"); glEnableVertexAttribArray(texcoord_index); glVertexAttribPointer(texcoord_index, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, @@ -290,10 +284,7 @@ static void render(FlRenderer* self, GPtrArray* framebuffers, int width, int height) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - - if (priv->has_gl_framebuffer_blit) { + if (self->has_gl_framebuffer_blit) { render_with_blit(self, framebuffers); } else { render_with_textures(self, framebuffers, width, height); @@ -304,21 +295,18 @@ static gboolean present_layers(FlRenderer* self, FlutterViewId view_id, const FlutterLayer** layers, size_t layers_count) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - g_return_val_if_fail(FL_IS_RENDERER(self), FALSE); // ignore incoming frame with wrong dimensions in trivial case with just one // layer - if (priv->blocking_main_thread && layers_count == 1 && + if (self->blocking_main_thread && layers_count == 1 && layers[0]->offset.x == 0 && layers[0]->offset.y == 0 && - (layers[0]->size.width != priv->target_width || - layers[0]->size.height != priv->target_height)) { + (layers[0]->size.width != self->target_width || + layers[0]->size.height != self->target_height)) { return TRUE; } - priv->had_first_frame = true; + self->had_first_frame = true; fl_renderer_unblock_main_thread(self); @@ -340,7 +328,7 @@ static gboolean present_layers(FlRenderer* self, } } - g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine)); + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); if (engine == nullptr) { return TRUE; } @@ -352,7 +340,7 @@ static gboolean present_layers(FlRenderer* self, if (view_id == flutter::kFlutterImplicitViewId) { // Store for rendering later - g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id), + g_hash_table_insert(self->framebuffers_by_view_id, GINT_TO_POINTER(view_id), g_ptr_array_ref(framebuffers)); } else { // Composite into a single framebuffer. @@ -374,7 +362,7 @@ static gboolean present_layers(FlRenderer* self, } FlFramebuffer* view_framebuffer = - fl_framebuffer_new(priv->general_format, width, height); + fl_framebuffer_new(self->general_format, width, height); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fl_framebuffer_get_id(view_framebuffer)); render(self, framebuffers, width, height); @@ -390,13 +378,13 @@ static gboolean present_layers(FlRenderer* self, size_t data_length = width * height * 4; g_autofree uint8_t* data = static_cast(malloc(data_length)); glBindFramebuffer(GL_READ_FRAMEBUFFER, fl_framebuffer_get_id(framebuffer)); - glReadPixels(0, 0, width, height, priv->general_format, GL_UNSIGNED_BYTE, + glReadPixels(0, 0, width, height, self->general_format, GL_UNSIGNED_BYTE, data); // Write into a texture in the views context. fl_renderable_make_current(renderable); FlFramebuffer* view_framebuffer = - fl_framebuffer_new(priv->general_format, width, height); + fl_framebuffer_new(self->general_format, width, height); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fl_framebuffer_get_id(view_framebuffer)); glBindTexture(GL_TEXTURE_2D, @@ -407,7 +395,7 @@ static gboolean present_layers(FlRenderer* self, g_autoptr(GPtrArray) secondary_framebuffers = g_ptr_array_new_with_free_func(g_object_unref); g_ptr_array_add(secondary_framebuffers, g_object_ref(view_framebuffer)); - g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id), + g_hash_table_insert(self->framebuffers_by_view_id, GINT_TO_POINTER(view_id), g_ptr_array_ref(secondary_framebuffers)); } @@ -432,32 +420,30 @@ typedef struct { // Perform the present on the main thread. static void present_layers_task_cb(gpointer user_data) { PresentLayersData* data = static_cast(user_data); - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(data->self)); + FlRenderer* self = data->self; // Perform the present. - fl_renderer_make_current(data->self); - data->result = present_layers(data->self, data->view_id, data->layers, - data->layers_count); - fl_renderer_clear_current(data->self); + fl_opengl_manager_make_current(self->opengl_manager); + data->result = + present_layers(self, data->view_id, data->layers, data->layers_count); + fl_opengl_manager_clear_current(self->opengl_manager); // Complete fl_renderer_present_layers(). - g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->present_mutex); + g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex); data->finished = TRUE; - g_cond_signal(&priv->present_condition); + g_cond_signal(&self->present_condition); } static void fl_renderer_dispose(GObject* object) { FlRenderer* self = FL_RENDERER(object); - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); fl_renderer_unblock_main_thread(self); - g_weak_ref_clear(&priv->engine); - g_clear_pointer(&priv->framebuffers_by_view_id, g_hash_table_unref); - g_mutex_clear(&priv->present_mutex); - g_cond_clear(&priv->present_condition); + g_weak_ref_clear(&self->engine); + g_clear_object(&self->opengl_manager); + g_clear_pointer(&self->framebuffers_by_view_id, g_hash_table_unref); + g_mutex_clear(&self->present_mutex); + g_cond_clear(&self->present_condition); G_OBJECT_CLASS(fl_renderer_parent_class)->dispose(object); } @@ -467,65 +453,33 @@ static void fl_renderer_class_init(FlRendererClass* klass) { } static void fl_renderer_init(FlRenderer* self) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - priv->framebuffers_by_view_id = g_hash_table_new_full( + self->framebuffers_by_view_id = g_hash_table_new_full( g_direct_hash, g_direct_equal, nullptr, reinterpret_cast(g_ptr_array_unref)); - g_mutex_init(&priv->present_mutex); - g_cond_init(&priv->present_condition); + g_mutex_init(&self->present_mutex); + g_cond_init(&self->present_condition); } -void fl_renderer_set_engine(FlRenderer* self, FlEngine* engine) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); +FlRenderer* fl_renderer_new(FlEngine* engine) { + FlRenderer* self = FL_RENDERER(g_object_new(fl_renderer_get_type(), nullptr)); - g_return_if_fail(FL_IS_RENDERER(self)); + g_weak_ref_init(&self->engine, engine); + self->opengl_manager = + FL_OPENGL_MANAGER(g_object_ref(fl_engine_get_opengl_manager(engine))); - g_weak_ref_init(&priv->engine, engine); -} - -void* fl_renderer_get_proc_address(FlRenderer* self, const char* name) { - g_return_val_if_fail(FL_IS_RENDERER(self), NULL); - - return reinterpret_cast(eglGetProcAddress(name)); -} - -void fl_renderer_make_current(FlRenderer* self) { - g_return_if_fail(FL_IS_RENDERER(self)); - FL_RENDERER_GET_CLASS(self)->make_current(self); -} - -void fl_renderer_make_resource_current(FlRenderer* self) { - g_return_if_fail(FL_IS_RENDERER(self)); - FL_RENDERER_GET_CLASS(self)->make_resource_current(self); -} - -void fl_renderer_clear_current(FlRenderer* self) { - g_return_if_fail(FL_IS_RENDERER(self)); - FL_RENDERER_GET_CLASS(self)->clear_current(self); -} - -guint32 fl_renderer_get_fbo(FlRenderer* self) { - g_return_val_if_fail(FL_IS_RENDERER(self), 0); - - // There is only one frame buffer object - always return that. - return 0; + return self; } gboolean fl_renderer_create_backing_store( FlRenderer* self, const FlutterBackingStoreConfig* config, FlutterBackingStore* backing_store_out) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - - fl_renderer_make_current(self); + fl_opengl_manager_make_current(self->opengl_manager); initialize(self); FlFramebuffer* framebuffer = fl_framebuffer_new( - priv->general_format, config->size.width, config->size.height); + self->general_format, config->size.width, config->size.height); if (!framebuffer) { g_warning("Failed to create backing store"); return FALSE; @@ -536,7 +490,7 @@ gboolean fl_renderer_create_backing_store( backing_store_out->open_gl.framebuffer.user_data = framebuffer; backing_store_out->open_gl.framebuffer.name = fl_framebuffer_get_id(framebuffer); - backing_store_out->open_gl.framebuffer.target = priv->sized_format; + backing_store_out->open_gl.framebuffer.target = self->sized_format; backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) { // Backing store destroyed in fl_renderer_collect_backing_store(), set // on FlutterCompositor.collect_backing_store_callback during engine start. @@ -548,7 +502,7 @@ gboolean fl_renderer_create_backing_store( gboolean fl_renderer_collect_backing_store( FlRenderer* self, const FlutterBackingStore* backing_store) { - fl_renderer_make_current(self); + fl_opengl_manager_make_current(self->opengl_manager); // OpenGL context is required when destroying #FlFramebuffer. g_object_unref(backing_store->open_gl.framebuffer.user_data); @@ -558,17 +512,14 @@ gboolean fl_renderer_collect_backing_store( void fl_renderer_wait_for_frame(FlRenderer* self, int target_width, int target_height) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - g_return_if_fail(FL_IS_RENDERER(self)); - priv->target_width = target_width; - priv->target_height = target_height; + self->target_width = target_width; + self->target_height = target_height; - if (priv->had_first_frame && !priv->blocking_main_thread) { - priv->blocking_main_thread = true; - g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine)); + if (self->had_first_frame && !self->blocking_main_thread) { + self->blocking_main_thread = true; + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); if (engine != nullptr) { fl_task_runner_block_main_thread(fl_engine_get_task_runner(engine)); } @@ -581,11 +532,9 @@ gboolean fl_renderer_present_layers(FlRenderer* self, size_t layers_count) { // Detach the context from raster thread. Needed because blitting // will be done on the main thread, which will make the context current. - fl_renderer_clear_current(self); + fl_opengl_manager_clear_current(self->opengl_manager); - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine)); + g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine)); // Schedule the present to run on the main thread. FlTaskRunner* task_runner = fl_engine_get_task_runner(engine); @@ -600,32 +549,29 @@ gboolean fl_renderer_present_layers(FlRenderer* self, fl_task_runner_post_callback(task_runner, present_layers_task_cb, &data); // Block until present completes. - g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&priv->present_mutex); + g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex); while (!data.finished) { - g_cond_wait(&priv->present_condition, &priv->present_mutex); + g_cond_wait(&self->present_condition, &self->present_mutex); } // Restore the context to the raster thread in case the engine needs it // to do some cleanup. - fl_renderer_make_current(self); + fl_opengl_manager_make_current(self->opengl_manager); return data.result; } void fl_renderer_setup(FlRenderer* self) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - g_return_if_fail(FL_IS_RENDERER(self)); // Note: NVIDIA and Vivante are temporarily disabled due to // https://github.com/flutter/flutter/issues/152099 - priv->has_gl_framebuffer_blit = + self->has_gl_framebuffer_blit = !is_nvidia() && !is_vivante() && (epoxy_gl_version() >= 30 || epoxy_has_gl_extension("GL_EXT_framebuffer_blit")); - if (!priv->has_gl_framebuffer_blit) { + if (!self->has_gl_framebuffer_blit) { setup_shader(self); } } @@ -635,9 +581,6 @@ void fl_renderer_render(FlRenderer* self, int width, int height, const GdkRGBA* background_color) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - g_return_if_fail(FL_IS_RENDERER(self)); glClearColor(background_color->red, background_color->green, @@ -645,7 +588,7 @@ void fl_renderer_render(FlRenderer* self, glClear(GL_COLOR_BUFFER_BIT); GPtrArray* framebuffers = reinterpret_cast((g_hash_table_lookup( - priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id)))); + self->framebuffers_by_view_id, GINT_TO_POINTER(view_id)))); if (framebuffers != nullptr) { render(self, framebuffers, width, height); } @@ -654,12 +597,9 @@ void fl_renderer_render(FlRenderer* self, } void fl_renderer_cleanup(FlRenderer* self) { - FlRendererPrivate* priv = reinterpret_cast( - fl_renderer_get_instance_private(self)); - g_return_if_fail(FL_IS_RENDERER(self)); - if (priv->program != 0) { - glDeleteProgram(priv->program); + if (self->program != 0) { + glDeleteProgram(self->program); } } diff --git a/engine/src/flutter/shell/platform/linux/fl_renderer.h b/engine/src/flutter/shell/platform/linux/fl_renderer.h index 3d1a173ebd..74f6d5b934 100644 --- a/engine/src/flutter/shell/platform/linux/fl_renderer.h +++ b/engine/src/flutter/shell/platform/linux/fl_renderer.h @@ -25,7 +25,7 @@ typedef enum { GQuark fl_renderer_error_quark(void) G_GNUC_CONST; -G_DECLARE_DERIVABLE_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject) +G_DECLARE_FINAL_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject) /** * FlRenderer: @@ -33,83 +33,15 @@ G_DECLARE_DERIVABLE_TYPE(FlRenderer, fl_renderer, FL, RENDERER, GObject) * #FlRenderer is an abstract class that allows Flutter to draw pixels. */ -struct _FlRendererClass { - GObjectClass parent_class; - - /** - * Virtual method called when Flutter needs to make the OpenGL context - * current. - * @renderer: an #FlRenderer. - */ - void (*make_current)(FlRenderer* renderer); - - /** - * Virtual method called when Flutter needs to make the OpenGL resource - * context current. - * @renderer: an #FlRenderer. - */ - void (*make_resource_current)(FlRenderer* renderer); - - /** - * Virtual method called when Flutter needs to clear the OpenGL context. - * @renderer: an #FlRenderer. - */ - void (*clear_current)(FlRenderer* renderer); -}; - /** - * fl_renderer_set_engine: - * @renderer: an #FlRenderer. + * fl_renderer_new: * @engine: an #FlEngine. * - * Called when the renderer is connected to an engine. + * Creates a new renderer. + * + * Returns: a new #FlRenderer. */ -void fl_renderer_set_engine(FlRenderer* renderer, FlEngine* engine); - -/** - * fl_renderer_get_proc_address: - * @renderer: an #FlRenderer. - * @name: a function name. - * - * Gets the rendering API function that matches the given name. - * - * Returns: a function pointer. - */ -void* fl_renderer_get_proc_address(FlRenderer* renderer, const char* name); - -/** - * fl_renderer_make_current: - * @renderer: an #FlRenderer. - * - * Makes the rendering context current. - */ -void fl_renderer_make_current(FlRenderer* renderer); - -/** - * fl_renderer_make_resource_current: - * @renderer: an #FlRenderer. - * - * Makes the resource rendering context current. - */ -void fl_renderer_make_resource_current(FlRenderer* renderer); - -/** - * fl_renderer_clear_current: - * @renderer: an #FlRenderer. - * - * Clears the current rendering context. - */ -void fl_renderer_clear_current(FlRenderer* renderer); - -/** - * fl_renderer_get_fbo: - * @renderer: an #FlRenderer. - * - * Gets the frame buffer object to render to. - * - * Returns: a frame buffer object index. - */ -guint32 fl_renderer_get_fbo(FlRenderer* renderer); +FlRenderer* fl_renderer_new(FlEngine* engine); /** * fl_renderer_create_backing_store: diff --git a/engine/src/flutter/shell/platform/linux/fl_renderer_gdk.cc b/engine/src/flutter/shell/platform/linux/fl_renderer_gdk.cc deleted file mode 100644 index a0bc4e7694..0000000000 --- a/engine/src/flutter/shell/platform/linux/fl_renderer_gdk.cc +++ /dev/null @@ -1,109 +0,0 @@ -// 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 "flutter/shell/platform/linux/fl_renderer_gdk.h" - -struct _FlRendererGdk { - FlRenderer parent_instance; - - // Window being rendered on. - GdkWindow* window; - - // OpenGL rendering context used by GDK. - GdkGLContext* gdk_context; - - // Main OpenGL rendering context used by Flutter. - GdkGLContext* main_context; - - // Secondary OpenGL rendering context used by Flutter. - GdkGLContext* resource_context; -}; - -G_DEFINE_TYPE(FlRendererGdk, fl_renderer_gdk, fl_renderer_get_type()) - -// Implements FlRenderer::make_current. -static void fl_renderer_gdk_make_current(FlRenderer* renderer) { - FlRendererGdk* self = FL_RENDERER_GDK(renderer); - gdk_gl_context_make_current(self->main_context); -} - -// Implements FlRenderer::make_resource_current. -static void fl_renderer_gdk_make_resource_current(FlRenderer* renderer) { - FlRendererGdk* self = FL_RENDERER_GDK(renderer); - gdk_gl_context_make_current(self->resource_context); -} - -// Implements FlRenderer::clear_current. -static void fl_renderer_gdk_clear_current(FlRenderer* renderer) { - gdk_gl_context_clear_current(); -} - -static void fl_renderer_gdk_dispose(GObject* object) { - FlRendererGdk* self = FL_RENDERER_GDK(object); - - g_clear_object(&self->gdk_context); - g_clear_object(&self->main_context); - g_clear_object(&self->resource_context); - - G_OBJECT_CLASS(fl_renderer_gdk_parent_class)->dispose(object); -} - -static void fl_renderer_gdk_class_init(FlRendererGdkClass* klass) { - G_OBJECT_CLASS(klass)->dispose = fl_renderer_gdk_dispose; - - FL_RENDERER_CLASS(klass)->make_current = fl_renderer_gdk_make_current; - FL_RENDERER_CLASS(klass)->make_resource_current = - fl_renderer_gdk_make_resource_current; - FL_RENDERER_CLASS(klass)->clear_current = fl_renderer_gdk_clear_current; -} - -static void fl_renderer_gdk_init(FlRendererGdk* self) {} - -FlRendererGdk* fl_renderer_gdk_new() { - FlRendererGdk* self = - FL_RENDERER_GDK(g_object_new(fl_renderer_gdk_get_type(), nullptr)); - return self; -} - -void fl_renderer_gdk_set_window(FlRendererGdk* self, GdkWindow* window) { - g_return_if_fail(FL_IS_RENDERER_GDK(self)); - - g_assert(self->window == nullptr); - self->window = window; -} - -gboolean fl_renderer_gdk_create_contexts(FlRendererGdk* self, GError** error) { - g_return_val_if_fail(FL_IS_RENDERER_GDK(self), FALSE); - - self->gdk_context = gdk_window_create_gl_context(self->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(self->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(self->window, error); - if (self->resource_context == nullptr) { - return FALSE; - } - if (!gdk_gl_context_realize(self->resource_context, error)) { - return FALSE; - } - - return TRUE; -} - -GdkGLContext* fl_renderer_gdk_get_context(FlRendererGdk* self) { - g_return_val_if_fail(FL_IS_RENDERER_GDK(self), nullptr); - return self->gdk_context; -} diff --git a/engine/src/flutter/shell/platform/linux/fl_renderer_gdk.h b/engine/src/flutter/shell/platform/linux/fl_renderer_gdk.h deleted file mode 100644 index 89a8ee212a..0000000000 --- a/engine/src/flutter/shell/platform/linux/fl_renderer_gdk.h +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_GDK_H_ -#define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_GDK_H_ - -#include "flutter/shell/platform/linux/fl_renderer.h" - -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(FlRendererGdk, - fl_renderer_gdk, - FL, - RENDERER_GDK, - FlRenderer) - -/** - * FlRendererGdk: - * - * #FlRendererGdk is an implementation of #FlRenderer that renders by OpenGL ES. - */ - -/** - * fl_renderer_gdk_new: - * - * Creates an object that allows Flutter to render by OpenGL ES. - * - * Returns: a new #FlRendererGdk. - */ -FlRendererGdk* fl_renderer_gdk_new(); - -/** - * fl_renderer_gdk_set_window: - * @renderer: an #FlRendererGdk. - * @window: the window that is being rendered on. - * - * Set the window that is being rendered on. This is only called once when the - * window is available. - */ -void fl_renderer_gdk_set_window(FlRendererGdk* renderer, GdkWindow* window); - -/** - * fl_renderer_gdk_create_contexts: - * @renderer: an #FlRendererGdk. - * @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_renderer_gdk_create_contexts(FlRendererGdk* renderer, - GError** error); - -/** - * fl_renderer_gdk_get_context: - * @renderer: an #FlRendererGdk. - * - * Returns: the main context used for rendering. - */ -GdkGLContext* fl_renderer_gdk_get_context(FlRendererGdk* renderer); - -G_END_DECLS - -#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_GDK_H_ diff --git a/engine/src/flutter/shell/platform/linux/fl_renderer_headless.cc b/engine/src/flutter/shell/platform/linux/fl_renderer_headless.cc deleted file mode 100644 index 1736e14373..0000000000 --- a/engine/src/flutter/shell/platform/linux/fl_renderer_headless.cc +++ /dev/null @@ -1,34 +0,0 @@ -// 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_headless.h" - -struct _FlRendererHeadless { - FlRenderer parent_instance; -}; - -G_DEFINE_TYPE(FlRendererHeadless, fl_renderer_headless, fl_renderer_get_type()) - -// Implements FlRenderer::make_current. -static void fl_renderer_headless_make_current(FlRenderer* renderer) {} - -// Implements FlRenderer::make_resource_current. -static void fl_renderer_headless_make_resource_current(FlRenderer* renderer) {} - -// Implements FlRenderer::clear_current. -static void fl_renderer_headless_clear_current(FlRenderer* renderer) {} - -static void fl_renderer_headless_class_init(FlRendererHeadlessClass* klass) { - FL_RENDERER_CLASS(klass)->make_current = fl_renderer_headless_make_current; - FL_RENDERER_CLASS(klass)->make_resource_current = - fl_renderer_headless_make_resource_current; - FL_RENDERER_CLASS(klass)->clear_current = fl_renderer_headless_clear_current; -} - -static void fl_renderer_headless_init(FlRendererHeadless* self) {} - -FlRendererHeadless* fl_renderer_headless_new() { - return FL_RENDERER_HEADLESS( - g_object_new(fl_renderer_headless_get_type(), nullptr)); -} diff --git a/engine/src/flutter/shell/platform/linux/fl_renderer_headless.h b/engine/src/flutter/shell/platform/linux/fl_renderer_headless.h deleted file mode 100644 index 7fac33d818..0000000000 --- a/engine/src/flutter/shell/platform/linux/fl_renderer_headless.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ -#define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ - -#include "flutter/shell/platform/linux/fl_renderer.h" - -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(FlRendererHeadless, - fl_renderer_headless, - FL, - RENDERER_HEADLESS, - FlRenderer) - -/** - * FlRendererHeadless: - * - * #FlRendererHeadless is an implementation of #FlRenderer that works without a - * display. - */ - -/** - * fl_renderer_headless_new: - * - * Creates an object that allows Flutter to operate without a display. - * - * Returns: a new #FlRendererHeadless. - */ -FlRendererHeadless* fl_renderer_headless_new(); - -G_END_DECLS - -#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ diff --git a/engine/src/flutter/shell/platform/linux/fl_renderer_test.cc b/engine/src/flutter/shell/platform/linux/fl_renderer_test.cc index 07a9db6cc7..9c189ce11f 100644 --- a/engine/src/flutter/shell/platform/linux/fl_renderer_test.cc +++ b/engine/src/flutter/shell/platform/linux/fl_renderer_test.cc @@ -11,7 +11,7 @@ #include "flutter/shell/platform/linux/fl_engine_private.h" #include "flutter/shell/platform/linux/fl_framebuffer.h" #include "flutter/shell/platform/linux/testing/mock_epoxy.h" -#include "flutter/shell/platform/linux/testing/mock_renderer.h" +#include "flutter/shell/platform/linux/testing/mock_renderable.h" #include @@ -28,9 +28,8 @@ TEST(FlRendererTest, BackgroundColor) { EXPECT_CALL(epoxy, glClearColor(0.2, 0.3, 0.4, 0.5)); g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new(); - g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(FlRenderer) renderer = fl_renderer_new(engine); fl_renderer_setup(FL_RENDERER(renderer)); - fl_renderer_set_engine(FL_RENDERER(renderer), engine); fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable)); fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024); FlutterBackingStoreConfig config = { @@ -78,8 +77,7 @@ TEST(FlRendererTest, RestoresGLState) { constexpr int kHeight = 100; g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new(); - g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); - fl_renderer_set_engine(FL_RENDERER(renderer), engine); + g_autoptr(FlRenderer) renderer = fl_renderer_new(engine); g_autoptr(FlFramebuffer) framebuffer = fl_framebuffer_new(GL_RGB, kWidth, kHeight); @@ -145,9 +143,8 @@ TEST(FlRendererTest, BlitFramebuffer) { EXPECT_CALL(epoxy, glBlitFramebuffer); g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new(); - g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(FlRenderer) renderer = fl_renderer_new(engine); fl_renderer_setup(FL_RENDERER(renderer)); - fl_renderer_set_engine(FL_RENDERER(renderer), engine); fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable)); fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024); FlutterBackingStoreConfig config = { @@ -203,9 +200,8 @@ TEST(FlRendererTest, BlitFramebufferExtension) { EXPECT_CALL(epoxy, glBlitFramebuffer); g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new(); - g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(FlRenderer) renderer = fl_renderer_new(engine); fl_renderer_setup(FL_RENDERER(renderer)); - fl_renderer_set_engine(FL_RENDERER(renderer), engine); fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable)); fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024); FlutterBackingStoreConfig config = { @@ -254,9 +250,8 @@ TEST(FlRendererTest, NoBlitFramebuffer) { EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(20)); g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new(); - g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(FlRenderer) renderer = fl_renderer_new(engine); fl_renderer_setup(FL_RENDERER(renderer)); - fl_renderer_set_engine(FL_RENDERER(renderer), engine); fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable)); fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024); FlutterBackingStoreConfig config = { @@ -308,9 +303,8 @@ TEST(FlRendererTest, BlitFramebufferNvidia) { EXPECT_CALL(epoxy, epoxy_gl_version).WillRepeatedly(::testing::Return(30)); g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new(); - g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(FlRenderer) renderer = fl_renderer_new(engine); fl_renderer_setup(FL_RENDERER(renderer)); - fl_renderer_set_engine(FL_RENDERER(renderer), engine); fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable)); fl_renderer_wait_for_frame(FL_RENDERER(renderer), 1024, 1024); FlutterBackingStoreConfig config = { @@ -363,9 +357,8 @@ TEST(FlRendererTest, MultiView) { g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new(); g_autoptr(FlMockRenderable) secondary_renderable = fl_mock_renderable_new(); - g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new(); + g_autoptr(FlRenderer) renderer = fl_renderer_new(engine); fl_renderer_setup(FL_RENDERER(renderer)); - fl_renderer_set_engine(FL_RENDERER(renderer), engine); fl_engine_set_implicit_view(engine, FL_RENDERABLE(renderable)); FlutterViewId view_id = fl_engine_add_view(engine, FL_RENDERABLE(secondary_renderable), 1024, 768, diff --git a/engine/src/flutter/shell/platform/linux/fl_view.cc b/engine/src/flutter/shell/platform/linux/fl_view.cc index d548e4c9d1..5ec1c152d9 100644 --- a/engine/src/flutter/shell/platform/linux/fl_view.cc +++ b/engine/src/flutter/shell/platform/linux/fl_view.cc @@ -13,9 +13,9 @@ #include "flutter/shell/platform/linux/fl_accessible_node.h" #include "flutter/shell/platform/linux/fl_engine_private.h" #include "flutter/shell/platform/linux/fl_key_event.h" +#include "flutter/shell/platform/linux/fl_opengl_manager.h" #include "flutter/shell/platform/linux/fl_plugin_registrar_private.h" #include "flutter/shell/platform/linux/fl_pointer_manager.h" -#include "flutter/shell/platform/linux/fl_renderer_gdk.h" #include "flutter/shell/platform/linux/fl_scrolling_manager.h" #include "flutter/shell/platform/linux/fl_socket_accessible.h" #include "flutter/shell/platform/linux/fl_touch_manager.h" @@ -43,9 +43,6 @@ struct _FlView { // ID for this view. FlutterViewId view_id; - // Object that performs the view rendering. - FlRendererGdk* renderer; - // Background color. GdkRGBA* background_color; @@ -197,7 +194,7 @@ static void handle_geometry_changed(FlView* self) { // Note: `gtk_widget_init()` initializes the size allocation to 1x1. if (allocation.width > 1 && allocation.height > 1 && gtk_widget_get_realized(GTK_WIDGET(self))) { - fl_renderer_wait_for_frame(FL_RENDERER(self->renderer), + fl_renderer_wait_for_frame(fl_engine_get_renderer(self->engine), allocation.width * scale_factor, allocation.height * scale_factor); } @@ -440,26 +437,26 @@ static void gesture_zoom_end_cb(FlView* self) { } static GdkGLContext* create_context_cb(FlView* self) { - fl_renderer_gdk_set_window(self->renderer, - gtk_widget_get_parent_window(GTK_WIDGET(self))); - init_scrolling(self); init_touch(self); + FlOpenGLManager* opengl_manager = fl_engine_get_opengl_manager(self->engine); g_autoptr(GError) error = nullptr; - if (!fl_renderer_gdk_create_contexts(self->renderer, &error)) { + if (!fl_opengl_manager_create_contexts( + opengl_manager, gtk_widget_get_parent_window(GTK_WIDGET(self)), + &error)) { gtk_gl_area_set_error(self->gl_area, error); return nullptr; } return GDK_GL_CONTEXT( - g_object_ref(fl_renderer_gdk_get_context(self->renderer))); + g_object_ref(fl_opengl_manager_get_context(opengl_manager))); } static void realize_cb(FlView* self) { g_autoptr(GError) error = nullptr; - fl_renderer_make_current(FL_RENDERER(self->renderer)); + fl_opengl_manager_make_current(fl_engine_get_opengl_manager(self->engine)); GError* gl_error = gtk_gl_area_get_error(self->gl_area); if (gl_error != NULL) { @@ -467,7 +464,7 @@ static void realize_cb(FlView* self) { return; } - fl_renderer_setup(FL_RENDERER(self->renderer)); + fl_renderer_setup(fl_engine_get_renderer(self->engine)); GtkWidget* toplevel_window = gtk_widget_get_toplevel(GTK_WIDGET(self)); @@ -481,7 +478,7 @@ static void realize_cb(FlView* self) { // Flutter engine will need to make the context current from raster thread // during initialization. - fl_renderer_clear_current(FL_RENDERER(self->renderer)); + fl_opengl_manager_clear_current(fl_engine_get_opengl_manager(self->engine)); if (!fl_engine_start(self->engine, &error)) { g_warning("Failed to start Flutter engine: %s", error->message); @@ -505,7 +502,7 @@ static gboolean render_cb(FlView* self, GdkGLContext* context) { int width = gtk_widget_get_allocated_width(GTK_WIDGET(self->gl_area)); int height = gtk_widget_get_allocated_height(GTK_WIDGET(self->gl_area)); gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(self->gl_area)); - fl_renderer_render(FL_RENDERER(self->renderer), self->view_id, + fl_renderer_render(fl_engine_get_renderer(self->engine), self->view_id, width * scale_factor, height * scale_factor, self->background_color); @@ -515,7 +512,7 @@ static gboolean render_cb(FlView* self, GdkGLContext* context) { static void unrealize_cb(FlView* self) { g_autoptr(GError) error = nullptr; - fl_renderer_make_current(FL_RENDERER(self->renderer)); + fl_opengl_manager_make_current(fl_engine_get_opengl_manager(self->engine)); GError* gl_error = gtk_gl_area_get_error(self->gl_area); if (gl_error != NULL) { @@ -523,7 +520,7 @@ static void unrealize_cb(FlView* self) { return; } - fl_renderer_cleanup(FL_RENDERER(self->renderer)); + fl_renderer_cleanup(fl_engine_get_renderer(self->engine)); } static void size_allocate_cb(FlView* self) { @@ -572,7 +569,6 @@ static void fl_view_dispose(GObject* object) { } g_clear_object(&self->engine); - g_clear_object(&self->renderer); g_clear_pointer(&self->background_color, gdk_rgba_free); g_clear_object(&self->window_state_monitor); g_clear_object(&self->scrolling_manager); @@ -754,9 +750,6 @@ G_MODULE_EXPORT FlView* fl_view_new(FlDartProject* project) { self->view_id = flutter::kFlutterImplicitViewId; self->engine = FL_ENGINE(g_object_ref(engine)); - FlRenderer* renderer = fl_engine_get_renderer(engine); - g_assert(FL_IS_RENDERER_GDK(renderer)); - self->renderer = FL_RENDERER_GDK(g_object_ref(renderer)); setup_engine(self); @@ -776,9 +769,6 @@ G_MODULE_EXPORT FlView* fl_view_new_for_engine(FlEngine* engine) { FlView* self = FL_VIEW(g_object_new(fl_view_get_type(), nullptr)); self->engine = FL_ENGINE(g_object_ref(engine)); - FlRenderer* renderer = fl_engine_get_renderer(engine); - g_assert(FL_IS_RENDERER_GDK(renderer)); - self->renderer = FL_RENDERER_GDK(g_object_ref(renderer)); self->view_id = fl_engine_add_view(engine, FL_RENDERABLE(self), 1, 1, 1.0, self->cancellable, view_added_cb, self); diff --git a/engine/src/flutter/shell/platform/linux/testing/fl_test.cc b/engine/src/flutter/shell/platform/linux/testing/fl_test.cc index 3c0da2eb10..f7c0f1515b 100644 --- a/engine/src/flutter/shell/platform/linux/testing/fl_test.cc +++ b/engine/src/flutter/shell/platform/linux/testing/fl_test.cc @@ -7,7 +7,7 @@ #include "flutter/shell/platform/linux/testing/fl_test.h" #include "flutter/shell/platform/linux/fl_engine_private.h" -#include "flutter/shell/platform/linux/testing/mock_renderer.h" +#include "flutter/shell/platform/linux/testing/mock_renderable.h" namespace { class ImModuleEnv : public ::testing::Environment { diff --git a/engine/src/flutter/shell/platform/linux/testing/mock_gtk.cc b/engine/src/flutter/shell/platform/linux/testing/mock_gtk.cc index 3b34c99a88..3a5c7a65f6 100644 --- a/engine/src/flutter/shell/platform/linux/testing/mock_gtk.cc +++ b/engine/src/flutter/shell/platform/linux/testing/mock_gtk.cc @@ -79,6 +79,10 @@ 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); diff --git a/engine/src/flutter/shell/platform/linux/testing/mock_renderer.cc b/engine/src/flutter/shell/platform/linux/testing/mock_renderable.cc similarity index 56% rename from engine/src/flutter/shell/platform/linux/testing/mock_renderer.cc rename to engine/src/flutter/shell/platform/linux/testing/mock_renderable.cc index 5ae2926efa..292bcf4465 100644 --- a/engine/src/flutter/shell/platform/linux/testing/mock_renderer.cc +++ b/engine/src/flutter/shell/platform/linux/testing/mock_renderable.cc @@ -2,19 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "flutter/shell/platform/linux/testing/mock_renderer.h" - -struct _FlMockRenderer { - FlRenderer parent_instance; -}; +#include "flutter/shell/platform/linux/testing/mock_renderable.h" struct _FlMockRenderable { GObject parent_instance; size_t redraw_count; }; -G_DEFINE_TYPE(FlMockRenderer, fl_mock_renderer, fl_renderer_get_type()) - static void mock_renderable_iface_init(FlRenderableInterface* iface); G_DEFINE_TYPE_WITH_CODE(FlMockRenderable, @@ -23,24 +17,6 @@ G_DEFINE_TYPE_WITH_CODE(FlMockRenderable, G_IMPLEMENT_INTERFACE(fl_renderable_get_type(), mock_renderable_iface_init)) -// Implements FlRenderer::make_current. -static void fl_mock_renderer_make_current(FlRenderer* renderer) {} - -// Implements FlRenderer::make_resource_current. -static void fl_mock_renderer_make_resource_current(FlRenderer* renderer) {} - -// Implements FlRenderer::clear_current. -static void fl_mock_renderer_clear_current(FlRenderer* renderer) {} - -static void fl_mock_renderer_class_init(FlMockRendererClass* klass) { - FL_RENDERER_CLASS(klass)->make_current = fl_mock_renderer_make_current; - FL_RENDERER_CLASS(klass)->make_resource_current = - fl_mock_renderer_make_resource_current; - FL_RENDERER_CLASS(klass)->clear_current = fl_mock_renderer_clear_current; -} - -static void fl_mock_renderer_init(FlMockRenderer* self) {} - static void mock_renderable_redraw(FlRenderable* renderable) { FlMockRenderable* self = FL_MOCK_RENDERABLE(renderable); self->redraw_count++; @@ -57,13 +33,6 @@ static void fl_mock_renderable_class_init(FlMockRenderableClass* klass) {} static void fl_mock_renderable_init(FlMockRenderable* self) {} -// Creates a stub renderer -FlMockRenderer* fl_mock_renderer_new() { - FlMockRenderer* self = - FL_MOCK_RENDERER(g_object_new(fl_mock_renderer_get_type(), nullptr)); - return self; -} - // Creates a sub renderable. FlMockRenderable* fl_mock_renderable_new() { return FL_MOCK_RENDERABLE( diff --git a/engine/src/flutter/shell/platform/linux/testing/mock_renderer.h b/engine/src/flutter/shell/platform/linux/testing/mock_renderable.h similarity index 50% rename from engine/src/flutter/shell/platform/linux/testing/mock_renderer.h rename to engine/src/flutter/shell/platform/linux/testing/mock_renderable.h index 5c6ada332f..6dcb6c12a8 100644 --- a/engine/src/flutter/shell/platform/linux/testing/mock_renderer.h +++ b/engine/src/flutter/shell/platform/linux/testing/mock_renderable.h @@ -2,34 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERER_H_ -#define FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERER_H_ +#ifndef FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERABLE_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERABLE_H_ #include "flutter/shell/platform/linux/fl_renderable.h" -#include "flutter/shell/platform/linux/fl_renderer.h" G_BEGIN_DECLS -G_DECLARE_FINAL_TYPE(FlMockRenderer, - fl_mock_renderer, - FL, - MOCK_RENDERER, - FlRenderer) - G_DECLARE_FINAL_TYPE(FlMockRenderable, fl_mock_renderable, FL, MOCK_RENDERABLE, GObject) -typedef gdouble (*FlMockRendererGetRefreshRate)(FlRenderer* renderer); - -FlMockRenderer* fl_mock_renderer_new(); - FlMockRenderable* fl_mock_renderable_new(); size_t fl_mock_renderable_get_redraw_count(FlMockRenderable* renderable); G_END_DECLS -#endif // FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERER_H_ +#endif // FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_RENDERABLE_H_