diff options
37 files changed, 478 insertions, 36 deletions
diff --git a/cc/animation/animation.cc b/cc/animation/animation.cc index 5c6fcd0..5d34627 100644 --- a/cc/animation/animation.cc +++ b/cc/animation/animation.cc @@ -20,7 +20,8 @@ static const char* const s_runStateNames[] = {"WAITING_FOR_TARGET_AVAILABILITY", "RUNNING", "PAUSED", "FINISHED", - "ABORTED"}; + "ABORTED", + "ABORTED_BUT_NEEDS_COMPLETION"}; static_assert(static_cast<int>(cc::Animation::LAST_RUN_STATE) + 1 == arraysize(s_runStateNames), diff --git a/cc/animation/animation.h b/cc/animation/animation.h index 645b71f..c146322 100644 --- a/cc/animation/animation.h +++ b/cc/animation/animation.h @@ -27,7 +27,10 @@ class CC_EXPORT Animation { // the STARTING state, and then into the RUNNING state. RUNNING animations may // toggle between RUNNING and PAUSED, and may be stopped by moving into either // the ABORTED or FINISHED states. A FINISHED animation was allowed to run to - // completion, but an ABORTED animation was not. + // completion, but an ABORTED animation was not. An animation in the state + // ABORTED_BUT_NEEDS_COMPLETION is an animation that was aborted for + // some reason, but needs to be finished. Currently this is for impl-only + // scroll offset animations that need to be completed on the main thread. enum RunState { WAITING_FOR_TARGET_AVAILABILITY = 0, WAITING_FOR_DELETION, @@ -36,8 +39,9 @@ class CC_EXPORT Animation { PAUSED, FINISHED, ABORTED, + ABORTED_BUT_NEEDS_COMPLETION, // This sentinel must be last. - LAST_RUN_STATE = ABORTED + LAST_RUN_STATE = ABORTED_BUT_NEEDS_COMPLETION }; enum Direction { diff --git a/cc/animation/animation_delegate.h b/cc/animation/animation_delegate.h index 732e693..aee077c 100644 --- a/cc/animation/animation_delegate.h +++ b/cc/animation/animation_delegate.h @@ -7,6 +7,7 @@ #include "base/time/time.h" #include "cc/animation/animation.h" +#include "cc/animation/animation_curve.h" namespace cc { @@ -23,6 +24,11 @@ class CC_EXPORT AnimationDelegate { TargetProperty::Type target_property, int group) = 0; + virtual void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) = 0; + protected: virtual ~AnimationDelegate() {} }; diff --git a/cc/animation/animation_events.cc b/cc/animation/animation_events.cc index edd435b..e747f8b 100644 --- a/cc/animation/animation_events.cc +++ b/cc/animation/animation_events.cc @@ -19,7 +19,38 @@ AnimationEvent::AnimationEvent(AnimationEvent::Type type, is_impl_only(false), opacity(0.f) {} -AnimationEvent::AnimationEvent(const AnimationEvent& other) = default; +AnimationEvent::AnimationEvent(const AnimationEvent& other) { + type = other.type; + layer_id = other.layer_id; + group_id = other.group_id; + target_property = other.target_property; + monotonic_time = other.monotonic_time; + is_impl_only = other.is_impl_only; + opacity = other.opacity; + transform = other.transform; + filters = other.filters; + animation_start_time = other.animation_start_time; + if (other.curve) + curve = other.curve->Clone(); +} + +AnimationEvent& AnimationEvent::operator=(const AnimationEvent& other) { + type = other.type; + layer_id = other.layer_id; + group_id = other.group_id; + target_property = other.target_property; + monotonic_time = other.monotonic_time; + is_impl_only = other.is_impl_only; + opacity = other.opacity; + transform = other.transform; + filters = other.filters; + animation_start_time = other.animation_start_time; + if (other.curve) + curve = other.curve->Clone(); + return *this; +} + +AnimationEvent::~AnimationEvent() {} AnimationEvents::AnimationEvents() {} diff --git a/cc/animation/animation_events.h b/cc/animation/animation_events.h index 650b9b5..73a7058 100644 --- a/cc/animation/animation_events.h +++ b/cc/animation/animation_events.h @@ -7,7 +7,9 @@ #include <vector> +#include "base/memory/scoped_ptr.h" #include "cc/animation/animation.h" +#include "cc/animation/animation_curve.h" #include "cc/base/cc_export.h" #include "cc/output/filter_operations.h" #include "ui/gfx/transform.h" @@ -15,14 +17,18 @@ namespace cc { struct CC_EXPORT AnimationEvent { - enum Type { STARTED, FINISHED, ABORTED, PROPERTY_UPDATE }; + enum Type { STARTED, FINISHED, ABORTED, PROPERTY_UPDATE, TAKEOVER }; AnimationEvent(Type type, int layer_id, int group_id, TargetProperty::Type target_property, base::TimeTicks monotonic_time); + AnimationEvent(const AnimationEvent& other); + AnimationEvent& operator=(const AnimationEvent& other); + + ~AnimationEvent(); Type type; int layer_id; @@ -33,6 +39,10 @@ struct CC_EXPORT AnimationEvent { float opacity; gfx::Transform transform; FilterOperations filters; + + // For continuing a scroll offset animation on the main thread. + double animation_start_time; + scoped_ptr<AnimationCurve> curve; }; class CC_EXPORT AnimationEvents { diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc index 6803f6c..a4264b0 100644 --- a/cc/animation/animation_host.cc +++ b/cc/animation/animation_host.cc @@ -98,10 +98,10 @@ class AnimationHost::ScrollOffsetAnimations : public AnimationDelegate { return true; } - void ScrollAnimationAbort() { + void ScrollAnimationAbort(bool needs_completion) { DCHECK(scroll_offset_animation_player_); scroll_offset_animation_player_->AbortAnimations( - TargetProperty::SCROLL_OFFSET); + TargetProperty::SCROLL_OFFSET, needs_completion); } // AnimationDelegate implementation. @@ -118,6 +118,10 @@ class AnimationHost::ScrollOffsetAnimations : public AnimationDelegate { void NotifyAnimationAborted(base::TimeTicks monotonic_time, TargetProperty::Type target_property, int group) override {} + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) override {} private: void ReattachScrollOffsetPlayerIfNeeded(int layer_id) { @@ -476,6 +480,16 @@ bool AnimationHost::OpacityIsAnimatingOnImplOnly(int layer_id) const { return animation && animation->is_impl_only(); } +bool AnimationHost::ScrollOffsetIsAnimatingOnImplOnly(int layer_id) const { + LayerAnimationController* controller = GetControllerForLayerId(layer_id); + if (!controller) + return false; + + Animation* animation = + controller->GetAnimation(TargetProperty::SCROLL_OFFSET); + return animation && animation->is_impl_only(); +} + bool AnimationHost::TransformIsAnimatingOnImplOnly(int layer_id) const { LayerAnimationController* controller = GetControllerForLayerId(layer_id); if (!controller) @@ -586,9 +600,9 @@ bool AnimationHost::ImplOnlyScrollAnimationUpdateTarget( layer_id, scroll_delta, max_scroll_offset, frame_monotonic_time); } -void AnimationHost::ScrollAnimationAbort() { +void AnimationHost::ScrollAnimationAbort(bool needs_completion) { DCHECK(scroll_offset_animations_); - return scroll_offset_animations_->ScrollAnimationAbort(); + return scroll_offset_animations_->ScrollAnimationAbort(needs_completion); } } // namespace cc diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h index 64f82be..e8ea9ae 100644 --- a/cc/animation/animation_host.h +++ b/cc/animation/animation_host.h @@ -115,6 +115,7 @@ class CC_EXPORT AnimationHost { bool FilterIsAnimatingOnImplOnly(int layer_id) const; bool OpacityIsAnimatingOnImplOnly(int layer_id) const; + bool ScrollOffsetIsAnimatingOnImplOnly(int layer_id) const; bool TransformIsAnimatingOnImplOnly(int layer_id) const; bool HasFilterAnimationThatInflatesBounds(int layer_id) const; @@ -151,7 +152,7 @@ class CC_EXPORT AnimationHost { const gfx::ScrollOffset& max_scroll_offset, base::TimeTicks frame_monotonic_time); - void ScrollAnimationAbort(); + void ScrollAnimationAbort(bool needs_completion); private: explicit AnimationHost(ThreadInstance thread_instance); diff --git a/cc/animation/animation_player.cc b/cc/animation/animation_player.cc index 0c8ad3c..77a7c21 100644 --- a/cc/animation/animation_player.cc +++ b/cc/animation/animation_player.cc @@ -160,10 +160,11 @@ void AnimationPlayer::AbortAnimation(int animation_id) { SetNeedsCommit(); } -void AnimationPlayer::AbortAnimations(TargetProperty::Type target_property) { +void AnimationPlayer::AbortAnimations(TargetProperty::Type target_property, + bool needs_completion) { if (element_animations_) { element_animations_->layer_animation_controller()->AbortAnimations( - target_property); + target_property, needs_completion); SetNeedsCommit(); } else { auto animations_to_remove = std::remove_if( @@ -211,6 +212,19 @@ void AnimationPlayer::NotifyAnimationAborted( target_property, group); } +void AnimationPlayer::NotifyAnimationTakeover( + base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) { + if (layer_animation_delegate_) { + DCHECK(curve); + layer_animation_delegate_->NotifyAnimationTakeover( + monotonic_time, target_property, animation_start_time, + std::move(curve)); + } +} + void AnimationPlayer::SetNeedsCommit() { DCHECK(animation_host_); animation_host_->SetNeedsCommit(); diff --git a/cc/animation/animation_player.h b/cc/animation/animation_player.h index 1276c93..a81b498 100644 --- a/cc/animation/animation_player.h +++ b/cc/animation/animation_player.h @@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/animation/animation.h" +#include "cc/animation/animation_curve.h" #include "cc/base/cc_export.h" namespace cc { @@ -69,7 +70,8 @@ class CC_EXPORT AnimationPlayer : public base::RefCounted<AnimationPlayer>, void PauseAnimation(int animation_id, double time_offset); void RemoveAnimation(int animation_id); void AbortAnimation(int animation_id); - void AbortAnimations(TargetProperty::Type target_property); + void AbortAnimations(TargetProperty::Type target_property, + bool needs_completion); void PushPropertiesTo(AnimationPlayer* player_impl); @@ -83,6 +85,10 @@ class CC_EXPORT AnimationPlayer : public base::RefCounted<AnimationPlayer>, void NotifyAnimationAborted(base::TimeTicks monotonic_time, TargetProperty::Type target_property, int group); + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve); // Whether this player has animations waiting to get sent to LAC. bool has_pending_animations_for_testing() const { diff --git a/cc/animation/animation_registrar.cc b/cc/animation/animation_registrar.cc index e5ecf83..e498045 100644 --- a/cc/animation/animation_registrar.cc +++ b/cc/animation/animation_registrar.cc @@ -132,6 +132,10 @@ void AnimationRegistrar::SetAnimationEvents( (*iter).second->NotifyAnimationPropertyUpdate( events->events_[event_index]); break; + + case AnimationEvent::TAKEOVER: + (*iter).second->NotifyAnimationTakeover(events->events_[event_index]); + break; } } } diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc index cded26a..485f3fd 100644 --- a/cc/animation/element_animations.cc +++ b/cc/animation/element_animations.cc @@ -270,6 +270,22 @@ void ElementAnimations::NotifyAnimationAborted( } } +void ElementAnimations::NotifyAnimationTakeover( + base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) { + DCHECK(curve); + for (PlayersListNode* node = players_list_->head(); + node != players_list_->end(); node = node->next()) { + scoped_ptr<AnimationCurve> animation_curve = curve->Clone(); + AnimationPlayer* player = node->value(); + player->NotifyAnimationTakeover(monotonic_time, target_property, + animation_start_time, + std::move(animation_curve)); + } +} + gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const { DCHECK(layer_animation_controller_); if (animation_host()) { diff --git a/cc/animation/element_animations.h b/cc/animation/element_animations.h index 61b85aa..ea33813 100644 --- a/cc/animation/element_animations.h +++ b/cc/animation/element_animations.h @@ -8,6 +8,8 @@ #include "base/containers/linked_list.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "cc/animation/animation_curve.h" #include "cc/animation/animation_delegate.h" #include "cc/animation/layer_animation_controller.h" #include "cc/animation/layer_animation_value_provider.h" @@ -103,6 +105,10 @@ class CC_EXPORT ElementAnimations : public AnimationDelegate, void NotifyAnimationAborted(base::TimeTicks monotonic_time, TargetProperty::Type target_property, int group) override; + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) override; // LayerAnimationValueProvider implementation. gfx::ScrollOffset ScrollOffsetForAnimation() const override; diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc index 1e8aa02..1f470b5 100644 --- a/cc/animation/layer_animation_controller.cc +++ b/cc/animation/layer_animation_controller.cc @@ -10,6 +10,7 @@ #include <vector> #include "cc/animation/animation.h" +#include "cc/animation/animation_curve.h" #include "cc/animation/animation_delegate.h" #include "cc/animation/animation_events.h" #include "cc/animation/animation_registrar.h" @@ -127,12 +128,23 @@ void LayerAnimationController::AbortAnimation(int animation_id) { } void LayerAnimationController::AbortAnimations( - TargetProperty::Type target_property) { + TargetProperty::Type target_property, + bool needs_completion) { + if (needs_completion) + DCHECK(target_property == TargetProperty::SCROLL_OFFSET); + bool aborted_transform_animation = false; for (size_t i = 0; i < animations_.size(); ++i) { if (animations_[i]->target_property() == target_property && !animations_[i]->is_finished()) { - animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_); + // Currently only impl-only scroll offset animations can be completed on + // the main thread. + if (needs_completion && animations_[i]->is_impl_only()) { + animations_[i]->SetRunState(Animation::ABORTED_BUT_NEEDS_COMPLETION, + last_tick_time_); + } else { + animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_); + } if (target_property == TargetProperty::TRANSFORM) aborted_transform_animation = true; } @@ -424,6 +436,17 @@ void LayerAnimationController::NotifyAnimationFinished( } } +void LayerAnimationController::NotifyAnimationTakeover( + const AnimationEvent& event) { + DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET); + if (layer_animation_delegate_) { + scoped_ptr<AnimationCurve> animation_curve = event.curve->Clone(); + layer_animation_delegate_->NotifyAnimationTakeover( + event.monotonic_time, event.target_property, event.animation_start_time, + std::move(animation_curve)); + } +} + void LayerAnimationController::NotifyAnimationAborted( const AnimationEvent& event) { bool aborted_transform_animation = false; @@ -923,6 +946,35 @@ void LayerAnimationController::MarkAnimationsForDeletion( continue; } + // If running on the compositor and need to complete an aborted animation + // on the main thread. + if (events && + animations_[i]->run_state() == + Animation::ABORTED_BUT_NEEDS_COMPLETION) { + AnimationEvent aborted_event(AnimationEvent::TAKEOVER, id_, group_id, + animations_[i]->target_property(), + monotonic_time); + aborted_event.animation_start_time = + (animations_[i]->start_time() - base::TimeTicks()).InSecondsF(); + const ScrollOffsetAnimationCurve* scroll_offset_animation_curve = + animations_[i]->curve()->ToScrollOffsetAnimationCurve(); + aborted_event.curve = scroll_offset_animation_curve->Clone(); + // Notify the compositor that the animation is finished. + if (layer_animation_delegate_) { + layer_animation_delegate_->NotifyAnimationFinished( + aborted_event.monotonic_time, aborted_event.target_property, + aborted_event.group_id); + } + // Notify main thread. + events->events_.push_back(aborted_event); + + // Remove the animation from the compositor. + animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION, + monotonic_time); + marked_animations_for_deletions = true; + continue; + } + bool all_anims_with_same_id_are_finished = false; // Since deleting an animation on the main thread leads to its deletion diff --git a/cc/animation/layer_animation_controller.h b/cc/animation/layer_animation_controller.h index a364172..28a4523 100644 --- a/cc/animation/layer_animation_controller.h +++ b/cc/animation/layer_animation_controller.h @@ -47,7 +47,8 @@ class CC_EXPORT LayerAnimationController void PauseAnimation(int animation_id, base::TimeDelta time_offset); void RemoveAnimation(int animation_id); void AbortAnimation(int animation_id); - void AbortAnimations(TargetProperty::Type target_property); + void AbortAnimations(TargetProperty::Type target_property, + bool needs_completion = false); // Ensures that the list of active animations on the main thread and the impl // thread are kept in sync. This function does not take ownership of the impl @@ -98,6 +99,7 @@ class CC_EXPORT LayerAnimationController void NotifyAnimationFinished(const AnimationEvent& event); void NotifyAnimationAborted(const AnimationEvent& event); void NotifyAnimationPropertyUpdate(const AnimationEvent& event); + void NotifyAnimationTakeover(const AnimationEvent& event); void AddValueObserver(LayerAnimationValueObserver* observer); void RemoveValueObserver(LayerAnimationValueObserver* observer); diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc index 764b470..5390d1b 100644 --- a/cc/animation/layer_animation_controller_unittest.cc +++ b/cc/animation/layer_animation_controller_unittest.cc @@ -1025,6 +1025,7 @@ class FakeAnimationDelegate : public AnimationDelegate { : started_(false), finished_(false), aborted_(false), + takeover_(false), start_time_(base::TimeTicks()) {} void NotifyAnimationStarted(TimeTicks monotonic_time, @@ -1046,18 +1047,28 @@ class FakeAnimationDelegate : public AnimationDelegate { aborted_ = true; } + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) override { + takeover_ = true; + } + bool started() { return started_; } bool finished() { return finished_; } bool aborted() { return aborted_; } + bool takeover() { return takeover_; } + TimeTicks start_time() { return start_time_; } private: bool started_; bool finished_; bool aborted_; + bool takeover_; TimeTicks start_time_; }; @@ -1906,6 +1917,72 @@ TEST(LayerAnimationControllerTest, ImplThreadAbortedAnimationGetsDeleted) { EXPECT_FALSE(controller_impl->GetAnimationById(animation_id)); } +// Test that an impl-only scroll offset animation that needs to be completed on +// the main thread gets deleted. +TEST(LayerAnimationControllerTest, ImplThreadTakeoverAnimationGetsDeleted) { + FakeLayerAnimationValueObserver dummy_impl; + scoped_refptr<LayerAnimationController> controller_impl( + LayerAnimationController::Create(0)); + controller_impl->AddValueObserver(&dummy_impl); + FakeLayerAnimationValueObserver dummy; + scoped_refptr<LayerAnimationController> controller( + LayerAnimationController::Create(0)); + controller->AddValueObserver(&dummy); + FakeAnimationDelegate delegate_impl; + controller_impl->set_layer_animation_delegate(&delegate_impl); + FakeAnimationDelegate delegate; + controller->set_layer_animation_delegate(&delegate); + + // Add impl-only scroll offset animation. + int animation_id = 1; + gfx::ScrollOffset initial_value(100.f, 300.f); + gfx::ScrollOffset target_value(300.f, 200.f); + scoped_ptr<ScrollOffsetAnimationCurve> curve( + ScrollOffsetAnimationCurve::Create(target_value, + EaseInOutTimingFunction::Create())); + curve->SetInitialValue(initial_value); + scoped_ptr<Animation> animation(Animation::Create( + std::move(curve), animation_id, 0, TargetProperty::SCROLL_OFFSET)); + animation->set_start_time(TicksFromSecondsF(123)); + animation->set_is_impl_only(true); + controller_impl->AddAnimation(std::move(animation)); + + controller->PushAnimationUpdatesTo(controller_impl.get()); + controller_impl->ActivateAnimations(); + EXPECT_TRUE(controller_impl->GetAnimationById(animation_id)); + + controller_impl->AbortAnimations(TargetProperty::SCROLL_OFFSET, + true /* needs_completion*/); + EXPECT_EQ(Animation::ABORTED_BUT_NEEDS_COMPLETION, + controller_impl->GetAnimation(TargetProperty::SCROLL_OFFSET) + ->run_state()); + EXPECT_FALSE(dummy.animation_waiting_for_deletion()); + EXPECT_FALSE(dummy_impl.animation_waiting_for_deletion()); + + AnimationEvents events; + controller_impl->Animate(kInitialTickTime); + controller_impl->UpdateState(true, &events); + EXPECT_TRUE(delegate_impl.finished()); + EXPECT_TRUE(dummy_impl.animation_waiting_for_deletion()); + EXPECT_EQ(1u, events.events_.size()); + EXPECT_EQ(AnimationEvent::TAKEOVER, events.events_[0].type); + EXPECT_EQ(123, events.events_[0].animation_start_time); + EXPECT_EQ( + target_value, + events.events_[0].curve->ToScrollOffsetAnimationCurve()->target_value()); + EXPECT_EQ(Animation::WAITING_FOR_DELETION, + controller_impl->GetAnimation(TargetProperty::SCROLL_OFFSET) + ->run_state()); + + controller->NotifyAnimationTakeover(events.events_[0]); + EXPECT_TRUE(delegate.takeover()); + + controller->PushAnimationUpdatesTo(controller_impl.get()); + controller_impl->ActivateAnimations(); + EXPECT_FALSE(controller->GetAnimationById(animation_id)); + EXPECT_FALSE(controller_impl->GetAnimationById(animation_id)); +} + // Ensure that we only generate FINISHED events for animations in a group // once all animations in that group are finished. TEST(LayerAnimationControllerTest, FinishedEventsForGroup) { diff --git a/cc/animation/scroll_offset_animation_curve.cc b/cc/animation/scroll_offset_animation_curve.cc index 1f44bba..86448b7 100644 --- a/cc/animation/scroll_offset_animation_curve.cc +++ b/cc/animation/scroll_offset_animation_curve.cc @@ -134,6 +134,11 @@ AnimationCurve::CurveType ScrollOffsetAnimationCurve::Type() const { } scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const { + return CloneToScrollOffsetAnimationCurve(); +} + +scoped_ptr<ScrollOffsetAnimationCurve> +ScrollOffsetAnimationCurve::CloneToScrollOffsetAnimationCurve() const { scoped_ptr<TimingFunction> timing_function( static_cast<TimingFunction*>(timing_function_->Clone().release())); scoped_ptr<ScrollOffsetAnimationCurve> curve_clone = @@ -142,7 +147,7 @@ scoped_ptr<AnimationCurve> ScrollOffsetAnimationCurve::Clone() const { curve_clone->total_animation_duration_ = total_animation_duration_; curve_clone->last_retarget_ = last_retarget_; curve_clone->has_set_initial_value_ = has_set_initial_value_; - return std::move(curve_clone); + return curve_clone; } static double VelocityBasedDurationBound(gfx::Vector2dF old_delta, diff --git a/cc/animation/scroll_offset_animation_curve.h b/cc/animation/scroll_offset_animation_curve.h index b874f11..8f9530a 100644 --- a/cc/animation/scroll_offset_animation_curve.h +++ b/cc/animation/scroll_offset_animation_curve.h @@ -36,6 +36,8 @@ class CC_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve { base::TimeDelta Duration() const override; CurveType Type() const override; scoped_ptr<AnimationCurve> Clone() const override; + scoped_ptr<ScrollOffsetAnimationCurve> CloneToScrollOffsetAnimationCurve() + const; private: ScrollOffsetAnimationCurve(const gfx::ScrollOffset& target_value, diff --git a/cc/blink/web_to_cc_animation_delegate_adapter.h b/cc/blink/web_to_cc_animation_delegate_adapter.h index 0978736..6c5453e 100644 --- a/cc/blink/web_to_cc_animation_delegate_adapter.h +++ b/cc/blink/web_to_cc_animation_delegate_adapter.h @@ -30,6 +30,10 @@ class WebToCCAnimationDelegateAdapter : public cc::AnimationDelegate { void NotifyAnimationAborted(base::TimeTicks monotonic_time, cc::TargetProperty::Type target_property, int group) override; + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + cc::TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<cc::AnimationCurve> curve) override {} blink::WebCompositorAnimationDelegate* delegate_; diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 3f14de8..a382cab 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -14,6 +14,7 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/animation/animation_host.h" #include "cc/animation/animation_registrar.h" #include "cc/animation/mutable_properties.h" #include "cc/base/math_util.h" @@ -501,6 +502,26 @@ scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) { return LayerImpl::Create(tree_impl, layer_id_, scroll_offset_); } +void LayerImpl::set_main_thread_scrolling_reasons( + uint32_t main_thread_scrolling_reasons) { + if (main_thread_scrolling_reasons_ == main_thread_scrolling_reasons) + return; + + if (main_thread_scrolling_reasons & + MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects && + layer_tree_impl()) { + if (layer_tree_impl()->ScrollOffsetIsAnimatingOnImplOnly(this)) { + layer_tree_impl()->animation_host()->ScrollAnimationAbort( + true /* needs_completion */); + } else if (layer_animation_controller()) { + layer_animation_controller()->AbortAnimations( + TargetProperty::SCROLL_OFFSET); + } + } + + main_thread_scrolling_reasons_ = main_thread_scrolling_reasons; +} + void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->SetTransformOrigin(transform_origin_); layer->SetBackgroundColor(background_color_); diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index c36dd9e0..7f4f922 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -128,6 +128,10 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void NotifyAnimationAborted(base::TimeTicks monotonic_time, TargetProperty::Type target_property, int group) override{}; + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) override {} // Tree structure. LayerImpl* parent() { return parent_; } @@ -506,9 +510,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, void ApplySentScrollDeltasFromAbortedCommit(); void set_main_thread_scrolling_reasons( - uint32_t main_thread_scrolling_reasons) { - main_thread_scrolling_reasons_ = main_thread_scrolling_reasons; - } + uint32_t main_thread_scrolling_reasons); uint32_t main_thread_scrolling_reasons() const { return main_thread_scrolling_reasons_; } diff --git a/cc/test/animation_timelines_test_common.h b/cc/test/animation_timelines_test_common.h index 9fdd451..e7b74915 100644 --- a/cc/test/animation_timelines_test_common.h +++ b/cc/test/animation_timelines_test_common.h @@ -155,6 +155,10 @@ class TestAnimationDelegate : public AnimationDelegate { void NotifyAnimationAborted(base::TimeTicks monotonic_time, TargetProperty::Type target_property, int group) override {} + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) override {} bool started_; bool finished_; }; diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h index a00233d..0a36af6 100644 --- a/cc/test/test_hooks.h +++ b/cc/test/test_hooks.h @@ -137,6 +137,10 @@ class TestHooks : public AnimationDelegate { void NotifyAnimationAborted(base::TimeTicks monotonic_time, TargetProperty::Type target_property, int group) override {} + void NotifyAnimationTakeover(base::TimeTicks monotonic_time, + TargetProperty::Type target_property, + double animation_start_time, + scoped_ptr<AnimationCurve> curve) override {} virtual void RequestNewOutputSurface() = 0; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 26dba53..da79b67 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -3748,7 +3748,7 @@ void LayerTreeHostImpl::UpdateRootLayerStateForSynchronousInputHandler() { void LayerTreeHostImpl::ScrollAnimationAbort(LayerImpl* layer_impl) { if (animation_host_) - return animation_host_->ScrollAnimationAbort(); + return animation_host_->ScrollAnimationAbort(false /* needs_completion */); layer_impl->layer_animation_controller()->AbortAnimations( TargetProperty::SCROLL_OFFSET); diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 2f543e9..25b066c 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -9457,6 +9457,64 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedAborted) { host_impl_->DidFinishImplFrame(); } +// Test that a smooth scroll offset animation is marked finished when a main +// thread scrolling reason is added. The animation is then finished on the +// main thread. +TEST_F(LayerTreeHostImplTimelinesTest, + ScrollAnimatedFinishedByMainThreadScrollingReason) { + const gfx::Size content_size(1000, 1000); + const gfx::Size viewport_size(500, 500); + CreateBasicVirtualViewportLayers(viewport_size, content_size); + + DrawFrame(); + + base::TimeTicks start_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(100); + + BeginFrameArgs begin_frame_args = + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE); + + // Perform animated scroll. + EXPECT_EQ( + InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 100)).thread); + + LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer(); + + begin_frame_args.frame_time = start_time; + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + EXPECT_TRUE(host_impl_->animation_host()->HasAnyAnimationTargetingProperty( + scrolling_layer->id(), TargetProperty::SCROLL_OFFSET)); + + EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset()); + host_impl_->DidFinishImplFrame(); + + begin_frame_args.frame_time = + start_time + base::TimeDelta::FromMilliseconds(50); + host_impl_->WillBeginImplFrame(begin_frame_args); + host_impl_->Animate(); + host_impl_->UpdateAnimationState(true); + + float y = scrolling_layer->CurrentScrollOffset().y(); + EXPECT_TRUE(y > 1 && y < 49); + + // Add main thread scrolling reason. + scrolling_layer->set_main_thread_scrolling_reasons( + MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects); + host_impl_->UpdateAnimationState(true); + + // The main thread scrolling reason should have marked the smooth scroll + // animation as finished. + EXPECT_FALSE( + host_impl_->animation_host()->HasActiveAnimation(scrolling_layer->id())); + EXPECT_TRUE(y > 1 && y < 49); + EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer()); + host_impl_->DidFinishImplFrame(); +} + // Evolved from LayerTreeHostImplTest.ScrollAnimated. TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) { const gfx::Size content_size(1000, 1000); diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index d595b77..3d608f1 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc @@ -1866,6 +1866,14 @@ bool LayerTreeImpl::OpacityIsAnimatingOnImplOnly(const LayerImpl* layer) const { : false; } +bool LayerTreeImpl::ScrollOffsetIsAnimatingOnImplOnly( + const LayerImpl* layer) const { + return layer_tree_host_impl_->animation_host() + ? layer_tree_host_impl_->animation_host() + ->ScrollOffsetIsAnimatingOnImplOnly(layer->id()) + : false; +} + bool LayerTreeImpl::TransformIsAnimatingOnImplOnly( const LayerImpl* layer) const { return layer_tree_host_impl_->animation_host() diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 4b8a401..1332f54 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h @@ -109,6 +109,9 @@ class CC_EXPORT LayerTreeImpl { bool RequiresHighResToDraw() const; bool SmoothnessTakesPriority() const; VideoFrameControllerClient* GetVideoFrameControllerClient() const; + AnimationHost* animation_host() const { + return layer_tree_host_impl_->animation_host(); + } // Tree specific methods exposed to layer-impl tree. // --------------------------------------------------------------------------- @@ -390,6 +393,7 @@ class CC_EXPORT LayerTreeImpl { bool FilterIsAnimatingOnImplOnly(const LayerImpl* layer) const; bool OpacityIsAnimatingOnImplOnly(const LayerImpl* layer) const; + bool ScrollOffsetIsAnimatingOnImplOnly(const LayerImpl* layer) const; bool TransformIsAnimatingOnImplOnly(const LayerImpl* layer) const; bool AnimationsPreserveAxisAlignment(const LayerImpl* layer) const; diff --git a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp index ca74779..a00f628 100644 --- a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp +++ b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp @@ -95,4 +95,18 @@ void CompositorAnimationPlayer::NotifyAnimationAborted( m_delegate->notifyAnimationAborted((monotonicTime - base::TimeTicks()).InSecondsF(), group); } +void CompositorAnimationPlayer::NotifyAnimationTakeover( + base::TimeTicks monotonicTime, + cc::TargetProperty::Type, + double animationStartTime, + scoped_ptr<cc::AnimationCurve> curve) +{ + if (m_delegate) { + m_delegate->notifyAnimationTakeover( + (monotonicTime - base::TimeTicks()).InSecondsF(), + animationStartTime, + std::move(curve)); + } +} + } // namespace blink diff --git a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h index b58d656..f8dcb6a 100644 --- a/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h +++ b/third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h @@ -8,6 +8,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "cc/animation/animation.h" +#include "cc/animation/animation_curve.h" #include "cc/animation/animation_delegate.h" #include "cc/animation/animation_player.h" #include "platform/PlatformExport.h" @@ -48,6 +49,7 @@ private: void NotifyAnimationStarted(base::TimeTicks monotonicTime, cc::TargetProperty::Type, int group) override; void NotifyAnimationFinished(base::TimeTicks monotonicTime, cc::TargetProperty::Type, int group) override; void NotifyAnimationAborted(base::TimeTicks monotonicTime, cc::TargetProperty::Type, int group) override; + void NotifyAnimationTakeover(base::TimeTicks monotonicTime, cc::TargetProperty::Type, double animationStartTime, scoped_ptr<cc::AnimationCurve>) override; scoped_refptr<cc::AnimationPlayer> m_animationPlayer; WebCompositorAnimationDelegate* m_delegate; diff --git a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp index c7d931e..f4202b3 100644 --- a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp +++ b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp @@ -39,6 +39,12 @@ CompositorScrollOffsetAnimationCurve::CompositorScrollOffsetAnimationCurve( { } +CompositorScrollOffsetAnimationCurve::CompositorScrollOffsetAnimationCurve( + cc::ScrollOffsetAnimationCurve* curve) + : m_curve(curve->CloneToScrollOffsetAnimationCurve()) +{ +} + CompositorScrollOffsetAnimationCurve::~CompositorScrollOffsetAnimationCurve() { } diff --git a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h index 5b927ca..9a0e81b 100644 --- a/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h +++ b/third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h @@ -28,6 +28,7 @@ public: }; CompositorScrollOffsetAnimationCurve(FloatPoint, TimingFunctionType, ScrollDurationBehavior); + CompositorScrollOffsetAnimationCurve(cc::ScrollOffsetAnimationCurve*); ~CompositorScrollOffsetAnimationCurve() override; // CompositorAnimationCurve implementation. diff --git a/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp b/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp index 6ab41fd..b086028 100644 --- a/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp +++ b/third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp @@ -36,6 +36,12 @@ public: durationBehavior); } + CompositorScrollOffsetAnimationCurve* createScrollOffsetAnimationCurve( + cc::ScrollOffsetAnimationCurve* curve) + { + return new CompositorScrollOffsetAnimationCurve(curve); + } + CompositorTransformAnimationCurve* createTransformAnimationCurve() override { return new CompositorTransformAnimationCurve(); diff --git a/third_party/WebKit/Source/platform/graphics/CompositorFactory.h b/third_party/WebKit/Source/platform/graphics/CompositorFactory.h index 612dfda..098e3e0 100644 --- a/third_party/WebKit/Source/platform/graphics/CompositorFactory.h +++ b/third_party/WebKit/Source/platform/graphics/CompositorFactory.h @@ -40,6 +40,9 @@ public: CompositorAnimationCurve::TimingFunctionType, CompositorScrollOffsetAnimationCurve::ScrollDurationBehavior) { return nullptr; } + virtual CompositorScrollOffsetAnimationCurve* createScrollOffsetAnimationCurve( + cc::ScrollOffsetAnimationCurve* curve) { return nullptr; } + virtual CompositorTransformAnimationCurve* createTransformAnimationCurve() { return nullptr; } virtual CompositorTransformOperations* createTransformOperations() { return nullptr; } diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp index 9baaff5..7c5c194 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp @@ -30,6 +30,7 @@ #include "platform/scroll/ScrollAnimator.h" +#include "cc/animation/scroll_offset_animation_curve.h" #include "platform/TraceEvent.h" #include "platform/animation/CompositorAnimation.h" #include "platform/graphics/CompositorFactory.h" @@ -120,15 +121,26 @@ ScrollResultOneDimensional ScrollAnimator::userScroll( FloatPoint targetPos = desiredTargetPosition(); targetPos.moveBy(pixelDelta); + if (willAnimateToOffset(targetPos)) { + m_lastGranularity = granularity; + // Report unused delta only if there is no animation running. See + // comment below regarding scroll latching. + return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); + } + // Report unused delta only if there is no animation and we are not + // starting one. This ensures we latch for the duration of the + // animation rather than animating multiple scrollers at the same time. + return ScrollResultOneDimensional(/* didScroll */ false, delta); +} + +bool ScrollAnimator::willAnimateToOffset(const FloatPoint& targetPos) +{ if (m_runState == RunState::PostAnimationCleanup) resetAnimationState(); if (m_animationCurve && m_runState != RunState::WaitingToCancelOnCompositor) { - if ((targetPos - m_targetOffset).isZero()) { - // Report unused delta only if there is no animation running. See - // comment below regarding scroll latching. - return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); - } + if ((targetPos - m_targetOffset).isZero()) + return true; m_targetOffset = targetPos; ASSERT(m_runState == RunState::RunningOnMainThread @@ -139,30 +151,25 @@ ScrollResultOneDimensional ScrollAnimator::userScroll( || m_runState == RunState::RunningOnCompositorButNeedsUpdate) { if (registerAndScheduleAnimation()) m_runState = RunState::RunningOnCompositorButNeedsUpdate; - return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); + return true; } // Running on the main thread, simply update the target offset instead // of sending to the compositor. m_animationCurve->updateTarget(m_timeFunction() - m_startTime, targetPos); - return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); + return true; } - if ((targetPos - currentPosition()).isZero()) { - // Report unused delta only if there is no animation and we are not - // starting one. This ensures we latch for the duration of the - // animation rather than animating multiple scrollers at the same time. - return ScrollResultOneDimensional(/* didScroll */ false, delta); - } + if ((targetPos - currentPosition()).isZero()) + return false; m_targetOffset = targetPos; m_startTime = m_timeFunction(); - m_lastGranularity = granularity; if (registerAndScheduleAnimation()) m_runState = RunState::WaitingToSendToCompositor; - return ScrollResultOneDimensional(/* didScroll */ true, /* unusedScrollDelta */ 0); + return true; } void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset) @@ -328,6 +335,28 @@ void ScrollAnimator::notifyCompositorAnimationFinished(int groupId) ScrollAnimatorCompositorCoordinator::compositorAnimationFinished(groupId); } +void ScrollAnimator::notifyAnimationTakeover( + double monotonicTime, + double animationStartTime, + scoped_ptr<cc::AnimationCurve> curve) +{ + // If there is already an animation running and the compositor asks to take + // over an animation, do nothing to avoid judder. + if (hasRunningAnimation()) + return; + + cc::ScrollOffsetAnimationCurve* scrollOffsetAnimationCurve = + curve->ToScrollOffsetAnimationCurve(); + FloatPoint targetValue(scrollOffsetAnimationCurve->target_value().x(), + scrollOffsetAnimationCurve->target_value().y()); + if (willAnimateToOffset(targetValue)) { + m_animationCurve = adoptPtr( + CompositorFactory::current().createScrollOffsetAnimationCurve( + std::move(scrollOffsetAnimationCurve))); + m_startTime = animationStartTime; + } +} + void ScrollAnimator::cancelAnimation() { ScrollAnimatorCompositorCoordinator::cancelAnimation(); diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h index 4bd57bd..bf788c9 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimator.h @@ -67,6 +67,11 @@ public: DECLARE_VIRTUAL_TRACE(); protected: + void notifyAnimationTakeover( + double monotonicTime, + double animationStartTime, + scoped_ptr<cc::AnimationCurve>) override; + OwnPtr<CompositorScrollOffsetAnimationCurve> m_animationCurve; double m_startTime; WTF::TimeFunction m_timeFunction; @@ -82,6 +87,11 @@ private: void addMainThreadScrollingReason(); void removeMainThreadScrollingReason(); + // Returns true if will animate to the given target position. Returns false + // only when there is no animation running and we are not starting one + // because we are already at targetPos. + bool willAnimateToOffset(const FloatPoint& targetPos); + FloatPoint m_targetOffset; ScrollGranularity m_lastGranularity; }; diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp index d35fe84..798d468 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp @@ -4,6 +4,7 @@ #include "platform/scroll/ScrollAnimatorCompositorCoordinator.h" +#include "cc/animation/scroll_offset_animation_curve.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/animation/CompositorAnimationPlayer.h" #include "platform/animation/CompositorAnimationTimeline.h" diff --git a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h index 55018f4..752b068 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h @@ -6,6 +6,7 @@ #define ScrollAnimatorCompositorCoordinator_h #include "base/gtest_prod_util.h" +#include "cc/animation/animation_curve.h" #include "platform/PlatformExport.h" #include "platform/animation/CompositorAnimationPlayerClient.h" #include "platform/heap/Handle.h" @@ -60,6 +61,10 @@ protected: void notifyAnimationStarted(double monotonicTime, int group) override; void notifyAnimationFinished(double monotonicTime, int group) override; void notifyAnimationAborted(double monotonicTime, int group) override; + void notifyAnimationTakeover( + double monotonicTime, + double animationStartTime, + scoped_ptr<cc::AnimationCurve>) override { }; // CompositorAnimationPlayerClient implementation. CompositorAnimationPlayer* compositorPlayer() const override; diff --git a/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h b/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h index 58339f8..78e8959 100644 --- a/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h +++ b/third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h @@ -6,6 +6,7 @@ #define WebCompositorAnimationDelegate_h #include "WebCommon.h" +#include "cc/animation/animation_curve.h" namespace blink { @@ -16,6 +17,14 @@ public: virtual void notifyAnimationStarted(double monotonicTime, int group) = 0; virtual void notifyAnimationFinished(double monotonicTime, int group) = 0; virtual void notifyAnimationAborted(double monotonicTime, int group) = 0; + // In the current state of things, notifyAnimationTakeover only applies to + // scroll offset animations since main thread scrolling reasons can be added + // while the compositor is animating. Keeping this non-pure virtual since + // it doesn't apply to CSS animations. + virtual void notifyAnimationTakeover( + double monotonicTime, + double animationStartTime, + scoped_ptr<cc::AnimationCurve> curve) { } }; } // namespace blink |