Flutter Engine
flutter_windows_engine.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/shell/platform/windows/flutter_windows_engine.h"
6 
7 #include <filesystem>
8 #include <iostream>
9 #include <sstream>
10 
11 #include "flutter/shell/platform/common/client_wrapper/binary_messenger_impl.h"
12 #include "flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h"
13 #include "flutter/shell/platform/common/json_message_codec.h"
14 #include "flutter/shell/platform/common/path_utils.h"
15 #include "flutter/shell/platform/windows/flutter_windows_view.h"
16 #include "flutter/shell/platform/windows/string_conversion.h"
17 #include "flutter/shell/platform/windows/system_utils.h"
18 #include "flutter/shell/platform/windows/task_runner.h"
19 #include "third_party/rapidjson/include/rapidjson/document.h"
20 
21 namespace flutter {
22 
23 namespace {
24 
25 // Creates and returns a FlutterRendererConfig that renders to the view (if any)
26 // of a FlutterWindowsEngine, using OpenGL (via ANGLE).
27 // The user_data received by the render callbacks refers to the
28 // FlutterWindowsEngine.
29 FlutterRendererConfig GetOpenGLRendererConfig() {
30  FlutterRendererConfig config = {};
31  config.type = kOpenGL;
32  config.open_gl.struct_size = sizeof(config.open_gl);
33  config.open_gl.make_current = [](void* user_data) -> bool {
34  auto host = static_cast<FlutterWindowsEngine*>(user_data);
35  if (!host->view()) {
36  return false;
37  }
38  return host->view()->MakeCurrent();
39  };
40  config.open_gl.clear_current = [](void* user_data) -> bool {
41  auto host = static_cast<FlutterWindowsEngine*>(user_data);
42  if (!host->view()) {
43  return false;
44  }
45  return host->view()->ClearContext();
46  };
47  config.open_gl.present = [](void* user_data) -> bool {
48  auto host = static_cast<FlutterWindowsEngine*>(user_data);
49  if (!host->view()) {
50  return false;
51  }
52  return host->view()->SwapBuffers();
53  };
54  config.open_gl.fbo_reset_after_present = true;
56  [](void* user_data, const FlutterFrameInfo* info) -> uint32_t {
57  auto host = static_cast<FlutterWindowsEngine*>(user_data);
58  if (host->view()) {
59  return host->view()->GetFrameBufferId(info->size.width,
60  info->size.height);
61  } else {
62  return kWindowFrameBufferID;
63  }
64  };
65  config.open_gl.gl_proc_resolver = [](void* user_data,
66  const char* what) -> void* {
67  return reinterpret_cast<void*>(eglGetProcAddress(what));
68  };
69  config.open_gl.make_resource_current = [](void* user_data) -> bool {
70  auto host = static_cast<FlutterWindowsEngine*>(user_data);
71  if (!host->view()) {
72  return false;
73  }
74  return host->view()->MakeResourceCurrent();
75  };
77  [](void* user_data, int64_t texture_id, size_t width, size_t height,
78  FlutterOpenGLTexture* texture) -> bool {
79  auto host = static_cast<FlutterWindowsEngine*>(user_data);
80  if (!host->texture_registrar()) {
81  return false;
82  }
83  return host->texture_registrar()->PopulateTexture(texture_id, width, height,
84  texture);
85  };
86  return config;
87 }
88 
89 // Creates and returns a FlutterRendererConfig that renders to the view (if any)
90 // of a FlutterWindowsEngine, using software rasterization.
91 // The user_data received by the render callbacks refers to the
92 // FlutterWindowsEngine.
93 FlutterRendererConfig GetSoftwareRendererConfig() {
94  FlutterRendererConfig config = {};
95  config.type = kSoftware;
96  config.software.struct_size = sizeof(config.software);
98  const void* allocation,
99  size_t row_bytes,
100  size_t height) {
101  auto host = static_cast<FlutterWindowsEngine*>(user_data);
102  if (!host->view()) {
103  return false;
104  }
105  return host->view()->PresentSoftwareBitmap(allocation, row_bytes, height);
106  };
107  return config;
108 }
109 
110 // Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage.
112  const FlutterPlatformMessage& engine_message) {
113  FlutterDesktopMessage message = {};
114  message.struct_size = sizeof(message);
115  message.channel = engine_message.channel;
116  message.message = engine_message.message;
117  message.message_size = engine_message.message_size;
118  message.response_handle = engine_message.response_handle;
119  return message;
120 }
121 
122 // Converts a LanguageInfo struct to a FlutterLocale struct. |info| must outlive
123 // the returned value, since the returned FlutterLocale has pointers into it.
124 FlutterLocale CovertToFlutterLocale(const LanguageInfo& info) {
125  FlutterLocale locale = {};
126  locale.struct_size = sizeof(FlutterLocale);
127  locale.language_code = info.language.c_str();
128  if (!info.region.empty()) {
129  locale.country_code = info.region.c_str();
130  }
131  if (!info.script.empty()) {
132  locale.script_code = info.script.c_str();
133  }
134  return locale;
135 }
136 
137 } // namespace
138 
140  : project_(std::make_unique<FlutterProjectBundle>(project)),
141  aot_data_(nullptr, nullptr) {
142  embedder_api_.struct_size = sizeof(FlutterEngineProcTable);
143  FlutterEngineGetProcAddresses(&embedder_api_);
144 
145  task_runner_ = TaskRunner::Create(
146  embedder_api_.GetCurrentTime, [this](const auto* task) {
147  if (!engine_) {
148  std::cerr << "Cannot post an engine task when engine is not running."
149  << std::endl;
150  return;
151  }
152  if (embedder_api_.RunTask(engine_, task) != kSuccess) {
153  std::cerr << "Failed to post an engine task." << std::endl;
154  }
155  });
156 
157  // Set up the legacy structs backing the API handles.
158  messenger_ = std::make_unique<FlutterDesktopMessenger>();
159  messenger_->engine = this;
160  plugin_registrar_ = std::make_unique<FlutterDesktopPluginRegistrar>();
161  plugin_registrar_->engine = this;
162 
163  messenger_wrapper_ = std::make_unique<BinaryMessengerImpl>(messenger_.get());
164  message_dispatcher_ =
165  std::make_unique<IncomingMessageDispatcher>(messenger_.get());
166 
168  texture_registrar_ =
169  std::make_unique<FlutterWindowsTextureRegistrar>(this, gl_procs_);
170  surface_manager_ = AngleSurfaceManager::Create();
171 #ifndef WINUWP
172  window_proc_delegate_manager_ =
173  std::make_unique<WindowProcDelegateManagerWin32>();
174 #endif
175 
176  // Set up internal channels.
177  // TODO: Replace this with an embedder.h API. See
178  // https://github.com/flutter/flutter/issues/71099
179  settings_channel_ =
180  std::make_unique<BasicMessageChannel<rapidjson::Document>>(
181  messenger_wrapper_.get(), "flutter/settings",
183 }
184 
186  Stop();
187 }
188 
190  const std::vector<std::string>& switches) {
191  project_->SetSwitches(switches);
192 }
193 
194 bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
195  if (!project_->HasValidPaths()) {
196  std::cerr << "Missing or unresolvable paths to assets." << std::endl;
197  return false;
198  }
199  std::string assets_path_string = project_->assets_path().u8string();
200  std::string icu_path_string = project_->icu_path().u8string();
201  if (embedder_api_.RunsAOTCompiledDartCode()) {
202  aot_data_ = project_->LoadAotData(embedder_api_);
203  if (!aot_data_) {
204  std::cerr << "Unable to start engine without AOT data." << std::endl;
205  return false;
206  }
207  }
208 
209  // FlutterProjectArgs is expecting a full argv, so when processing it for
210  // flags the first item is treated as the executable and ignored. Add a dummy
211  // value so that all provided arguments are used.
212  std::vector<std::string> switches = project_->GetSwitches();
213  std::vector<const char*> argv = {"placeholder"};
215  switches.begin(), switches.end(), std::back_inserter(argv),
216  [](const std::string& arg) -> const char* { return arg.c_str(); });
217 
218  const std::vector<std::string>& entrypoint_args =
219  project_->dart_entrypoint_arguments();
220  std::vector<const char*> entrypoint_argv;
222  entrypoint_args.begin(), entrypoint_args.end(),
223  std::back_inserter(entrypoint_argv),
224  [](const std::string& arg) -> const char* { return arg.c_str(); });
225 
226  // Configure task runners.
227  FlutterTaskRunnerDescription platform_task_runner = {};
228  platform_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription);
229  platform_task_runner.user_data = task_runner_.get();
230  platform_task_runner.runs_task_on_current_thread_callback =
231  [](void* user_data) -> bool {
232  return static_cast<TaskRunner*>(user_data)->RunsTasksOnCurrentThread();
233  };
234  platform_task_runner.post_task_callback = [](FlutterTask task,
235  uint64_t target_time_nanos,
236  void* user_data) -> void {
237  static_cast<TaskRunner*>(user_data)->PostFlutterTask(task,
238  target_time_nanos);
239  };
240  FlutterCustomTaskRunners custom_task_runners = {};
241  custom_task_runners.struct_size = sizeof(FlutterCustomTaskRunners);
242  custom_task_runners.platform_task_runner = &platform_task_runner;
243 
245  args.struct_size = sizeof(FlutterProjectArgs);
246  args.assets_path = assets_path_string.c_str();
247  args.icu_data_path = icu_path_string.c_str();
248  args.command_line_argc = static_cast<int>(argv.size());
249  args.command_line_argv = argv.size() > 0 ? argv.data() : nullptr;
250  args.dart_entrypoint_argc = static_cast<int>(entrypoint_argv.size());
251  args.dart_entrypoint_argv =
252  entrypoint_argv.size() > 0 ? entrypoint_argv.data() : nullptr;
254  [](const FlutterPlatformMessage* engine_message,
255  void* user_data) -> void {
256  auto host = static_cast<FlutterWindowsEngine*>(user_data);
257  return host->HandlePlatformMessage(engine_message);
258  };
259  args.on_pre_engine_restart_callback = [](void* user_data) {
260  auto host = static_cast<FlutterWindowsEngine*>(user_data);
261  host->view()->OnPreEngineRestart();
262  };
263 
264  args.custom_task_runners = &custom_task_runners;
265 
266  if (aot_data_) {
267  args.aot_data = aot_data_.get();
268  }
269  if (entrypoint) {
270  args.custom_dart_entrypoint = entrypoint;
271  }
272 
273  FlutterRendererConfig renderer_config = surface_manager_
274  ? GetOpenGLRendererConfig()
275  : GetSoftwareRendererConfig();
276 
277  auto result = embedder_api_.Run(FLUTTER_ENGINE_VERSION, &renderer_config,
278  &args, this, &engine_);
279  if (result != kSuccess || engine_ == nullptr) {
280  std::cerr << "Failed to start Flutter engine: error " << result
281  << std::endl;
282  return false;
283  }
284 
285  SendSystemSettings();
286 
287  return true;
288 }
289 
291  if (engine_) {
292  if (plugin_registrar_destruction_callback_) {
293  plugin_registrar_destruction_callback_(plugin_registrar_.get());
294  }
295  FlutterEngineResult result = embedder_api_.Shutdown(engine_);
296  engine_ = nullptr;
297  return (result == kSuccess);
298  }
299  return false;
300 }
301 
303  view_ = view;
304 }
305 
306 // Returns the currently configured Plugin Registrar.
308  return plugin_registrar_.get();
309 }
310 
313  plugin_registrar_destruction_callback_ = callback;
314 }
315 
318  if (engine_) {
319  embedder_api_.SendWindowMetricsEvent(engine_, &event);
320  }
321 }
322 
324  if (engine_) {
325  embedder_api_.SendPointerEvent(engine_, &event, 1);
326  }
327 }
328 
331  void* user_data) {
332  if (engine_) {
333  embedder_api_.SendKeyEvent(engine_, &event, callback, user_data);
334  }
335 }
336 
338  const char* channel,
339  const uint8_t* message,
340  const size_t message_size,
341  const FlutterDesktopBinaryReply reply,
342  void* user_data) {
343  FlutterPlatformMessageResponseHandle* response_handle = nullptr;
344  if (reply != nullptr && user_data != nullptr) {
347  engine_, reply, user_data, &response_handle);
348  if (result != kSuccess) {
349  std::cout << "Failed to create response handle\n";
350  return false;
351  }
352  }
353 
354  FlutterPlatformMessage platform_message = {
355  sizeof(FlutterPlatformMessage),
356  channel,
357  message,
358  message_size,
359  response_handle,
360  };
361 
362  FlutterEngineResult message_result =
363  embedder_api_.SendPlatformMessage(engine_, &platform_message);
364  if (response_handle != nullptr) {
365  embedder_api_.PlatformMessageReleaseResponseHandle(engine_,
366  response_handle);
367  }
368  return message_result == kSuccess;
369 }
370 
373  const uint8_t* data,
374  size_t data_length) {
375  embedder_api_.SendPlatformMessageResponse(engine_, handle, data, data_length);
376 }
377 
379  const FlutterPlatformMessage* engine_message) {
380  if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
381  std::cerr << "Invalid message size received. Expected: "
382  << sizeof(FlutterPlatformMessage) << " but received "
383  << engine_message->struct_size << std::endl;
384  return;
385  }
386 
387  auto message = ConvertToDesktopMessage(*engine_message);
388 
389  message_dispatcher_->HandleMessage(
390  message, [this] {}, [this] {});
391 }
392 
394  embedder_api_.ReloadSystemFonts(engine_);
395 }
396 
398  if (engine_) {
399  SendSystemSettings();
400  }
401 }
402 
403 void FlutterWindowsEngine::SendSystemSettings() {
404  std::vector<LanguageInfo> languages = GetPreferredLanguageInfo();
405  std::vector<FlutterLocale> flutter_locales;
406  flutter_locales.reserve(languages.size());
407  for (const auto& info : languages) {
408  flutter_locales.push_back(CovertToFlutterLocale(info));
409  }
410  // Convert the locale list to the locale pointer list that must be provided.
411  std::vector<const FlutterLocale*> flutter_locale_list;
412  flutter_locale_list.reserve(flutter_locales.size());
414  flutter_locales.begin(), flutter_locales.end(),
415  std::back_inserter(flutter_locale_list),
416  [](const auto& arg) -> const auto* { return &arg; });
417  embedder_api_.UpdateLocales(engine_, flutter_locale_list.data(),
418  flutter_locale_list.size());
419 
420  rapidjson::Document settings(rapidjson::kObjectType);
421  auto& allocator = settings.GetAllocator();
422  settings.AddMember("alwaysUse24HourFormat",
423  Prefer24HourTime(GetUserTimeFormat()), allocator);
424  settings.AddMember("textScaleFactor", 1.0, allocator);
425  settings.AddMember("platformBrightness",
426  Utf8FromUtf16(GetPreferredBrightness()), allocator);
427  settings_channel_->Send(settings);
428 }
429 
431  return (embedder_api_.RegisterExternalTexture(engine_, texture_id) ==
432  kSuccess);
433 }
434 
436  return (embedder_api_.UnregisterExternalTexture(engine_, texture_id) ==
437  kSuccess);
438 }
439 
441  int64_t texture_id) {
442  return (embedder_api_.MarkExternalTextureFrameAvailable(
443  engine_, texture_id) == kSuccess);
444 }
445 
447  uint64_t target,
449  const std::vector<uint8_t>& data) {
450  return (embedder_api_.DispatchSemanticsAction(
451  engine_, target, action, data.data(), data.size()) == kSuccess);
452 }
453 
455  if (engine_ && semantics_enabled_ != enabled) {
456  semantics_enabled_ = enabled;
457  embedder_api_.UpdateSemanticsEnabled(engine_, enabled);
458  }
459 }
460 
461 } // namespace flutter
size_t struct_size
This size of this struct. Must be sizeof(FlutterLocale).
Definition: embedder.h:1152
G_BEGIN_DECLS FlValue * args
FlutterSoftwareRendererConfig software
Definition: embedder.h:558
void SetPluginRegistrarDestructionCallback(FlutterDesktopOnPluginRegistrarDestroyed callback)
const char * channel
Definition: embedder.h:758
if(match !=nullptr)
Definition: fl_engine.cc:79
static std::unique_ptr< AngleSurfaceManager > Create()
FlutterEngineRunsAOTCompiledDartCodeFnPtr RunsAOTCompiledDartCode
Definition: embedder.h:2408
G_BEGIN_DECLS FlTexture * texture
bool RegisterExternalTexture(int64_t texture_id)
FlutterEngineUpdateSemanticsEnabledFnPtr UpdateSemanticsEnabled
Definition: embedder.h:2396
FlutterEngineGetCurrentTimeFnPtr GetCurrentTime
Definition: embedder.h:2405
FlutterEngineRegisterExternalTextureFnPtr RegisterExternalTexture
Definition: embedder.h:2392
const char * icu_data_path
Definition: embedder.h:1378
FlutterEngineRunTaskFnPtr RunTask
Definition: embedder.h:2406
const FlutterPlatformMessageResponseHandle * response_handle
Definition: embedder.h:767
static std::unique_ptr< TaskRunner > Create(CurrentTimeProc get_current_time, const TaskExpiredCallback &on_task_expired)
size_t struct_size
The size of this struct. Must be sizeof(FlutterTaskRunnerDescription).
Definition: embedder.h:913
const FlutterCustomTaskRunners * custom_task_runners
Definition: embedder.h:1493
Function-pointer-based versions of the APIs above.
Definition: embedder.h:2372
bool Prefer24HourTime(std::wstring time_format)
OnPreEngineRestartCallback on_pre_engine_restart_callback
Definition: embedder.h:1591
bool SendPlatformMessage(const char *channel, const uint8_t *message, const size_t message_size, const FlutterDesktopBinaryReply reply, void *user_data)
void * user_data
Definition: ref_ptr.h:252
std::wstring GetPreferredBrightness()
FlutterEngineSendKeyEventFnPtr SendKeyEvent
Definition: embedder.h:2385
FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage
Definition: embedder.h:2386
int64_t texture_id
GAsyncResult * result
FlutterEngineSendPlatformMessageResponseFnPtr SendPlatformMessageResponse
Definition: embedder.h:2391
std::string Utf8FromUtf16(const std::wstring_view utf16_string)
constexpr uint32_t kWindowFrameBufferID
FlutterEngineUnregisterExternalTextureFnPtr UnregisterExternalTexture
Definition: embedder.h:2393
const FlutterDesktopMessageResponseHandle * response_handle
bool MarkExternalTextureFrameAvailable(int64_t texture_id)
UIntFrameInfoCallback fbo_with_frame_info_callback
Definition: embedder.h:437
FlutterWindowsEngine(const FlutterProjectBundle &project)
FlutterPlatformMessageCallback platform_message_callback
Definition: embedder.h:1402
bool RunWithEntrypoint(const char *entrypoint)
void SendPointerEvent(const FlutterPointerEvent &event)
void SetSwitches(const std::vector< std::string > &switches)
FlKeyEvent FlKeyResponderAsyncCallback callback
FlutterEngineUpdateLocalesFnPtr UpdateLocales
Definition: embedder.h:2407
const char *const * command_line_argv
Definition: embedder.h:1396
FlutterDesktopPluginRegistrarRef GetRegistrar()
FlutterEngineRunFnPtr Run
Definition: embedder.h:2378
FlutterSemanticsAction
Definition: embedder.h:101
size_t struct_size
The size of this struct. Must be sizeof(FlutterEngineProcs).
Definition: embedder.h:2374
FlKeyEvent * event
const char * script_code
Definition: embedder.h:1166
const char * country_code
Definition: embedder.h:1161
const char *const * dart_entrypoint_argv
Definition: embedder.h:1566
bool UnregisterExternalTexture(int64_t texture_id)
FlutterEnginePlatformMessageCreateResponseHandleFnPtr PlatformMessageCreateResponseHandle
Definition: embedder.h:2388
std::wstring GetUserTimeFormat()
void SendWindowMetricsEvent(const FlutterWindowMetricsEvent &event)
#define FLUTTER_ENGINE_VERSION
Definition: embedder.h:63
FlutterRendererType type
Definition: embedder.h:555
uint32_t * target
const uint8_t * message
Definition: embedder.h:759
FlutterEnginePlatformMessageReleaseResponseHandleFnPtr PlatformMessageReleaseResponseHandle
Definition: embedder.h:2390
size_t struct_size
The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Definition: embedder.h:388
FlutterEngineReloadSystemFontsFnPtr ReloadSystemFonts
Definition: embedder.h:2400
SemanticsAction action
BoolCallback make_resource_current
Definition: embedder.h:407
static FlutterDesktopMessage ConvertToDesktopMessage(const FlutterPlatformMessage &engine_message)
BoolCallback clear_current
Definition: embedder.h:390
TextureFrameCallback gl_external_texture_frame_callback
Definition: embedder.h:429
int32_t width
FlutterEngineResult FlutterEngineGetProcAddresses(FlutterEngineProcTable *table)
Gets the table of engine function pointers.
Definition: embedder.cc:2291
static const JsonMessageCodec & GetInstance()
const uint8_t * message
FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent
Definition: embedder.h:2383
FlutterEngineMarkExternalTextureFrameAvailableFnPtr MarkExternalTextureFrameAvailable
Definition: embedder.h:2395
int32_t height
const char * custom_dart_entrypoint
Definition: embedder.h:1488
const char * assets_path
Definition: embedder.h:1354
BoolCallback make_current
Definition: embedder.h:389
FlutterOpenGLRendererConfig open_gl
Definition: embedder.h:557
void SendKeyEvent(const FlutterKeyEvent &event, FlutterKeyEventCallback callback, void *user_data)
FlutterEngineShutdownFnPtr Shutdown
Definition: embedder.h:2379
std::vector< LanguageInfo > GetPreferredLanguageInfo()
FlutterEngineResult
Definition: embedder.h:65
size_t struct_size
The size of this struct. Must be sizeof(FlutterProjectArgs).
Definition: embedder.h:1350
FlutterEngineDispatchSemanticsActionFnPtr DispatchSemanticsAction
Definition: embedder.h:2398
void SendPlatformMessageResponse(const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
const FlutterTaskRunnerDescription * platform_task_runner
Definition: embedder.h:943
void HandlePlatformMessage(const FlutterPlatformMessage *)
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
void(* FlutterKeyEventCallback)(bool, void *)
Definition: embedder.h:748
FlutterEngineAOTData aot_data
Definition: embedder.h:1543
ProcResolver gl_proc_resolver
Definition: embedder.h:424
size_t struct_size
The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
Definition: embedder.h:938
size_t struct_size
The size of this struct. Must be sizeof(FlutterPlatformMessage).
Definition: embedder.h:757
const char * language_code
Definition: embedder.h:1156
FlutterEngineSendPointerEventFnPtr SendPointerEvent
Definition: embedder.h:2384
void SetView(FlutterWindowsView *view)
int command_line_argc
The command line argument count used to initialize the project.
Definition: embedder.h:1380
size_t struct_size
The size of this struct. Must be sizeof(FlutterSoftwareRendererConfig).
Definition: embedder.h:546
SoftwareSurfacePresentCallback surface_present_callback
Definition: embedder.h:551
bool DispatchSemanticsAction(uint64_t id, FlutterSemanticsAction action, const std::vector< uint8_t > &data)