• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // 2021.2.10 Framework adapted to ACE.
5 //           Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
6 
7 #define FML_USED_ON_EMBEDDER
8 
9 #include "flutter/fml/build_config.h"
10 #include "flutter/fml/make_copyable.h"
11 #include "flutter/fml/native_library.h"
12 
13 #if OS_WIN
14 #define FLUTTER_EXPORT __declspec(dllexport)
15 #else  // OS_WIN
16 #define FLUTTER_EXPORT __attribute__((visibility("default")))
17 #endif  // OS_WIN
18 
19 extern "C" {
20 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
21 // Used for debugging dart:* sources.
22 extern const uint8_t kPlatformStrongDill[];
23 extern const intptr_t kPlatformStrongDillSize;
24 #endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
25 }
26 
27 #include "flutter/assets/directory_asset_bundle.h"
28 #include "flutter/common/task_runners.h"
29 #include "flutter/fml/command_line.h"
30 #include "flutter/fml/file.h"
31 #include "flutter/fml/make_copyable.h"
32 #include "flutter/fml/message_loop.h"
33 #include "flutter/fml/paths.h"
34 #include "flutter/fml/trace_event.h"
35 #include "flutter/shell/common/persistent_cache.h"
36 #include "flutter/shell/common/rasterizer.h"
37 #include "flutter/shell/common/switches.h"
38 #include "flutter/shell/platform/embedder/embedder.h"
39 #include "flutter/shell/platform/embedder/embedder_engine.h"
40 #include "flutter/shell/platform/embedder/embedder_platform_message_response.h"
41 #include "flutter/shell/platform/embedder/embedder_render_target.h"
42 #include "flutter/shell/platform/embedder/embedder_safe_access.h"
43 #include "flutter/shell/platform/embedder/embedder_task_runner.h"
44 #include "flutter/shell/platform/embedder/embedder_thread_host.h"
45 #include "flutter/shell/platform/embedder/platform_view_embedder.h"
46 
47 #include <iostream>
48 
49 #ifdef USE_GLFW_WINDOW
50 namespace {
51 
52 HandleTouchEventCallback g_HandleTouchEventCallback;
53 
54 }
55 #endif
56 
LogEmbedderError(FlutterEngineResult code,const char * name,const char * function,const char * file,int line)57 static FlutterEngineResult LogEmbedderError(FlutterEngineResult code,
58                                             const char* name,
59                                             const char* function,
60                                             const char* file,
61                                             int line) {
62   FML_LOG(ERROR) << "Returning error '" << name << "' (" << code
63                  << ") from Flutter Embedder API call to '" << function
64                  << "'. Origin: " << file << ":" << line;
65   return code;
66 }
67 
68 #define LOG_EMBEDDER_ERROR(code) \
69   LogEmbedderError(code, #code, __FUNCTION__, __FILE__, __LINE__)
70 
IsOpenGLRendererConfigValid(const FlutterRendererConfig * config)71 static bool IsOpenGLRendererConfigValid(const FlutterRendererConfig* config) {
72   if (config->type != kOpenGL) {
73     return false;
74   }
75 
76   const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
77 
78   if (SAFE_ACCESS(open_gl_config, make_current, nullptr) == nullptr ||
79       SAFE_ACCESS(open_gl_config, clear_current, nullptr) == nullptr ||
80       SAFE_ACCESS(open_gl_config, present, nullptr) == nullptr ||
81       SAFE_ACCESS(open_gl_config, fbo_callback, nullptr) == nullptr) {
82     return false;
83   }
84 
85   return true;
86 }
87 
IsSoftwareRendererConfigValid(const FlutterRendererConfig * config)88 static bool IsSoftwareRendererConfigValid(const FlutterRendererConfig* config) {
89   if (config->type != kSoftware) {
90     return false;
91   }
92 
93   const FlutterSoftwareRendererConfig* software_config = &config->software;
94 
95   if (SAFE_ACCESS(software_config, surface_present_callback, nullptr) ==
96       nullptr) {
97     return false;
98   }
99 
100   return true;
101 }
102 
IsRendererValid(const FlutterRendererConfig * config)103 static bool IsRendererValid(const FlutterRendererConfig* config) {
104   if (config == nullptr) {
105     return false;
106   }
107 
108   switch (config->type) {
109     case kOpenGL:
110       return IsOpenGLRendererConfigValid(config);
111     case kSoftware:
112       return IsSoftwareRendererConfigValid(config);
113     default:
114       return false;
115   }
116 
117   return false;
118 }
119 
120 #if OS_LINUX || OS_WIN
DefaultGLProcResolver(const char * name)121 static void* DefaultGLProcResolver(const char* name) {
122   static fml::RefPtr<fml::NativeLibrary> proc_library =
123 #if OS_LINUX
124       fml::NativeLibrary::CreateForCurrentProcess();
125 #elif OS_WIN  // OS_LINUX
126       fml::NativeLibrary::Create("opengl32.dll");
127 #endif        // OS_WIN
128   return static_cast<void*>(
129       const_cast<uint8_t*>(proc_library->ResolveSymbol(name)));
130 }
131 #endif  // OS_LINUX || OS_WIN
132 
133 static flutter::Shell::CreateCallback<flutter::PlatformView>
InferOpenGLPlatformViewCreationCallback(const FlutterRendererConfig * config,void * user_data,flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,std::unique_ptr<flutter::EmbedderExternalViewEmbedder> external_view_embedder)134 InferOpenGLPlatformViewCreationCallback(
135     const FlutterRendererConfig* config,
136     void* user_data,
137     flutter::PlatformViewEmbedder::PlatformDispatchTable
138         platform_dispatch_table,
139     std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
140         external_view_embedder) {
141   if (config->type != kOpenGL) {
142     return nullptr;
143   }
144 
145   auto gl_make_current = [ptr = config->open_gl.make_current,
146                           user_data]() -> bool { return ptr(user_data); };
147 
148   auto gl_clear_current = [ptr = config->open_gl.clear_current,
149                            user_data]() -> bool { return ptr(user_data); };
150 
151   auto gl_present = [ptr = config->open_gl.present, user_data]() -> bool {
152     return ptr(user_data);
153   };
154 
155   auto gl_send_surface = [ptr = config->open_gl.send_current_surface,
156                           user_data](const void* pixels, const size_t size,
157                                      const int32_t width,
158                                      const int32_t height) -> bool {
159     return ptr(pixels, size, width, height);
160   };
161 
162   auto gl_fbo_callback = [ptr = config->open_gl.fbo_callback,
163                           user_data]() -> intptr_t { return ptr(user_data); };
164 
165   const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
166   std::function<bool()> gl_make_resource_current_callback = nullptr;
167   if (SAFE_ACCESS(open_gl_config, make_resource_current, nullptr) != nullptr) {
168     gl_make_resource_current_callback =
169         [ptr = config->open_gl.make_resource_current, user_data]() {
170           return ptr(user_data);
171         };
172   }
173 
174   std::function<SkMatrix(void)> gl_surface_transformation_callback = nullptr;
175   if (SAFE_ACCESS(open_gl_config, surface_transformation, nullptr) != nullptr) {
176     gl_surface_transformation_callback =
177         [ptr = config->open_gl.surface_transformation, user_data]() {
178           FlutterTransformation transformation = ptr(user_data);
179           return SkMatrix::MakeAll(transformation.scaleX,  //
180                                    transformation.skewX,   //
181                                    transformation.transX,  //
182                                    transformation.skewY,   //
183                                    transformation.scaleY,  //
184                                    transformation.transY,  //
185                                    transformation.pers0,   //
186                                    transformation.pers1,   //
187                                    transformation.pers2    //
188           );
189         };
190   }
191 
192   flutter::GPUSurfaceGLDelegate::GLProcResolver gl_proc_resolver = nullptr;
193   if (SAFE_ACCESS(open_gl_config, gl_proc_resolver, nullptr) != nullptr) {
194     gl_proc_resolver = [ptr = config->open_gl.gl_proc_resolver,
195                         user_data](const char* gl_proc_name) {
196       return ptr(user_data, gl_proc_name);
197     };
198   } else {
199 #if OS_LINUX || OS_WIN
200     gl_proc_resolver = DefaultGLProcResolver;
201 #endif
202   }
203 
204   bool fbo_reset_after_present =
205       SAFE_ACCESS(open_gl_config, fbo_reset_after_present, false);
206 
207   flutter::EmbedderSurfaceGL::GLDispatchTable gl_dispatch_table = {
208       gl_make_current,                     // gl_make_current_callback
209       gl_clear_current,                    // gl_clear_current_callback
210       gl_present,                          // gl_present_callback
211       gl_send_surface,                     // gl_send_surface_callback
212       gl_fbo_callback,                     // gl_fbo_callback
213       gl_make_resource_current_callback,   // gl_make_resource_current_callback
214       gl_surface_transformation_callback,  // gl_surface_transformation_callback
215       gl_proc_resolver,                    // gl_proc_resolver
216   };
217 
218   return fml::MakeCopyable(
219       [gl_dispatch_table, fbo_reset_after_present, platform_dispatch_table,
220        external_view_embedder =
221            std::move(external_view_embedder)](flutter::Shell& shell) mutable {
222         return std::make_unique<flutter::PlatformViewEmbedder>(
223             shell,                    // delegate
224             shell.GetTaskRunners(),   // task runners
225             gl_dispatch_table,        // embedder GL dispatch table
226             fbo_reset_after_present,  // fbo reset after present
227             platform_dispatch_table,  // embedder platform dispatch table
228             std::move(external_view_embedder)  // external view embedder
229         );
230       });
231 }
232 
233 static flutter::Shell::CreateCallback<flutter::PlatformView>
InferSoftwarePlatformViewCreationCallback(const FlutterRendererConfig * config,void * user_data,flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,std::unique_ptr<flutter::EmbedderExternalViewEmbedder> external_view_embedder)234 InferSoftwarePlatformViewCreationCallback(
235     const FlutterRendererConfig* config,
236     void* user_data,
237     flutter::PlatformViewEmbedder::PlatformDispatchTable
238         platform_dispatch_table,
239     std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
240         external_view_embedder) {
241   if (config->type != kSoftware) {
242     return nullptr;
243   }
244 
245   auto software_present_backing_store =
246       [ptr = config->software.surface_present_callback, user_data](
247           const void* allocation, size_t row_bytes, size_t height) -> bool {
248     return ptr(user_data, allocation, row_bytes, height);
249   };
250 
251   flutter::EmbedderSurfaceSoftware::SoftwareDispatchTable
252       software_dispatch_table = {
253           software_present_backing_store,  // required
254       };
255 
256   return fml::MakeCopyable(
257       [software_dispatch_table, platform_dispatch_table,
258        external_view_embedder =
259            std::move(external_view_embedder)](flutter::Shell& shell) mutable {
260         return std::make_unique<flutter::PlatformViewEmbedder>(
261             shell,                             // delegate
262             shell.GetTaskRunners(),            // task runners
263             software_dispatch_table,           // software dispatch table
264             platform_dispatch_table,           // platform dispatch table
265             std::move(external_view_embedder)  // external view embedder
266         );
267       });
268 }
269 
270 static flutter::Shell::CreateCallback<flutter::PlatformView>
InferPlatformViewCreationCallback(const FlutterRendererConfig * config,void * user_data,flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,std::unique_ptr<flutter::EmbedderExternalViewEmbedder> external_view_embedder)271 InferPlatformViewCreationCallback(
272     const FlutterRendererConfig* config,
273     void* user_data,
274     flutter::PlatformViewEmbedder::PlatformDispatchTable
275         platform_dispatch_table,
276     std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
277         external_view_embedder) {
278   if (config == nullptr) {
279     return nullptr;
280   }
281 
282   switch (config->type) {
283     case kOpenGL:
284       return InferOpenGLPlatformViewCreationCallback(
285           config, user_data, platform_dispatch_table,
286           std::move(external_view_embedder));
287     case kSoftware:
288       return InferSoftwarePlatformViewCreationCallback(
289           config, user_data, platform_dispatch_table,
290           std::move(external_view_embedder));
291     default:
292       return nullptr;
293   }
294   return nullptr;
295 }
296 
MakeSkSurfaceFromBackingStore(GrContext * context,const FlutterBackingStoreConfig & config,const FlutterOpenGLTexture * texture)297 static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
298     GrContext* context,
299     const FlutterBackingStoreConfig& config,
300     const FlutterOpenGLTexture* texture) {
301   GrGLTextureInfo texture_info;
302   texture_info.fTarget = texture->target;
303   texture_info.fID = texture->name;
304   texture_info.fFormat = texture->format;
305 
306   GrBackendTexture backend_texture(config.size.width,   //
307                                    config.size.height,  //
308                                    GrMipMapped::kNo,    //
309                                    texture_info         //
310   );
311 
312   SkSurfaceProps surface_properties(
313       SkSurfaceProps::InitType::kLegacyFontHost_InitType);
314 
315   auto surface = SkSurface::MakeFromBackendTexture(
316       context,                   // context
317       backend_texture,           // back-end texture
318       kTopLeft_GrSurfaceOrigin,  // surface origin
319       1,                         // sample count
320       kN32_SkColorType,          // color type
321       SkColorSpace::MakeSRGB(),  // color space
322       &surface_properties,       // surface properties
323       static_cast<SkSurface::TextureReleaseProc>(
324           texture->destruction_callback),  // release proc
325       texture->user_data                   // release context
326   );
327 
328   if (!surface) {
329     FML_LOG(ERROR) << "Could not wrap embedder supplied render texture.";
330     texture->destruction_callback(texture->user_data);
331     return nullptr;
332   }
333 
334   return surface;
335 }
336 
MakeSkSurfaceFromBackingStore(GrContext * context,const FlutterBackingStoreConfig & config,const FlutterOpenGLFramebuffer * framebuffer)337 static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
338     GrContext* context,
339     const FlutterBackingStoreConfig& config,
340     const FlutterOpenGLFramebuffer* framebuffer) {
341   GrGLFramebufferInfo framebuffer_info = {};
342   framebuffer_info.fFormat = framebuffer->target;
343   framebuffer_info.fFBOID = framebuffer->name;
344 
345   GrBackendRenderTarget backend_render_target(
346       config.size.width,   // width
347       config.size.height,  // height
348       1,                   // sample count
349       0,                   // stencil bits
350       framebuffer_info     // framebuffer info
351   );
352 
353   SkSurfaceProps surface_properties(
354       SkSurfaceProps::InitType::kLegacyFontHost_InitType);
355 
356   auto surface = SkSurface::MakeFromBackendRenderTarget(
357       context,                   //  context
358       backend_render_target,     // backend render target
359       kTopLeft_GrSurfaceOrigin,  // surface origin
360       kN32_SkColorType,          // color type
361       SkColorSpace::MakeSRGB(),  // color space
362       &surface_properties,       // surface properties
363       static_cast<SkSurface::RenderTargetReleaseProc>(
364           framebuffer->destruction_callback),  // release proc
365       framebuffer->user_data                   // release context
366   );
367 
368   if (!surface) {
369     FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
370     framebuffer->destruction_callback(framebuffer->user_data);
371     return nullptr;
372   }
373   return surface;
374 }
375 
MakeSkSurfaceFromBackingStore(GrContext * context,const FlutterBackingStoreConfig & config,const FlutterSoftwareBackingStore * software)376 static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
377     GrContext* context,
378     const FlutterBackingStoreConfig& config,
379     const FlutterSoftwareBackingStore* software) {
380   const auto image_info =
381       SkImageInfo::MakeN32Premul(config.size.width, config.size.height);
382 
383   struct Captures {
384     VoidCallback destruction_callback;
385     void* user_data;
386   };
387   auto captures = std::make_unique<Captures>();
388   captures->destruction_callback = software->destruction_callback;
389   captures->user_data = software->user_data;
390   auto release_proc = [](void* pixels, void* context) {
391     auto captures = reinterpret_cast<Captures*>(context);
392     captures->destruction_callback(captures->user_data);
393   };
394 
395   auto surface = SkSurface::MakeRasterDirectReleaseProc(
396       image_info,                               // image info
397       const_cast<void*>(software->allocation),  // pixels
398       software->row_bytes,                      // row bytes
399       release_proc,                             // release proc
400       captures.release()                        // release context
401   );
402 
403   if (!surface) {
404     FML_LOG(ERROR)
405         << "Could not wrap embedder supplied software render buffer.";
406     software->destruction_callback(software->user_data);
407     return nullptr;
408   }
409   return surface;
410 }
411 
412 static std::unique_ptr<flutter::EmbedderRenderTarget>
CreateEmbedderRenderTarget(const FlutterCompositor * compositor,const FlutterBackingStoreConfig & config,GrContext * context)413 CreateEmbedderRenderTarget(const FlutterCompositor* compositor,
414                            const FlutterBackingStoreConfig& config,
415                            GrContext* context) {
416   FlutterBackingStore backing_store = {};
417   backing_store.struct_size = sizeof(backing_store);
418 
419   // Safe access checks on the compositor struct have been performed in
420   // InferExternalViewEmbedderFromArgs and are not necessary here.
421   auto c_create_callback = compositor->create_backing_store_callback;
422   auto c_collect_callback = compositor->collect_backing_store_callback;
423 
424   if (!c_create_callback(&config, &backing_store, compositor->user_data)) {
425     FML_LOG(ERROR) << "Could not create the embedder backing store.";
426     return nullptr;
427   }
428 
429   if (backing_store.struct_size != sizeof(backing_store)) {
430     FML_LOG(ERROR) << "Embedder modified the backing store struct size.";
431     return nullptr;
432   }
433 
434   // In case we return early without creating an embedder render target, the
435   // embedder has still given us ownership of its baton which we must return
436   // back to it. If this method is successful, the closure is released when the
437   // render target is eventually released.
438   fml::ScopedCleanupClosure collect_callback(
439       [c_collect_callback, backing_store, user_data = compositor->user_data]() {
440         c_collect_callback(&backing_store, user_data);
441       });
442 
443   // No safe access checks on the renderer are necessary since we allocated
444   // the struct.
445 
446   sk_sp<SkSurface> render_surface;
447 
448   switch (backing_store.type) {
449     case kFlutterBackingStoreTypeOpenGL:
450       switch (backing_store.open_gl.type) {
451         case kFlutterOpenGLTargetTypeTexture:
452           render_surface = MakeSkSurfaceFromBackingStore(
453               context, config, &backing_store.open_gl.texture);
454           break;
455         case kFlutterOpenGLTargetTypeFramebuffer:
456           render_surface = MakeSkSurfaceFromBackingStore(
457               context, config, &backing_store.open_gl.framebuffer);
458           break;
459       }
460       break;
461     case kFlutterBackingStoreTypeSoftware:
462       render_surface = MakeSkSurfaceFromBackingStore(context, config,
463                                                      &backing_store.software);
464       break;
465   };
466 
467   if (!render_surface) {
468     FML_LOG(ERROR) << "Could not create a surface from an embedder provided "
469                       "render target.";
470     return nullptr;
471   }
472 
473   return std::make_unique<flutter::EmbedderRenderTarget>(
474       backing_store, std::move(render_surface), collect_callback.Release());
475 }
476 
477 static std::pair<std::unique_ptr<flutter::EmbedderExternalViewEmbedder>,
478                  bool /* halt engine launch if true */>
InferExternalViewEmbedderFromArgs(const FlutterCompositor * compositor)479 InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor) {
480   if (compositor == nullptr) {
481     return {nullptr, false};
482   }
483 
484   auto c_create_callback =
485       SAFE_ACCESS(compositor, create_backing_store_callback, nullptr);
486   auto c_collect_callback =
487       SAFE_ACCESS(compositor, collect_backing_store_callback, nullptr);
488   auto c_present_callback =
489       SAFE_ACCESS(compositor, present_layers_callback, nullptr);
490 
491   // Make sure the required callbacks are present
492   if (!c_create_callback || !c_collect_callback || !c_present_callback) {
493     FML_LOG(ERROR) << "Required compositor callbacks absent.";
494     return {nullptr, true};
495   }
496 
497   FlutterCompositor captured_compositor = *compositor;
498 
499   flutter::EmbedderExternalViewEmbedder::CreateRenderTargetCallback
500       create_render_target_callback =
501           [captured_compositor](GrContext* context, const auto& config) {
502             return CreateEmbedderRenderTarget(&captured_compositor, config,
503                                               context);
504           };
505 
506   flutter::EmbedderExternalViewEmbedder::PresentCallback present_callback =
507       [c_present_callback,
508        user_data = compositor->user_data](const auto& layers) {
509         return c_present_callback(
510             const_cast<const FlutterLayer**>(layers.data()), layers.size(),
511             user_data);
512       };
513 
514   return {std::make_unique<flutter::EmbedderExternalViewEmbedder>(
515               create_render_target_callback, present_callback),
516           false};
517 }
518 
519 struct _FlutterPlatformMessageResponseHandle {
520   fml::RefPtr<flutter::PlatformMessage> message;
521 };
522 
FlutterEngineRun(const FlutterRendererConfig * config,const FlutterProjectArgs * args,void * user_data,FLUTTER_API_SYMBOL (FlutterEngine)* engine_out)523 FlutterEngineResult FlutterEngineRun(const FlutterRendererConfig* config,
524                                      const FlutterProjectArgs* args,
525                                      void* user_data,
526                                      FLUTTER_API_SYMBOL(FlutterEngine) *
527                                          engine_out) {
528   auto result =
529       FlutterEngineInitialize(config, args, user_data, engine_out);
530 
531   if (result != kSuccess) {
532     return result;
533   }
534 
535   return FlutterEngineRunInitialized(*engine_out);
536 }
537 
FlutterEngineInitialize(const FlutterRendererConfig * config,const FlutterProjectArgs * args,void * user_data,FLUTTER_API_SYMBOL (FlutterEngine)* engine_out)538 FlutterEngineResult FlutterEngineInitialize(const FlutterRendererConfig* config,
539                                             const FlutterProjectArgs* args,
540                                             void* user_data,
541                                             FLUTTER_API_SYMBOL(FlutterEngine) *
542                                                 engine_out) {
543   // Step 0: Figure out arguments for shell creation.
544   if (engine_out == nullptr) {
545     return LOG_EMBEDDER_ERROR(kInvalidArguments);
546   }
547 
548   if (args == nullptr) {
549     return LOG_EMBEDDER_ERROR(kInvalidArguments);
550   }
551 
552   if (!IsRendererValid(config)) {
553     FML_LOG(WARNING) << "Invalid renderer config.";
554     return LOG_EMBEDDER_ERROR(kInvalidArguments);
555   }
556 
557   flutter::Settings settings;
558   settings.task_observer_add = [](intptr_t key, fml::closure callback) {
559     fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
560   };
561   settings.task_observer_remove = [](intptr_t key) {
562     fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
563   };
564 
565   flutter::VsyncWaiterEmbedder::VsyncCallback vsync_callback = nullptr;
566   if (SAFE_ACCESS(args, vsync_callback, nullptr) != nullptr) {
567     vsync_callback = [ptr = args->vsync_callback, user_data](intptr_t baton) {
568       return ptr(user_data, baton);
569     };
570   }
571 
572   auto external_view_embedder_result =
573       InferExternalViewEmbedderFromArgs(SAFE_ACCESS(args, compositor, nullptr));
574   if (external_view_embedder_result.second) {
575     return LOG_EMBEDDER_ERROR(kInvalidArguments);
576   }
577 
578   flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table =
579       {
580           vsync_callback,
581       };
582 
583   auto on_create_platform_view = InferPlatformViewCreationCallback(
584       config, user_data, platform_dispatch_table,
585       std::move(external_view_embedder_result.first));
586 
587   if (!on_create_platform_view) {
588     return LOG_EMBEDDER_ERROR(kInvalidArguments);
589   }
590 
591   flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
592       [](flutter::Shell& shell) {
593         return std::make_unique<flutter::Rasterizer>(shell,
594                                                      shell.GetTaskRunners());
595       };
596 
597   // TODO(chinmaygarde): This is the wrong spot for this. It belongs in the
598   // platform view jump table.
599   flutter::EmbedderExternalTextureGL::ExternalTextureCallback
600       external_texture_callback;
601   if (config->type == kOpenGL) {
602     const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
603     if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
604                     nullptr) != nullptr) {
605       external_texture_callback =
606           [ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
607               int64_t texture_identifier, GrContext* context,
608               const SkISize& size) -> sk_sp<SkImage> {
609         FlutterOpenGLTexture texture = {};
610 
611         if (!ptr(user_data, texture_identifier, size.width(), size.height(),
612                  &texture)) {
613           return nullptr;
614         }
615 
616         GrGLTextureInfo gr_texture_info = {texture.target, texture.name,
617                                            texture.format};
618 
619         GrBackendTexture gr_backend_texture(size.width(), size.height(),
620                                             GrMipMapped::kNo, gr_texture_info);
621         SkImage::TextureReleaseProc release_proc = texture.destruction_callback;
622         auto image = SkImage::MakeFromTexture(
623             context,                   // context
624             gr_backend_texture,        // texture handle
625             kTopLeft_GrSurfaceOrigin,  // origin
626             kRGBA_8888_SkColorType,    // color type
627             kPremul_SkAlphaType,       // alpha type
628             nullptr,                   // colorspace
629             release_proc,              // texture release proc
630             texture.user_data          // texture release context
631         );
632 
633         if (!image) {
634           // In case Skia rejects the image, call the release proc so that
635           // embedders can perform collection of intermediates.
636           if (release_proc) {
637             release_proc(texture.user_data);
638           }
639           FML_LOG(ERROR) << "Could not create external texture.";
640           return nullptr;
641         }
642 
643         return image;
644       };
645     }
646   }
647 
648   auto thread_host =
649       flutter::EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(
650           SAFE_ACCESS(args, custom_task_runners, nullptr));
651 
652   if (!thread_host || !thread_host->IsValid()) {
653     FML_LOG(ERROR) << "Could not setup or infer thread configuration to run "
654                       "the Flutter engine on.";
655     return LOG_EMBEDDER_ERROR(kInvalidArguments);
656   }
657 
658   auto task_runners = thread_host->GetTaskRunners();
659 
660   if (!task_runners.IsValid()) {
661     FML_LOG(ERROR) << "Task runner configuration specified is invalid.";
662     return LOG_EMBEDDER_ERROR(kInvalidArguments);
663   }
664 
665   flutter::RunConfiguration run_configuration;
666   // Create the engine but don't launch the shell or run the root isolate.
667   auto embedder_engine = std::make_unique<flutter::EmbedderEngine>(
668       std::move(thread_host),        //
669       std::move(task_runners),       //
670       std::move(settings),           //
671       std::move(run_configuration),  //
672       on_create_platform_view,       //
673       on_create_rasterizer,          //
674       external_texture_callback      //
675   );
676 
677   // Release the ownership of the embedder engine to the caller.
678   *engine_out = reinterpret_cast<FLUTTER_API_SYMBOL(FlutterEngine)>(
679       embedder_engine.release());
680   return kSuccess;
681 }
682 
FlutterEngineRunInitialized(FLUTTER_API_SYMBOL (FlutterEngine)engine)683 FlutterEngineResult FlutterEngineRunInitialized(
684     FLUTTER_API_SYMBOL(FlutterEngine) engine) {
685   if (!engine) {
686     return LOG_EMBEDDER_ERROR(kInvalidArguments);
687   }
688 
689   auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
690 
691   // The engine must not already be running. Initialize may only be called once
692   // on an engine instance.
693   if (embedder_engine->IsValid()) {
694     return LOG_EMBEDDER_ERROR(kInvalidArguments);
695   }
696 
697   // Step 1: Launch the shell.
698   if (!embedder_engine->LaunchShell()) {
699     FML_LOG(ERROR) << "Could not launch the engine using supplied "
700                       "initialization arguments.";
701     return LOG_EMBEDDER_ERROR(kInvalidArguments);
702   }
703 
704   // Step 2: Tell the platform view to initialize itself.
705   if (!embedder_engine->NotifyCreated()) {
706     return LOG_EMBEDDER_ERROR(kInvalidArguments);
707   }
708 
709   // Step 3: Launch the root isolate.
710   if (!embedder_engine->RunRootIsolate()) {
711     return LOG_EMBEDDER_ERROR(kInvalidArguments);
712   }
713 
714   return kSuccess;
715 }
716 
717 FLUTTER_EXPORT
FlutterEngineDeinitialize(FLUTTER_API_SYMBOL (FlutterEngine)engine)718 FlutterEngineResult FlutterEngineDeinitialize(FLUTTER_API_SYMBOL(FlutterEngine)
719                                                   engine) {
720   if (engine == nullptr) {
721     return LOG_EMBEDDER_ERROR(kInvalidArguments);
722   }
723   auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
724   embedder_engine->NotifyDestroyed();
725   embedder_engine->CollectShell();
726   return kSuccess;
727 }
728 
FlutterEngineShutdown(FLUTTER_API_SYMBOL (FlutterEngine)engine)729 FlutterEngineResult FlutterEngineShutdown(FLUTTER_API_SYMBOL(FlutterEngine)
730                                               engine) {
731   auto result = FlutterEngineDeinitialize(engine);
732   if (result != kSuccess) {
733     return result;
734   }
735   auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
736   delete embedder_engine;
737   return kSuccess;
738 }
739 
FlutterEngineSetIdleNotificationCallback(FLUTTER_API_SYMBOL (FlutterEngine)engine,const IdleCallback & idle_notification_callback)740 FlutterEngineResult FlutterEngineSetIdleNotificationCallback(
741     FLUTTER_API_SYMBOL(FlutterEngine) engine,
742     const IdleCallback& idle_notification_callback) {
743     if (engine == nullptr || idle_notification_callback == nullptr) {
744         return LOG_EMBEDDER_ERROR(kInvalidArguments);
745     }
746 
747     return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetIdleNotificationCallback(
748         idle_notification_callback)
749            ? kSuccess
750            : LOG_EMBEDDER_ERROR(kInvalidArguments);
751 }
752 
FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterWindowMetricsEvent * flutter_metrics)753 FlutterEngineResult FlutterEngineSendWindowMetricsEvent(
754     FLUTTER_API_SYMBOL(FlutterEngine) engine,
755     const FlutterWindowMetricsEvent* flutter_metrics) {
756   if (engine == nullptr || flutter_metrics == nullptr) {
757     return LOG_EMBEDDER_ERROR(kInvalidArguments);
758   }
759 
760   flutter::ViewportMetrics metrics;
761 
762   metrics.physical_width = SAFE_ACCESS(flutter_metrics, width, 0.0);
763   metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0);
764   metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0);
765 
766   return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetViewportMetrics(
767              std::move(metrics))
768              ? kSuccess
769              : LOG_EMBEDDER_ERROR(kInvalidArguments);
770 }
771 
772 // Returns the flutter::PointerData::Change for the given FlutterPointerPhase.
ToPointerDataChange(FlutterPointerPhase phase)773 inline flutter::PointerData::Change ToPointerDataChange(
774     FlutterPointerPhase phase) {
775   switch (phase) {
776     case kCancel:
777       return flutter::PointerData::Change::kCancel;
778     case kUp:
779       return flutter::PointerData::Change::kUp;
780     case kDown:
781       return flutter::PointerData::Change::kDown;
782     case kMove:
783       return flutter::PointerData::Change::kMove;
784     case kAdd:
785       return flutter::PointerData::Change::kAdd;
786     case kRemove:
787       return flutter::PointerData::Change::kRemove;
788     case kHover:
789       return flutter::PointerData::Change::kHover;
790   }
791   return flutter::PointerData::Change::kCancel;
792 }
793 
794 // Returns the flutter::PointerData::DeviceKind for the given
795 // FlutterPointerDeviceKind.
ToPointerDataKind(FlutterPointerDeviceKind device_kind)796 inline flutter::PointerData::DeviceKind ToPointerDataKind(
797     FlutterPointerDeviceKind device_kind) {
798   switch (device_kind) {
799     case kFlutterPointerDeviceKindMouse:
800       return flutter::PointerData::DeviceKind::kMouse;
801     case kFlutterPointerDeviceKindTouch:
802       return flutter::PointerData::DeviceKind::kTouch;
803   }
804   return flutter::PointerData::DeviceKind::kMouse;
805 }
806 
807 // Returns the flutter::PointerData::SignalKind for the given
808 // FlutterPointerSignaKind.
ToPointerDataSignalKind(FlutterPointerSignalKind kind)809 inline flutter::PointerData::SignalKind ToPointerDataSignalKind(
810     FlutterPointerSignalKind kind) {
811   switch (kind) {
812     case kFlutterPointerSignalKindNone:
813       return flutter::PointerData::SignalKind::kNone;
814     case kFlutterPointerSignalKindScroll:
815       return flutter::PointerData::SignalKind::kScroll;
816   }
817   return flutter::PointerData::SignalKind::kNone;
818 }
819 
820 // Returns the buttons to synthesize for a PointerData from a
821 // FlutterPointerEvent with no type or buttons set.
PointerDataButtonsForLegacyEvent(flutter::PointerData::Change change)822 inline int64_t PointerDataButtonsForLegacyEvent(
823     flutter::PointerData::Change change) {
824   switch (change) {
825     case flutter::PointerData::Change::kDown:
826     case flutter::PointerData::Change::kMove:
827       // These kinds of change must have a non-zero `buttons`, otherwise gesture
828       // recognizers will ignore these events.
829       return flutter::kPointerButtonMousePrimary;
830     case flutter::PointerData::Change::kCancel:
831     case flutter::PointerData::Change::kAdd:
832     case flutter::PointerData::Change::kRemove:
833     case flutter::PointerData::Change::kHover:
834     case flutter::PointerData::Change::kUp:
835       return 0;
836   }
837   return 0;
838 }
839 
FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterPointerEvent * pointers,size_t events_count)840 FlutterEngineResult FlutterEngineSendPointerEvent(
841     FLUTTER_API_SYMBOL(FlutterEngine) engine,
842     const FlutterPointerEvent* pointers,
843     size_t events_count) {
844   if (engine == nullptr || pointers == nullptr || events_count == 0) {
845     return LOG_EMBEDDER_ERROR(kInvalidArguments);
846   }
847 
848   auto packet = std::make_unique<flutter::PointerDataPacket>(events_count);
849 
850   const FlutterPointerEvent* current = pointers;
851 
852   for (size_t i = 0; i < events_count; ++i) {
853     flutter::PointerData pointer_data;
854     pointer_data.Clear();
855     pointer_data.time_stamp = SAFE_ACCESS(current, timestamp, 0);
856     pointer_data.change = ToPointerDataChange(
857         SAFE_ACCESS(current, phase, FlutterPointerPhase::kCancel));
858     pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
859     pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
860     pointer_data.device = SAFE_ACCESS(current, device, 0);
861     pointer_data.signal_kind = ToPointerDataSignalKind(
862         SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
863     pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
864     pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
865     FlutterPointerDeviceKind device_kind = SAFE_ACCESS(current, device_kind, 0);
866     // For backwards compatibility with embedders written before the device kind
867     // and buttons were exposed, if the device kind is not set treat it as a
868     // mouse, with a synthesized primary button state based on the phase.
869     if (device_kind == 0) {
870       pointer_data.kind = flutter::PointerData::DeviceKind::kMouse;
871       pointer_data.buttons =
872           PointerDataButtonsForLegacyEvent(pointer_data.change);
873     } else {
874       pointer_data.kind = ToPointerDataKind(device_kind);
875       if (pointer_data.kind == flutter::PointerData::DeviceKind::kTouch) {
876         // For touch events, set the button internally rather than requiring
877         // it at the API level, since it's a confusing construction to expose.
878         if (pointer_data.change == flutter::PointerData::Change::kDown ||
879             pointer_data.change == flutter::PointerData::Change::kMove) {
880           pointer_data.buttons = flutter::kPointerButtonTouchContact;
881         }
882       } else {
883         // Buttons use the same mask values, so pass them through directly.
884         pointer_data.buttons = SAFE_ACCESS(current, buttons, 0);
885       }
886     }
887     packet->SetPointerData(i, pointer_data);
888     current = reinterpret_cast<const FlutterPointerEvent*>(
889         reinterpret_cast<const uint8_t*>(current) + current->struct_size);
890   }
891 
892 #ifdef USE_GLFW_WINDOW
893   if (g_HandleTouchEventCallback && g_HandleTouchEventCallback(packet)) {
894     return kSuccess;
895   }
896 
897   return LOG_EMBEDDER_ERROR(kInvalidArguments);
898 #else
899     return kSuccess;
900 #endif
901 }
902 
FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterPlatformMessage * flutter_message)903 FlutterEngineResult FlutterEngineSendPlatformMessage(
904     FLUTTER_API_SYMBOL(FlutterEngine) engine,
905     const FlutterPlatformMessage* flutter_message) {
906   if (engine == nullptr || flutter_message == nullptr) {
907     return LOG_EMBEDDER_ERROR(kInvalidArguments);
908   }
909 
910   if (SAFE_ACCESS(flutter_message, channel, nullptr) == nullptr) {
911     return LOG_EMBEDDER_ERROR(kInvalidArguments);
912   }
913 
914   size_t message_size = SAFE_ACCESS(flutter_message, message_size, 0);
915   const uint8_t* message_data = SAFE_ACCESS(flutter_message, message, nullptr);
916 
917   if (message_size != 0 && message_data == nullptr) {
918     return LOG_EMBEDDER_ERROR(kInvalidArguments);
919   }
920 
921   const FlutterPlatformMessageResponseHandle* response_handle =
922       SAFE_ACCESS(flutter_message, response_handle, nullptr);
923 
924   fml::RefPtr<flutter::PlatformMessageResponse> response;
925   if (response_handle && response_handle->message) {
926     response = response_handle->message->response();
927   }
928 
929   fml::RefPtr<flutter::PlatformMessage> message;
930   if (message_size == 0) {
931     message = fml::MakeRefCounted<flutter::PlatformMessage>(
932         flutter_message->channel, response);
933   } else {
934     message = fml::MakeRefCounted<flutter::PlatformMessage>(
935         flutter_message->channel,
936         std::vector<uint8_t>(message_data, message_data + message_size),
937         response);
938   }
939 
940   return reinterpret_cast<flutter::EmbedderEngine*>(engine)
941                  ->SendPlatformMessage(std::move(message))
942              ? kSuccess
943              : LOG_EMBEDDER_ERROR(kInvalidArguments);
944 }
945 
FlutterPlatformMessageCreateResponseHandle(FLUTTER_API_SYMBOL (FlutterEngine)engine,FlutterDataCallback data_callback,void * user_data,FlutterPlatformMessageResponseHandle ** response_out)946 FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(
947     FLUTTER_API_SYMBOL(FlutterEngine) engine,
948     FlutterDataCallback data_callback,
949     void* user_data,
950     FlutterPlatformMessageResponseHandle** response_out) {
951   if (engine == nullptr || data_callback == nullptr ||
952       response_out == nullptr) {
953     return LOG_EMBEDDER_ERROR(kInvalidArguments);
954   }
955 
956   flutter::EmbedderPlatformMessageResponse::Callback response_callback =
957       [user_data, data_callback](const uint8_t* data, size_t size) {
958         data_callback(data, size, user_data);
959       };
960 
961   auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
962                                   ->GetTaskRunners()
963                                   .GetPlatformTaskRunner();
964 
965   auto handle = new FlutterPlatformMessageResponseHandle();
966 
967   handle->message = fml::MakeRefCounted<flutter::PlatformMessage>(
968       "",  // The channel is empty and unused as the response handle is going to
969            // referenced directly in the |FlutterEngineSendPlatformMessage| with
970            // the container message discarded.
971       fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
972           std::move(platform_task_runner), response_callback));
973   *response_out = handle;
974   return kSuccess;
975 }
976 
FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL (FlutterEngine)engine,FlutterPlatformMessageResponseHandle * response)977 FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(
978     FLUTTER_API_SYMBOL(FlutterEngine) engine,
979     FlutterPlatformMessageResponseHandle* response) {
980   if (engine == nullptr || response == nullptr) {
981     return LOG_EMBEDDER_ERROR(kInvalidArguments);
982   }
983   delete response;
984   return kSuccess;
985 }
986 
FlutterEngineSendPlatformMessageResponse(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterPlatformMessageResponseHandle * handle,const uint8_t * data,size_t data_length)987 FlutterEngineResult FlutterEngineSendPlatformMessageResponse(
988     FLUTTER_API_SYMBOL(FlutterEngine) engine,
989     const FlutterPlatformMessageResponseHandle* handle,
990     const uint8_t* data,
991     size_t data_length) {
992   if (data_length != 0 && data == nullptr) {
993     return LOG_EMBEDDER_ERROR(kInvalidArguments);
994   }
995 
996   auto response = handle->message->response();
997 
998   if (response) {
999     if (data_length == 0) {
1000       response->CompleteEmpty();
1001     } else {
1002       response->Complete(std::make_unique<fml::DataMapping>(
1003           std::vector<uint8_t>({data, data + data_length})));
1004     }
1005   }
1006 
1007   delete handle;
1008 
1009   return kSuccess;
1010 }
1011 
__FlutterEngineFlushPendingTasksNow()1012 FlutterEngineResult __FlutterEngineFlushPendingTasksNow() {
1013   fml::MessageLoop::GetCurrent().RunExpiredTasksNow();
1014   return kSuccess;
1015 }
1016 
FlutterEngineRegisterExternalTexture(FLUTTER_API_SYMBOL (FlutterEngine)engine,int64_t texture_identifier)1017 FlutterEngineResult FlutterEngineRegisterExternalTexture(
1018     FLUTTER_API_SYMBOL(FlutterEngine) engine,
1019     int64_t texture_identifier) {
1020   if (engine == nullptr || texture_identifier == 0) {
1021     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1022   }
1023   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->RegisterTexture(
1024           texture_identifier)) {
1025     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
1026   }
1027   return kSuccess;
1028 }
1029 
FlutterEngineUnregisterExternalTexture(FLUTTER_API_SYMBOL (FlutterEngine)engine,int64_t texture_identifier)1030 FlutterEngineResult FlutterEngineUnregisterExternalTexture(
1031     FLUTTER_API_SYMBOL(FlutterEngine) engine,
1032     int64_t texture_identifier) {
1033   if (engine == nullptr || texture_identifier == 0) {
1034     return kInvalidArguments;
1035   }
1036 
1037   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->UnregisterTexture(
1038           texture_identifier)) {
1039     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
1040   }
1041 
1042   return kSuccess;
1043 }
1044 
FlutterEngineMarkExternalTextureFrameAvailable(FLUTTER_API_SYMBOL (FlutterEngine)engine,int64_t texture_identifier)1045 FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable(
1046     FLUTTER_API_SYMBOL(FlutterEngine) engine,
1047     int64_t texture_identifier) {
1048   if (engine == nullptr || texture_identifier == 0) {
1049     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1050   }
1051   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
1052            ->MarkTextureFrameAvailable(texture_identifier)) {
1053     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
1054   }
1055   return kSuccess;
1056 }
1057 
FlutterEngineOnVsync(FLUTTER_API_SYMBOL (FlutterEngine)engine,intptr_t baton,uint64_t frame_start_time_nanos,uint64_t frame_target_time_nanos)1058 FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine)
1059                                              engine,
1060                                          intptr_t baton,
1061                                          uint64_t frame_start_time_nanos,
1062                                          uint64_t frame_target_time_nanos) {
1063   if (engine == nullptr) {
1064     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1065   }
1066 
1067   TRACE_EVENT0("flutter", "FlutterEngineOnVsync");
1068 
1069   auto start_time = fml::TimePoint::FromEpochDelta(
1070       fml::TimeDelta::FromNanoseconds(frame_start_time_nanos));
1071 
1072   auto target_time = fml::TimePoint::FromEpochDelta(
1073       fml::TimeDelta::FromNanoseconds(frame_target_time_nanos));
1074 
1075   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->OnVsyncEvent(
1076           baton, start_time, target_time)) {
1077     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
1078   }
1079 
1080   return kSuccess;
1081 }
1082 
FlutterEngineTraceEventDurationBegin(const char * name)1083 void FlutterEngineTraceEventDurationBegin(const char* name) {
1084   fml::tracing::TraceEvent0("flutter", name);
1085 }
1086 
FlutterEngineTraceEventDurationEnd(const char * name)1087 void FlutterEngineTraceEventDurationEnd(const char* name) {
1088   fml::tracing::TraceEventEnd(name);
1089 }
1090 
FlutterEngineTraceEventInstant(const char * name)1091 void FlutterEngineTraceEventInstant(const char* name) {
1092   fml::tracing::TraceEventInstant0("flutter", name);
1093 }
1094 
FlutterEnginePostRenderThreadTask(FLUTTER_API_SYMBOL (FlutterEngine)engine,VoidCallback callback,void * baton)1095 FlutterEngineResult FlutterEnginePostRenderThreadTask(
1096     FLUTTER_API_SYMBOL(FlutterEngine) engine,
1097     VoidCallback callback,
1098     void* baton) {
1099   if (engine == nullptr || callback == nullptr) {
1100     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1101   }
1102 
1103   auto task = [callback, baton]() { callback(baton); };
1104 
1105   return reinterpret_cast<flutter::EmbedderEngine*>(engine)
1106                  ->PostRenderThreadTask(task)
1107              ? kSuccess
1108              : LOG_EMBEDDER_ERROR(kInternalInconsistency);
1109 }
1110 
FlutterEngineGetCurrentTime()1111 uint64_t FlutterEngineGetCurrentTime() {
1112   return fml::TimePoint::Now().ToEpochDelta().ToNanoseconds();
1113 }
1114 
FlutterEngineRunTask(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterTask * task)1115 FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine)
1116                                              engine,
1117                                          const FlutterTask* task) {
1118   if (engine == nullptr) {
1119     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1120   }
1121 
1122   return reinterpret_cast<flutter::EmbedderEngine*>(engine)->RunTask(task)
1123              ? kSuccess
1124              : LOG_EMBEDDER_ERROR(kInvalidArguments);
1125 }
1126 
1127 #ifdef USE_GLFW_WINDOW
FlutterEngineRegisterHandleTouchEventCallback(HandleTouchEventCallback && callback)1128 void FlutterEngineRegisterHandleTouchEventCallback(HandleTouchEventCallback&& callback) {
1129   g_HandleTouchEventCallback = std::move(callback);
1130 }
1131 #endif
1132