From 9516005dba6d2f2ee1ef9c9bf4e5e81d622ae761 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Fri, 11 Mar 2022 16:53:01 +0800 Subject: [PATCH 1/2] Always update the latest frame target time when the 'Animator::Render' method is called --- shell/common/animator.cc | 3 +++ shell/common/animator.h | 3 +++ shell/common/animator_unittests.cc | 12 +++++++++--- shell/common/shell.cc | 15 +++++++++------ shell/common/shell.h | 4 ++++ 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 86496d1fbbff9..b65e1c64a6a2a 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -174,6 +174,9 @@ void Animator::Render(std::unique_ptr layer_tree) { "Animator::Render"); frame_timings_recorder_->RecordBuildEnd(fml::TimePoint::Now()); + delegate_.OnAnimatorUpdateLatestFrameTargetTime( + frame_timings_recorder_->GetVsyncTargetTime()); + // Commit the pending continuation. PipelineProduceResult result = producer_continuation_.Complete(std::move(layer_tree)); diff --git a/shell/common/animator.h b/shell/common/animator.h index b63fd29b85903..ab6e2c253daba 100644 --- a/shell/common/animator.h +++ b/shell/common/animator.h @@ -36,6 +36,9 @@ class Animator final { virtual void OnAnimatorNotifyIdle(fml::TimePoint deadline) = 0; + virtual void OnAnimatorUpdateLatestFrameTargetTime( + fml::TimePoint frame_target_time) = 0; + virtual void OnAnimatorDraw( std::shared_ptr> pipeline, std::unique_ptr frame_timings_recorder) = 0; diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc index 3e7fcb682416c..929cf050446bd 100644 --- a/shell/common/animator_unittests.cc +++ b/shell/common/animator_unittests.cc @@ -32,6 +32,9 @@ class FakeAnimatorDelegate : public Animator::Delegate { notify_idle_called_ = true; } + MOCK_METHOD1(OnAnimatorUpdateLatestFrameTargetTime, + void(fml::TimePoint frame_target_time)); + MOCK_METHOD2( OnAnimatorDraw, void(std::shared_ptr> pipeline, @@ -222,9 +225,12 @@ TEST_F(ShellTest, AnimatorDoesNotNotifyDelegateIfPipelineIsNotEmpty) { [&](fml::TimePoint frame_target_time, uint64_t frame_number) { begin_frame_latch.Signal(); }); - - // It will only be called once even though we call the method Animator::Render - // twice. because it will only be called when the pipeline is empty. + // It should always be called when the method 'Animator::Render' is called, + // regardless of whether the pipeline is empty or not. + EXPECT_CALL(delegate, OnAnimatorUpdateLatestFrameTargetTime).Times(2); + // It will only be called once even though we call the method + // 'Animator::Render' twice. because it will only be called when the pipeline + // is empty. EXPECT_CALL(delegate, OnAnimatorDraw).Times(1); for (int i = 0; i < 2; i++) { diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 7ae9ff7a98d5f..536c968ebb7f6 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1106,23 +1106,26 @@ void Shell::OnAnimatorNotifyIdle(fml::TimePoint deadline) { } } -// |Animator::Delegate| -void Shell::OnAnimatorDraw( - std::shared_ptr> pipeline, - std::unique_ptr frame_timings_recorder) { +void Shell::OnAnimatorUpdateLatestFrameTargetTime( + fml::TimePoint frame_target_time) { FML_DCHECK(is_setup_); // record the target time for use by rasterizer. { std::scoped_lock time_recorder_lock(time_recorder_mutex_); - const fml::TimePoint frame_target_time = - frame_timings_recorder->GetVsyncTargetTime(); if (!latest_frame_target_time_) { latest_frame_target_time_ = frame_target_time; } else if (latest_frame_target_time_ < frame_target_time) { latest_frame_target_time_ = frame_target_time; } } +} + +// |Animator::Delegate| +void Shell::OnAnimatorDraw( + std::shared_ptr> pipeline, + std::unique_ptr frame_timings_recorder) { + FML_DCHECK(is_setup_); auto discard_callback = [this](flutter::LayerTree& tree) { std::scoped_lock lock(resize_mutex_); diff --git a/shell/common/shell.h b/shell/common/shell.h index 099743e6be978..46395048cae8b 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -579,6 +579,10 @@ class Shell final : public PlatformView::Delegate, // |Animator::Delegate| void OnAnimatorNotifyIdle(fml::TimePoint deadline) override; + // |Animator::Delegate| + void OnAnimatorUpdateLatestFrameTargetTime( + fml::TimePoint frame_target_time) override; + // |Animator::Delegate| void OnAnimatorDraw( std::shared_ptr> pipeline, From 30c041ef46ecac054ceb35a1b2c5250966218706 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Mon, 21 Mar 2022 22:05:03 +0800 Subject: [PATCH 2/2] tweak comment --- shell/common/animator_unittests.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc index 929cf050446bd..32ed28c61c94b 100644 --- a/shell/common/animator_unittests.cc +++ b/shell/common/animator_unittests.cc @@ -225,7 +225,7 @@ TEST_F(ShellTest, AnimatorDoesNotNotifyDelegateIfPipelineIsNotEmpty) { [&](fml::TimePoint frame_target_time, uint64_t frame_number) { begin_frame_latch.Signal(); }); - // It should always be called when the method 'Animator::Render' is called, + // It must always be called when the method 'Animator::Render' is called, // regardless of whether the pipeline is empty or not. EXPECT_CALL(delegate, OnAnimatorUpdateLatestFrameTargetTime).Times(2); // It will only be called once even though we call the method