@@ -649,6 +649,18 @@ bool WaylandDisplay::SetupEngine(const std::string &bundle_path, const std::vect
649
649
},
650
650
};
651
651
652
+ // configure platform task runner; render tasks runner will still be provided by flutter
653
+ FlutterTaskRunnerDescription platform_task_runner = {};
654
+ FlutterCustomTaskRunners task_runners = {};
655
+ task_runners.struct_size = sizeof (FlutterCustomTaskRunners);
656
+ task_runners.platform_task_runner = &platform_task_runner;
657
+ if (ConfigurePlatformTaskRunner (&platform_task_runner)) {
658
+ args.custom_task_runners = &task_runners;
659
+ } else {
660
+ dbgE (" Couldn't configure platform task runner\n " );
661
+ exit (1 );
662
+ }
663
+
652
664
std::string libapp_aot_path = bundle_path + " /" + FlutterGetAppAotElfName (); // dw: TODO: There seems to be no convention name we could use, so let's temporary hardcode the path.
653
665
654
666
if (FlutterEngineRunsAOTCompiledDartCode ()) {
@@ -1011,6 +1023,16 @@ ssize_t WaylandDisplay::vSyncSendNotifyData() {
1011
1023
return rv;
1012
1024
}
1013
1025
1026
+ static void set_sleep_to_next_platform_event (const uint64_t timestamp_of_next_platform_event, struct timespec &ts) {
1027
+ if (timestamp_of_next_platform_event == 0 ) {
1028
+ ts = {.tv_sec = LONG_MAX, .tv_nsec = 0 };
1029
+ } else {
1030
+ const uint64_t now = FlutterEngineGetCurrentTime ();
1031
+ const uint64_t time_to_sleep = now <= timestamp_of_next_platform_event ? timestamp_of_next_platform_event - now : 0 ;
1032
+ timespec_from_nsec (&ts, time_to_sleep);
1033
+ }
1034
+ }
1035
+
1014
1036
bool WaylandDisplay::Run () {
1015
1037
if (!valid_) {
1016
1038
dbgE (" Could not run an invalid display.\n " );
@@ -1034,26 +1056,28 @@ bool WaylandDisplay::Run() {
1034
1056
1035
1057
wl_display_flush (display_);
1036
1058
1059
+ uint64_t timestamp_of_next_platform_event_ns = 0 ;
1060
+
1037
1061
do {
1038
- int rv;
1039
1062
1040
- struct pollfd fds[4 ] = {
1063
+ struct timespec ts;
1064
+ set_sleep_to_next_platform_event (timestamp_of_next_platform_event_ns, ts);
1065
+
1066
+ int rv, ppoll_rv;
1067
+
1068
+ struct pollfd fds[5 ] = {
1041
1069
{.fd = vsync.sv_ [vsync.SOCKET_READER ], .events = POLLIN, .revents = 0 },
1042
1070
{.fd = fd, .events = POLLIN | POLLERR, .revents = 0 },
1043
1071
{.fd = key.timer_fd_ , .events = POLLIN | POLLERR, .revents = 0 },
1044
1072
{.fd = memory_watcher_.event_fd , .events = POLLIN | POLLERR, .revents = 0 },
1073
+ {.fd = event_loop_._platform_event_loop_eventfd , .events = POLLIN | POLLERR, .revents = 0 }
1045
1074
};
1046
1075
1047
1076
do {
1048
- static const struct timespec ts = {
1049
- .tv_sec = LONG_MAX,
1050
- .tv_nsec = 0 ,
1051
- };
1052
-
1053
- rv = ppoll (&fds[0 ], std::size (fds), &ts, nullptr );
1054
- } while (rv == -1 && errno == EINTR);
1077
+ ppoll_rv = ppoll (&fds[0 ], std::size (fds), &ts, nullptr );
1078
+ } while (ppoll_rv == -1 && errno == EINTR);
1055
1079
1056
- if (rv == -1 ) {
1080
+ if (ppoll_rv == -1 ) {
1057
1081
printf (" ERROR: ppoll returned -1 (errno: %d)\n " , errno);
1058
1082
return false ;
1059
1083
}
@@ -1115,6 +1139,18 @@ bool WaylandDisplay::Run() {
1115
1139
}
1116
1140
}
1117
1141
1142
+ const bool event_loop_wakeup = fds[4 ].revents & POLLIN;
1143
+ if (event_loop_wakeup) {
1144
+ uint64_t result;
1145
+ do {
1146
+ rv = read (fds[4 ].fd , &result, sizeof result);
1147
+ } while (rv == -1 && errno == EINTR);
1148
+ }
1149
+ // in case of event loop wakeup or if timeout of another event passed - flush events queue
1150
+ if (event_loop_wakeup || ppoll_rv == 0 ) {
1151
+ timestamp_of_next_platform_event_ns = event_loop_._platform_event_loop ->ProcessEvents ();
1152
+ }
1153
+
1118
1154
break ;
1119
1155
} while (true );
1120
1156
@@ -1243,4 +1279,37 @@ bool WaylandDisplay::SetupEGL() {
1243
1279
1244
1280
return true ;
1245
1281
}
1282
+
1283
+ void WaylandDisplay::RunFlutterTask (const FlutterTask *task) {
1284
+ if (!engine_) {
1285
+ dbgE (" FlutterEngineRunTask called before engine was initialized\n " );
1286
+ } else if (FlutterEngineRunTask (engine_, task) != kSuccess ) {
1287
+ dbgW (" FlutterEngineRunTask failed\n " );
1288
+ }
1289
+ }
1290
+
1291
+ bool WaylandDisplay::ConfigurePlatformTaskRunner (FlutterTaskRunnerDescription *task_runner) {
1292
+
1293
+ event_loop_._platform_event_loop_eventfd = eventfd (0 , 0 );
1294
+ if (event_loop_._platform_event_loop_eventfd == -1 ) {
1295
+ dbgE (" Couldn't create platform event loop event.\n " );
1296
+ return false ;
1297
+ }
1298
+
1299
+ event_loop_._platform_event_loop = std::make_unique<PlatformEventLoop>(
1300
+ std::this_thread::get_id (),
1301
+ std::bind (&WaylandDisplay::RunFlutterTask,this ,std::placeholders::_1),
1302
+ event_loop_._platform_event_loop_eventfd );
1303
+
1304
+ task_runner->struct_size = sizeof (FlutterTaskRunnerDescription);
1305
+ task_runner->user_data = event_loop_._platform_event_loop .get ();
1306
+
1307
+ task_runner->runs_task_on_current_thread_callback = [](void *state) -> bool {
1308
+ return reinterpret_cast <PlatformEventLoop *>(state)->RunsTasksOnCurrentThread ();
1309
+ };
1310
+ task_runner->post_task_callback = [](FlutterTask task, uint64_t target_time_nanos, void *state) -> void {
1311
+ reinterpret_cast <PlatformEventLoop *>(state)->PostTask (task, target_time_nanos);
1312
+ };
1313
+ return true ;
1314
+ }
1246
1315
} // namespace flutter
0 commit comments