88
99#include < gmodule.h>
1010
11+ static constexpr int kMicrosecondsPerNanosecond = 1000 ;
12+
13+ // Unique number associated with platform tasks
14+ static constexpr size_t kPlatformTaskRunnerIdentifier = 1 ;
15+
1116struct _FlEngine {
1217 GObject parent_instance;
1318
19+ // Thread the GLib main loop is running on
20+ GThread* thread;
21+
1422 FlDartProject* project;
1523 FlRenderer* renderer;
1624 FLUTTER_API_SYMBOL (FlutterEngine) engine;
@@ -20,7 +28,39 @@ G_DEFINE_QUARK(fl_engine_error_quark, fl_engine_error)
2028
2129G_DEFINE_TYPE(FlEngine, fl_engine, G_TYPE_OBJECT)
2230
23- // Callback from Flutter engine that are passed to the renderer
31+ // Subclass of GSource that integrates Flutter tasks into the GLib main loop
32+ typedef struct {
33+ GSource parent;
34+ FlEngine* self;
35+ FlutterTask task;
36+ } FlutterSource;
37+
38+ // Callback to run a Flutter task in the GLib main loop
39+ static gboolean flutter_source_dispatch (GSource* source,
40+ GSourceFunc callback,
41+ gpointer user_data) {
42+ FlutterSource* fl_source = reinterpret_cast <FlutterSource*>(source);
43+ FlEngine* self = fl_source->self ;
44+
45+ FlutterEngineResult result =
46+ FlutterEngineRunTask (self->engine , &fl_source->task );
47+ if (result != kSuccess )
48+ g_warning (" Failed to run Flutter task\n " );
49+
50+ return G_SOURCE_REMOVE;
51+ }
52+
53+ // Table of functions for Flutter GLib main loop integration
54+ static GSourceFuncs flutter_source_funcs = {
55+ nullptr , // prepare
56+ nullptr , // check
57+ flutter_source_dispatch, // dispatch
58+ nullptr , // finalize
59+ nullptr ,
60+ nullptr // Internal usage
61+ };
62+
63+ // Flutter engine callbacks
2464
2565static void * fl_engine_gl_proc_resolver (void * user_data, const char * name) {
2666 FlEngine* self = static_cast <FlEngine*>(user_data);
@@ -59,6 +99,26 @@ static bool fl_engine_gl_present(void* user_data) {
5999 return result;
60100}
61101
102+ static bool fl_engine_runs_task_on_current_thread (void * user_data) {
103+ FlEngine* self = static_cast <FlEngine*>(user_data);
104+ return self->thread == g_thread_self ();
105+ }
106+
107+ static void fl_engine_post_task_callback (FlutterTask task,
108+ uint64_t target_time_nanos,
109+ void * user_data) {
110+ FlEngine* self = static_cast <FlEngine*>(user_data);
111+
112+ g_autoptr (GSource) source =
113+ g_source_new (&flutter_source_funcs, sizeof (FlutterSource));
114+ FlutterSource* fl_source = reinterpret_cast <FlutterSource*>(source);
115+ fl_source->self = self;
116+ fl_source->task = task;
117+ g_source_set_ready_time (source,
118+ target_time_nanos / kMicrosecondsPerNanosecond );
119+ g_source_attach (source, nullptr );
120+ }
121+
62122static void fl_engine_dispose (GObject* object) {
63123 FlEngine* self = FL_ENGINE (object);
64124
@@ -74,7 +134,9 @@ static void fl_engine_class_init(FlEngineClass* klass) {
74134 G_OBJECT_CLASS (klass)->dispose = fl_engine_dispose;
75135}
76136
77- static void fl_engine_init (FlEngine* self) {}
137+ static void fl_engine_init (FlEngine* self) {
138+ self->thread = g_thread_self ();
139+ }
78140
79141FlEngine* fl_engine_new (FlDartProject* project, FlRenderer* renderer) {
80142 g_return_val_if_fail (FL_IS_DART_PROJECT (project), nullptr );
@@ -102,10 +164,23 @@ gboolean fl_engine_start(FlEngine* self, GError** error) {
102164 config.open_gl .fbo_callback = fl_engine_gl_fbo_callback;
103165 config.open_gl .present = fl_engine_gl_present;
104166
167+ FlutterTaskRunnerDescription platform_task_runner = {};
168+ platform_task_runner.struct_size = sizeof (FlutterTaskRunnerDescription);
169+ platform_task_runner.user_data = self;
170+ platform_task_runner.runs_task_on_current_thread_callback =
171+ fl_engine_runs_task_on_current_thread;
172+ platform_task_runner.post_task_callback = fl_engine_post_task_callback;
173+ platform_task_runner.identifier = kPlatformTaskRunnerIdentifier ;
174+
175+ FlutterCustomTaskRunners custom_task_runners = {};
176+ custom_task_runners.struct_size = sizeof (FlutterCustomTaskRunners);
177+ custom_task_runners.platform_task_runner = &platform_task_runner;
178+
105179 FlutterProjectArgs args = {};
106180 args.struct_size = sizeof (FlutterProjectArgs);
107181 args.assets_path = fl_dart_project_get_assets_path (self->project );
108182 args.icu_data_path = fl_dart_project_get_icu_data_path (self->project );
183+ args.custom_task_runners = &custom_task_runners;
109184
110185 FlutterEngineResult result = FlutterEngineInitialize (
111186 FLUTTER_ENGINE_VERSION, &config, &args, self, &self->engine );
0 commit comments