Flutter Engine
 
Loading...
Searching...
No Matches
tester_main.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#define FML_USED_ON_EMBEDDER
6
7#include <cstdlib>
8#include <cstring>
9#include <iostream>
10
15#include "flutter/fml/file.h"
18#include "flutter/fml/paths.h"
27
28#include "third_party/abseil-cpp/absl/base/no_destructor.h"
29#include "third_party/dart/runtime/include/bin/dart_io_api.h"
30#include "third_party/dart/runtime/include/dart_api.h"
31#include "third_party/skia/include/core/SkSurface.h"
32
33// Impeller should only be enabled if the Vulkan backend is enabled.
34#define ALLOW_IMPELLER (IMPELLER_SUPPORTS_RENDERING && IMPELLER_ENABLE_VULKAN)
35
36#if ALLOW_IMPELLER
37#include <vulkan/vulkan.h> // nogncheck
38#include "impeller/display_list/aiks_context.h" // nogncheck
39#include "impeller/entity/vk/entity_shaders_vk.h" // nogncheck
40#include "impeller/entity/vk/framebuffer_blend_shaders_vk.h" // nogncheck
41#include "impeller/entity/vk/modern_shaders_vk.h" // nogncheck
44#include "impeller/renderer/context.h" // nogncheck
45#include "impeller/renderer/vk/compute_shaders_vk.h" // nogncheck
46#include "shell/gpu/gpu_surface_vulkan_impeller.h" // nogncheck
47
48static std::vector<std::shared_ptr<fml::Mapping>> ShaderLibraryMappings() {
49 return {
50 std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_vk_data,
51 impeller_entity_shaders_vk_length),
52 std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_vk_data,
53 impeller_modern_shaders_vk_length),
54 std::make_shared<fml::NonOwnedMapping>(
55 impeller_framebuffer_blend_shaders_vk_data,
56 impeller_framebuffer_blend_shaders_vk_length),
57 std::make_shared<fml::NonOwnedMapping>(
58 impeller_compute_shaders_vk_data, impeller_compute_shaders_vk_length),
59 };
60}
61
65 std::shared_ptr<impeller::ContextVK> context;
66 std::shared_ptr<impeller::SurfaceContextVK> surface_context;
67
68 bool Initialize(bool enable_validation);
69};
70
71bool ImpellerVulkanContextHolder::Initialize(bool enable_validation) {
72 impeller::ContextVK::Settings context_settings;
73 context_settings.proc_address_callback = &vkGetInstanceProcAddr;
74 context_settings.shader_libraries_data = ShaderLibraryMappings();
76 context_settings.enable_validation = enable_validation;
77 // Enable lazy shader mode for faster test execution as most tests
78 // will never render anything at all.
79 context_settings.flags.lazy_shader_mode = true;
80
81 context = impeller::ContextVK::Create(std::move(context_settings));
82 if (!context || !context->IsValid()) {
83 VALIDATION_LOG << "Could not create Vulkan context.";
84 return false;
85 }
86
87 impeller::vk::SurfaceKHR vk_surface;
88 impeller::vk::HeadlessSurfaceCreateInfoEXT surface_create_info;
89 auto res = context->GetInstance().createHeadlessSurfaceEXT(
90 &surface_create_info, // surface create info
91 nullptr, // allocator
92 &vk_surface // surface
93 );
94 if (res != impeller::vk::Result::eSuccess) {
95 VALIDATION_LOG << "Could not create surface for tester "
96 << impeller::vk::to_string(res);
97 return false;
98 }
99
100 impeller::vk::UniqueSurfaceKHR surface{vk_surface, context->GetInstance()};
101 surface_context = context->CreateSurfaceContext();
102 if (!surface_context->SetWindowSurface(std::move(surface),
103 impeller::ISize{1, 1})) {
104 VALIDATION_LOG << "Could not set up surface for context.";
105 return false;
106 }
107 return true;
108}
109
110#else
112#endif // IMPELLER_SUPPORTS_RENDERING
113
114#if defined(FML_OS_WIN)
115#include <combaseapi.h>
116#endif // defined(FML_OS_WIN)
117
118#if defined(FML_OS_POSIX)
119#include <signal.h>
120#endif // defined(FML_OS_POSIX)
121
122namespace flutter {
123
124static absl::NoDestructor<std::unique_ptr<Shell>> g_shell;
125
126static constexpr int64_t kImplicitViewId = 0ll;
127
128static void ConfigureShell(Shell* shell) {
129 auto device_pixel_ratio = 3.0;
130 auto physical_width = 2400.0; // 800 at 3x resolution.
131 auto physical_height = 1800.0; // 600 at 3x resolution.
132
133 std::vector<std::unique_ptr<Display>> displays;
134 displays.push_back(std::make_unique<Display>(
135 0, 60, physical_width, physical_height, device_pixel_ratio));
136 shell->OnDisplayUpdates(std::move(displays));
137
138 flutter::ViewportMetrics metrics{};
139 metrics.device_pixel_ratio = device_pixel_ratio;
140 metrics.physical_width = physical_width;
141 metrics.physical_height = physical_height;
142 metrics.display_id = 0;
143 metrics.physical_min_width_constraint = physical_width;
144 metrics.physical_max_width_constraint = physical_width;
145 metrics.physical_min_height_constraint = physical_height;
146 metrics.physical_max_height_constraint = physical_height;
147 shell->GetPlatformView()->SetViewportMetrics(kImplicitViewId, metrics);
148}
149
151 // |ExternalViewEmbedder|
152 DlCanvas* GetRootCanvas() override { return nullptr; }
153
154 // |ExternalViewEmbedder|
155 void CancelFrame() override {}
156
157 // |ExternalViewEmbedder|
158 void BeginFrame(GrDirectContext* context,
160 raster_thread_merger) override {}
161
162 // |ExternalViewEmbedder|
163 void PrepareFlutterView(DlISize frame_size,
164 double device_pixel_ratio) override {}
165
166 // |ExternalViewEmbedder|
167 void PrerollCompositeEmbeddedView(
168 int64_t view_id,
169 std::unique_ptr<EmbeddedViewParams> params) override {}
170
171 // |ExternalViewEmbedder|
172 DlCanvas* CompositeEmbeddedView(int64_t view_id) override {
173 return &builder_;
174 }
175
176 private:
177 DisplayListBuilder builder_;
178};
179
181 public:
183 bool render_to_surface)
184 : GPUSurfaceSoftware(delegate, render_to_surface) {}
185
186 bool EnableRasterCache() const override { return false; }
187};
188
191 public:
193 const TaskRunners& task_runners,
194 ImpellerVulkanContextHolder&& impeller_context_holder)
195 : PlatformView(delegate, task_runners),
196 impeller_context_holder_(std::move(impeller_context_holder)) {}
197
199#if ALLOW_IMPELLER
200 if (impeller_context_holder_.context) {
201 impeller_context_holder_.context->Shutdown();
202 }
203#endif
204 }
205
206 // |PlatformView|
207 std::shared_ptr<impeller::Context> GetImpellerContext() const override {
208#if ALLOW_IMPELLER
209 return std::static_pointer_cast<impeller::Context>(
210 impeller_context_holder_.context);
211#else
212 return nullptr;
213#endif // ALLOW_IMPELLER
214 }
215
216 // |PlatformView|
217 std::unique_ptr<Surface> CreateRenderingSurface() override {
218#if ALLOW_IMPELLER
220 FML_DCHECK(impeller_context_holder_.context);
221 auto surface = std::make_unique<GPUSurfaceVulkanImpeller>(
222 nullptr, impeller_context_holder_.surface_context);
223 FML_DCHECK(surface->IsValid());
224 return surface;
225 }
226#endif // ALLOW_IMPELLER
227 auto surface = std::make_unique<TesterGPUSurfaceSoftware>(
228 this, true /* render to surface */);
229 FML_DCHECK(surface->IsValid());
230 return surface;
231 }
232
233 // |GPUSurfaceSoftwareDelegate|
234 sk_sp<SkSurface> AcquireBackingStore(const DlISize& size) override {
235 if (sk_surface_ != nullptr && //
236 sk_surface_->width() == size.width &&
237 sk_surface_->height() == size.height) {
238 // The old and new surface sizes are the same. Nothing to do here.
239 return sk_surface_;
240 }
241
242 SkImageInfo info = SkImageInfo::MakeN32(
243 size.width, size.height, kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
244 sk_surface_ = SkSurfaces::Raster(info, nullptr);
245
246 if (sk_surface_ == nullptr) {
247 FML_LOG(ERROR)
248 << "Could not create backing store for software rendering.";
249 return nullptr;
250 }
251
252 return sk_surface_;
253 }
254
255 // |GPUSurfaceSoftwareDelegate|
256 bool PresentBackingStore(sk_sp<SkSurface> backing_store) override {
257 return true;
258 }
259
260 // |PlatformView|
261 std::shared_ptr<ExternalViewEmbedder> CreateExternalViewEmbedder() override {
262 return external_view_embedder_;
263 }
264
265 private:
266 sk_sp<SkSurface> sk_surface_ = nullptr;
267 [[maybe_unused]] ImpellerVulkanContextHolder impeller_context_holder_;
268 std::shared_ptr<TesterExternalViewEmbedder> external_view_embedder_ =
269 std::make_shared<TesterExternalViewEmbedder>();
270};
271
272// Checks whether the engine's main Dart isolate has no pending work. If so,
273// then exit the given message loop.
275 public:
277 fml::RefPtr<fml::TaskRunner> main_task_runner,
278 fml::RefPtr<fml::TaskRunner> ui_task_runner,
279 bool run_forever)
280 : shell_(shell),
281 main_task_runner_(std::move(main_task_runner)),
282 ui_task_runner_(std::move(ui_task_runner)),
283 run_forever_(run_forever) {}
284
286 return static_cast<int>(last_error_.value_or(DartErrorCode::NoError));
287 }
288
290 last_error_ = shell_.GetUIIsolateLastError();
291 if (shell_.EngineHasLivePorts()) {
292 // The UI isolate still has live ports and is running. Nothing to do
293 // just yet.
294 return;
295 }
296 if (shell_.EngineHasPendingMicrotasks()) {
297 // Post an empty task to force a run of the engine task observer that
298 // drains the microtask queue.
299 ui_task_runner_->PostTask([] {});
300 return;
301 }
302
303 if (run_forever_) {
304 // We need this script to run forever. We have already recorded the last
305 // error. Keep going.
306 return;
307 }
308
309 if (!has_terminated_) {
310 // Only try to terminate the loop once.
311 has_terminated_ = true;
312 fml::TaskRunner::RunNowOrPostTask(main_task_runner_, []() {
314 });
315 }
316 }
317
318 private:
319 Shell& shell_;
320 fml::RefPtr<fml::TaskRunner> main_task_runner_;
321 fml::RefPtr<fml::TaskRunner> ui_task_runner_;
322 bool run_forever_ = false;
323 std::optional<DartErrorCode> last_error_;
324 bool has_terminated_ = false;
325
327};
328
329// Processes spawned via dart:io inherit their signal handling from the parent
330// process. As part of spawning, the spawner blocks signals temporarily, so we
331// need to explicitly unblock the signals we care about in the new process. In
332// particular, we need to unblock SIGPROF for CPU profiling to work on the
333// mutator thread in the main isolate in this process (threads spawned by the VM
334// know about this limitation and automatically have this signal unblocked).
335static void UnblockSIGPROF() {
336#if defined(FML_OS_POSIX)
337 sigset_t set;
338 sigemptyset(&set);
339 sigaddset(&set, SIGPROF);
340 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
341#endif // defined(FML_OS_POSIX)
342}
343
344int RunTester(const flutter::Settings& settings,
345 bool run_forever,
346 bool multithreaded) {
347 const auto thread_label = "io.flutter.test.";
348
349 // Necessary if we want to use the CPU profiler on the main isolate's mutator
350 // thread.
351 //
352 // OSX WARNING: avoid spawning additional threads before this call due to a
353 // kernel bug that may enable SIGPROF on an unintended thread in the process.
355
357
358 auto current_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
359
360 std::unique_ptr<ThreadHost> threadhost;
361 fml::RefPtr<fml::TaskRunner> platform_task_runner;
362 fml::RefPtr<fml::TaskRunner> raster_task_runner;
363 fml::RefPtr<fml::TaskRunner> ui_task_runner;
364 fml::RefPtr<fml::TaskRunner> io_task_runner;
365
366 if (multithreaded) {
367 threadhost = std::make_unique<ThreadHost>(
370 platform_task_runner = current_task_runner;
371 raster_task_runner = threadhost->raster_thread->GetTaskRunner();
372 ui_task_runner = threadhost->ui_thread->GetTaskRunner();
373 io_task_runner = threadhost->io_thread->GetTaskRunner();
374 } else {
375 platform_task_runner = raster_task_runner = ui_task_runner =
376 io_task_runner = current_task_runner;
377 }
378
379 const flutter::TaskRunners task_runners(thread_label, // dart thread label
380 platform_task_runner, // platform
381 raster_task_runner, // raster
382 ui_task_runner, // ui
383 io_task_runner // io
384 );
385
386 ImpellerVulkanContextHolder impeller_context_holder;
387
388#if ALLOW_IMPELLER
389 if (settings.enable_impeller) {
390 if (!impeller_context_holder.Initialize(
391 settings.enable_vulkan_validation)) {
392 return EXIT_FAILURE;
393 }
394 }
395#endif // ALLOW_IMPELLER
396
397 Shell::CreateCallback<PlatformView> on_create_platform_view =
398 fml::MakeCopyable([impeller_context_holder = std::move(
399 impeller_context_holder)](Shell& shell) mutable {
400 return std::make_unique<TesterPlatformView>(
401 shell, shell.GetTaskRunners(), std::move(impeller_context_holder));
402 });
403
404 Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
405 return std::make_unique<Rasterizer>(
407 };
408
410 task_runners, //
411 settings, //
412 on_create_platform_view, //
413 on_create_rasterizer //
414 )
415 .release());
416 auto shell = g_shell->get();
417
418 if (!shell || !shell->IsSetup()) {
419 FML_LOG(ERROR) << "Could not set up the shell.";
420 return EXIT_FAILURE;
421 }
422
423 if (settings.application_kernel_asset.empty()) {
424 FML_LOG(ERROR) << "Dart kernel file not specified.";
425 return EXIT_FAILURE;
426 }
427
428 shell->GetPlatformView()->NotifyCreated();
429
430 // Initialize default testing locales. There is no platform to
431 // pass locales on the tester, so to retain expected locale behavior,
432 // we emulate it in here by passing in 'en_US' and 'zh_CN' as test locales.
433 const char* locale_json =
434 "{\"method\":\"setLocale\",\"args\":[\"en\",\"US\",\"\",\"\",\"zh\","
435 "\"CN\",\"\",\"\"]}";
436 auto locale_bytes = fml::MallocMapping::Copy(
437 locale_json, locale_json + std::strlen(locale_json));
439 shell->GetPlatformView()->DispatchPlatformMessage(
440 std::make_unique<flutter::PlatformMessage>(
441 "flutter/localization", std::move(locale_bytes), response));
442
443 std::initializer_list<fml::FileMapping::Protection> protection = {
445 auto main_dart_file_mapping = std::make_unique<fml::FileMapping>(
449 protection);
450
451 auto isolate_configuration =
452 IsolateConfiguration::CreateForKernel(std::move(main_dart_file_mapping));
453
454 if (!isolate_configuration) {
455 FML_LOG(ERROR) << "Could create isolate configuration.";
456 return EXIT_FAILURE;
457 }
458
459 auto asset_manager = std::make_shared<flutter::AssetManager>();
460 asset_manager->PushBack(std::make_unique<flutter::DirectoryAssetBundle>(
461 fml::Duplicate(settings.assets_dir), true));
462 asset_manager->PushBack(std::make_unique<flutter::DirectoryAssetBundle>(
463 fml::OpenDirectory(settings.assets_path.c_str(), false,
465 true));
466
467 RunConfiguration run_configuration(std::move(isolate_configuration),
468 std::move(asset_manager));
469
470 // The script completion task observer that will be installed on the UI thread
471 // that watched if the engine has any live ports.
472 ScriptCompletionTaskObserver completion_observer(
473 *shell, // a valid shell
475 .GetTaskRunner(), // the message loop to terminate
476 ui_task_runner, // runner for Dart microtasks
477 run_forever // should the exit be ignored
478 );
479
480 bool engine_did_run = false;
481
483 auto task_observer_add = [&completion_observer]() {
485 reinterpret_cast<intptr_t>(&completion_observer),
486 [&completion_observer]() { completion_observer.DidProcessTask(); });
487 };
488
489 auto task_observer_remove = [&completion_observer, &latch]() {
491 reinterpret_cast<intptr_t>(&completion_observer));
492 latch.Signal();
493 };
494
495 shell->RunEngine(std::move(run_configuration),
496 [&engine_did_run, &ui_task_runner,
497 &task_observer_add](Engine::RunStatus run_status) mutable {
498 if (run_status != flutter::Engine::RunStatus::Failure) {
499 engine_did_run = true;
500 // Now that our engine is initialized we can install the
501 // ScriptCompletionTaskObserver
503 task_observer_add);
504 }
505 });
506
507 ConfigureShell(shell);
508
509 // Run the message loop and wait for the script to do its thing.
511
512 // Cleanup the completion observer synchronously as it is living on the
513 // stack.
514 fml::TaskRunner::RunNowOrPostTask(ui_task_runner, task_observer_remove);
515 latch.Wait();
516
517 delete g_shell->release();
518
519 if (!engine_did_run) {
520 // If the engine itself didn't have a chance to run, there is no point in
521 // asking it if there was an error. Signal a failure unconditionally.
522 return EXIT_FAILURE;
523 }
524
525 return completion_observer.GetExitCodeForLastError();
526}
527
528#ifdef _WIN32
529#define EXPORTED __declspec(dllexport)
530#else
531#define EXPORTED __attribute__((visibility("default")))
532#endif
533
534extern "C" {
535EXPORTED Dart_Handle LoadLibraryFromKernel(const char* path) {
536 std::shared_ptr<fml::FileMapping> mapping =
538 if (!mapping) {
539 return Dart_Null();
540 }
542}
543
544EXPORTED Dart_Handle LookupEntryPoint(const char* uri, const char* name) {
545 if (!uri || !name) {
546 return Dart_Null();
547 }
548 Dart_Handle lib = Dart_LookupLibrary(Dart_NewStringFromCString(uri));
549 if (Dart_IsError(lib)) {
550 return lib;
551 }
552 return Dart_GetField(lib, Dart_NewStringFromCString(name));
553}
554
555EXPORTED void Spawn(const char* entrypoint, const char* route) {
556 auto shell = g_shell->get();
557 auto isolate = Dart_CurrentIsolate();
558 auto spawn_task = [shell, entrypoint = std::string(entrypoint),
559 route = std::string(route)]() {
560 auto configuration = RunConfiguration::InferFromSettings(
561 shell->GetSettings(), /*io_worker=*/nullptr,
562 /*launch_type=*/IsolateLaunchType::kExistingGroup);
563 configuration.SetEntrypoint(entrypoint);
564
565 Shell::CreateCallback<PlatformView> on_create_platform_view =
566 fml::MakeCopyable([](Shell& shell) mutable {
567 ImpellerVulkanContextHolder impeller_context_holder;
568 return std::make_unique<TesterPlatformView>(
569 shell, shell.GetTaskRunners(),
570 std::move(impeller_context_holder));
571 });
572
573 Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
574 return std::make_unique<Rasterizer>(
576 };
577
578 // Spawn a shell, and keep it running until it has no live ports, then
579 // delete it on the platform thread.
580 auto spawned_shell =
581 shell
582 ->Spawn(std::move(configuration), route, on_create_platform_view,
583 on_create_rasterizer)
584 .release();
585
586 ConfigureShell(spawned_shell);
587
589 spawned_shell->GetTaskRunners().GetUITaskRunner(), [spawned_shell]() {
590 fml::MessageLoop::GetCurrent().AddTaskObserver(
591 reinterpret_cast<intptr_t>(spawned_shell), [spawned_shell]() {
592 if (spawned_shell->EngineHasLivePorts()) {
593 return;
594 }
595
596 fml::MessageLoop::GetCurrent().RemoveTaskObserver(
597 reinterpret_cast<intptr_t>(spawned_shell));
598 // Shell must be deleted on the platform task runner.
599 fml::TaskRunner::RunNowOrPostTask(
600 spawned_shell->GetTaskRunners().GetPlatformTaskRunner(),
601 [spawned_shell]() { delete spawned_shell; });
602 });
603 });
604 };
605 Dart_ExitIsolate();
606 // The global shell pointer is never deleted, short of application exit.
607 // This UI task runner cannot be latched because it will block spawning a new
608 // shell in the case where flutter_tester is running multithreaded.
610 shell->GetTaskRunners().GetPlatformTaskRunner(), spawn_task);
611
612 Dart_EnterIsolate(isolate);
613}
614
616 // Enable Isolate.exit().
617 FML_DCHECK(Dart_CurrentIsolate() != nullptr);
618 Dart_Handle isolate_lib = Dart_LookupLibrary(tonic::ToDart("dart:isolate"));
620 Dart_Handle isolate_type = Dart_GetNonNullableType(
621 isolate_lib, tonic::ToDart("Isolate"), 0, nullptr);
623 Dart_Handle result =
624 Dart_SetField(isolate_type, tonic::ToDart("_mayExit"), Dart_True());
626}
627}
628
629} // namespace flutter
630
631int main(int argc, char* argv[]) {
632 dart::bin::SetExecutableName(argv[0]);
633 dart::bin::SetExecutableArguments(argc - 1, argv);
634
635 auto command_line = fml::CommandLineFromPlatformOrArgcArgv(argc, argv);
636
637 if (command_line.HasOption(flutter::FlagForSwitch(flutter::Switch::Help))) {
638 flutter::PrintUsage("flutter_tester");
639 return EXIT_SUCCESS;
640 }
641
642 auto settings = flutter::SettingsFromCommandLine(command_line);
643 if (!command_line.positional_args().empty()) {
644 // The tester may not use the switch for the main dart file path. Specifying
645 // it as a positional argument instead.
646 settings.application_kernel_asset = command_line.positional_args()[0];
647 }
648
649 if (settings.application_kernel_asset.empty()) {
650 FML_LOG(ERROR) << "Dart kernel file not specified.";
651 return EXIT_FAILURE;
652 }
653
654 settings.leak_vm = false;
655 settings.enable_platform_isolates = true;
656
657 if (settings.icu_data_path.empty()) {
658 settings.icu_data_path = "icudtl.dat";
659 }
660
661 // The tools that read logs get confused if there is a log tag specified.
662 settings.log_tag = "";
663
664 settings.log_message_callback = [](const std::string& tag,
665 const std::string& message) {
666 if (!tag.empty()) {
667 std::cout << tag << ": ";
668 }
669 std::cout << message << std::endl;
670 };
671
672 settings.task_observer_add = [](intptr_t key, const fml::closure& callback) {
675 callback);
676 return queue_id;
677 };
678
679 settings.task_observer_remove = [](fml::TaskQueueId queue_id, intptr_t key) {
681 key);
682 };
683
684 settings.unhandled_exception_callback = [](const std::string& error,
685 const std::string& stack_trace) {
686 FML_LOG(ERROR) << "Unhandled exception" << std::endl
687 << "Exception: " << error << std::endl
688 << "Stack trace: " << stack_trace;
689 ::exit(1);
690 return true;
691 };
692
693#if defined(FML_OS_WIN)
694 CoInitializeEx(nullptr, COINIT_MULTITHREADED);
695#endif // defined(FML_OS_WIN)
696
697 return flutter::RunTester(settings,
698 command_line.HasOption(flutter::FlagForSwitch(
699 flutter::Switch::RunForever)),
700 command_line.HasOption(flutter::FlagForSwitch(
701 flutter::Switch::ForceMultithreading)));
702}
static Dart_Handle LoadLibraryFromKernel(const std::shared_ptr< const fml::Mapping > &mapping)
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
RunStatus
Indicates the result of the call to Engine::Run.
Definition engine.h:74
Interface implemented by all platform surfaces that can present a software backing store to the "scre...
static std::unique_ptr< IsolateConfiguration > CreateForKernel(std::unique_ptr< const fml::Mapping > kernel)
Creates a JIT isolate configuration using the specified snapshot. This is a convenience method for th...
Used to forward events from the platform view to interested subsystems. This forwarding is done by th...
virtual const Settings & OnPlatformViewGetSettings() const =0
Called by the platform view on the platform thread to get the settings object associated with the pla...
Platform views are created by the shell on the platform task runner. Unless explicitly specified,...
PlatformView::Delegate & delegate_
Specifies all the configuration required by the runtime library to launch the root isolate....
static RunConfiguration InferFromSettings(const Settings &settings, const fml::RefPtr< fml::TaskRunner > &io_worker=nullptr, IsolateLaunchType launch_type=IsolateLaunchType::kNewGroup)
Attempts to infer a run configuration from the settings object. This tries to create a run configurat...
ScriptCompletionTaskObserver(Shell &shell, fml::RefPtr< fml::TaskRunner > main_task_runner, fml::RefPtr< fml::TaskRunner > ui_task_runner, bool run_forever)
std::optional< DartErrorCode > GetUIIsolateLastError() const
Used by embedders to get the last error from the Dart UI Isolate, if one exists.
Definition shell.cc:792
static std::unique_ptr< Shell > Create(const PlatformData &platform_data, const TaskRunners &task_runners, Settings settings, const CreateCallback< PlatformView > &on_create_platform_view, const CreateCallback< Rasterizer > &on_create_rasterizer, bool is_gpu_disabled=false)
Creates a shell instance using the provided settings. The callbacks to create the various shell subco...
Definition shell.cc:221
bool EngineHasLivePorts() const
Used by embedders to check if the Engine is running and has any live ports remaining....
Definition shell.cc:812
void RunEngine(RunConfiguration run_configuration)
Starts an isolate for the given RunConfiguration.
Definition shell.cc:754
std::unique_ptr< Shell > Spawn(RunConfiguration run_configuration, const std::string &initial_route, const CreateCallback< PlatformView > &on_create_platform_view, const CreateCallback< Rasterizer > &on_create_rasterizer) const
Creates one Shell from another Shell where the created Shell takes the opportunity to share any inter...
Definition shell.cc:672
bool EngineHasPendingMicrotasks() const
Used by embedders to check if the Engine is running and has any microtasks that have been queued but ...
Definition shell.cc:823
void OnDisplayUpdates(std::vector< std::unique_ptr< Display > > displays)
Notifies the display manager of the updates.
Definition shell.cc:2381
const TaskRunners & GetTaskRunners() const override
If callers wish to interact directly with any shell subcomponents, they must (on the platform thread)...
Definition shell.cc:911
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
Definition shell.h:121
bool IsSetup() const
Used by embedders to check if all shell subcomponents are initialized. It is the embedder's responsib...
Definition shell.cc:834
fml::WeakPtr< PlatformView > GetPlatformView()
Platform views may only be accessed on the platform task runner.
Definition shell.cc:930
bool EnableRasterCache() const override
TesterGPUSurfaceSoftware(GPUSurfaceSoftwareDelegate *delegate, bool render_to_surface)
std::shared_ptr< ExternalViewEmbedder > CreateExternalViewEmbedder() override
sk_sp< SkSurface > AcquireBackingStore(const DlISize &size) override
Called when the GPU surface needs a new buffer to render a new frame into.
std::unique_ptr< Surface > CreateRenderingSurface() override
std::shared_ptr< impeller::Context > GetImpellerContext() const override
bool PresentBackingStore(sk_sp< SkSurface > backing_store) override
Called by the platform when a frame has been rendered into the backing store and the platform must di...
TesterPlatformView(Delegate &delegate, const TaskRunners &task_runners, ImpellerVulkanContextHolder &&impeller_context_holder)
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
Definition mapping.cc:20
static MallocMapping Copy(const T *begin, const T *end)
Definition mapping.h:162
void RemoveTaskObserver(intptr_t key)
static void EnsureInitializedForCurrentThread()
void AddTaskObserver(intptr_t key, const fml::closure &callback)
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
static TaskQueueId GetCurrentTaskQueueId()
static MessageLoopTaskQueues * GetInstance()
void AddTaskObserver(TaskQueueId queue_id, intptr_t key, const fml::closure &callback)
void RemoveTaskObserver(TaskQueueId queue_id, intptr_t key)
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
virtual void PostTask(const fml::closure &task) override
static std::shared_ptr< ContextVK > Create(Settings settings)
const EmbeddedViewParams * params
VkSurfaceKHR surface
Definition main.cc:65
G_BEGIN_DECLS GBytes * message
const uint8_t uint32_t uint32_t GError ** error
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
#define FML_LOG(severity)
Definition logging.h:101
#define FML_CHECK(condition)
Definition logging.h:104
#define FML_DCHECK(condition)
Definition logging.h:122
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
char ** argv
Definition library.h:9
static void UnblockSIGPROF()
EXPORTED Dart_Handle LookupEntryPoint(const char *uri, const char *name)
@ NoError
No error has occurred.
int RunTester(const flutter::Settings &settings, bool run_forever, bool multithreaded)
void PrintUsage(const std::string &executable_name)
Definition switches.cc:89
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
DEF_SWITCHES_START aot vmservice shared library name
Definition switch_defs.h:27
constexpr FlutterViewId kImplicitViewId
EXPORTED void ForceShutdownIsolate()
static void ConfigureShell(Shell *shell)
static absl::NoDestructor< std::unique_ptr< Shell > > g_shell
Settings SettingsFromCommandLine(const fml::CommandLine &command_line, bool require_merged_platform_ui_thread)
Definition switches.cc:230
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition switch_defs.h:71
EXPORTED void Spawn(const char *entrypoint, const char *route)
EXPORTED Dart_Handle LoadLibraryFromKernel(const char *path)
const std::string_view FlagForSwitch(Switch swtch)
Definition switches.cc:146
std::string AbsolutePath(const std::string &path)
fml::UniqueFD GetCachesDirectory()
fml::UniqueFD Duplicate(fml::UniqueFD::element_type descriptor)
fml::UniqueFD OpenDirectory(const char *path, bool create_if_necessary, FilePermission permission)
Definition file_posix.cc:97
internal::CopyableLambda< T > MakeCopyable(T lambda)
std::function< void()> closure
Definition closure.h:14
CommandLine CommandLineFromPlatformOrArgcArgv(int argc, const char *const *argv)
fml::UniqueFD OpenFile(const char *path, bool create_if_necessary, FilePermission permission)
This can open a directory on POSIX, but not on Windows.
Definition file_posix.cc:66
void Initialize(zx::channel directory_request, std::optional< zx::eventpair > view_ref)
Initializes Dart bindings for the Fuchsia application model.
Definition fuchsia.cc:102
Definition ref_ptr.h:261
Dart_Handle ToDart(const T &object)
bool CheckAndHandleError(Dart_Handle handle)
Definition dart_error.cc:33
std::vector< FlutterEngineDisplay > * displays
std::string application_kernel_asset
Definition settings.h:140
fml::UniqueFD::element_type assets_dir
Definition settings.h:331
std::string assets_path
Definition settings.h:333
bool enable_vulkan_validation
Definition settings.h:252
std::vector< std::shared_ptr< fml::Mapping > > shader_libraries_data
Definition context_vk.h:81
PFN_vkGetInstanceProcAddr proc_address_callback
Definition context_vk.h:80
bool lazy_shader_mode
Definition flags.h:12
int main(int argc, char *argv[])
#define EXPORTED
#define VALIDATION_LOG
Definition validation.h:91