5#define FML_USED_ON_EMBEDDER
11#include "flutter/assets/asset_manager.h"
12#include "flutter/assets/directory_asset_bundle.h"
13#include "flutter/flow/embedded_views.h"
14#include "flutter/fml/build_config.h"
15#include "flutter/fml/file.h"
16#include "flutter/fml/make_copyable.h"
17#include "flutter/fml/message_loop.h"
18#include "flutter/fml/paths.h"
19#include "flutter/fml/synchronization/waitable_event.h"
20#include "flutter/fml/task_runner.h"
21#include "flutter/shell/common/platform_view.h"
22#include "flutter/shell/common/rasterizer.h"
23#include "flutter/shell/common/shell.h"
24#include "flutter/shell/common/switches.h"
25#include "flutter/shell/common/thread_host.h"
26#include "flutter/shell/gpu/gpu_surface_software.h"
27#include "flutter/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"
34#define ALLOW_IMPELLER (IMPELLER_SUPPORTS_RENDERING && IMPELLER_ENABLE_VULKAN)
38#include "impeller/entity/vk/entity_shaders_vk.h"
39#include "impeller/entity/vk/framebuffer_blend_shaders_vk.h"
40#include "impeller/entity/vk/modern_shaders_vk.h"
44#include "impeller/renderer/vk/compute_shaders_vk.h"
47#include "impeller/scene/shaders/vk/scene_shaders_vk.h"
52 std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_vk_data,
53 impeller_entity_shaders_vk_length),
54 std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_vk_data,
55 impeller_modern_shaders_vk_length),
56 std::make_shared<fml::NonOwnedMapping>(
57 impeller_framebuffer_blend_shaders_vk_data,
58 impeller_framebuffer_blend_shaders_vk_length),
60 std::make_shared<fml::NonOwnedMapping>(impeller_scene_shaders_vk_data,
61 impeller_scene_shaders_vk_length),
63 std::make_shared<fml::NonOwnedMapping>(
64 impeller_compute_shaders_vk_data, impeller_compute_shaders_vk_length),
71 std::shared_ptr<impeller::ContextVK> context;
72 std::shared_ptr<impeller::SurfaceContextVK> surface_context;
85 if (!context || !context->IsValid()) {
90 impeller::vk::SurfaceKHR vk_surface;
91 impeller::vk::HeadlessSurfaceCreateInfoEXT surface_create_info;
92 auto res = context->GetInstance().createHeadlessSurfaceEXT(
97 if (res != impeller::vk::Result::eSuccess) {
103 impeller::vk::UniqueSurfaceKHR
surface{vk_surface, context->GetInstance()};
104 surface_context = context->CreateSurfaceContext();
105 if (!surface_context->SetWindowSurface(std::move(
surface),
117#if defined(FML_OS_WIN)
118#include <combaseapi.h>
121#if defined(FML_OS_POSIX)
127static absl::NoDestructor<std::unique_ptr<Shell>>
g_shell;
132 auto device_pixel_ratio = 3.0;
133 auto physical_width = 2400.0;
134 auto physical_height = 1800.0;
136 std::vector<std::unique_ptr<Display>> displays;
137 displays.push_back(std::make_unique<Display>(
138 0, 60, physical_width, physical_height, device_pixel_ratio));
139 shell->OnDisplayUpdates(std::move(displays));
143 metrics.physical_width = physical_width;
144 metrics.physical_height = physical_height;
145 metrics.display_id = 0;
151 DlCanvas* GetRootCanvas()
override {
return nullptr; }
154 void CancelFrame()
override {}
159 raster_thread_merger)
override {}
162 void PrepareFlutterView(
SkISize frame_size,
163 double device_pixel_ratio)
override {}
166 void PrerollCompositeEmbeddedView(
168 std::unique_ptr<EmbeddedViewParams>
params)
override {}
171 DlCanvas* CompositeEmbeddedView(int64_t view_id)
override {
182 bool render_to_surface)
195 impeller_context_holder_(
std::move(impeller_context_holder)) {}
199 if (impeller_context_holder_.context) {
200 impeller_context_holder_.context->Shutdown();
208 return std::static_pointer_cast<impeller::Context>(
209 impeller_context_holder_.context);
220 auto surface = std::make_unique<GPUSurfaceVulkanImpeller>(
221 impeller_context_holder_.surface_context);
226 auto surface = std::make_unique<TesterGPUSurfaceSoftware>(
234 if (sk_surface_ !=
nullptr &&
245 if (sk_surface_ ==
nullptr) {
247 <<
"Could not create backing store for software rendering.";
261 return external_view_embedder_;
267 std::shared_ptr<TesterExternalViewEmbedder> external_view_embedder_ =
268 std::make_shared<TesterExternalViewEmbedder>();
279 main_task_runner_(
std::move(main_task_runner)),
280 run_forever_(run_forever) {}
300 if (!has_terminated_) {
302 has_terminated_ =
true;
312 bool run_forever_ =
false;
313 std::optional<DartErrorCode> last_error_;
314 bool has_terminated_ =
false;
326#if defined(FML_OS_POSIX)
329 sigaddset(&
set, SIGPROF);
330 pthread_sigmask(SIG_UNBLOCK, &
set, NULL);
336 bool multithreaded) {
337 const auto thread_label =
"io.flutter.test.";
350 std::unique_ptr<ThreadHost> threadhost;
357 threadhost = std::make_unique<ThreadHost>(
358 thread_label, ThreadHost::Type::kPlatform | ThreadHost::Type::kIo |
360 platform_task_runner = current_task_runner;
361 raster_task_runner = threadhost->raster_thread->GetTaskRunner();
362 ui_task_runner = threadhost->ui_thread->GetTaskRunner();
363 io_task_runner = threadhost->io_thread->GetTaskRunner();
365 platform_task_runner = raster_task_runner = ui_task_runner =
366 io_task_runner = current_task_runner;
370 platform_task_runner,
380 if (!impeller_context_holder.Initialize(
381 settings.enable_vulkan_validation)) {
389 impeller_context_holder)](
Shell&
shell)
mutable {
390 return std::make_unique<TesterPlatformView>(
391 shell,
shell.GetTaskRunners(), std::move(impeller_context_holder));
395 return std::make_unique<Rasterizer>(
402 on_create_platform_view,
413 if (
settings.application_kernel_asset.empty()) {
418 shell->GetPlatformView()->NotifyCreated();
423 const char* locale_json =
424 "{\"method\":\"setLocale\",\"args\":[\"en\",\"US\",\"\",\"\",\"zh\","
425 "\"CN\",\"\",\"\"]}";
427 locale_json, locale_json + std::strlen(locale_json));
429 shell->GetPlatformView()->DispatchPlatformMessage(
430 std::make_unique<flutter::PlatformMessage>(
431 "flutter/localization", std::move(locale_bytes), response));
433 std::initializer_list<fml::FileMapping::Protection> protection = {
435 auto main_dart_file_mapping = std::make_unique<fml::FileMapping>(
441 auto isolate_configuration =
444 if (!isolate_configuration) {
445 FML_LOG(
ERROR) <<
"Could create isolate configuration.";
449 auto asset_manager = std::make_shared<flutter::AssetManager>();
450 asset_manager->PushBack(std::make_unique<flutter::DirectoryAssetBundle>(
452 asset_manager->PushBack(std::make_unique<flutter::DirectoryAssetBundle>(
458 std::move(asset_manager));
469 bool engine_did_run =
false;
472 auto task_observer_add = [&completion_observer]() {
474 reinterpret_cast<intptr_t
>(&completion_observer),
475 [&completion_observer]() { completion_observer.
DidProcessTask(); });
478 auto task_observer_remove = [&completion_observer, &latch]() {
480 reinterpret_cast<intptr_t
>(&completion_observer));
484 shell->RunEngine(std::move(run_configuration),
485 [&engine_did_run, &ui_task_runner,
488 engine_did_run =
true;
508 if (!engine_did_run) {
518#define EXPORTED __declspec(dllexport)
520#define EXPORTED __attribute__((visibility("default")))
525 std::shared_ptr<fml::FileMapping> mapping =
547 auto spawn_task = [
shell, entrypoint = std::string(entrypoint),
550 shell->GetSettings(),
nullptr,
552 configuration.SetEntrypoint(entrypoint);
557 return std::make_unique<TesterPlatformView>(
559 std::move(impeller_context_holder));
563 return std::make_unique<Rasterizer>(
571 ->Spawn(std::move(configuration),
route, on_create_platform_view,
572 on_create_rasterizer)
578 spawned_shell->GetTaskRunners().GetUITaskRunner(), [spawned_shell]() {
579 fml::MessageLoop::GetCurrent().AddTaskObserver(
580 reinterpret_cast<intptr_t>(spawned_shell), [spawned_shell]() {
581 if (spawned_shell->EngineHasLivePorts()) {
585 fml::MessageLoop::GetCurrent().RemoveTaskObserver(
586 reinterpret_cast<intptr_t>(spawned_shell));
588 fml::TaskRunner::RunNowOrPostTask(
589 spawned_shell->GetTaskRunners().GetPlatformTaskRunner(),
590 [spawned_shell]() { delete spawned_shell; });
599 shell->GetTaskRunners().GetPlatformTaskRunner(), spawn_task);
632 if (!command_line.positional_args().empty()) {
635 settings.application_kernel_asset = command_line.positional_args()[0];
638 if (
settings.application_kernel_asset.empty()) {
644 settings.enable_platform_isolates =
true;
646 if (
settings.icu_data_path.empty()) {
647 settings.icu_data_path =
"icudtl.dat";
653 settings.log_message_callback = [](
const std::string& tag,
656 std::cout << tag <<
": ";
658 std::cout <<
message << std::endl;
669 settings.unhandled_exception_callback = [](
const std::string&
error,
670 const std::string& stack_trace) {
672 <<
"Exception: " <<
error << std::endl
673 <<
"Stack trace: " << stack_trace;
678#if defined(FML_OS_WIN)
679 CoInitializeEx(
nullptr, COINIT_MULTITHREADED);
684 flutter::Switch::RunForever)),
686 flutter::Switch::ForceMultithreading)));
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
static sk_sp< SkColorSpace > MakeSRGB()
static Dart_Handle LoadLibraryFromKernel(const std::shared_ptr< const fml::Mapping > &mapping)
Developer-facing API for rendering anything within the engine.
RunStatus
Indicates the result of the call to Engine::Run.
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...
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, bool run_forever)
int GetExitCodeForLastError() const
std::optional< DartErrorCode > GetUIIsolateLastError() const
Used by embedders to get the last error from the Dart UI Isolate, if one exists.
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...
bool EngineHasLivePorts() const
Used by embedders to check if the Engine is running and has any live ports remaining....
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
bool EnableRasterCache() const override
TesterGPUSurfaceSoftware(GPUSurfaceSoftwareDelegate *delegate, bool render_to_surface)
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
static MallocMapping Copy(const T *begin, const T *end)
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 void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
static std::shared_ptr< ContextVK > Create(Settings settings)
DART_EXPORT Dart_Handle Dart_GetNonNullableType(Dart_Handle library, Dart_Handle class_name, intptr_t number_of_type_arguments, Dart_Handle *type_arguments)
struct _Dart_Handle * Dart_Handle
DART_EXPORT Dart_Handle Dart_True(void)
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void)
DART_EXPORT Dart_Handle Dart_Null(void)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT void Dart_ExitIsolate(void)
@ kRaster
Suitable for thread which raster data.
const EmbeddedViewParams * params
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
void SetExecutableName(const char *executable_name)
void SetExecutableArguments(int script_index, char **argv)
static std::vector< std::shared_ptr< fml::Mapping > > ShaderLibraryMappings()
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)
Settings SettingsFromCommandLine(const fml::CommandLine &command_line)
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
DEF_SWITCHES_START aot vmservice shared library name
constexpr FlutterViewId kImplicitViewId
EXPORTED void ForceShutdownIsolate()
static void ConfigureShell(Shell *shell)
static absl::NoDestructor< std::unique_ptr< Shell > > g_shell
EXPORTED void Spawn(const char *entrypoint, const char *route)
it will be possible to load the file into Perfetto s trace viewer 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 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
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 defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however route
EXPORTED Dart_Handle LoadLibraryFromKernel(const char *path)
const std::string_view FlagForSwitch(Switch swtch)
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)
internal::CopyableLambda< T > MakeCopyable(T lambda)
std::function< void()> closure
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.
void Initialize(zx::channel directory_request, std::optional< zx::eventpair > view_ref)
Initializes Dart bindings for the Fuchsia application model.
Dart_Handle ToDart(const T &object)
bool CheckAndHandleError(Dart_Handle handle)
static SkString to_string(int n)
static constexpr SkISize Make(int32_t w, int32_t h)
static SkImageInfo MakeN32(int width, int height, SkAlphaType at)
double device_pixel_ratio
std::vector< std::shared_ptr< fml::Mapping > > shader_libraries_data
PFN_vkGetInstanceProcAddr proc_address_callback
fml::UniqueFD cache_directory
int main(int argc, char *argv[])
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName)