blob: 7d1f74bdb3897c7bc708d5d235e3c033dbee45cd [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/embedder/embedder_engine.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/shell/platform/embedder/vsync_waiter_embedder.h"
namespace flutter {
struct ShellArgs {
Settings settings;
Shell::CreateCallback<PlatformView> on_create_platform_view;
Shell::CreateCallback<Rasterizer> on_create_rasterizer;
ShellArgs(Settings p_settings,
Shell::CreateCallback<PlatformView> p_on_create_platform_view,
Shell::CreateCallback<Rasterizer> p_on_create_rasterizer)
: settings(std::move(p_settings)),
on_create_platform_view(std::move(p_on_create_platform_view)),
on_create_rasterizer(std::move(p_on_create_rasterizer)) {}
};
EmbedderEngine::EmbedderEngine(
std::unique_ptr<EmbedderThreadHost> thread_host,
flutter::TaskRunners task_runners,
flutter::Settings settings,
RunConfiguration run_configuration,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer,
std::unique_ptr<EmbedderExternalTextureResolver> external_texture_resolver)
: thread_host_(std::move(thread_host)),
task_runners_(task_runners),
run_configuration_(std::move(run_configuration)),
shell_args_(std::make_unique<ShellArgs>(std::move(settings),
on_create_platform_view,
on_create_rasterizer)),
external_texture_resolver_(std::move(external_texture_resolver)) {}
EmbedderEngine::~EmbedderEngine() = default;
bool EmbedderEngine::LaunchShell() {
if (!shell_args_) {
FML_DLOG(ERROR) << "Invalid shell arguments.";
return false;
}
if (shell_) {
FML_DLOG(ERROR) << "Shell already initialized";
}
shell_ = Shell::Create(
flutter::PlatformData(), task_runners_, shell_args_->settings,
shell_args_->on_create_platform_view, shell_args_->on_create_rasterizer);
// Reset the args no matter what. They will never be used to initialize a
// shell again.
shell_args_.reset();
return IsValid();
}
bool EmbedderEngine::CollectShell() {
shell_.reset();
return IsValid();
}
bool EmbedderEngine::RunRootIsolate() {
if (!IsValid() || !run_configuration_.IsValid()) {
return false;
}
shell_->RunEngine(std::move(run_configuration_));
return true;
}
bool EmbedderEngine::IsValid() const {
return static_cast<bool>(shell_);
}
const TaskRunners& EmbedderEngine::GetTaskRunners() const {
return task_runners_;
}
bool EmbedderEngine::NotifyCreated() {
if (!IsValid()) {
return false;
}
shell_->GetPlatformView()->NotifyCreated();
return true;
}
bool EmbedderEngine::NotifyDestroyed() {
if (!IsValid()) {
return false;
}
shell_->GetPlatformView()->NotifyDestroyed();
return true;
}
bool EmbedderEngine::SetViewportMetrics(flutter::ViewportMetrics metrics) {
if (!IsValid()) {
return false;
}
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->SetViewportMetrics(std::move(metrics));
return true;
}
bool EmbedderEngine::DispatchPointerDataPacket(
std::unique_ptr<flutter::PointerDataPacket> packet) {
if (!IsValid() || !packet) {
return false;
}
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->DispatchPointerDataPacket(std::move(packet));
return true;
}
bool EmbedderEngine::DispatchKeyDataPacket(
std::unique_ptr<flutter::KeyDataPacket> packet,
KeyDataResponse callback) {
if (!IsValid() || !packet) {
return false;
}
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->DispatchKeyDataPacket(std::move(packet), std::move(callback));
return true;
}
bool EmbedderEngine::SendPlatformMessage(
std::unique_ptr<PlatformMessage> message) {
if (!IsValid() || !message) {
return false;
}
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->DispatchPlatformMessage(std::move(message));
return true;
}
bool EmbedderEngine::RegisterTexture(int64_t texture) {
if (!IsValid()) {
return false;
}
shell_->GetPlatformView()->RegisterTexture(
external_texture_resolver_->ResolveExternalTexture(texture));
return true;
}
bool EmbedderEngine::UnregisterTexture(int64_t texture) {
if (!IsValid()) {
return false;
}
shell_->GetPlatformView()->UnregisterTexture(texture);
return true;
}
bool EmbedderEngine::MarkTextureFrameAvailable(int64_t texture) {
if (!IsValid()) {
return false;
}
shell_->GetPlatformView()->MarkTextureFrameAvailable(texture);
return true;
}
bool EmbedderEngine::SetSemanticsEnabled(bool enabled) {
if (!IsValid()) {
return false;
}
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->SetSemanticsEnabled(enabled);
return true;
}
bool EmbedderEngine::SetAccessibilityFeatures(int32_t flags) {
if (!IsValid()) {
return false;
}
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->SetAccessibilityFeatures(flags);
return true;
}
bool EmbedderEngine::DispatchSemanticsAction(int id,
flutter::SemanticsAction action,
fml::MallocMapping args) {
if (!IsValid()) {
return false;
}
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->DispatchSemanticsAction(id, action, std::move(args));
return true;
}
bool EmbedderEngine::OnVsyncEvent(intptr_t baton,
fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
if (!IsValid()) {
return false;
}
return VsyncWaiterEmbedder::OnEmbedderVsync(baton, frame_start_time,
frame_target_time);
}
bool EmbedderEngine::ReloadSystemFonts() {
if (!IsValid()) {
return false;
}
return shell_->ReloadSystemFonts();
}
bool EmbedderEngine::PostRenderThreadTask(const fml::closure& task) {
if (!IsValid()) {
return false;
}
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(task);
return true;
}
bool EmbedderEngine::RunTask(const FlutterTask* task) {
// The shell doesn't need to be running or valid for access to the thread
// host. This is why there is no `IsValid` check here. This allows embedders
// to perform custom task runner interop before the shell is running.
if (task == nullptr) {
return false;
}
return thread_host_->PostTask(reinterpret_cast<int64_t>(task->runner),
task->task);
}
bool EmbedderEngine::PostTaskOnEngineManagedNativeThreads(
std::function<void(FlutterNativeThreadType)> closure) const {
if (!IsValid() || closure == nullptr) {
return false;
}
const auto trampoline = [closure](FlutterNativeThreadType type,
fml::RefPtr<fml::TaskRunner> runner) {
runner->PostTask([closure, type] { closure(type); });
};
// Post the task to all thread host threads.
const auto& task_runners = shell_->GetTaskRunners();
trampoline(kFlutterNativeThreadTypeRender,
task_runners.GetRasterTaskRunner());
trampoline(kFlutterNativeThreadTypeWorker, task_runners.GetIOTaskRunner());
trampoline(kFlutterNativeThreadTypeUI, task_runners.GetUITaskRunner());
trampoline(kFlutterNativeThreadTypePlatform,
task_runners.GetPlatformTaskRunner());
// Post the task to all worker threads.
auto vm = shell_->GetDartVM();
vm->GetConcurrentMessageLoop()->PostTaskToAllWorkers(
[closure]() { closure(kFlutterNativeThreadTypeWorker); });
return true;
}
Shell& EmbedderEngine::GetShell() {
FML_DCHECK(shell_);
return *shell_.get();
}
} // namespace flutter