diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 39cb93b88e9ea..d0f91bcaae8f4 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -27,7 +27,6 @@ Animator::Animator(Delegate& delegate, : delegate_(delegate), task_runners_(std::move(task_runners)), waiter_(std::move(waiter)), - dart_frame_deadline_(0), #if SHELL_ENABLE_METAL layer_tree_pipeline_(std::make_shared(2)), #else // SHELL_ENABLE_METAL @@ -41,11 +40,6 @@ Animator::Animator(Delegate& delegate, : 2)), #endif // SHELL_ENABLE_METAL pending_frame_semaphore_(1), - paused_(false), - regenerate_layer_tree_(false), - frame_scheduled_(false), - notify_idle_task_id_(0), - dimension_change_pending_(false), weak_factory_(this) { } @@ -92,10 +86,10 @@ const char* Animator::FrameParity() { return (frame_number % 2) ? "even" : "odd"; } -static int64_t FxlToDartOrEarlier(fml::TimePoint time) { - int64_t dart_now = Dart_TimelineGetMicros(); +static fml::TimePoint FxlToDartOrEarlier(fml::TimePoint time) { + auto dart_now = fml::TimeDelta::FromMicroseconds(Dart_TimelineGetMicros()); fml::TimePoint fxl_now = fml::TimePoint::Now(); - return (time - fxl_now).ToMicroseconds() + dart_now; + return fml::TimePoint::FromEpochDelta(time - fxl_now + dart_now); } void Animator::BeginFrame( @@ -275,7 +269,8 @@ void Animator::AwaitVSync() { } }); - delegate_.OnAnimatorNotifyIdle(dart_frame_deadline_); + delegate_.OnAnimatorNotifyIdle( + dart_frame_deadline_.ToEpochDelta().ToMicroseconds()); } void Animator::ScheduleSecondaryVsyncCallback(uintptr_t id, diff --git a/shell/common/animator.h b/shell/common/animator.h index 8061e223a5b03..544c6c77ba370 100644 --- a/shell/common/animator.h +++ b/shell/common/animator.h @@ -106,15 +106,15 @@ class Animator final { std::unique_ptr frame_timings_recorder_; uint64_t frame_request_number_ = 1; - int64_t dart_frame_deadline_; + fml::TimePoint dart_frame_deadline_; std::shared_ptr layer_tree_pipeline_; fml::Semaphore pending_frame_semaphore_; LayerTreePipeline::ProducerContinuation producer_continuation_; - bool paused_; - bool regenerate_layer_tree_; - bool frame_scheduled_; - int notify_idle_task_id_; - bool dimension_change_pending_; + bool paused_ = true; + bool regenerate_layer_tree_ = false; + bool frame_scheduled_ = false; + int notify_idle_task_id_ = 0; + bool dimension_change_pending_ = false; SkISize last_layer_tree_size_ = {0, 0}; std::deque trace_flow_ids_; diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc index ecb9e254a97f5..34c237ea93182 100644 --- a/shell/common/animator_unittests.cc +++ b/shell/common/animator_unittests.cc @@ -73,6 +73,9 @@ TEST_F(ShellTest, VSyncTargetTime) { fml::TaskRunner::RunNowOrPostTask(shell->GetTaskRunners().GetUITaskRunner(), [engine = shell->GetEngine()]() { if (engine) { + // Engine needs a surface for frames to + // be scheduled. + engine->OnOutputSurfaceCreated(); // this implies we can re-use the last // frame to trigger begin frame rather // than re-generating the layer tree. @@ -94,5 +97,28 @@ TEST_F(ShellTest, VSyncTargetTime) { ASSERT_FALSE(DartVMRef::IsInstanceRunning()); } +TEST_F(ShellTest, AnimatorStartsPaused) { + // Create all te prerequisites for a shell. + ASSERT_FALSE(DartVMRef::IsInstanceRunning()); + auto settings = CreateSettingsForFixture(); + TaskRunners task_runners = GetTaskRunnersForFixture(); + + auto shell = CreateShell(std::move(settings), task_runners); + ASSERT_TRUE(DartVMRef::IsInstanceRunning()); + + auto configuration = RunConfiguration::InferFromSettings(settings); + ASSERT_TRUE(configuration.IsValid()); + + configuration.SetEntrypoint("emptyMain"); + + RunEngine(shell.get(), std::move(configuration)); + + ASSERT_FALSE(IsAnimatorRunning(shell.get())); + + // teardown. + DestroyShell(std::move(shell), std::move(task_runners)); + ASSERT_FALSE(DartVMRef::IsInstanceRunning()); +} + } // namespace testing } // namespace flutter diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 28321a9fd166c..8f0a4503e0a49 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -265,7 +265,6 @@ tonic::DartErrorHandleType Engine::GetUIIsolateLastError() { void Engine::OnOutputSurfaceCreated() { have_surface_ = true; - StartAnimatorIfPossible(); ScheduleFrame(); } @@ -465,6 +464,7 @@ std::string Engine::DefaultRouteName() { } void Engine::ScheduleFrame(bool regenerate_layer_tree) { + StartAnimatorIfPossible(); animator_->RequestFrame(regenerate_layer_tree); } diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index 3e55654a19c88..b5cc9c8e3ae52 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -381,5 +381,22 @@ void ShellTest::DestroyShell(std::unique_ptr shell, latch.Wait(); } +bool ShellTest::IsAnimatorRunning(Shell* shell) { + fml::AutoResetWaitableEvent latch; + bool running = false; + if (!shell) { + return running; + } + fml::TaskRunner::RunNowOrPostTask( + shell->GetTaskRunners().GetUITaskRunner(), [shell, &running, &latch]() { + if (shell && shell->engine_ && shell->engine_->animator_) { + running = !shell->engine_->animator_->paused_; + } + latch.Signal(); + }); + latch.Wait(); + return running; +} + } // namespace testing } // namespace flutter diff --git a/shell/common/shell_test.h b/shell/common/shell_test.h index b2f1052fa98e1..1524c150e377a 100644 --- a/shell/common/shell_test.h +++ b/shell/common/shell_test.h @@ -96,6 +96,8 @@ class ShellTest : public FixtureTest { const SkData& key, const SkData& value); + static bool IsAnimatorRunning(Shell* shell); + enum ServiceProtocolEnum { kGetSkSLs, kEstimateRasterCacheMemory,