diff --git a/shell/common/shell.cc b/shell/common/shell.cc index d11a14f06b4e2..c6a756d1e50b9 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -47,7 +47,8 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( Settings settings, fml::RefPtr isolate_snapshot, const Shell::CreateCallback& on_create_platform_view, - const Shell::CreateCallback& on_create_rasterizer) { + const Shell::CreateCallback& on_create_rasterizer, + const InitedCallback& on_create_inited) { if (!task_runners.IsValid()) { FML_LOG(ERROR) << "Task runners to run the shell were invalid."; return nullptr; @@ -62,16 +63,17 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( std::promise> snapshot_delegate_promise; auto snapshot_delegate_future = snapshot_delegate_promise.get_future(); fml::TaskRunner::RunNowOrPostTask( - task_runners.GetRasterTaskRunner(), [&rasterizer_promise, // - &snapshot_delegate_promise, + task_runners.GetRasterTaskRunner(), fml::MakeCopyable([ + rasterizer_promise = std::move(rasterizer_promise), // + snapshot_delegate_promise = std::move(snapshot_delegate_promise), on_create_rasterizer, // shell = shell.get() // - ]() { + ]() mutable { TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem"); std::unique_ptr rasterizer(on_create_rasterizer(*shell)); snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate()); rasterizer_promise.set_value(std::move(rasterizer)); - }); + })); // Create the platform view on the platform thread (this thread). auto platform_view = on_create_platform_view(*shell.get()); @@ -106,13 +108,13 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( // https://github.com/flutter/flutter/issues/42948 fml::TaskRunner::RunNowOrPostTask( io_task_runner, - [&io_manager_promise, // - &weak_io_manager_promise, // - &unref_queue_promise, // - platform_view = platform_view->GetWeakPtr(), // - io_task_runner, // - is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch() // - ]() { + fml::MakeCopyable([io_manager_promise = std::move(io_manager_promise), // + weak_io_manager_promise = std::move(weak_io_manager_promise), // + unref_queue_promise = std::move(unref_queue_promise), // + platform_view = platform_view->GetWeakPtr(), // + io_task_runner, // + is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch() // + ]() mutable { TRACE_EVENT0("flutter", "ShellSetupIOSubsystem"); auto io_manager = std::make_unique( platform_view.getUnsafe()->CreateResourceContext(), @@ -120,7 +122,7 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( weak_io_manager_promise.set_value(io_manager->GetWeakPtr()); unref_queue_promise.set_value(io_manager->GetSkiaUnrefQueue()); io_manager_promise.set_value(std::move(io_manager)); - }); + })); // Send dispatcher_maker to the engine constructor because shell won't have // platform_view set until Shell::Setup is called later. @@ -131,15 +133,20 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( auto engine_future = engine_promise.get_future(); fml::TaskRunner::RunNowOrPostTask( shell->GetTaskRunners().GetUITaskRunner(), - fml::MakeCopyable([&engine_promise, // - shell = shell.get(), // - &dispatcher_maker, // - &platform_data, // - isolate_snapshot = std::move(isolate_snapshot), // - vsync_waiter = std::move(vsync_waiter), // - &weak_io_manager_future, // - &snapshot_delegate_future, // - &unref_queue_future // + fml::MakeCopyable([engine_promise = std::move(engine_promise), // + shell = shell.get(), // + dispatcher_maker = std::move(dispatcher_maker), // + platform_data = std::move(platform_data), // + isolate_snapshot = std::move(isolate_snapshot), // + vsync_waiter = std::move(vsync_waiter), // + weak_io_manager_future = std::move(weak_io_manager_future), // + snapshot_delegate_future = std::move(snapshot_delegate_future), // + unref_queue_future = std::move(unref_queue_future), // + platform_view = std::move(platform_view), + engine_future = std::move(engine_future), + rasterizer_future = std::move(rasterizer_future), + io_manager_future = std::move(io_manager_future), + on_create_inited ]() mutable { TRACE_EVENT0("flutter", "ShellSetupUISubsystem"); const auto& task_runners = shell->GetTaskRunners(); @@ -162,16 +169,27 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( unref_queue_future.get(), // snapshot_delegate_future.get() // )); - })); - if (!shell->Setup(std::move(platform_view), // - engine_future.get(), // - rasterizer_future.get(), // - io_manager_future.get()) // - ) { - return nullptr; - } + auto engine = engine_future.get(); + auto rasterizer = rasterizer_future.get(); + auto io_manager = io_manager_future.get(); + + shell->platform_view_ = std::move(platform_view); + shell->engine_ = std::move(engine); + shell->rasterizer_ = std::move(rasterizer); + shell->io_manager_ = std::move(io_manager); + + if (on_create_inited) { + fml::TaskRunner::RunNowOrPostTask(shell->GetTaskRunners().GetPlatformTaskRunner(), + [on_create_inited]() { + on_create_inited(true); + }); + } + shell->initialized_promise_.set_value(true); + })); + + shell->initialized_future_ = shell->initialized_promise_.get_future(); return shell; } @@ -255,7 +273,8 @@ std::unique_ptr Shell::Create( const PlatformData platform_data, Settings settings, Shell::CreateCallback on_create_platform_view, - Shell::CreateCallback on_create_rasterizer) { + Shell::CreateCallback on_create_rasterizer, + const InitedCallback on_create_inited) { PerformInitializationTasks(settings); PersistentCache::SetCacheSkSL(settings.cache_sksl); @@ -272,7 +291,8 @@ std::unique_ptr Shell::Create( vm_data->GetIsolateSnapshot(), // isolate snapshot on_create_platform_view, // on_create_rasterizer, // - std::move(vm) // + std::move(vm), // + on_create_inited ); } @@ -283,7 +303,7 @@ std::unique_ptr Shell::Create( fml::RefPtr isolate_snapshot, const Shell::CreateCallback& on_create_platform_view, const Shell::CreateCallback& on_create_rasterizer, - DartVMRef vm) { + DartVMRef vm, const Shell::InitedCallback& on_create_inited) { PerformInitializationTasks(settings); PersistentCache::SetCacheSkSL(settings.cache_sksl); @@ -306,7 +326,8 @@ std::unique_ptr Shell::Create( settings, // isolate_snapshot = std::move(isolate_snapshot), // on_create_platform_view, // - on_create_rasterizer // + on_create_rasterizer, // + on_create_inited ]() mutable { shell = CreateShellOnPlatformThread(std::move(vm), std::move(task_runners), // @@ -314,7 +335,8 @@ std::unique_ptr Shell::Create( settings, // std::move(isolate_snapshot), // on_create_platform_view, // - on_create_rasterizer // + on_create_rasterizer, // + on_create_inited ); latch.Signal(); })); @@ -468,6 +490,10 @@ void Shell::RunEngine( platform_runner->PostTask( [result_callback, run_result]() { result_callback(run_result); }); }; + + ensureInitialized(); + ensureSetupped(); + FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); @@ -581,6 +607,23 @@ bool Shell::Setup(std::unique_ptr platform_view, return true; } +void Shell::ensureInitialized() { + bool valid = initialized_future_.valid(); + if (valid) { + bool initialized = initialized_future_.get(); + FML_DCHECK(initialized); + } +} + +void Shell::ensureSetupped() { + if (!is_setup_) { + Setup(std::move(platform_view_), + std::move(engine_), + std::move(rasterizer_), + std::move(io_manager_)); + } +} + const Settings& Shell::GetSettings() const { return settings_; } @@ -589,17 +632,21 @@ const TaskRunners& Shell::GetTaskRunners() const { return task_runners_; } -fml::TaskRunnerAffineWeakPtr Shell::GetRasterizer() const { +fml::TaskRunnerAffineWeakPtr Shell::GetRasterizer() const{ FML_DCHECK(is_setup_); return weak_rasterizer_; } fml::WeakPtr Shell::GetEngine() { + ensureInitialized(); + ensureSetupped(); FML_DCHECK(is_setup_); return weak_engine_; } fml::WeakPtr Shell::GetPlatformView() { + ensureInitialized(); + ensureSetupped(); FML_DCHECK(is_setup_); return weak_platform_view_; } @@ -800,6 +847,9 @@ void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) { // |PlatformView::Delegate| void Shell::OnPlatformViewDispatchPlatformMessage( fml::RefPtr message) { + ensureInitialized(); + ensureSetupped(); + FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); diff --git a/shell/common/shell.h b/shell/common/shell.h index e0288bf99ea01..0a8433892c988 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -96,6 +96,8 @@ class Shell final : public PlatformView::Delegate, template using CreateCallback = std::function(Shell&)>; + using InitedCallback = std::function; + //---------------------------------------------------------------------------- /// @brief Creates a shell instance using the provided settings. The /// callbacks to create the various shell subcomponents will be @@ -164,7 +166,8 @@ class Shell final : public PlatformView::Delegate, const PlatformData platform_data, Settings settings, CreateCallback on_create_platform_view, - CreateCallback on_create_rasterizer); + CreateCallback on_create_rasterizer, + const InitedCallback on_create_inited = nullptr); //---------------------------------------------------------------------------- /// @brief Creates a shell instance using the provided settings. The @@ -208,7 +211,7 @@ class Shell final : public PlatformView::Delegate, fml::RefPtr isolate_snapshot, const CreateCallback& on_create_platform_view, const CreateCallback& on_create_rasterizer, - DartVMRef vm); + DartVMRef vm, const InitedCallback& on_create_inited = nullptr); //---------------------------------------------------------------------------- /// @brief Destroys the shell. This is a synchronous operation and @@ -391,6 +394,8 @@ class Shell final : public PlatformView::Delegate, > service_protocol_handlers_; bool is_setup_ = false; + std::promise initialized_promise_; + std::future initialized_future_; uint64_t next_pointer_flow_id_ = 0; bool first_frame_rasterized_ = false; @@ -430,13 +435,18 @@ class Shell final : public PlatformView::Delegate, Settings settings, fml::RefPtr isolate_snapshot, const Shell::CreateCallback& on_create_platform_view, - const Shell::CreateCallback& on_create_rasterizer); + const Shell::CreateCallback& on_create_rasterizer, + const InitedCallback& on_create_inited = nullptr); bool Setup(std::unique_ptr platform_view, std::unique_ptr engine, std::unique_ptr rasterizer, std::unique_ptr io_manager); + void ensureInitialized(); + + void ensureSetupped(); + void ReportTimings(); // |PlatformView::Delegate| diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 51a741fa4109f..b5d20e56ae2dd 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -509,12 +509,21 @@ - (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI { _threadHost.ui_thread->GetTaskRunner(), // ui _threadHost.io_thread->GetTaskRunner() // io ); - // Create the shell. This is a blocking operation. + // Create the shell. This is a asynchronous operation. _shell = flutter::Shell::Create(std::move(task_runners), // task runners std::move(platformData), // platform data std::move(settings), // settings on_create_platform_view, // platform view creation - on_create_rasterizer // rasterizer creation + on_create_rasterizer, // rasterizer creation + [self, entrypoint = entrypoint, + profilerEnabled = profilerEnabled, + threadLabel = [threadLabel copy]](bool initialized) { + if (initialized) { + [self postInitialized:profilerEnabled threadLabel:threadLabel]; + } else { + FML_LOG(ERROR) << "Could not start a shell FlutterEngine with entrypoint: " << entrypoint.UTF8String; + } + } ); } else { flutter::TaskRunners task_runners(threadLabel.UTF8String, // label @@ -523,19 +532,28 @@ - (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI { _threadHost.ui_thread->GetTaskRunner(), // ui _threadHost.io_thread->GetTaskRunner() // io ); - // Create the shell. This is a blocking operation. + // Create the shell. This is a asynchronous operation. _shell = flutter::Shell::Create(std::move(task_runners), // task runners std::move(platformData), // platform data std::move(settings), // settings on_create_platform_view, // platform view creation - on_create_rasterizer // rasterizer creation + on_create_rasterizer, // rasterizer creation + [self, entrypoint = entrypoint, + profilerEnabled, + threadLabel = [threadLabel copy]](bool initialized) { + if (initialized) { + [self postInitialized:profilerEnabled threadLabel:threadLabel]; + } else { + FML_LOG(ERROR) << "Could not start a shell FlutterEngine with entrypoint: " << entrypoint.UTF8String; + } + } ); } - if (_shell == nullptr) { - FML_LOG(ERROR) << "Could not start a shell FlutterEngine with entrypoint: " - << entrypoint.UTF8String; - } else { + return _shell != nullptr; +} + +- (void)postInitialized:(BOOL)profilerEnabled threadLabel:(NSString*)threadLabel { [self setupChannels]; [self onLocaleUpdated:nil]; if (!_platformViewsController) { @@ -547,9 +565,6 @@ - (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI { if (profilerEnabled) { [self startProfiler:threadLabel]; } - } - - return _shell != nullptr; } - (BOOL)run {