diff options
Diffstat (limited to 'chromium/cc/animation')
-rw-r--r-- | chromium/cc/animation/animation.cc | 23 | ||||
-rw-r--r-- | chromium/cc/animation/animation.h | 13 | ||||
-rw-r--r-- | chromium/cc/animation/animation_delegate.h | 6 | ||||
-rw-r--r-- | chromium/cc/animation/animation_host.cc | 45 | ||||
-rw-r--r-- | chromium/cc/animation/animation_host.h | 1 | ||||
-rw-r--r-- | chromium/cc/animation/animation_host_unittest.cc | 7 | ||||
-rw-r--r-- | chromium/cc/animation/element_animations_unittest.cc | 20 | ||||
-rw-r--r-- | chromium/cc/animation/keyframe_effect.cc | 34 | ||||
-rw-r--r-- | chromium/cc/animation/keyframe_effect.h | 5 | ||||
-rw-r--r-- | chromium/cc/animation/keyframe_model.cc | 5 | ||||
-rw-r--r-- | chromium/cc/animation/transform_operations.h | 2 | ||||
-rw-r--r-- | chromium/cc/animation/worklet_animation.cc | 9 | ||||
-rw-r--r-- | chromium/cc/animation/worklet_animation_unittest.cc | 14 |
13 files changed, 56 insertions, 128 deletions
diff --git a/chromium/cc/animation/animation.cc b/chromium/cc/animation/animation.cc index 5c40eed8453..df27dc32d11 100644 --- a/chromium/cc/animation/animation.cc +++ b/chromium/cc/animation/animation.cc @@ -127,20 +127,15 @@ void Animation::Tick(base::TimeTicks tick_time) { // time and then ticks it which side-steps the start time altogether. See // crbug.com/1076012 for alternative design choices considered for future // improvement. - TickWithLocalTime(tick_time - base::TimeTicks()); + keyframe_effect_->Pause(tick_time - base::TimeTicks(), + PauseCondition::kAfterStart); + keyframe_effect_->Tick(base::TimeTicks()); } else { DCHECK(!tick_time.is_null()); keyframe_effect_->Tick(tick_time); } } -void Animation::TickWithLocalTime(base::TimeDelta local_time) { - // TODO(yigu): KeyframeEffect should support ticking KeyframeModel - // directly without using Pause(). https://crbug.com/1076012. - keyframe_effect_->Pause(local_time); - keyframe_effect_->Tick(base::TimeTicks()); -} - bool Animation::IsScrollLinkedAnimation() const { return animation_timeline_ && animation_timeline_->IsScrollTimeline(); } @@ -211,10 +206,6 @@ void Animation::DelegateAnimationEvent(const AnimationEvent& event) { } } -size_t Animation::TickingKeyframeModelsCount() const { - return keyframe_effect_->TickingKeyframeModelsCount(); -} - bool Animation::AffectsCustomProperty() const { return keyframe_effect_->AffectsCustomProperty(); } @@ -287,12 +278,4 @@ void Animation::NotifyKeyframeModelFinishedForTesting( DispatchAndDelegateAnimationEvent(event); } -void Animation::UpdateScrollTimeline(base::Optional<ElementId> scroller_id, - base::Optional<double> start_scroll_offset, - base::Optional<double> end_scroll_offset) { - ToScrollTimeline(animation_timeline_) - ->UpdateScrollerIdAndScrollOffsets(scroller_id, start_scroll_offset, - end_scroll_offset); -} - } // namespace cc diff --git a/chromium/cc/animation/animation.h b/chromium/cc/animation/animation.h index 7fa4136d591..6cc50117d1f 100644 --- a/chromium/cc/animation/animation.h +++ b/chromium/cc/animation/animation.h @@ -65,17 +65,6 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { } void SetAnimationTimeline(AnimationTimeline* timeline); - // TODO(yigu): There is a reverse dependency between AnimationTimeline and - // Animation. ScrollTimeline update should be handled by AnimationHost instead - // of Animation. This could be fixed once the snapshotting in blink is - // implemented. https://crbug.com/1023508. - - // Should be called when the ScrollTimeline attached to this animation has a - // change, such as when the scroll source changes ElementId. - void UpdateScrollTimeline(base::Optional<ElementId> scroller_id, - base::Optional<double> start_scroll_offset, - base::Optional<double> end_scroll_offset); - scoped_refptr<ElementAnimations> element_animations() const; void set_animation_delegate(AnimationDelegate* delegate) { @@ -118,7 +107,6 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { // to be dispatched. void DispatchAndDelegateAnimationEvent(const AnimationEvent& event); - size_t TickingKeyframeModelsCount() const; bool AffectsCustomProperty() const; void SetNeedsPushProperties(); @@ -151,7 +139,6 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { explicit Animation(int id); Animation(int id, std::unique_ptr<KeyframeEffect>); virtual ~Animation(); - void TickWithLocalTime(base::TimeDelta local_time); AnimationHost* animation_host_; AnimationTimeline* animation_timeline_; diff --git a/chromium/cc/animation/animation_delegate.h b/chromium/cc/animation/animation_delegate.h index 0adbb115c59..6931c8b0d18 100644 --- a/chromium/cc/animation/animation_delegate.h +++ b/chromium/cc/animation/animation_delegate.h @@ -13,12 +13,6 @@ namespace cc { class CC_ANIMATION_EXPORT AnimationDelegate { public: - // TODO(yigu): The Notify* methods will be called multiple times per - // animation (once for effect/property pairing). - // Ideally, we would only notify start once (e.g., wait on all effects to - // start before notifying delegate) this way effect becomes an internal - // details of the animation. Perhaps we can do that at some point maybe as - // part of https://bugs.chromium.org/p/chromium/issues/detail?id=810003 virtual void NotifyAnimationStarted(base::TimeTicks monotonic_time, int target_property, int group) = 0; diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc index 1dfe39e66c9..d2154f19594 100644 --- a/chromium/cc/animation/animation_host.cc +++ b/chromium/cc/animation/animation_host.cc @@ -219,6 +219,8 @@ void AnimationHost::SetNeedsCommit() { } void AnimationHost::SetNeedsPushProperties() { + if (needs_push_properties_) + return; needs_push_properties_ = true; if (mutator_host_client_) mutator_host_client_->SetMutatorsNeedCommit(); @@ -227,6 +229,14 @@ void AnimationHost::SetNeedsPushProperties() { void AnimationHost::PushPropertiesTo(MutatorHost* mutator_host_impl) { auto* host_impl = static_cast<AnimationHost*>(mutator_host_impl); + // Update animation counts and whether raf was requested. These explicitly + // do not request push properties and are pushed as part of the next commit + // when it happens as requesting a commit leads to performance issues: + // https://crbug.com/1083244 + host_impl->main_thread_animations_count_ = main_thread_animations_count_; + host_impl->current_frame_had_raf_ = current_frame_had_raf_; + host_impl->next_frame_has_pending_raf_ = next_frame_has_pending_raf_; + if (needs_push_properties_) { needs_push_properties_ = false; PushTimelinesToImplThread(host_impl); @@ -289,9 +299,6 @@ void AnimationHost::PushPropertiesToImplThread(AnimationHost* host_impl) { // Update the impl-only scroll offset animations. scroll_offset_animations_->PushPropertiesTo( host_impl->scroll_offset_animations_impl_.get()); - host_impl->main_thread_animations_count_ = main_thread_animations_count_; - host_impl->current_frame_had_raf_ = current_frame_had_raf_; - host_impl->next_frame_has_pending_raf_ = next_frame_has_pending_raf_; // The pending info list is cleared in LayerTreeHostImpl::CommitComplete // and should be empty when pushing properties. @@ -752,37 +759,25 @@ void AnimationHost::SetMutationUpdate( } } -size_t AnimationHost::CompositedAnimationsCount() const { - size_t composited_animations_count = 0; - for (const auto& it : ticking_animations_) - composited_animations_count += it->TickingKeyframeModelsCount(); - return composited_animations_count; -} - void AnimationHost::SetAnimationCounts( size_t total_animations_count, bool current_frame_had_raf, bool next_frame_has_pending_raf) { + // Though these changes are pushed as part of AnimationHost::PushPropertiesTo + // we don't SetNeedsPushProperties as pushing the values requires a commit. + // Instead we allow them to be pushed whenever the next required commit + // happens to avoid unnecessary work. See https://crbug.com/1083244. + // If an animation is being run on the compositor, it will have a ticking // Animation (which will have a corresponding impl-thread version). Therefore // to find the count of main-only animations, we can simply subtract the // number of ticking animations from the total count. size_t ticking_animations_count = ticking_animations_.size(); - if (main_thread_animations_count_ != - total_animations_count - ticking_animations_count) { - main_thread_animations_count_ = - total_animations_count - ticking_animations_count; - DCHECK_GE(main_thread_animations_count_, 0u); - SetNeedsPushProperties(); - } - if (current_frame_had_raf != current_frame_had_raf_) { - current_frame_had_raf_ = current_frame_had_raf; - SetNeedsPushProperties(); - } - if (next_frame_has_pending_raf != next_frame_has_pending_raf_) { - next_frame_has_pending_raf_ = next_frame_has_pending_raf; - SetNeedsPushProperties(); - } + main_thread_animations_count_ = + total_animations_count - ticking_animations_count; + DCHECK_GE(main_thread_animations_count_, 0u); + current_frame_had_raf_ = current_frame_had_raf; + next_frame_has_pending_raf_ = next_frame_has_pending_raf; } size_t AnimationHost::MainThreadAnimationsCount() const { diff --git a/chromium/cc/animation/animation_host.h b/chromium/cc/animation/animation_host.h index de1ae6f8811..534f8c0c642 100644 --- a/chromium/cc/animation/animation_host.h +++ b/chromium/cc/animation/animation_host.h @@ -207,7 +207,6 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, void SetMutationUpdate( std::unique_ptr<MutatorOutputState> output_state) override; - size_t CompositedAnimationsCount() const override; size_t MainThreadAnimationsCount() const override; bool HasCustomPropertyAnimations() const override; bool CurrentFrameHadRAF() const override; diff --git a/chromium/cc/animation/animation_host_unittest.cc b/chromium/cc/animation/animation_host_unittest.cc index c2659983070..4dc4f9905d5 100644 --- a/chromium/cc/animation/animation_host_unittest.cc +++ b/chromium/cc/animation/animation_host_unittest.cc @@ -363,6 +363,9 @@ TEST_F(AnimationHostTest, LayerTreeMutatorUpdateReflectsScrollAnimations) { } TEST_F(AnimationHostTest, TickScrollLinkedAnimation) { + client_.RegisterElementId(element_id_, ElementListType::ACTIVE); + client_impl_.RegisterElementId(element_id_, ElementListType::PENDING); + client_impl_.RegisterElementId(element_id_, ElementListType::ACTIVE); PropertyTrees property_trees; property_trees.is_main_thread = false; property_trees.is_active = true; @@ -378,7 +381,7 @@ TEST_F(AnimationHostTest, TickScrollLinkedAnimation) { scoped_refptr<Animation> animation = Animation::Create(animation_id); host_impl_->AddAnimationTimeline(scroll_timeline); scroll_timeline->AttachAnimation(animation); - animation->AddToTicking(); + ASSERT_TRUE(animation->IsScrollLinkedAnimation()); animation->AttachElement(element_id_); @@ -393,7 +396,7 @@ TEST_F(AnimationHostTest, TickScrollLinkedAnimation) { EXPECT_TRUE(host_impl_->TickAnimations(base::TimeTicks(), property_trees.scroll_tree, false)); - EXPECT_EQ(keyframe_model->run_state(), KeyframeModel::PAUSED); + EXPECT_EQ(keyframe_model->run_state(), KeyframeModel::STARTING); double tick_time = (scroll_timeline->CurrentTime(scroll_tree, false).value() - base::TimeTicks()) .InSecondsF(); diff --git a/chromium/cc/animation/element_animations_unittest.cc b/chromium/cc/animation/element_animations_unittest.cc index 34debd1808a..9e1fa8337f3 100644 --- a/chromium/cc/animation/element_animations_unittest.cc +++ b/chromium/cc/animation/element_animations_unittest.cc @@ -3874,26 +3874,6 @@ TEST_F(ElementAnimationsTest, RemoveAndReAddAnimationToTicking) { EXPECT_EQ(1u, host_->ticking_animations_for_testing().size()); } -TEST_F(ElementAnimationsTest, TickingKeyframeModelsCount) { - CreateTestLayer(false, false); - AttachTimelineAnimationLayer(); - - // Add an animation and ensure the animation is in the host's ticking - // animations. - animation_->AddKeyframeModel(CreateKeyframeModel( - std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)), - 2, TargetProperty::OPACITY)); - EXPECT_EQ(1u, animation_->TickingKeyframeModelsCount()); - EXPECT_EQ(1u, host_->CompositedAnimationsCount()); - animation_->AddKeyframeModel(CreateKeyframeModel( - std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1)), 1, - TargetProperty::TRANSFORM)); - EXPECT_EQ(2u, animation_->TickingKeyframeModelsCount()); - EXPECT_EQ(2u, host_->CompositedAnimationsCount()); - animation_->keyframe_effect()->RemoveFromTicking(); - EXPECT_EQ(0u, host_->CompositedAnimationsCount()); -} - // This test verifies that finished keyframe models don't get copied over to // impl thread. TEST_F(ElementAnimationsTest, FinishedKeyframeModelsNotCopiedToImpl) { diff --git a/chromium/cc/animation/keyframe_effect.cc b/chromium/cc/animation/keyframe_effect.cc index 5af52eb211b..710d4f51c13 100644 --- a/chromium/cc/animation/keyframe_effect.cc +++ b/chromium/cc/animation/keyframe_effect.cc @@ -214,14 +214,28 @@ void KeyframeEffect::UpdateTickingState() { } } -void KeyframeEffect::Pause(base::TimeDelta pause_offset) { - for (auto& keyframe_model : keyframe_models_) +void KeyframeEffect::Pause(base::TimeDelta pause_offset, + PauseCondition pause_condition) { + bool did_pause = false; + for (auto& keyframe_model : keyframe_models_) { + // TODO(crbug.com/1076012): KeyframeEffect is paused with local time for + // scroll-linked animations. To make sure the start event of a keyframe + // model is sent to blink, we should not set its run state to PAUSED until + // such event is sent. This should be revisited once KeyframeEffect is able + // to tick scroll-linked keyframe models directly. + if (pause_condition == PauseCondition::kAfterStart && + (keyframe_model->run_state() == + KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY || + keyframe_model->run_state() == KeyframeModel::STARTING)) + continue; keyframe_model->Pause(pause_offset); - - if (has_bound_element_animations()) { - animation_->SetNeedsCommit(); - SetNeedsPushProperties(); + did_pause = true; } + + if (!did_pause || !has_bound_element_animations()) + return; + animation_->SetNeedsCommit(); + SetNeedsPushProperties(); } void KeyframeEffect::AddKeyframeModel( @@ -458,14 +472,6 @@ bool KeyframeEffect::HasTickingKeyframeModel() const { return false; } -size_t KeyframeEffect::TickingKeyframeModelsCount() const { - size_t ticking_keyframe_models_count = 0; - for (const auto& it : keyframe_models_) - if (!it->is_finished()) - ticking_keyframe_models_count++; - return ticking_keyframe_models_count; -} - bool KeyframeEffect::AffectsCustomProperty() const { for (const auto& it : keyframe_models_) if (it->target_property_id() == TargetProperty::CSS_CUSTOM_PROPERTY) diff --git a/chromium/cc/animation/keyframe_effect.h b/chromium/cc/animation/keyframe_effect.h index e7806e4cc1d..0e1280f82e1 100644 --- a/chromium/cc/animation/keyframe_effect.h +++ b/chromium/cc/animation/keyframe_effect.h @@ -22,6 +22,7 @@ namespace cc { class Animation; +enum class PauseCondition { kUnconditional, kAfterStart }; struct PropertyAnimationState; // A KeyframeEffect owns a group of KeyframeModels for a single target @@ -86,7 +87,8 @@ class CC_ANIMATION_EXPORT KeyframeEffect { void UpdateState(bool start_ready_keyframe_models, AnimationEvents* events); void UpdateTickingState(); - void Pause(base::TimeDelta pause_offset); + void Pause(base::TimeDelta pause_offset, + PauseCondition = PauseCondition::kUnconditional); void AddKeyframeModel(std::unique_ptr<KeyframeModel> keyframe_model); void PauseKeyframeModel(int keyframe_model_id, base::TimeDelta time_offset); @@ -106,7 +108,6 @@ class CC_ANIMATION_EXPORT KeyframeEffect { // Returns true if there are any KeyframeModels that have neither finished // nor aborted. bool HasTickingKeyframeModel() const; - size_t TickingKeyframeModelsCount() const; bool AffectsCustomProperty() const; diff --git a/chromium/cc/animation/keyframe_model.cc b/chromium/cc/animation/keyframe_model.cc index 25e2c6d232b..bb779226080 100644 --- a/chromium/cc/animation/keyframe_model.cc +++ b/chromium/cc/animation/keyframe_model.cc @@ -156,7 +156,7 @@ void KeyframeModel::SetRunState(RunState run_state, void KeyframeModel::Pause(base::TimeDelta pause_offset) { // Convert pause offset which is in local time to monotonic time. - // TODO(yigu): This should be scaled by playbackrate. http://crbug.com/912407 + // TODO(crbug.com/912407): This should be scaled by playbackrate. base::TimeTicks monotonic_time = pause_offset + start_time_ + total_paused_duration_; SetRunState(PAUSED, monotonic_time); @@ -246,8 +246,7 @@ bool KeyframeModel::InEffect(base::TimeTicks monotonic_time) const { return CalculateActiveTime(monotonic_time).has_value(); } -// TODO(yigu): Local time should be scaled by playback rate by spec. -// https://crbug.com/912407. +// TODO(crbug.com/912407): Local time should be scaled by playback rate by spec. base::TimeDelta KeyframeModel::ConvertMonotonicTimeToLocalTime( base::TimeTicks monotonic_time) const { // When waiting on receiving a start time, then our global clock is 'stuck' at diff --git a/chromium/cc/animation/transform_operations.h b/chromium/cc/animation/transform_operations.h index 2fecd424325..f0c669cf3e7 100644 --- a/chromium/cc/animation/transform_operations.h +++ b/chromium/cc/animation/transform_operations.h @@ -9,8 +9,8 @@ #include <unordered_map> #include <vector> +#include "base/check_op.h" #include "base/gtest_prod_util.h" -#include "base/logging.h" #include "cc/animation/animation_export.h" #include "cc/animation/transform_operation.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/animation/worklet_animation.cc b/chromium/cc/animation/worklet_animation.cc index 17ed083efcc..fd9a9c700ea 100644 --- a/chromium/cc/animation/worklet_animation.cc +++ b/chromium/cc/animation/worklet_animation.cc @@ -92,7 +92,8 @@ void WorkletAnimation::Tick(base::TimeTicks monotonic_time) { // animations lifecycle. To avoid this we pause the underlying keyframe effect // at the local time obtained from the user script - essentially turning each // call to |WorkletAnimation::Tick| into a seek in the effect. - TickWithLocalTime(local_time_.value()); + keyframe_effect_->Pause(local_time_.value()); + keyframe_effect_->Tick(base::TimeTicks()); } void WorkletAnimation::UpdateState(bool start_ready_animations, @@ -162,10 +163,6 @@ void WorkletAnimation::UpdateInputState(MutatorInputState* input_state, switch (state_) { case State::PENDING: - // TODO(yigu): cc side WorkletAnimation is only capable of handling single - // keyframe effect at the moment. We should pass in the number of effects - // once Worklet Group Effect is fully implemented in cc. - // https://crbug.com/767043. input_state->Add({worklet_animation_id(), name(), current_time->InMillisecondsF(), CloneOptions(), CloneEffectTimings()}); @@ -186,8 +183,6 @@ void WorkletAnimation::UpdateInputState(MutatorInputState* input_state, void WorkletAnimation::SetOutputState( const MutatorOutputState::AnimationState& state) { - // TODO(yigu): cc side WorkletAnimation is only capable of handling single - // keyframe effect at the moment. https://crbug.com/767043. DCHECK_EQ(state.local_times.size(), 1u); local_time_ = state.local_times[0]; } diff --git a/chromium/cc/animation/worklet_animation_unittest.cc b/chromium/cc/animation/worklet_animation_unittest.cc index e827c3740e3..ed610a56c19 100644 --- a/chromium/cc/animation/worklet_animation_unittest.cc +++ b/chromium/cc/animation/worklet_animation_unittest.cc @@ -555,20 +555,6 @@ TEST_F(WorkletAnimationTest, SkipLockedAnimations) { EXPECT_EQ(input->updated_animations.size(), 1u); } -TEST_F(WorkletAnimationTest, UpdateScrollTimelineScrollerId) { - auto scroll_timeline = base::WrapRefCounted(new MockScrollTimeline()); - EXPECT_EQ(scroll_timeline->GetPendingIdForTest(), ElementId()); - - scoped_refptr<WorkletAnimation> worklet_animation = WorkletAnimation::Create( - worklet_animation_id_, "test_name", 1, nullptr, nullptr); - host_->AddAnimationTimeline(scroll_timeline); - scroll_timeline->AttachAnimation(worklet_animation); - ElementId scroller_id = ElementId(1); - worklet_animation->UpdateScrollTimeline(scroller_id, base::nullopt, - base::nullopt); - EXPECT_EQ(scroll_timeline->GetPendingIdForTest(), scroller_id); -} - } // namespace } // namespace cc |