Flutter Engine
embedder_config_builder.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/shell/platform/embedder/tests/embedder_config_builder.h"
6 
7 #include "flutter/runtime/dart_vm.h"
8 #include "flutter/shell/platform/embedder/embedder.h"
9 #include "third_party/skia/include/core/SkBitmap.h"
10 
11 #ifdef SHELL_ENABLE_GL
12 #include "flutter/shell/platform/embedder/tests/embedder_test_compositor_gl.h"
13 #include "flutter/shell/platform/embedder/tests/embedder_test_context_gl.h"
14 #endif
15 
16 #ifdef SHELL_ENABLE_METAL
17 #include "flutter/shell/platform/embedder/tests/embedder_test_context_metal.h"
18 #endif
19 
20 namespace flutter {
21 namespace testing {
22 
24  EmbedderTestContext& context,
25  InitializationPreference preference)
26  : context_(context) {
27  project_args_.struct_size = sizeof(project_args_);
28  project_args_.shutdown_dart_vm_when_done = true;
29  project_args_.platform_message_callback =
30  [](const FlutterPlatformMessage* message, void* context) {
31  reinterpret_cast<EmbedderTestContext*>(context)
32  ->PlatformMessageCallback(message);
33  };
34 
35  custom_task_runners_.struct_size = sizeof(FlutterCustomTaskRunners);
36 
37 #ifdef SHELL_ENABLE_GL
38  opengl_renderer_config_.struct_size = sizeof(FlutterOpenGLRendererConfig);
39  opengl_renderer_config_.make_current = [](void* context) -> bool {
40  return reinterpret_cast<EmbedderTestContextGL*>(context)->GLMakeCurrent();
41  };
42  opengl_renderer_config_.clear_current = [](void* context) -> bool {
43  return reinterpret_cast<EmbedderTestContextGL*>(context)->GLClearCurrent();
44  };
45  opengl_renderer_config_.present_with_info =
46  [](void* context, const FlutterPresentInfo* present_info) -> bool {
47  return reinterpret_cast<EmbedderTestContextGL*>(context)->GLPresent(
48  present_info->fbo_id);
49  };
50  opengl_renderer_config_.fbo_with_frame_info_callback =
51  [](void* context, const FlutterFrameInfo* frame_info) -> uint32_t {
52  return reinterpret_cast<EmbedderTestContextGL*>(context)->GLGetFramebuffer(
53  *frame_info);
54  };
55  opengl_renderer_config_.make_resource_current = [](void* context) -> bool {
56  return reinterpret_cast<EmbedderTestContextGL*>(context)
57  ->GLMakeResourceCurrent();
58  };
59  opengl_renderer_config_.gl_proc_resolver = [](void* context,
60  const char* name) -> void* {
61  return reinterpret_cast<EmbedderTestContextGL*>(context)->GLGetProcAddress(
62  name);
63  };
64  opengl_renderer_config_.fbo_reset_after_present = true;
65  opengl_renderer_config_.surface_transformation =
66  [](void* context) -> FlutterTransformation {
67  return reinterpret_cast<EmbedderTestContext*>(context)
68  ->GetRootSurfaceTransformation();
69  };
70 #endif
71 
72 #ifdef SHELL_ENABLE_METAL
73  InitializeMetalRendererConfig();
74 #endif
75 
76  software_renderer_config_.struct_size = sizeof(FlutterSoftwareRendererConfig);
77  software_renderer_config_.surface_present_callback =
78  [](void* context, const void* allocation, size_t row_bytes,
79  size_t height) {
80  auto image_info =
81  SkImageInfo::MakeN32Premul(SkISize::Make(row_bytes / 4, height));
82  SkBitmap bitmap;
83  if (!bitmap.installPixels(image_info, const_cast<void*>(allocation),
84  row_bytes)) {
85  FML_LOG(ERROR) << "Could not copy pixels for the software "
86  "composition from the engine.";
87  return false;
88  }
89  bitmap.setImmutable();
90  return reinterpret_cast<EmbedderTestContextSoftware*>(context)->Present(
91  SkImage::MakeFromBitmap(bitmap));
92  };
93 
94  // The first argument is treated as the executable name. Don't make tests have
95  // to do this manually.
96  AddCommandLineArgument("embedder_unittest");
97 
98  if (preference != InitializationPreference::kNoInitialize) {
99  SetAssetsPath();
104  AddCommandLineArgument("--disable-observatory");
105 
108  SetSnapshots();
109  }
112  SetAOTDataElf();
113  }
114  }
115 }
116 
118 
120  return project_args_;
121 }
122 
124  renderer_config_.type = FlutterRendererType::kSoftware;
125  renderer_config_.software = software_renderer_config_;
126  context_.SetupSurface(surface_size);
127 }
128 
130 #ifdef SHELL_ENABLE_GL
131  // SetOpenGLRendererConfig must be called before this.
132  FML_CHECK(renderer_config_.type == FlutterRendererType::kOpenGL);
133  renderer_config_.open_gl.fbo_callback = [](void* context) -> uint32_t {
134  FlutterFrameInfo frame_info = {};
135  // fbo_callback doesn't use the frame size information, only
136  // fbo_callback_with_frame_info does.
137  frame_info.struct_size = sizeof(FlutterFrameInfo);
138  frame_info.size.width = 0;
139  frame_info.size.height = 0;
140  return reinterpret_cast<EmbedderTestContextGL*>(context)->GLGetFramebuffer(
141  frame_info);
142  };
143 #endif
144 }
145 
147 #ifdef SHELL_ENABLE_GL
148  // SetOpenGLRendererConfig must be called before this.
149  FML_CHECK(renderer_config_.type == FlutterRendererType::kOpenGL);
150  renderer_config_.open_gl.present = [](void* context) -> bool {
151  // passing a placeholder fbo_id.
152  return reinterpret_cast<EmbedderTestContextGL*>(context)->GLPresent(0);
153  };
154 #endif
155 }
156 
158 #ifdef SHELL_ENABLE_GL
159  renderer_config_.type = FlutterRendererType::kOpenGL;
160  renderer_config_.open_gl = opengl_renderer_config_;
161  context_.SetupSurface(surface_size);
162 #endif
163 }
164 
166 #ifdef SHELL_ENABLE_METAL
167  renderer_config_.type = FlutterRendererType::kMetal;
168  renderer_config_.metal = metal_renderer_config_;
169  context_.SetupSurface(surface_size);
170 #endif
171 }
172 
174  project_args_.assets_path = context_.GetAssetsPath().c_str();
175 }
176 
178  if (auto mapping = context_.GetVMSnapshotData()) {
179  project_args_.vm_snapshot_data = mapping->GetMapping();
180  project_args_.vm_snapshot_data_size = mapping->GetSize();
181  }
182 
183  if (auto mapping = context_.GetVMSnapshotInstructions()) {
184  project_args_.vm_snapshot_instructions = mapping->GetMapping();
185  project_args_.vm_snapshot_instructions_size = mapping->GetSize();
186  }
187 
188  if (auto mapping = context_.GetIsolateSnapshotData()) {
189  project_args_.isolate_snapshot_data = mapping->GetMapping();
190  project_args_.isolate_snapshot_data_size = mapping->GetSize();
191  }
192 
193  if (auto mapping = context_.GetIsolateSnapshotInstructions()) {
194  project_args_.isolate_snapshot_instructions = mapping->GetMapping();
195  project_args_.isolate_snapshot_instructions_size = mapping->GetSize();
196  }
197 }
198 
200  project_args_.aot_data = context_.GetAOTData();
201 }
202 
204  project_args_.root_isolate_create_callback =
206 }
207 
209  project_args_.update_semantics_node_callback =
213 }
214 
216  project_args_.log_message_callback =
218 }
219 
220 void EmbedderConfigBuilder::SetLogTag(std::string tag) {
221  log_tag_ = std::move(tag);
222  project_args_.log_tag = log_tag_.c_str();
223 }
224 
228 }
229 
230 void EmbedderConfigBuilder::SetDartEntrypoint(std::string entrypoint) {
231  if (entrypoint.size() == 0) {
232  return;
233  }
234 
235  dart_entrypoint_ = std::move(entrypoint);
236  project_args_.custom_dart_entrypoint = dart_entrypoint_.c_str();
237 }
238 
240  if (arg.size() == 0) {
241  return;
242  }
243 
244  command_line_arguments_.emplace_back(std::move(arg));
245 }
246 
248  if (arg.size() == 0) {
249  return;
250  }
251 
252  dart_entrypoint_arguments_.emplace_back(std::move(arg));
253 }
254 
256  const FlutterTaskRunnerDescription* runner) {
257  if (runner == nullptr) {
258  return;
259  }
260  custom_task_runners_.platform_task_runner = runner;
261  project_args_.custom_task_runners = &custom_task_runners_;
262 }
263 
265  const FlutterTaskRunnerDescription* runner) {
266  if (runner == nullptr) {
267  return;
268  }
269 
270  custom_task_runners_.render_task_runner = runner;
271  project_args_.custom_task_runners = &custom_task_runners_;
272 }
273 
275  const std::function<void(const FlutterPlatformMessage*)>& callback) {
277 }
278 
279 void EmbedderConfigBuilder::SetCompositor(bool avoid_backing_store_cache) {
280  context_.SetupCompositor();
281  auto& compositor = context_.GetCompositor();
282  compositor_.struct_size = sizeof(compositor_);
283  compositor_.user_data = &compositor;
284  compositor_.create_backing_store_callback =
285  [](const FlutterBackingStoreConfig* config, //
286  FlutterBackingStore* backing_store_out, //
287  void* user_data //
288  ) {
289  return reinterpret_cast<EmbedderTestCompositor*>(user_data)
290  ->CreateBackingStore(config, backing_store_out);
291  };
292  compositor_.collect_backing_store_callback =
293  [](const FlutterBackingStore* backing_store, //
294  void* user_data //
295  ) {
296  return reinterpret_cast<EmbedderTestCompositor*>(user_data)
297  ->CollectBackingStore(backing_store);
298  };
299  compositor_.present_layers_callback = [](const FlutterLayer** layers, //
300  size_t layers_count, //
301  void* user_data //
302  ) {
303  return reinterpret_cast<EmbedderTestCompositor*>(user_data)->Present(
304  layers, //
305  layers_count //
306 
307  );
308  };
309  compositor_.avoid_backing_store_cache = avoid_backing_store_cache;
310  project_args_.compositor = &compositor_;
311 }
312 
314  return compositor_;
315 }
316 
319  auto& compositor = context_.GetCompositor();
320  // TODO(wrightgeorge): figure out a better way of plumbing through the
321  // GrDirectContext
322  compositor.SetBackingStoreProducer(
323  std::make_unique<EmbedderTestBackingStoreProducer>(
324  compositor.GetGrContext(), type));
325 }
326 
328  return SetupEngine(true);
329 }
330 
332  return SetupEngine(false);
333 }
334 
335 UniqueEngine EmbedderConfigBuilder::SetupEngine(bool run) const {
336  FlutterEngine engine = nullptr;
337  FlutterProjectArgs project_args = project_args_;
338 
339  std::vector<const char*> args;
340  args.reserve(command_line_arguments_.size());
341 
342  for (const auto& arg : command_line_arguments_) {
343  args.push_back(arg.c_str());
344  }
345 
346  if (args.size() > 0) {
347  project_args.command_line_argv = args.data();
348  project_args.command_line_argc = args.size();
349  } else {
350  // Clear it out in case this is not the first engine launch from the
351  // embedder config builder.
352  project_args.command_line_argv = nullptr;
353  project_args.command_line_argc = 0;
354  }
355 
356  std::vector<const char*> dart_args;
357  dart_args.reserve(dart_entrypoint_arguments_.size());
358 
359  for (const auto& arg : dart_entrypoint_arguments_) {
360  dart_args.push_back(arg.c_str());
361  }
362 
363  if (dart_args.size() > 0) {
364  project_args.dart_entrypoint_argv = dart_args.data();
365  project_args.dart_entrypoint_argc = dart_args.size();
366  } else {
367  // Clear it out in case this is not the first engine launch from the
368  // embedder config builder.
369  project_args.dart_entrypoint_argv = nullptr;
370  project_args.dart_entrypoint_argc = 0;
371  }
372 
373  auto result =
374  run ? FlutterEngineRun(FLUTTER_ENGINE_VERSION, &renderer_config_,
375  &project_args, &context_, &engine)
376  : FlutterEngineInitialize(FLUTTER_ENGINE_VERSION, &renderer_config_,
377  &project_args, &context_, &engine);
378 
379  if (result != kSuccess) {
380  return {};
381  }
382 
383  return UniqueEngine{engine};
384 }
385 
386 #ifdef SHELL_ENABLE_METAL
387 
388 void EmbedderConfigBuilder::InitializeMetalRendererConfig() {
390  return;
391  }
392 
393  metal_renderer_config_.struct_size = sizeof(metal_renderer_config_);
394  EmbedderTestContextMetal& metal_context =
395  reinterpret_cast<EmbedderTestContextMetal&>(context_);
396 
397  metal_renderer_config_.device =
398  metal_context.GetTestMetalContext()->GetMetalDevice();
399  metal_renderer_config_.present_command_queue =
400  metal_context.GetTestMetalContext()->GetMetalCommandQueue();
401  metal_renderer_config_.get_next_drawable_callback =
402  [](void* user_data, const FlutterFrameInfo* frame_info) {
403  return reinterpret_cast<EmbedderTestContextMetal*>(user_data)
404  ->GetNextDrawable(frame_info);
405  };
406  metal_renderer_config_.present_drawable_callback =
407  [](void* user_data, const FlutterMetalTexture* texture) -> bool {
408  EmbedderTestContextMetal* metal_context =
409  reinterpret_cast<EmbedderTestContextMetal*>(user_data);
410  return metal_context->Present(texture->texture_id);
411  };
412  metal_renderer_config_.external_texture_frame_callback =
413  [](void* user_data, int64_t texture_id, size_t width, size_t height,
414  FlutterMetalExternalTexture* texture_out) -> bool {
415  EmbedderTestContextMetal* metal_context =
416  reinterpret_cast<EmbedderTestContextMetal*>(user_data);
417  return metal_context->PopulateExternalTexture(texture_id, width, height,
418  texture_out);
419  };
420 }
421 
422 #endif // SHELL_ENABLE_METAL
423 
424 } // namespace testing
425 } // namespace flutter
G_BEGIN_DECLS FlValue * args
const FlutterCompositor * compositor
Definition: embedder.h:1528
FlutterSoftwareRendererConfig software
Definition: embedder.h:558
KeyCallType type
virtual EmbedderTestContextType GetContextType() const =0
bool PopulateExternalTexture(int64_t texture_id, size_t w, size_t h, FlutterMetalExternalTexture *output)
G_BEGIN_DECLS FlTexture * texture
const uint8_t * isolate_snapshot_data
Definition: embedder.h:1423
FlutterComputePlatformResolvedLocaleCallback compute_platform_resolved_locale_callback
Definition: embedder.h:1554
uint32_t width
Definition: embedder.h:328
const FlutterTaskRunnerDescription * render_task_runner
Definition: embedder.h:948
const FlutterCustomTaskRunners * custom_task_runners
Definition: embedder.h:1493
size_t vm_snapshot_instructions_size
Definition: embedder.h:1418
EmbedderConfigBuilder(EmbedderTestContext &context, InitializationPreference preference=InitializationPreference::kSnapshotsInitialize)
void * user_data
Dart_NativeFunction function
Definition: fuchsia.cc:51
int64_t texture_id
GAsyncResult * result
void SetCompositor(bool avoid_backing_store_cache=false)
#define FML_LOG(severity)
Definition: logging.h:65
void SetPlatformMessageCallback(const std::function< void(const FlutterPlatformMessage *)> &callback)
FlutterPlatformMessageCallback platform_message_callback
Definition: embedder.h:1402
FlutterLogMessageCallback log_message_callback
Definition: embedder.h:1574
static FlutterUpdateSemanticsNodeCallback GetUpdateSemanticsNodeCallbackHook()
FlKeyEvent FlKeyResponderAsyncCallback callback
const char *const * command_line_argv
Definition: embedder.h:1396
const char * log_tag
Definition: embedder.h:1581
const fml::Mapping * GetVMSnapshotInstructions() const
uint32_t height
Definition: embedder.h:329
bool shutdown_dart_vm_when_done
Definition: embedder.h:1512
const char *const * dart_entrypoint_argv
Definition: embedder.h:1566
const fml::Mapping * GetVMSnapshotData() const
FlutterUIntSize size
The size of the surface that will be backed by the fbo.
Definition: embedder.h:363
virtual void SetupSurface(SkISize surface_size)=0
size_t struct_size
The size of this struct. Must be sizeof(FlutterFrameInfo).
Definition: embedder.h:361
#define FLUTTER_ENGINE_VERSION
Definition: embedder.h:63
FlutterRendererType type
Definition: embedder.h:555
void SetPlatformMessageCallback(const std::function< void(const FlutterPlatformMessage *)> &callback)
FlutterEngineResult FlutterEngineRun(size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
Initialize and run a Flutter engine instance and return a handle to it. This is a convenience method ...
Definition: embedder.cc:869
FlutterEngineAOTData GetAOTData() const
FlutterUpdateSemanticsNodeCallback update_semantics_node_callback
Definition: embedder.h:1446
void SetRenderTaskRunner(const FlutterTaskRunnerDescription *runner)
void SetPlatformTaskRunner(const FlutterTaskRunnerDescription *runner)
FlutterUpdateSemanticsCustomActionCallback update_semantics_custom_action_callback
Definition: embedder.h:1457
const uint8_t * vm_snapshot_data
Definition: embedder.h:1407
static FlutterUpdateSemanticsCustomActionCallback GetUpdateSemanticsCustomActionCallbackHook()
const uint8_t * vm_snapshot_instructions
Definition: embedder.h:1415
int32_t width
FlutterEngineResult FlutterEngineInitialize(size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
Initialize a Flutter engine instance. This does not run the Flutter application code till the Flutter...
Definition: embedder.cc:885
int32_t height
const char * custom_dart_entrypoint
Definition: embedder.h:1488
const char * assets_path
Definition: embedder.h:1354
FlutterOpenGLRendererConfig open_gl
Definition: embedder.h:557
size_t isolate_snapshot_instructions_size
Definition: embedder.h:1434
size_t struct_size
The size of this struct. Must be sizeof(FlutterProjectArgs).
Definition: embedder.h:1350
const char * name
Definition: fuchsia.cc:50
#define FML_CHECK(condition)
Definition: logging.h:68
const std::string & GetAssetsPath() const
UIntCallback fbo_callback
Definition: embedder.h:400
const FlutterTaskRunnerDescription * platform_task_runner
Definition: embedder.h:943
void SetBackingStoreProducer(std::unique_ptr< EmbedderTestBackingStoreProducer > backingstore_producer)
FlutterMetalRendererConfig metal
Definition: embedder.h:559
size_t isolate_snapshot_data_size
Definition: embedder.h:1426
static FlutterComputePlatformResolvedLocaleCallback GetComputePlatformResolvedLocaleCallbackHook()
FlutterEngineAOTData aot_data
Definition: embedder.h:1543
const fml::Mapping * GetIsolateSnapshotInstructions() const
const uint8_t * isolate_snapshot_instructions
Definition: embedder.h:1431
size_t struct_size
The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
Definition: embedder.h:938
VoidCallback root_isolate_create_callback
Definition: embedder.h:1437
size_t vm_snapshot_data_size
Definition: embedder.h:1410
static FlutterLogMessageCallback GetLogMessageCallbackHook()
int command_line_argc
The command line argument count used to initialize the project.
Definition: embedder.h:1380
size_t struct_size
The size of this struct. Must be sizeof(FlutterSoftwareRendererConfig).
Definition: embedder.h:546
void SetRenderTargetType(EmbedderTestBackingStoreProducer::RenderTargetType type)
SoftwareSurfacePresentCallback surface_present_callback
Definition: embedder.h:551
void SetSoftwareRendererConfig(SkISize surface_size=SkISize::Make(1, 1))
const fml::Mapping * GetIsolateSnapshotData() const