• 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   // Step 0: Figure out arguments for shell creation.
529   if (engine_out == nullptr) {
530     return LOG_EMBEDDER_ERROR(kInvalidArguments);
531   }
532 
533   if (args == nullptr) {
534     return LOG_EMBEDDER_ERROR(kInvalidArguments);
535   }
536 
537   if (!IsRendererValid(config)) {
538     FML_LOG(WARNING) << "Invalid renderer config.";
539     return LOG_EMBEDDER_ERROR(kInvalidArguments);
540   }
541 
542   flutter::Settings settings;
543   settings.task_observer_add = [](intptr_t key, fml::closure callback) {
544     fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
545   };
546   settings.task_observer_remove = [](intptr_t key) {
547     fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
548   };
549 
550   flutter::VsyncWaiterEmbedder::VsyncCallback vsync_callback = nullptr;
551   if (SAFE_ACCESS(args, vsync_callback, nullptr) != nullptr) {
552     vsync_callback = [ptr = args->vsync_callback, user_data](intptr_t baton) {
553       return ptr(user_data, baton);
554     };
555   }
556 
557   auto external_view_embedder_result =
558       InferExternalViewEmbedderFromArgs(SAFE_ACCESS(args, compositor, nullptr));
559   if (external_view_embedder_result.second) {
560     return LOG_EMBEDDER_ERROR(kInvalidArguments);
561   }
562 
563   flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table =
564       {
565           vsync_callback,
566       };
567 
568   auto on_create_platform_view = InferPlatformViewCreationCallback(
569       config, user_data, platform_dispatch_table,
570       std::move(external_view_embedder_result.first));
571 
572   if (!on_create_platform_view) {
573     return LOG_EMBEDDER_ERROR(kInvalidArguments);
574   }
575 
576   flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
577       [](flutter::Shell& shell) {
578         return std::make_unique<flutter::Rasterizer>(shell,
579                                                      shell.GetTaskRunners());
580       };
581 
582   // TODO(chinmaygarde): This is the wrong spot for this. It belongs in the
583   // platform view jump table.
584   flutter::EmbedderExternalTextureGL::ExternalTextureCallback
585       external_texture_callback;
586   if (config->type == kOpenGL) {
587     const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
588     if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
589                     nullptr) != nullptr) {
590       external_texture_callback =
591           [ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
592               int64_t texture_identifier, GrContext* context,
593               const SkISize& size) -> sk_sp<SkImage> {
594         FlutterOpenGLTexture texture = {};
595 
596         if (!ptr(user_data, texture_identifier, size.width(), size.height(),
597                  &texture)) {
598           return nullptr;
599         }
600 
601         GrGLTextureInfo gr_texture_info = {texture.target, texture.name,
602                                            texture.format};
603 
604         GrBackendTexture gr_backend_texture(size.width(), size.height(),
605                                             GrMipMapped::kNo, gr_texture_info);
606         SkImage::TextureReleaseProc release_proc = texture.destruction_callback;
607         auto image = SkImage::MakeFromTexture(
608             context,                   // context
609             gr_backend_texture,        // texture handle
610             kTopLeft_GrSurfaceOrigin,  // origin
611             kRGBA_8888_SkColorType,    // color type
612             kPremul_SkAlphaType,       // alpha type
613             nullptr,                   // colorspace
614             release_proc,              // texture release proc
615             texture.user_data          // texture release context
616         );
617 
618         if (!image) {
619           // In case Skia rejects the image, call the release proc so that
620           // embedders can perform collection of intermediates.
621           if (release_proc) {
622             release_proc(texture.user_data);
623           }
624           FML_LOG(ERROR) << "Could not create external texture.";
625           return nullptr;
626         }
627 
628         return image;
629       };
630     }
631   }
632 
633   auto thread_host =
634       flutter::EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(
635           SAFE_ACCESS(args, custom_task_runners, nullptr));
636 
637   if (!thread_host || !thread_host->IsValid()) {
638     FML_LOG(ERROR) << "Could not setup or infer thread configuration to run "
639                       "the Flutter engine on.";
640     return LOG_EMBEDDER_ERROR(kInvalidArguments);
641   }
642 
643   auto task_runners = thread_host->GetTaskRunners();
644 
645   if (!task_runners.IsValid()) {
646     FML_LOG(ERROR) << "Task runner configuration specified is invalid.";
647     return LOG_EMBEDDER_ERROR(kInvalidArguments);
648   }
649 
650   // Step 1: Create the engine.
651   auto embedder_engine =
652       std::make_unique<flutter::EmbedderEngine>(std::move(thread_host),    //
653                                                 std::move(task_runners),   //
654                                                 settings,                  //
655                                                 on_create_platform_view,   //
656                                                 on_create_rasterizer,      //
657                                                 external_texture_callback  //
658       );
659 
660   if (!embedder_engine->IsValid()) {
661     return LOG_EMBEDDER_ERROR(kInvalidArguments);
662   }
663 
664   // Step 2: Setup the rendering surface.
665   if (!embedder_engine->NotifyCreated()) {
666     return LOG_EMBEDDER_ERROR(kInvalidArguments);
667   }
668 
669   // Step 3: Run the engine.
670   flutter::RunConfiguration run_configuration;
671   if (!embedder_engine->Run(std::move(run_configuration))) {
672     return LOG_EMBEDDER_ERROR(kInvalidArguments);
673   }
674 
675   // Finally! Release the ownership of the embedder engine to the caller.
676   *engine_out = reinterpret_cast<FLUTTER_API_SYMBOL(FlutterEngine)>(
677       embedder_engine.release());
678   return kSuccess;
679 }
680 
FlutterEngineShutdown(FLUTTER_API_SYMBOL (FlutterEngine)engine)681 FlutterEngineResult FlutterEngineShutdown(FLUTTER_API_SYMBOL(FlutterEngine)
682                                               engine) {
683   if (engine == nullptr) {
684     return LOG_EMBEDDER_ERROR(kInvalidArguments);
685   }
686   auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
687   embedder_engine->NotifyDestroyed();
688   delete embedder_engine;
689   return kSuccess;
690 }
691 
FlutterEngineSetIdleNotificationCallback(FLUTTER_API_SYMBOL (FlutterEngine)engine,const IdleCallback & idle_notification_callback)692 FlutterEngineResult FlutterEngineSetIdleNotificationCallback(
693     FLUTTER_API_SYMBOL(FlutterEngine) engine,
694     const IdleCallback& idle_notification_callback) {
695     if (engine == nullptr || idle_notification_callback == nullptr) {
696         return LOG_EMBEDDER_ERROR(kInvalidArguments);
697     }
698 
699     return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetIdleNotificationCallback(
700         idle_notification_callback)
701            ? kSuccess
702            : LOG_EMBEDDER_ERROR(kInvalidArguments);
703 }
704 
FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterWindowMetricsEvent * flutter_metrics)705 FlutterEngineResult FlutterEngineSendWindowMetricsEvent(
706     FLUTTER_API_SYMBOL(FlutterEngine) engine,
707     const FlutterWindowMetricsEvent* flutter_metrics) {
708   if (engine == nullptr || flutter_metrics == nullptr) {
709     return LOG_EMBEDDER_ERROR(kInvalidArguments);
710   }
711 
712   flutter::ViewportMetrics metrics;
713 
714   metrics.physical_width = SAFE_ACCESS(flutter_metrics, width, 0.0);
715   metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0);
716   metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0);
717 
718   return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetViewportMetrics(
719              std::move(metrics))
720              ? kSuccess
721              : LOG_EMBEDDER_ERROR(kInvalidArguments);
722 }
723 
724 // Returns the flutter::PointerData::Change for the given FlutterPointerPhase.
ToPointerDataChange(FlutterPointerPhase phase)725 inline flutter::PointerData::Change ToPointerDataChange(
726     FlutterPointerPhase phase) {
727   switch (phase) {
728     case kCancel:
729       return flutter::PointerData::Change::kCancel;
730     case kUp:
731       return flutter::PointerData::Change::kUp;
732     case kDown:
733       return flutter::PointerData::Change::kDown;
734     case kMove:
735       return flutter::PointerData::Change::kMove;
736     case kAdd:
737       return flutter::PointerData::Change::kAdd;
738     case kRemove:
739       return flutter::PointerData::Change::kRemove;
740     case kHover:
741       return flutter::PointerData::Change::kHover;
742   }
743   return flutter::PointerData::Change::kCancel;
744 }
745 
746 // Returns the flutter::PointerData::DeviceKind for the given
747 // FlutterPointerDeviceKind.
ToPointerDataKind(FlutterPointerDeviceKind device_kind)748 inline flutter::PointerData::DeviceKind ToPointerDataKind(
749     FlutterPointerDeviceKind device_kind) {
750   switch (device_kind) {
751     case kFlutterPointerDeviceKindMouse:
752       return flutter::PointerData::DeviceKind::kMouse;
753     case kFlutterPointerDeviceKindTouch:
754       return flutter::PointerData::DeviceKind::kTouch;
755   }
756   return flutter::PointerData::DeviceKind::kMouse;
757 }
758 
759 // Returns the flutter::PointerData::SignalKind for the given
760 // FlutterPointerSignaKind.
ToPointerDataSignalKind(FlutterPointerSignalKind kind)761 inline flutter::PointerData::SignalKind ToPointerDataSignalKind(
762     FlutterPointerSignalKind kind) {
763   switch (kind) {
764     case kFlutterPointerSignalKindNone:
765       return flutter::PointerData::SignalKind::kNone;
766     case kFlutterPointerSignalKindScroll:
767       return flutter::PointerData::SignalKind::kScroll;
768   }
769   return flutter::PointerData::SignalKind::kNone;
770 }
771 
772 // Returns the buttons to synthesize for a PointerData from a
773 // FlutterPointerEvent with no type or buttons set.
PointerDataButtonsForLegacyEvent(flutter::PointerData::Change change)774 inline int64_t PointerDataButtonsForLegacyEvent(
775     flutter::PointerData::Change change) {
776   switch (change) {
777     case flutter::PointerData::Change::kDown:
778     case flutter::PointerData::Change::kMove:
779       // These kinds of change must have a non-zero `buttons`, otherwise gesture
780       // recognizers will ignore these events.
781       return flutter::kPointerButtonMousePrimary;
782     case flutter::PointerData::Change::kCancel:
783     case flutter::PointerData::Change::kAdd:
784     case flutter::PointerData::Change::kRemove:
785     case flutter::PointerData::Change::kHover:
786     case flutter::PointerData::Change::kUp:
787       return 0;
788   }
789   return 0;
790 }
791 
FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterPointerEvent * pointers,size_t events_count)792 FlutterEngineResult FlutterEngineSendPointerEvent(
793     FLUTTER_API_SYMBOL(FlutterEngine) engine,
794     const FlutterPointerEvent* pointers,
795     size_t events_count) {
796   if (engine == nullptr || pointers == nullptr || events_count == 0) {
797     return LOG_EMBEDDER_ERROR(kInvalidArguments);
798   }
799 
800   auto packet = std::make_unique<flutter::PointerDataPacket>(events_count);
801 
802   const FlutterPointerEvent* current = pointers;
803 
804   for (size_t i = 0; i < events_count; ++i) {
805     flutter::PointerData pointer_data;
806     pointer_data.Clear();
807     pointer_data.time_stamp = SAFE_ACCESS(current, timestamp, 0);
808     pointer_data.change = ToPointerDataChange(
809         SAFE_ACCESS(current, phase, FlutterPointerPhase::kCancel));
810     pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
811     pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
812     pointer_data.device = SAFE_ACCESS(current, device, 0);
813     pointer_data.signal_kind = ToPointerDataSignalKind(
814         SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
815     pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
816     pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
817     FlutterPointerDeviceKind device_kind = SAFE_ACCESS(current, device_kind, 0);
818     // For backwards compatibility with embedders written before the device kind
819     // and buttons were exposed, if the device kind is not set treat it as a
820     // mouse, with a synthesized primary button state based on the phase.
821     if (device_kind == 0) {
822       pointer_data.kind = flutter::PointerData::DeviceKind::kMouse;
823       pointer_data.buttons =
824           PointerDataButtonsForLegacyEvent(pointer_data.change);
825     } else {
826       pointer_data.kind = ToPointerDataKind(device_kind);
827       if (pointer_data.kind == flutter::PointerData::DeviceKind::kTouch) {
828         // For touch events, set the button internally rather than requiring
829         // it at the API level, since it's a confusing construction to expose.
830         if (pointer_data.change == flutter::PointerData::Change::kDown ||
831             pointer_data.change == flutter::PointerData::Change::kMove) {
832           pointer_data.buttons = flutter::kPointerButtonTouchContact;
833         }
834       } else {
835         // Buttons use the same mask values, so pass them through directly.
836         pointer_data.buttons = SAFE_ACCESS(current, buttons, 0);
837       }
838     }
839     packet->SetPointerData(i, pointer_data);
840     current = reinterpret_cast<const FlutterPointerEvent*>(
841         reinterpret_cast<const uint8_t*>(current) + current->struct_size);
842   }
843 
844 #ifdef USE_GLFW_WINDOW
845   if (g_HandleTouchEventCallback && g_HandleTouchEventCallback(packet)) {
846     return kSuccess;
847   }
848 
849   return LOG_EMBEDDER_ERROR(kInvalidArguments);
850 #else
851     return kSuccess;
852 #endif
853 }
854 
FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterPlatformMessage * flutter_message)855 FlutterEngineResult FlutterEngineSendPlatformMessage(
856     FLUTTER_API_SYMBOL(FlutterEngine) engine,
857     const FlutterPlatformMessage* flutter_message) {
858   if (engine == nullptr || flutter_message == nullptr) {
859     return LOG_EMBEDDER_ERROR(kInvalidArguments);
860   }
861 
862   if (SAFE_ACCESS(flutter_message, channel, nullptr) == nullptr) {
863     return LOG_EMBEDDER_ERROR(kInvalidArguments);
864   }
865 
866   size_t message_size = SAFE_ACCESS(flutter_message, message_size, 0);
867   const uint8_t* message_data = SAFE_ACCESS(flutter_message, message, nullptr);
868 
869   if (message_size != 0 && message_data == nullptr) {
870     return LOG_EMBEDDER_ERROR(kInvalidArguments);
871   }
872 
873   const FlutterPlatformMessageResponseHandle* response_handle =
874       SAFE_ACCESS(flutter_message, response_handle, nullptr);
875 
876   fml::RefPtr<flutter::PlatformMessageResponse> response;
877   if (response_handle && response_handle->message) {
878     response = response_handle->message->response();
879   }
880 
881   fml::RefPtr<flutter::PlatformMessage> message;
882   if (message_size == 0) {
883     message = fml::MakeRefCounted<flutter::PlatformMessage>(
884         flutter_message->channel, response);
885   } else {
886     message = fml::MakeRefCounted<flutter::PlatformMessage>(
887         flutter_message->channel,
888         std::vector<uint8_t>(message_data, message_data + message_size),
889         response);
890   }
891 
892   return reinterpret_cast<flutter::EmbedderEngine*>(engine)
893                  ->SendPlatformMessage(std::move(message))
894              ? kSuccess
895              : LOG_EMBEDDER_ERROR(kInvalidArguments);
896 }
897 
FlutterPlatformMessageCreateResponseHandle(FLUTTER_API_SYMBOL (FlutterEngine)engine,FlutterDataCallback data_callback,void * user_data,FlutterPlatformMessageResponseHandle ** response_out)898 FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(
899     FLUTTER_API_SYMBOL(FlutterEngine) engine,
900     FlutterDataCallback data_callback,
901     void* user_data,
902     FlutterPlatformMessageResponseHandle** response_out) {
903   if (engine == nullptr || data_callback == nullptr ||
904       response_out == nullptr) {
905     return LOG_EMBEDDER_ERROR(kInvalidArguments);
906   }
907 
908   flutter::EmbedderPlatformMessageResponse::Callback response_callback =
909       [user_data, data_callback](const uint8_t* data, size_t size) {
910         data_callback(data, size, user_data);
911       };
912 
913   auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
914                                   ->GetTaskRunners()
915                                   .GetPlatformTaskRunner();
916 
917   auto handle = new FlutterPlatformMessageResponseHandle();
918 
919   handle->message = fml::MakeRefCounted<flutter::PlatformMessage>(
920       "",  // The channel is empty and unused as the response handle is going to
921            // referenced directly in the |FlutterEngineSendPlatformMessage| with
922            // the container message discarded.
923       fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
924           std::move(platform_task_runner), response_callback));
925   *response_out = handle;
926   return kSuccess;
927 }
928 
FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL (FlutterEngine)engine,FlutterPlatformMessageResponseHandle * response)929 FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(
930     FLUTTER_API_SYMBOL(FlutterEngine) engine,
931     FlutterPlatformMessageResponseHandle* response) {
932   if (engine == nullptr || response == nullptr) {
933     return LOG_EMBEDDER_ERROR(kInvalidArguments);
934   }
935   delete response;
936   return kSuccess;
937 }
938 
FlutterEngineSendPlatformMessageResponse(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterPlatformMessageResponseHandle * handle,const uint8_t * data,size_t data_length)939 FlutterEngineResult FlutterEngineSendPlatformMessageResponse(
940     FLUTTER_API_SYMBOL(FlutterEngine) engine,
941     const FlutterPlatformMessageResponseHandle* handle,
942     const uint8_t* data,
943     size_t data_length) {
944   if (data_length != 0 && data == nullptr) {
945     return LOG_EMBEDDER_ERROR(kInvalidArguments);
946   }
947 
948   auto response = handle->message->response();
949 
950   if (response) {
951     if (data_length == 0) {
952       response->CompleteEmpty();
953     } else {
954       response->Complete(std::make_unique<fml::DataMapping>(
955           std::vector<uint8_t>({data, data + data_length})));
956     }
957   }
958 
959   delete handle;
960 
961   return kSuccess;
962 }
963 
__FlutterEngineFlushPendingTasksNow()964 FlutterEngineResult __FlutterEngineFlushPendingTasksNow() {
965   fml::MessageLoop::GetCurrent().RunExpiredTasksNow();
966   return kSuccess;
967 }
968 
FlutterEngineRegisterExternalTexture(FLUTTER_API_SYMBOL (FlutterEngine)engine,int64_t texture_identifier)969 FlutterEngineResult FlutterEngineRegisterExternalTexture(
970     FLUTTER_API_SYMBOL(FlutterEngine) engine,
971     int64_t texture_identifier) {
972   if (engine == nullptr || texture_identifier == 0) {
973     return LOG_EMBEDDER_ERROR(kInvalidArguments);
974   }
975   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->RegisterTexture(
976           texture_identifier)) {
977     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
978   }
979   return kSuccess;
980 }
981 
FlutterEngineUnregisterExternalTexture(FLUTTER_API_SYMBOL (FlutterEngine)engine,int64_t texture_identifier)982 FlutterEngineResult FlutterEngineUnregisterExternalTexture(
983     FLUTTER_API_SYMBOL(FlutterEngine) engine,
984     int64_t texture_identifier) {
985   if (engine == nullptr || texture_identifier == 0) {
986     return kInvalidArguments;
987   }
988 
989   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->UnregisterTexture(
990           texture_identifier)) {
991     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
992   }
993 
994   return kSuccess;
995 }
996 
FlutterEngineMarkExternalTextureFrameAvailable(FLUTTER_API_SYMBOL (FlutterEngine)engine,int64_t texture_identifier)997 FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable(
998     FLUTTER_API_SYMBOL(FlutterEngine) engine,
999     int64_t texture_identifier) {
1000   if (engine == nullptr || texture_identifier == 0) {
1001     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1002   }
1003   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
1004            ->MarkTextureFrameAvailable(texture_identifier)) {
1005     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
1006   }
1007   return kSuccess;
1008 }
1009 
FlutterEngineOnVsync(FLUTTER_API_SYMBOL (FlutterEngine)engine,intptr_t baton,uint64_t frame_start_time_nanos,uint64_t frame_target_time_nanos)1010 FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine)
1011                                              engine,
1012                                          intptr_t baton,
1013                                          uint64_t frame_start_time_nanos,
1014                                          uint64_t frame_target_time_nanos) {
1015   if (engine == nullptr) {
1016     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1017   }
1018 
1019   TRACE_EVENT0("flutter", "FlutterEngineOnVsync");
1020 
1021   auto start_time = fml::TimePoint::FromEpochDelta(
1022       fml::TimeDelta::FromNanoseconds(frame_start_time_nanos));
1023 
1024   auto target_time = fml::TimePoint::FromEpochDelta(
1025       fml::TimeDelta::FromNanoseconds(frame_target_time_nanos));
1026 
1027   if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->OnVsyncEvent(
1028           baton, start_time, target_time)) {
1029     return LOG_EMBEDDER_ERROR(kInternalInconsistency);
1030   }
1031 
1032   return kSuccess;
1033 }
1034 
FlutterEngineTraceEventDurationBegin(const char * name)1035 void FlutterEngineTraceEventDurationBegin(const char* name) {
1036   fml::tracing::TraceEvent0("flutter", name);
1037 }
1038 
FlutterEngineTraceEventDurationEnd(const char * name)1039 void FlutterEngineTraceEventDurationEnd(const char* name) {
1040   fml::tracing::TraceEventEnd(name);
1041 }
1042 
FlutterEngineTraceEventInstant(const char * name)1043 void FlutterEngineTraceEventInstant(const char* name) {
1044   fml::tracing::TraceEventInstant0("flutter", name);
1045 }
1046 
FlutterEnginePostRenderThreadTask(FLUTTER_API_SYMBOL (FlutterEngine)engine,VoidCallback callback,void * baton)1047 FlutterEngineResult FlutterEnginePostRenderThreadTask(
1048     FLUTTER_API_SYMBOL(FlutterEngine) engine,
1049     VoidCallback callback,
1050     void* baton) {
1051   if (engine == nullptr || callback == nullptr) {
1052     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1053   }
1054 
1055   auto task = [callback, baton]() { callback(baton); };
1056 
1057   return reinterpret_cast<flutter::EmbedderEngine*>(engine)
1058                  ->PostRenderThreadTask(task)
1059              ? kSuccess
1060              : LOG_EMBEDDER_ERROR(kInternalInconsistency);
1061 }
1062 
FlutterEngineGetCurrentTime()1063 uint64_t FlutterEngineGetCurrentTime() {
1064   return fml::TimePoint::Now().ToEpochDelta().ToNanoseconds();
1065 }
1066 
FlutterEngineRunTask(FLUTTER_API_SYMBOL (FlutterEngine)engine,const FlutterTask * task)1067 FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine)
1068                                              engine,
1069                                          const FlutterTask* task) {
1070   if (engine == nullptr) {
1071     return LOG_EMBEDDER_ERROR(kInvalidArguments);
1072   }
1073 
1074   return reinterpret_cast<flutter::EmbedderEngine*>(engine)->RunTask(task)
1075              ? kSuccess
1076              : LOG_EMBEDDER_ERROR(kInvalidArguments);
1077 }
1078 
1079 #ifdef USE_GLFW_WINDOW
FlutterEngineRegisterHandleTouchEventCallback(HandleTouchEventCallback && callback)1080 void FlutterEngineRegisterHandleTouchEventCallback(HandleTouchEventCallback&& callback) {
1081   g_HandleTouchEventCallback = std::move(callback);
1082 }
1083 #endif
1084