summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorymalik <ymalik@chromium.org>2016-02-29 23:32:07 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-01 07:33:37 +0000
commit6581bb3e791018e48d078a910ddfdce19a1c10bb (patch)
tree4ecb54dae2af25a8af24515c9914ef6098c8cf2b
parent1b2d1c9f119d12e861e202f39353cc5fb33f982a (diff)
downloadchromium_src-6581bb3e791018e48d078a910ddfdce19a1c10bb.zip
chromium_src-6581bb3e791018e48d078a910ddfdce19a1c10bb.tar.gz
chromium_src-6581bb3e791018e48d078a910ddfdce19a1c10bb.tar.bz2
Share animations from compositor to main thread.
This CL introduces a new state that a compositor animation can be in, namely, ABORT_BUT_NEEDS_COMPLETION. When a main thread scrolling reason is added, the current scroll offset animation is put into this state. The layer animation controller looks for impl-only animations in this state and passes a TAKEOVER animation event to the main thread with the animation_curve. The main thread then completes the animation. Notes: - This CL is for impl only animations, i.e, the jidder bug won't be fixed for an animation running on cc that was initiated by the main thread (keyboard scroll). Future CL will add the takeover logic for MT-initiated animations. - This CL doesn't support the takeover notification from the old animation path. The old path is where we don't use CompositorAnimationPlayer and its better to not add the plumbing for something that will be removed soon anyway. Design-doc https://docs.google.com/a/google.com/document/d/1JUYvp5gilux7bca8vfmE4Rr5BUjSthizmz7g4BnOnBA/edit?usp=sharing Test page: http://philipwalton.github.io/polyfill/demos/position-sticky/ BUG=581875 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1734063003 Cr-Commit-Position: refs/heads/master@{#378411}
-rw-r--r--cc/animation/animation.cc3
-rw-r--r--cc/animation/animation.h8
-rw-r--r--cc/animation/animation_delegate.h6
-rw-r--r--cc/animation/animation_events.cc33
-rw-r--r--cc/animation/animation_events.h12
-rw-r--r--cc/animation/animation_host.cc22
-rw-r--r--cc/animation/animation_host.h3
-rw-r--r--cc/animation/animation_player.cc18
-rw-r--r--cc/animation/animation_player.h8
-rw-r--r--cc/animation/animation_registrar.cc4
-rw-r--r--cc/animation/element_animations.cc16
-rw-r--r--cc/animation/element_animations.h6
-rw-r--r--cc/animation/layer_animation_controller.cc56
-rw-r--r--cc/animation/layer_animation_controller.h4
-rw-r--r--cc/animation/layer_animation_controller_unittest.cc77
-rw-r--r--cc/animation/scroll_offset_animation_curve.cc7
-rw-r--r--cc/animation/scroll_offset_animation_curve.h2
-rw-r--r--cc/blink/web_to_cc_animation_delegate_adapter.h4
-rw-r--r--cc/layers/layer_impl.cc21
-rw-r--r--cc/layers/layer_impl.h8
-rw-r--r--cc/test/animation_timelines_test_common.h4
-rw-r--r--cc/test/test_hooks.h4
-rw-r--r--cc/trees/layer_tree_host_impl.cc2
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc58
-rw-r--r--cc/trees/layer_tree_impl.cc8
-rw-r--r--cc/trees/layer_tree_impl.h4
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.cpp14
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorAnimationPlayer.h2
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.cpp6
-rw-r--r--third_party/WebKit/Source/platform/animation/CompositorScrollOffsetAnimationCurve.h1
-rw-r--r--third_party/WebKit/Source/platform/graphics/CompositorFactory.cpp6
-rw-r--r--third_party/WebKit/Source/platform/graphics/CompositorFactory.h3
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimator.cpp59
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimator.h10
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.cpp1
-rw-r--r--third_party/WebKit/Source/platform/scroll/ScrollAnimatorCompositorCoordinator.h5
-rw-r--r--third_party/WebKit/public/platform/WebCompositorAnimationDelegate.h9
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