Skip to content

Commit

Permalink
Implement FlutterTizenEngine spawn
Browse files Browse the repository at this point in the history
Signed-off-by: swan.seo <[email protected]>
  • Loading branch information
Swanseo0 committed Jan 25, 2023
1 parent 5a343b3 commit dbbbf55
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 25 deletions.
18 changes: 18 additions & 0 deletions flutter/shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,16 @@ FlutterEngineResult FlutterEngineRun(size_t version,
FLUTTER_API_SYMBOL(FlutterEngine) *
engine_out);

FLUTTER_EXPORT
FlutterEngineResult FlutterEngineSpawn(size_t version,
const FlutterRendererConfig* config,
const FlutterProjectArgs* args,
void* user_data,
FLUTTER_API_SYMBOL(FlutterEngine)
spawner,
FLUTTER_API_SYMBOL(FlutterEngine) *
engine_out);

//------------------------------------------------------------------------------
/// @brief Shuts down a Flutter engine instance. The engine handle is no
/// longer valid for any calls in the embedder API after this point.
Expand Down Expand Up @@ -2441,6 +2451,13 @@ typedef FlutterEngineResult (*FlutterEngineRunFnPtr)(
const FlutterProjectArgs* args,
void* user_data,
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
typedef FlutterEngineResult (*FlutterEngineSpawnFnPtr)(
size_t version,
const FlutterRendererConfig* config,
const FlutterProjectArgs* args,
void* user_data,
FLUTTER_API_SYMBOL(FlutterEngine) engine_spawner,
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
typedef FlutterEngineResult (*FlutterEngineShutdownFnPtr)(
FLUTTER_API_SYMBOL(FlutterEngine) engine);
typedef FlutterEngineResult (*FlutterEngineInitializeFnPtr)(
Expand Down Expand Up @@ -2554,6 +2571,7 @@ typedef struct {
FlutterEngineCreateAOTDataFnPtr CreateAOTData;
FlutterEngineCollectAOTDataFnPtr CollectAOTData;
FlutterEngineRunFnPtr Run;
FlutterEngineSpawnFnPtr Spawn;
FlutterEngineShutdownFnPtr Shutdown;
FlutterEngineInitializeFnPtr Initialize;
FlutterEngineDeinitializeFnPtr Deinitialize;
Expand Down
1 change: 1 addition & 0 deletions flutter/shell/platform/tizen/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ template("embedder") {
"flutter_tizen.cc",
"flutter_tizen_elementary.cc",
"flutter_tizen_engine.cc",
"flutter_tizen_engine_group.cc",
"flutter_tizen_texture_registrar.cc",
"flutter_tizen_view.cc",
"logger.cc",
Expand Down
20 changes: 11 additions & 9 deletions flutter/shell/platform/tizen/flutter_tizen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "flutter/shell/platform/common/incoming_message_dispatcher.h"
#include "flutter/shell/platform/tizen/flutter_project_bundle.h"
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"
#include "flutter/shell/platform/tizen/flutter_tizen_view.h"
#include "flutter/shell/platform/tizen/logger.h"
#include "flutter/shell/platform/tizen/public/flutter_platform_view.h"
Expand Down Expand Up @@ -71,20 +72,22 @@ FlutterDesktopEngineRef FlutterDesktopEngineCreate(
}
flutter::Logger::Start();

auto engine = std::make_unique<flutter::FlutterTizenEngine>(project);
return HandleForEngine(engine.release());
auto engine =
flutter::FlutterTizenEngineGroup::GetInstance().MakeEngineWithProject(
project);

return HandleForEngine(engine);
}

bool FlutterDesktopEngineRun(const FlutterDesktopEngineRef engine) {
return EngineFromHandle(engine)->RunEngine();
return EngineFromHandle(engine)->RunOrSpawnEngine();
}

void FlutterDesktopEngineShutdown(FlutterDesktopEngineRef engine_ref) {
flutter::Logger::Stop();

flutter::FlutterTizenEngine* engine = EngineFromHandle(engine_ref);
engine->StopEngine();
delete engine;
flutter::FlutterTizenEngineGroup::GetInstance().StopEngine(engine->id());
}

FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
Expand Down Expand Up @@ -219,12 +222,11 @@ FlutterDesktopViewRef FlutterDesktopViewCreateFromNewWindow(

auto view = std::make_unique<flutter::FlutterTizenView>(std::move(window));

// Take ownership of the engine, starting it if necessary.
view->SetEngine(
std::unique_ptr<flutter::FlutterTizenEngine>(EngineFromHandle(engine)));
// Starting it if necessary.
view->SetEngine(EngineFromHandle(engine));
view->CreateRenderSurface(window_properties.renderer_type);
if (!view->engine()->IsRunning()) {
if (!view->engine()->RunEngine()) {
if (!view->engine()->RunOrSpawnEngine()) {
return nullptr;
}
}
Expand Down
7 changes: 3 additions & 4 deletions flutter/shell/platform/tizen/flutter_tizen_elementary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ FlutterDesktopViewRef FlutterDesktopViewCreateFromElmParent(
auto view =
std::make_unique<flutter::FlutterTizenView>(std::move(tizen_view));

// Take ownership of the engine, starting it if necessary.
view->SetEngine(
std::unique_ptr<flutter::FlutterTizenEngine>(EngineFromHandle(engine)));
// Starting it if necessary.
view->SetEngine(EngineFromHandle(engine));
view->CreateRenderSurface(FlutterDesktopRendererType::kEvasGL);
if (!view->engine()->IsRunning()) {
if (!view->engine()->RunEngine()) {
if (!view->engine()->RunOrSpawnEngine()) {
return nullptr;
}
}
Expand Down
134 changes: 134 additions & 0 deletions flutter/shell/platform/tizen/flutter_tizen_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "flutter/shell/platform/tizen/flutter_platform_node_delegate_tizen.h"
#include "flutter/shell/platform/tizen/tizen_renderer_egl.h"
#endif
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"
#include "flutter/shell/platform/tizen/flutter_tizen_view.h"
#include "flutter/shell/platform/tizen/logger.h"
#include "flutter/shell/platform/tizen/system_utils.h"
Expand Down Expand Up @@ -100,6 +101,14 @@ void FlutterTizenEngine::CreateRenderer(
#endif
}

bool FlutterTizenEngine::RunOrSpawnEngine() {
if (FlutterTizenEngineGroup::GetInstance().GetEngineCount() <= 1) {
return RunEngine();
} else {
return SpawnEngine();
}
}

bool FlutterTizenEngine::RunEngine() {
if (engine_ != nullptr) {
FT_LOG(Error) << "The engine has already started.";
Expand Down Expand Up @@ -258,6 +267,131 @@ bool FlutterTizenEngine::RunEngine() {
return true;
}

bool FlutterTizenEngine::SpawnEngine() {
if (engine_ != nullptr) {
FT_LOG(Error) << "The engine has already started.";
return false;
}
if (IsHeaded() && !renderer_->IsValid()) {
FT_LOG(Error) << "The display was not valid.";
return false;
}

if (!project_->HasValidPaths()) {
FT_LOG(Error) << "Missing or unresolvable path to assets.";
return false;
}
std::string assets_path_string = project_->assets_path().u8string();
std::string icu_path_string = project_->icu_path().u8string();
if (embedder_api_.RunsAOTCompiledDartCode()) {
aot_data_ = project_->LoadAotData(embedder_api_);
if (!aot_data_) {
FT_LOG(Error) << "Unable to start engine without AOT data.";
return false;
}
}

// FlutterProjectArgs is expecting a full argv, so when processing it for
// flags the first item is treated as the executable and ignored. Add a dummy
// value so that all provided arguments are used.
std::vector<std::string> engine_args = project_->engine_arguments();
std::vector<const char*> engine_argv = {"placeholder"};
std::transform(
engine_args.begin(), engine_args.end(), std::back_inserter(engine_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

const std::vector<std::string>& entrypoint_args =
project_->dart_entrypoint_arguments();
std::vector<const char*> entrypoint_argv;
std::transform(
entrypoint_args.begin(), entrypoint_args.end(),
std::back_inserter(entrypoint_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });

FlutterProjectArgs args = {};
args.struct_size = sizeof(FlutterProjectArgs);
args.assets_path = assets_path_string.c_str();
args.icu_data_path = icu_path_string.c_str();
args.command_line_argc = static_cast<int>(engine_argv.size());
args.command_line_argv =
engine_argv.size() > 0 ? engine_argv.data() : nullptr;
args.dart_entrypoint_argc = static_cast<int>(entrypoint_argv.size());
args.dart_entrypoint_argv =
entrypoint_argv.size() > 0 ? entrypoint_argv.data() : nullptr;
args.platform_message_callback =
[](const FlutterPlatformMessage* engine_message, void* user_data) {
if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
FT_LOG(Error) << "Invalid message size received. Expected: "
<< sizeof(FlutterPlatformMessage) << ", but received "
<< engine_message->struct_size;
return;
}
auto* engine = reinterpret_cast<FlutterTizenEngine*>(user_data);
FlutterDesktopMessage message =
engine->ConvertToDesktopMessage(*engine_message);
engine->message_dispatcher_->HandleMessage(message);
};
if (aot_data_) {
args.aot_data = aot_data_.get();
}
if (!project_->custom_dart_entrypoint().empty()) {
args.custom_dart_entrypoint = project_->custom_dart_entrypoint().c_str();
}
#ifndef WEARABLE_PROFILE
args.update_semantics_node_callback = OnUpdateSemanticsNode;
args.update_semantics_custom_action_callback = OnUpdateSemanticsCustomActions;

if (IsHeaded() && dynamic_cast<TizenRendererEvasGL*>(renderer_.get())) {
vsync_waiter_ = std::make_unique<TizenVsyncWaiter>(this);
args.vsync_callback = [](void* user_data, intptr_t baton) -> void {
auto* engine = reinterpret_cast<FlutterTizenEngine*>(user_data);
engine->vsync_waiter_->AsyncWaitForVsync(baton);
};
}
#endif

auto* spawner = FlutterTizenEngineGroup::GetInstance().GetEngineSpawner();
FlutterRendererConfig renderer_config = GetRendererConfig();
FlutterEngineResult result =
embedder_api_.Spawn(FLUTTER_ENGINE_VERSION, &renderer_config, &args, this,
spawner->engine_, &engine_);

if (result != kSuccess || engine_ == nullptr) {
FT_LOG(Error) << "Failed to start the Flutter engine with error: "
<< result;
return false;
}

internal_plugin_registrar_ =
std::make_unique<PluginRegistrar>(plugin_registrar_.get());
accessibility_channel_ = std::make_unique<AccessibilityChannel>(
internal_plugin_registrar_->messenger());
app_control_channel_ = std::make_unique<AppControlChannel>(
internal_plugin_registrar_->messenger());
lifecycle_channel_ = std::make_unique<LifecycleChannel>(
internal_plugin_registrar_->messenger());
settings_channel_ = std::make_unique<SettingsChannel>(
internal_plugin_registrar_->messenger());

if (IsHeaded()) {
texture_registrar_ = std::make_unique<FlutterTizenTextureRegistrar>(this);
key_event_channel_ = std::make_unique<KeyEventChannel>(
internal_plugin_registrar_->messenger(),
[this](const FlutterKeyEvent& event, FlutterKeyEventCallback callback,
void* user_data) { SendKeyEvent(event, callback, user_data); });
navigation_channel_ = std::make_unique<NavigationChannel>(
internal_plugin_registrar_->messenger());
platform_view_channel_ = std::make_unique<PlatformViewChannel>(
internal_plugin_registrar_->messenger());
}

accessibility_settings_ = std::make_unique<AccessibilitySettings>(this);

SetupLocales();

return true;
}

bool FlutterTizenEngine::StopEngine() {
if (engine_) {
if (platform_view_channel_) {
Expand Down
13 changes: 13 additions & 0 deletions flutter/shell/platform/tizen/flutter_tizen_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,19 @@ class FlutterTizenEngine {
// Creates a GL renderer from the given type.
void CreateRenderer(FlutterDesktopRendererType renderer_type);

// If the engine is the only engine of the engine group, starts running the
// engine. Otherwise, spawns the engine.
bool RunOrSpawnEngine();

// Starts running the engine with the given entrypoint. If null, defaults to
// main().
//
// Returns false if the engine couldn't be started.
bool RunEngine();

// Returns false if the engine couldn't be spawned.
bool SpawnEngine();

// Returns true if the engine is currently running.
bool IsRunning() { return engine_ != nullptr; }

Expand All @@ -81,6 +88,10 @@ class FlutterTizenEngine {
// headless engines.
FlutterTizenView* view() { return view_; }

void SetId(uint32_t id) { id_ = id; }

uint32_t id() { return id_; }

FlutterDesktopMessengerRef messenger() { return messenger_.get(); }

IncomingMessageDispatcher* message_dispatcher() {
Expand Down Expand Up @@ -288,6 +299,8 @@ class FlutterTizenEngine {
// The vsync waiter for the embedder.
std::unique_ptr<TizenVsyncWaiter> vsync_waiter_;
#endif

uint32_t id_;
};

} // namespace flutter
Expand Down
40 changes: 40 additions & 0 deletions flutter/shell/platform/tizen/flutter_tizen_engine_group.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "flutter/shell/platform/tizen/flutter_tizen_engine_group.h"

#include <random>

namespace flutter {

FlutterTizenEngine* FlutterTizenEngineGroup::MakeEngineWithProject(
const FlutterProjectBundle& project) {
std::unique_ptr<FlutterTizenEngine> engine =
std::make_unique<flutter::FlutterTizenEngine>(project);

static std::random_device random_device;
static std::mt19937 generator(random_device());
static std::uniform_int_distribution<uint32_t> distribution(0, 99999);

engine->SetId(distribution(generator));

engines_.push_back(std::move(engine));
return engines_.back().get();
}

FlutterTizenEngine* FlutterTizenEngineGroup::GetEngineSpawner() {
return engines_[0].get();
}

int FlutterTizenEngineGroup::GetEngineCount() {
return engines_.size();
}

void FlutterTizenEngineGroup::StopEngine(uint32_t id) {
for (auto it = engines_.begin(); it != engines_.end(); ++it) {
if (id == it->get()->id()) {
it->get()->StopEngine();
engines_.erase(it);
return;
}
}
}

} // namespace flutter
32 changes: 32 additions & 0 deletions flutter/shell/platform/tizen/flutter_tizen_engine_group.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef EMBEDDER_FLUTTER_TIZEN_ENGINE_GROUP_H_
#define EMBEDDER_FLUTTER_TIZEN_ENGINE_GROUP_H_

#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"

namespace flutter {

class FlutterTizenEngineGroup {
public:
static FlutterTizenEngineGroup& GetInstance() {
static FlutterTizenEngineGroup instance;
return instance;
}

FlutterTizenEngine* GetEngineSpawner();

FlutterTizenEngine* MakeEngineWithProject(
const FlutterProjectBundle& project);

int GetEngineCount();

void StopEngine(uint32_t id);

private:
FlutterTizenEngineGroup() {}

std::vector<std::unique_ptr<FlutterTizenEngine>> engines_;
};

} // namespace flutter

#endif
7 changes: 3 additions & 4 deletions flutter/shell/platform/tizen/flutter_tizen_nui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ FlutterDesktopViewRef FlutterDesktopViewCreateFromImageView(
auto view =
std::make_unique<flutter::FlutterTizenView>(std::move(tizen_view));

// Take ownership of the engine, starting it if necessary.
view->SetEngine(
std::unique_ptr<flutter::FlutterTizenEngine>(EngineFromHandle(engine)));
// Starting it if necessary.
view->SetEngine(EngineFromHandle(engine));
view->CreateRenderSurface(FlutterDesktopRendererType::kEGL);
if (!view->engine()->IsRunning()) {
if (!view->engine()->RunEngine()) {
if (!view->engine()->RunOrSpawnEngine()) {
return nullptr;
}
}
Expand Down
Loading

0 comments on commit dbbbf55

Please sign in to comment.