From c8f75e73397d2728e7d507a497688e4c6127548f Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Mon, 15 Jun 2020 11:22:30 +1200 Subject: [PATCH 1/3] Add support for headless mode --- ci/licenses_golden/licenses_flutter | 2 + shell/platform/linux/BUILD.gn | 1 + shell/platform/linux/fl_engine.cc | 39 ++++++++++++++++--- shell/platform/linux/fl_plugin_registrar.cc | 5 ++- .../linux/fl_plugin_registrar_private.h | 3 +- shell/platform/linux/fl_renderer_headless.cc | 29 ++++++++++++++ shell/platform/linux/fl_renderer_headless.h | 38 ++++++++++++++++++ .../linux/public/flutter_linux/fl_engine.h | 10 +++++ 8 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 shell/platform/linux/fl_renderer_headless.cc create mode 100644 shell/platform/linux/fl_renderer_headless.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 4497a763ed419..29b47a92fdc43 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1239,6 +1239,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar_private.h FILE: ../../../flutter/shell/platform/linux/fl_plugin_registry.cc FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc FILE: ../../../flutter/shell/platform/linux/fl_renderer.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_x11.cc FILE: ../../../flutter/shell/platform/linux/fl_renderer_x11.h FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec.cc diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index b64394e94e792..08b81bb6a10c5 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -94,6 +94,7 @@ source_set("flutter_linux_sources") { "fl_plugin_registrar.cc", "fl_plugin_registry.cc", "fl_renderer.cc", + "fl_renderer_headless.cc", "fl_renderer_x11.cc", "fl_standard_message_codec.cc", "fl_standard_method_codec.cc", diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index c1fd69e48f706..98745efbdd01f 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -6,7 +6,10 @@ #include "flutter/shell/platform/linux/fl_engine_private.h" #include "flutter/shell/platform/linux/fl_binary_messenger_private.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_headless.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h" #include @@ -35,7 +38,15 @@ struct _FlEngine { G_DEFINE_QUARK(fl_engine_error_quark, fl_engine_error) -G_DEFINE_TYPE(FlEngine, fl_engine, G_TYPE_OBJECT) +static void fl_view_plugin_registry_iface_init( + FlPluginRegistryInterface* iface); + +G_DEFINE_TYPE_WITH_CODE( + FlEngine, + fl_engine, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(), + fl_view_plugin_registry_iface_init)) // Subclass of GSource that integrates Flutter tasks into the GLib main loop. typedef struct { @@ -169,6 +180,20 @@ static void fl_engine_platform_message_response_cb(const uint8_t* data, (GDestroyNotify)g_bytes_unref); } +// Implements FlPluginRegistry::get_registrar_for_plugin. +static FlPluginRegistrar* fl_view_get_registrar_for_plugin( + FlPluginRegistry* registry, + const gchar* name) { + FlEngine* self = FL_ENGINE(registry); + + return fl_plugin_registrar_new(nullptr, self->binary_messenger); +} + +static void fl_view_plugin_registry_iface_init( + FlPluginRegistryInterface* iface) { + iface->get_registrar_for_plugin = fl_view_get_registrar_for_plugin; +} + static void fl_engine_dispose(GObject* object) { FlEngine* self = FL_ENGINE(object); @@ -210,13 +235,17 @@ FlEngine* fl_engine_new(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); - FlEngine* self = - static_cast(g_object_new(fl_engine_get_type(), nullptr)); - self->project = static_cast(g_object_ref(project)); - self->renderer = static_cast(g_object_ref(renderer)); + 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)); return self; } +G_MODULE_EXPORT FlEngine* fl_engine_new_headless(FlDartProject* project) { + g_autoptr(FlRendererHeadless) renderer = fl_renderer_headless_new(); + return fl_engine_new(project, FL_RENDERER(renderer)); +} + gboolean fl_engine_start(FlEngine* self, GError** error) { g_return_val_if_fail(FL_IS_ENGINE(self), FALSE); diff --git a/shell/platform/linux/fl_plugin_registrar.cc b/shell/platform/linux/fl_plugin_registrar.cc index 093a16e0e9bd5..9ca72258b6e73 100644 --- a/shell/platform/linux/fl_plugin_registrar.cc +++ b/shell/platform/linux/fl_plugin_registrar.cc @@ -48,14 +48,15 @@ static void fl_plugin_registrar_init(FlPluginRegistrar* self) {} FlPluginRegistrar* fl_plugin_registrar_new(FlView* view, FlBinaryMessenger* messenger) { - g_return_val_if_fail(FL_IS_VIEW(view), nullptr); + g_return_val_if_fail(view == nullptr || FL_IS_VIEW(view), nullptr); g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr); FlPluginRegistrar* self = FL_PLUGIN_REGISTRAR( g_object_new(fl_plugin_registrar_get_type(), nullptr)); self->view = view; - g_object_weak_ref(G_OBJECT(view), view_weak_notify_cb, self); + if (view != nullptr) + g_object_weak_ref(G_OBJECT(view), view_weak_notify_cb, self); self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger)); return self; diff --git a/shell/platform/linux/fl_plugin_registrar_private.h b/shell/platform/linux/fl_plugin_registrar_private.h index 3a3b753d8a3fe..712f32a3d98c3 100644 --- a/shell/platform/linux/fl_plugin_registrar_private.h +++ b/shell/platform/linux/fl_plugin_registrar_private.h @@ -12,7 +12,8 @@ G_BEGIN_DECLS /** * fl_plugin_registrar_new: - * @view: the #FlView that is being plugged into. + * @view: (allow-none): the #FlView that is being plugged into or %NULL for + * headless mode. * @messenger: the #FlBinaryMessenger to communicate with. * * Creates a new #FlPluginRegistrar. diff --git a/shell/platform/linux/fl_renderer_headless.cc b/shell/platform/linux/fl_renderer_headless.cc new file mode 100644 index 0000000000000..90f917a2b316f --- /dev/null +++ b/shell/platform/linux/fl_renderer_headless.cc @@ -0,0 +1,29 @@ +// 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()) + +static EGLSurface fl_renderer_headless_create_surface(FlRenderer* renderer, + EGLDisplay display, + EGLConfig config) { + return EGL_NO_SURFACE; +} + +static void fl_renderer_headless_class_init(FlRendererHeadlessClass* klass) { + FL_RENDERER_CLASS(klass)->create_surface = + fl_renderer_headless_create_surface; +} + +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/shell/platform/linux/fl_renderer_headless.h b/shell/platform/linux/fl_renderer_headless.h new file mode 100644 index 0000000000000..274a10e543a16 --- /dev/null +++ b/shell/platform/linux/fl_renderer_headless.h @@ -0,0 +1,38 @@ +// 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 + +#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/shell/platform/linux/public/flutter_linux/fl_engine.h b/shell/platform/linux/public/flutter_linux/fl_engine.h index 62997228781d8..201c38f4a06d2 100644 --- a/shell/platform/linux/public/flutter_linux/fl_engine.h +++ b/shell/platform/linux/public/flutter_linux/fl_engine.h @@ -24,6 +24,16 @@ G_DECLARE_FINAL_TYPE(FlEngine, fl_engine, FL, ENGINE, GObject) * #FlEngine is an object that contains a running Flutter engine. */ +/** + * fl_engine_new_headless: + * @project: an #FlDartProject. + * + * Creates new Flutter engine running in headless mode. + * + * Returns: a new #FlEngine. + */ +FlEngine* fl_engine_new_headless(FlDartProject* project); + /** * fl_engine_get_binary_messenger: * @engine: an #FlEngine. From f70b89f35bd2f55128457914b15cf4161a8c26e6 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Tue, 16 Jun 2020 11:43:02 +1200 Subject: [PATCH 2/3] Fix method name --- shell/platform/linux/fl_engine.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index 98745efbdd01f..dd292d5f3b184 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -38,7 +38,7 @@ struct _FlEngine { G_DEFINE_QUARK(fl_engine_error_quark, fl_engine_error) -static void fl_view_plugin_registry_iface_init( +static void fl_engine_plugin_registry_iface_init( FlPluginRegistryInterface* iface); G_DEFINE_TYPE_WITH_CODE( @@ -46,7 +46,7 @@ G_DEFINE_TYPE_WITH_CODE( fl_engine, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(), - fl_view_plugin_registry_iface_init)) + fl_engine_plugin_registry_iface_init)) // Subclass of GSource that integrates Flutter tasks into the GLib main loop. typedef struct { @@ -181,7 +181,7 @@ static void fl_engine_platform_message_response_cb(const uint8_t* data, } // Implements FlPluginRegistry::get_registrar_for_plugin. -static FlPluginRegistrar* fl_view_get_registrar_for_plugin( +static FlPluginRegistrar* fl_engine_get_registrar_for_plugin( FlPluginRegistry* registry, const gchar* name) { FlEngine* self = FL_ENGINE(registry); @@ -189,9 +189,9 @@ static FlPluginRegistrar* fl_view_get_registrar_for_plugin( return fl_plugin_registrar_new(nullptr, self->binary_messenger); } -static void fl_view_plugin_registry_iface_init( +static void fl_engine_plugin_registry_iface_init( FlPluginRegistryInterface* iface) { - iface->get_registrar_for_plugin = fl_view_get_registrar_for_plugin; + iface->get_registrar_for_plugin = fl_engine_get_registrar_for_plugin; } static void fl_engine_dispose(GObject* object) { From 5b55e9088a082f3e18911cae15607b3592ab3d9c Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Tue, 16 Jun 2020 11:49:03 +1200 Subject: [PATCH 3/3] Remove unused include --- shell/platform/linux/fl_renderer_headless.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/platform/linux/fl_renderer_headless.h b/shell/platform/linux/fl_renderer_headless.h index 274a10e543a16..7fac33d818f58 100644 --- a/shell/platform/linux/fl_renderer_headless.h +++ b/shell/platform/linux/fl_renderer_headless.h @@ -5,8 +5,6 @@ #ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ #define FLUTTER_SHELL_PLATFORM_LINUX_FL_RENDERER_HEADLESS_H_ -#include - #include "flutter/shell/platform/linux/fl_renderer.h" G_BEGIN_DECLS