From ae4316af505ca338b31908974cc33c011da1ed94 Mon Sep 17 00:00:00 2001 From: sunnyps Date: Tue, 24 Feb 2015 16:54:58 -0800 Subject: [PATCH] cc: Make scrollbar animations not require traversing the layer tree. Review URL: https://codereview.chromium.org/956453002 Cr-Commit-Position: refs/heads/master@{#317933} --- cc/animation/scrollbar_animation_controller.cc | 24 +++--- cc/animation/scrollbar_animation_controller.h | 26 +++++-- .../scrollbar_animation_controller_linear_fade.cc | 22 +++--- .../scrollbar_animation_controller_linear_fade.h | 2 - ...ar_animation_controller_linear_fade_unittest.cc | 72 ++++++++++++------ .../scrollbar_animation_controller_thinning.cc | 39 +++++----- .../scrollbar_animation_controller_thinning.h | 2 - ...llbar_animation_controller_thinning_unittest.cc | 27 +++++-- cc/test/fake_layer_tree_host_impl_client.h | 2 +- cc/trees/layer_tree_host_impl.cc | 48 ++++++------ cc/trees/layer_tree_host_impl.h | 19 ++--- cc/trees/layer_tree_host_impl_unittest.cc | 88 ++++++++++++++-------- cc/trees/single_thread_proxy.h | 2 +- cc/trees/thread_proxy.cc | 6 +- cc/trees/thread_proxy.h | 2 +- 15 files changed, 225 insertions(+), 156 deletions(-) diff --git a/cc/animation/scrollbar_animation_controller.cc b/cc/animation/scrollbar_animation_controller.cc index ffb228708256..48b199d6e665 100644 --- a/cc/animation/scrollbar_animation_controller.cc +++ b/cc/animation/scrollbar_animation_controller.cc @@ -7,15 +7,18 @@ #include #include "base/time/time.h" +#include "cc/trees/layer_tree_impl.h" namespace cc { ScrollbarAnimationController::ScrollbarAnimationController( + LayerImpl* scroll_layer, ScrollbarAnimationControllerClient* client, base::TimeDelta delay_before_starting, base::TimeDelta resize_delay_before_starting, base::TimeDelta duration) - : client_(client), + : scroll_layer_(scroll_layer), + client_(client), delay_before_starting_(delay_before_starting), resize_delay_before_starting_(resize_delay_before_starting), duration_(duration), @@ -26,6 +29,8 @@ ScrollbarAnimationController::ScrollbarAnimationController( } ScrollbarAnimationController::~ScrollbarAnimationController() { + if (is_animating_) + client_->StopAnimatingScrollbarAnimationController(this); } void ScrollbarAnimationController::Animate(base::TimeTicks now) { @@ -37,11 +42,6 @@ void ScrollbarAnimationController::Animate(base::TimeTicks now) { float progress = AnimationProgressAtTime(now); RunAnimationFrame(progress); - - if (is_animating_) { - delayed_scrollbar_fade_.Cancel(); - client_->SetNeedsScrollbarAnimationFrame(); - } } float ScrollbarAnimationController::AnimationProgressAtTime( @@ -62,38 +62,40 @@ void ScrollbarAnimationController::DidScrollUpdate(bool on_resize) { // As an optimization, we avoid spamming fade delay tasks during active fast // scrolls. But if we're not within one, we need to post every scroll update. if (!currently_scrolling_) - PostDelayedFade(on_resize); + PostDelayedAnimationTask(on_resize); else scroll_gesture_has_scrolled_ = true; } void ScrollbarAnimationController::DidScrollEnd() { if (scroll_gesture_has_scrolled_) { - PostDelayedFade(false); + PostDelayedAnimationTask(false); scroll_gesture_has_scrolled_ = false; } currently_scrolling_ = false; } -void ScrollbarAnimationController::PostDelayedFade(bool on_resize) { +void ScrollbarAnimationController::PostDelayedAnimationTask(bool on_resize) { base::TimeDelta delay = on_resize ? resize_delay_before_starting_ : delay_before_starting_; delayed_scrollbar_fade_.Reset( base::Bind(&ScrollbarAnimationController::StartAnimation, weak_factory_.GetWeakPtr())); - client_->PostDelayedScrollbarFade(delayed_scrollbar_fade_.callback(), delay); + client_->PostDelayedScrollbarAnimationTask(delayed_scrollbar_fade_.callback(), + delay); } void ScrollbarAnimationController::StartAnimation() { delayed_scrollbar_fade_.Cancel(); is_animating_ = true; last_awaken_time_ = base::TimeTicks(); - client_->SetNeedsScrollbarAnimationFrame(); + client_->StartAnimatingScrollbarAnimationController(this); } void ScrollbarAnimationController::StopAnimation() { is_animating_ = false; + client_->StopAnimatingScrollbarAnimationController(this); } } // namespace cc diff --git a/cc/animation/scrollbar_animation_controller.h b/cc/animation/scrollbar_animation_controller.h index 92efe7553188..795c7c1766c0 100644 --- a/cc/animation/scrollbar_animation_controller.h +++ b/cc/animation/scrollbar_animation_controller.h @@ -9,17 +9,25 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "cc/base/cc_export.h" +#include "cc/layers/layer_impl.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { +class ScrollbarAnimationController; + class CC_EXPORT ScrollbarAnimationControllerClient { public: - virtual ~ScrollbarAnimationControllerClient() {} + virtual void StartAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) = 0; + virtual void StopAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) = 0; + virtual void PostDelayedScrollbarAnimationTask(const base::Closure& task, + base::TimeDelta delay) = 0; + virtual void SetNeedsRedrawForScrollbarAnimation() = 0; - virtual void PostDelayedScrollbarFade(const base::Closure& start_fade, - base::TimeDelta delay) = 0; - virtual void SetNeedsScrollbarAnimationFrame() = 0; + protected: + virtual ~ScrollbarAnimationControllerClient() {} }; // This abstract class represents the compositor-side analogy of @@ -38,7 +46,8 @@ class CC_EXPORT ScrollbarAnimationController { virtual void DidMouseMoveNear(float distance) {} protected: - ScrollbarAnimationController(ScrollbarAnimationControllerClient* client, + ScrollbarAnimationController(LayerImpl* scroll_layer, + ScrollbarAnimationControllerClient* client, base::TimeDelta delay_before_starting, base::TimeDelta resize_delay_before_starting, base::TimeDelta duration); @@ -48,18 +57,21 @@ class CC_EXPORT ScrollbarAnimationController { void StartAnimation(); void StopAnimation(); + LayerImpl* scroll_layer_; + ScrollbarAnimationControllerClient* client_; + private: // Returns how far through the animation we are as a progress value from // 0 to 1. float AnimationProgressAtTime(base::TimeTicks now); - void PostDelayedFade(bool on_resize); + void PostDelayedAnimationTask(bool on_resize); - ScrollbarAnimationControllerClient* client_; base::TimeTicks last_awaken_time_; base::TimeDelta delay_before_starting_; base::TimeDelta resize_delay_before_starting_; base::TimeDelta duration_; + bool is_animating_; bool currently_scrolling_; diff --git a/cc/animation/scrollbar_animation_controller_linear_fade.cc b/cc/animation/scrollbar_animation_controller_linear_fade.cc index 1b5dfd933daf..d1049bda1cb9 100644 --- a/cc/animation/scrollbar_animation_controller_linear_fade.cc +++ b/cc/animation/scrollbar_animation_controller_linear_fade.cc @@ -17,12 +17,9 @@ ScrollbarAnimationControllerLinearFade::Create( base::TimeDelta delay_before_starting, base::TimeDelta resize_delay_before_starting, base::TimeDelta duration) { - return make_scoped_ptr( - new ScrollbarAnimationControllerLinearFade(scroll_layer, - client, - delay_before_starting, - resize_delay_before_starting, - duration)); + return make_scoped_ptr(new ScrollbarAnimationControllerLinearFade( + scroll_layer, client, delay_before_starting, resize_delay_before_starting, + duration)); } ScrollbarAnimationControllerLinearFade::ScrollbarAnimationControllerLinearFade( @@ -31,18 +28,20 @@ ScrollbarAnimationControllerLinearFade::ScrollbarAnimationControllerLinearFade( base::TimeDelta delay_before_starting, base::TimeDelta resize_delay_before_starting, base::TimeDelta duration) - : ScrollbarAnimationController(client, + : ScrollbarAnimationController(scroll_layer, + client, delay_before_starting, resize_delay_before_starting, - duration), - scroll_layer_(scroll_layer) { + duration) { } ScrollbarAnimationControllerLinearFade:: - ~ScrollbarAnimationControllerLinearFade() {} + ~ScrollbarAnimationControllerLinearFade() { +} void ScrollbarAnimationControllerLinearFade::RunAnimationFrame(float progress) { ApplyOpacityToScrollbars(1.f - progress); + client_->SetNeedsRedrawForScrollbarAnimation(); if (progress == 1.f) StopAnimation(); } @@ -59,8 +58,7 @@ void ScrollbarAnimationControllerLinearFade::ApplyOpacityToScrollbars( LayerImpl::ScrollbarSet* scrollbars = scroll_layer_->scrollbars(); for (LayerImpl::ScrollbarSet::iterator it = scrollbars->begin(); - it != scrollbars->end(); - ++it) { + it != scrollbars->end(); ++it) { ScrollbarLayerImplBase* scrollbar = *it; if (scrollbar->is_overlay_scrollbar()) diff --git a/cc/animation/scrollbar_animation_controller_linear_fade.h b/cc/animation/scrollbar_animation_controller_linear_fade.h index 73d60311fef4..05940a07ffc4 100644 --- a/cc/animation/scrollbar_animation_controller_linear_fade.h +++ b/cc/animation/scrollbar_animation_controller_linear_fade.h @@ -40,8 +40,6 @@ class CC_EXPORT ScrollbarAnimationControllerLinearFade float OpacityAtTime(base::TimeTicks now) const; void ApplyOpacityToScrollbars(float opacity); - LayerImpl* scroll_layer_; - DISALLOW_COPY_AND_ASSIGN(ScrollbarAnimationControllerLinearFade); }; diff --git a/cc/animation/scrollbar_animation_controller_linear_fade_unittest.cc b/cc/animation/scrollbar_animation_controller_linear_fade_unittest.cc index 2295124158a7..f7a5878b9435 100644 --- a/cc/animation/scrollbar_animation_controller_linear_fade_unittest.cc +++ b/cc/animation/scrollbar_animation_controller_linear_fade_unittest.cc @@ -20,14 +20,24 @@ class ScrollbarAnimationControllerLinearFadeTest public ScrollbarAnimationControllerClient { public: ScrollbarAnimationControllerLinearFadeTest() - : host_impl_(&proxy_, &shared_bitmap_manager_), needs_frame_count_(0) {} + : host_impl_(&proxy_, &shared_bitmap_manager_) {} - void PostDelayedScrollbarFade(const base::Closure& start_fade, - base::TimeDelta delay) override { + void StartAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) override { + is_animating_ = true; + } + void StopAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) override { + is_animating_ = false; + } + void PostDelayedScrollbarAnimationTask(const base::Closure& start_fade, + base::TimeDelta delay) override { start_fade_ = start_fade; delay_ = delay; } - void SetNeedsScrollbarAnimationFrame() override { needs_frame_count_++; } + void SetNeedsRedrawForScrollbarAnimation() override { + did_request_redraw_ = true; + } protected: void SetUp() override { @@ -57,11 +67,8 @@ class ScrollbarAnimationControllerLinearFadeTest scroll_layer_ptr->SetBounds(gfx::Size(200, 200)); scrollbar_controller_ = ScrollbarAnimationControllerLinearFade::Create( - scroll_layer_ptr, - this, - base::TimeDelta::FromSeconds(2), - base::TimeDelta::FromSeconds(5), - base::TimeDelta::FromSeconds(3)); + scroll_layer_ptr, this, base::TimeDelta::FromSeconds(2), + base::TimeDelta::FromSeconds(5), base::TimeDelta::FromSeconds(3)); } virtual ScrollbarOrientation orientation() const { return HORIZONTAL; } @@ -75,7 +82,8 @@ class ScrollbarAnimationControllerLinearFadeTest base::Closure start_fade_; base::TimeDelta delay_; - int needs_frame_count_; + bool is_animating_; + bool did_request_redraw_; }; class VerticalScrollbarAnimationControllerLinearFadeTest @@ -104,7 +112,6 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, HiddenInBegin) { scrollbar_layer_->SetOpacity(0.0f); scrollbar_controller_->Animate(base::TimeTicks()); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->opacity()); - EXPECT_EQ(0, needs_frame_count_); } TEST_F(ScrollbarAnimationControllerLinearFadeTest, @@ -123,8 +130,6 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, time += base::TimeDelta::FromSeconds(100); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->opacity()); - - EXPECT_EQ(0, needs_frame_count_); } TEST_F(ScrollbarAnimationControllerLinearFadeTest, HideOnResize) { @@ -263,20 +268,24 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, AwakenByScrollingGesture) { EXPECT_TRUE(start_fade_.Equals(base::Closure())); time += base::TimeDelta::FromSeconds(100); + scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); scrollbar_controller_->DidScrollEnd(); start_fade_.Run(); time += base::TimeDelta::FromSeconds(2); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->opacity()); @@ -285,50 +294,60 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, AwakenByScrollingGesture) { scrollbar_controller_->DidScrollBegin(); scrollbar_controller_->DidScrollUpdate(false); scrollbar_controller_->DidScrollEnd(); + start_fade_.Run(); time += base::TimeDelta::FromSeconds(2); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->opacity()); - - EXPECT_EQ(8, needs_frame_count_); + EXPECT_FALSE(is_animating_); } TEST_F(ScrollbarAnimationControllerLinearFadeTest, AwakenByProgrammaticScroll) { base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollUpdate(false); + start_fade_.Run(); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); scrollbar_controller_->DidScrollUpdate(false); - start_fade_.Run(); - time += base::TimeDelta::FromSeconds(1); + start_fade_.Run(); + time += base::TimeDelta::FromSeconds(2); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->opacity()); @@ -336,22 +355,25 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, AwakenByProgrammaticScroll) { scrollbar_controller_->DidScrollUpdate(false); start_fade_.Run(); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->opacity()); - - EXPECT_EQ(11, needs_frame_count_); + EXPECT_FALSE(is_animating_); } TEST_F(ScrollbarAnimationControllerLinearFadeTest, @@ -360,10 +382,12 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollUpdate(false); start_fade_.Run(); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); @@ -371,6 +395,7 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->opacity()); @@ -378,12 +403,10 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->opacity()); - - scrollbar_controller_->Animate(time); - - EXPECT_EQ(4, needs_frame_count_); + EXPECT_FALSE(is_animating_); } TEST_F(ScrollbarAnimationControllerLinearFadeTest, @@ -392,10 +415,12 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollUpdate(false); start_fade_.Run(); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); @@ -403,6 +428,7 @@ TEST_F(ScrollbarAnimationControllerLinearFadeTest, EXPECT_FLOAT_EQ(2.0f / 3.0f, scrollbar_layer_->opacity()); time += base::TimeDelta::FromSeconds(1); + EXPECT_TRUE(is_animating_); scrollbar_controller_->Animate(time); EXPECT_FLOAT_EQ(1.0f / 3.0f, scrollbar_layer_->opacity()); diff --git a/cc/animation/scrollbar_animation_controller_thinning.cc b/cc/animation/scrollbar_animation_controller_thinning.cc index 0405074b55a3..af6987e0e0b0 100644 --- a/cc/animation/scrollbar_animation_controller_thinning.cc +++ b/cc/animation/scrollbar_animation_controller_thinning.cc @@ -7,6 +7,7 @@ #include "base/time/time.h" #include "cc/layers/layer_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" +#include "cc/trees/layer_tree_impl.h" namespace { const float kIdleThicknessScale = 0.4f; @@ -23,12 +24,9 @@ ScrollbarAnimationControllerThinning::Create( base::TimeDelta delay_before_starting, base::TimeDelta resize_delay_before_starting, base::TimeDelta duration) { - return make_scoped_ptr( - new ScrollbarAnimationControllerThinning(scroll_layer, - client, - delay_before_starting, - resize_delay_before_starting, - duration)); + return make_scoped_ptr(new ScrollbarAnimationControllerThinning( + scroll_layer, client, delay_before_starting, resize_delay_before_starting, + duration)); } ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning( @@ -37,11 +35,11 @@ ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning( base::TimeDelta delay_before_starting, base::TimeDelta resize_delay_before_starting, base::TimeDelta duration) - : ScrollbarAnimationController(client, + : ScrollbarAnimationController(scroll_layer, + client, delay_before_starting, resize_delay_before_starting, duration), - scroll_layer_(scroll_layer), mouse_is_over_scrollbar_(false), mouse_is_near_scrollbar_(false), thickness_change_(NONE), @@ -56,9 +54,10 @@ ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() { void ScrollbarAnimationControllerThinning::RunAnimationFrame(float progress) { float opacity = OpacityAtAnimationProgress(progress); - float thumb_thickness_scale = ThumbThicknessScaleAtAnimationProgress( - progress); + float thumb_thickness_scale = + ThumbThicknessScaleAtAnimationProgress(progress); ApplyOpacityAndThumbThicknessScale(opacity, thumb_thickness_scale); + client_->SetNeedsRedrawForScrollbarAnimation(); if (progress == 1.f) { opacity_change_ = NONE; thickness_change_ = NONE; @@ -77,7 +76,7 @@ void ScrollbarAnimationControllerThinning::DidMouseMoveOffScrollbar() { void ScrollbarAnimationControllerThinning::DidScrollUpdate(bool on_resize) { ScrollbarAnimationController::DidScrollUpdate(on_resize); ApplyOpacityAndThumbThicknessScale( - 1, mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale); + 1, mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale); if (!mouse_is_over_scrollbar_) opacity_change_ = DECREASE; @@ -114,9 +113,8 @@ float ScrollbarAnimationControllerThinning::OpacityAtAnimationProgress( return ret; } -float -ScrollbarAnimationControllerThinning::ThumbThicknessScaleAtAnimationProgress( - float progress) { +float ScrollbarAnimationControllerThinning:: + ThumbThicknessScaleAtAnimationProgress(float progress) { if (thickness_change_ == NONE) return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale; float factor = thickness_change_ == INCREASE ? progress : (1.f - progress); @@ -135,14 +133,14 @@ float ScrollbarAnimationControllerThinning::AdjustScale( } void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale( - float opacity, float thumb_thickness_scale) { + float opacity, + float thumb_thickness_scale) { if (!scroll_layer_->scrollbars()) return; LayerImpl::ScrollbarSet* scrollbars = scroll_layer_->scrollbars(); for (LayerImpl::ScrollbarSet::iterator it = scrollbars->begin(); - it != scrollbars->end(); - ++it) { + it != scrollbars->end(); ++it) { ScrollbarLayerImplBase* scrollbar = *it; if (scrollbar->is_overlay_scrollbar()) { float effectiveOpacity = @@ -151,10 +149,9 @@ void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale( : 0; scrollbar->SetOpacity(effectiveOpacity); - scrollbar->SetThumbThicknessScaleFactor( - AdjustScale(thumb_thickness_scale, - scrollbar->thumb_thickness_scale_factor(), - thickness_change_)); + scrollbar->SetThumbThicknessScaleFactor(AdjustScale( + thumb_thickness_scale, scrollbar->thumb_thickness_scale_factor(), + thickness_change_)); } } } diff --git a/cc/animation/scrollbar_animation_controller_thinning.h b/cc/animation/scrollbar_animation_controller_thinning.h index 2cf30f5b8210..f22d94c928d3 100644 --- a/cc/animation/scrollbar_animation_controller_thinning.h +++ b/cc/animation/scrollbar_animation_controller_thinning.h @@ -62,8 +62,6 @@ class CC_EXPORT ScrollbarAnimationControllerThinning void ApplyOpacityAndThumbThicknessScale(float opacity, float thumb_thickness_scale); - LayerImpl* scroll_layer_; - bool mouse_is_over_scrollbar_; bool mouse_is_near_scrollbar_; // Are we narrowing or thickening the bars. diff --git a/cc/animation/scrollbar_animation_controller_thinning_unittest.cc b/cc/animation/scrollbar_animation_controller_thinning_unittest.cc index 04036ba63955..01763c91cae5 100644 --- a/cc/animation/scrollbar_animation_controller_thinning_unittest.cc +++ b/cc/animation/scrollbar_animation_controller_thinning_unittest.cc @@ -22,11 +22,22 @@ class ScrollbarAnimationControllerThinningTest ScrollbarAnimationControllerThinningTest() : host_impl_(&proxy_, &shared_bitmap_manager_) {} - void PostDelayedScrollbarFade(const base::Closure& start_fade, - base::TimeDelta delay) override { + void StartAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) override { + is_animating_ = true; + } + void StopAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) override { + is_animating_ = false; + } + void PostDelayedScrollbarAnimationTask(const base::Closure& start_fade, + base::TimeDelta delay) override { start_fade_ = start_fade; + delay_ = delay; + } + void SetNeedsRedrawForScrollbarAnimation() override { + did_request_redraw_ = true; } - void SetNeedsScrollbarAnimationFrame() override {} protected: void SetUp() override { @@ -57,11 +68,8 @@ class ScrollbarAnimationControllerThinningTest scroll_layer_ptr->SetBounds(gfx::Size(200, 200)); scrollbar_controller_ = ScrollbarAnimationControllerThinning::Create( - scroll_layer_ptr, - this, - base::TimeDelta::FromSeconds(2), - base::TimeDelta::FromSeconds(5), - base::TimeDelta::FromSeconds(3)); + scroll_layer_ptr, this, base::TimeDelta::FromSeconds(2), + base::TimeDelta::FromSeconds(5), base::TimeDelta::FromSeconds(3)); } FakeImplProxy proxy_; @@ -72,6 +80,9 @@ class ScrollbarAnimationControllerThinningTest scoped_ptr scrollbar_layer_; base::Closure start_fade_; + base::TimeDelta delay_; + bool is_animating_; + bool did_request_redraw_; }; // Check initialization of scrollbar. diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h index d7a785b619be..63d7f43e525e 100644 --- a/cc/test/fake_layer_tree_host_impl_client.h +++ b/cc/test/fake_layer_tree_host_impl_client.h @@ -35,7 +35,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient { int priority_cutoff) override; bool IsInsideDraw() override; void RenewTreePriority() override {} - void PostDelayedScrollbarFadeOnImplThread(const base::Closure& start_fade, + void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, base::TimeDelta delay) override {} void DidActivateSyncTree() override {} void DidPrepareTiles() override {} diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index e13da9acd872..77e635cd9cb5 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -3114,6 +3114,19 @@ void LayerTreeHostImpl::AnimateTopControls(base::TimeTicks time) { client_->RenewTreePriority(); } +void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks monotonic_time) { + if (scrollbar_animation_controllers_.empty()) + return; + + TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateScrollbars"); + std::set controllers_copy = + scrollbar_animation_controllers_; + for (auto& it : controllers_copy) + it->Animate(monotonic_time); + + SetNeedsAnimate(); +} + void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) { if (!settings_.accelerated_animation_enabled || !needs_animate_layers() || @@ -3184,36 +3197,25 @@ int LayerTreeHostImpl::SourceAnimationFrameNumber() const { return fps_counter_->current_frame_number(); } -void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks time) { - AnimateScrollbarsRecursive(active_tree_->root_layer(), time); +void LayerTreeHostImpl::StartAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) { + scrollbar_animation_controllers_.insert(controller); + SetNeedsAnimate(); } -void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer, - base::TimeTicks time) { - if (!layer) - return; - - ScrollbarAnimationController* scrollbar_controller = - layer->scrollbar_animation_controller(); - if (scrollbar_controller) - scrollbar_controller->Animate(time); - - for (size_t i = 0; i < layer->children().size(); ++i) - AnimateScrollbarsRecursive(layer->children()[i], time); +void LayerTreeHostImpl::StopAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) { + scrollbar_animation_controllers_.erase(controller); } -void LayerTreeHostImpl::PostDelayedScrollbarFade( - const base::Closure& start_fade, +void LayerTreeHostImpl::PostDelayedScrollbarAnimationTask( + const base::Closure& task, base::TimeDelta delay) { - client_->PostDelayedScrollbarFadeOnImplThread(start_fade, delay); + client_->PostDelayedAnimationTaskOnImplThread(task, delay); } -void LayerTreeHostImpl::SetNeedsScrollbarAnimationFrame() { - TRACE_EVENT_INSTANT0( - "cc", - "LayerTreeHostImpl::SetNeedsRedraw due to scrollbar fade", - TRACE_EVENT_SCOPE_THREAD); - SetNeedsAnimate(); +void LayerTreeHostImpl::SetNeedsRedrawForScrollbarAnimation() { + SetNeedsRedraw(); } void LayerTreeHostImpl::SetTreePriority(TreePriority priority) { diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 60f4b4479f88..deab76b37bb2 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -103,9 +103,8 @@ class LayerTreeHostImplClient { int priority_cutoff) = 0; virtual bool IsInsideDraw() = 0; virtual void RenewTreePriority() = 0; - virtual void PostDelayedScrollbarFadeOnImplThread( - const base::Closure& start_fade, - base::TimeDelta delay) = 0; + virtual void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, + base::TimeDelta delay) = 0; virtual void DidActivateSyncTree() = 0; virtual void DidPrepareTiles() = 0; @@ -258,9 +257,13 @@ class CC_EXPORT LayerTreeHostImpl void SetIsLikelyToRequireADraw(bool is_likely_to_require_a_draw) override; // ScrollbarAnimationControllerClient implementation. - void PostDelayedScrollbarFade(const base::Closure& start_fade, - base::TimeDelta delay) override; - void SetNeedsScrollbarAnimationFrame() override; + void StartAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) override; + void StopAnimatingScrollbarAnimationController( + ScrollbarAnimationController* controller) override; + void PostDelayedScrollbarAnimationTask(const base::Closure& task, + base::TimeDelta delay) override; + void SetNeedsRedrawForScrollbarAnimation() override; // OutputSurfaceClient implementation. void DeferredInitialize() override; @@ -584,9 +587,6 @@ class CC_EXPORT LayerTreeHostImpl bool HandleMouseOverScrollbar(LayerImpl* layer_impl, const gfx::PointF& device_viewport_point); - void AnimateScrollbarsRecursive(LayerImpl* layer, - base::TimeTicks time); - LayerImpl* FindScrollLayerForDeviceViewportPoint( const gfx::PointF& device_viewport_point, InputHandler::ScrollInputType type, @@ -716,6 +716,7 @@ class CC_EXPORT LayerTreeHostImpl base::TimeDelta begin_impl_frame_interval_; scoped_ptr animation_registrar_; + std::set scrollbar_animation_controllers_; RenderingStatsInstrumentation* rendering_stats_instrumentation_; MicroBenchmarkControllerImpl micro_benchmark_controller_; diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 4fc26b2763f8..110bee999392 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -150,10 +150,10 @@ class LayerTreeHostImplTest : public testing::Test, } bool IsInsideDraw() override { return false; } void RenewTreePriority() override {} - void PostDelayedScrollbarFadeOnImplThread(const base::Closure& start_fade, + void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, base::TimeDelta delay) override { - scrollbar_fade_start_ = start_fade; - requested_scrollbar_animation_delay_ = delay; + animation_task_ = task; + requested_animation_delay_ = delay; } void DidActivateSyncTree() override {} void DidPrepareTiles() override {} @@ -406,8 +406,8 @@ class LayerTreeHostImplTest : public testing::Test, bool did_request_prepare_tiles_; bool did_complete_page_scale_animation_; bool reduce_memory_result_; - base::Closure scrollbar_fade_start_; - base::TimeDelta requested_scrollbar_animation_delay_; + base::Closure animation_task_; + base::TimeDelta requested_animation_delay_; size_t current_limit_bytes_; int current_priority_cutoff_value_; }; @@ -1621,52 +1621,77 @@ TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) { base::TimeTicks fake_now = gfx::FrameTime::Now(); - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + EXPECT_FALSE(did_request_animate_); EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); // If no scroll happened during a scroll gesture, it should have no effect. host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); host_impl_->ScrollEnd(); - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + EXPECT_FALSE(did_request_animate_); EXPECT_FALSE(did_request_redraw_); - EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure())); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); // After a scroll, a fade animation should be scheduled about 20ms from now. host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5)); - host_impl_->ScrollEnd(); + EXPECT_FALSE(did_request_animate_); + EXPECT_TRUE(did_request_redraw_); did_request_redraw_ = false; + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + + host_impl_->ScrollEnd(); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + + fake_now += requested_animation_delay_; + requested_animation_delay_ = base::TimeDelta(); + animation_task_.Run(); + animation_task_ = base::Closure(); + EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; - EXPECT_LT(base::TimeDelta::FromMilliseconds(19), - requested_scrollbar_animation_delay_); EXPECT_FALSE(did_request_redraw_); - EXPECT_FALSE(did_request_animate_); - requested_scrollbar_animation_delay_ = base::TimeDelta(); - scrollbar_fade_start_.Run(); - host_impl_->Animate(fake_now); // After the fade begins, we should start getting redraws instead of a // scheduled animation. - fake_now += base::TimeDelta::FromMilliseconds(25); - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + host_impl_->Animate(fake_now); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; + EXPECT_TRUE(did_request_redraw_); + did_request_redraw_ = false; + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); // Setting the scroll offset outside a scroll should also cause the scrollbar // to appear and to schedule a fade. host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread( gfx::ScrollOffset(5, 5)); - EXPECT_LT(base::TimeDelta::FromMilliseconds(19), - requested_scrollbar_animation_delay_); - EXPECT_FALSE(did_request_redraw_); EXPECT_FALSE(did_request_animate_); - requested_scrollbar_animation_delay_ = base::TimeDelta(); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + requested_animation_delay_ = base::TimeDelta(); + animation_task_ = base::Closure(); // Unnecessarily Fade animation of solid color scrollbar is not triggered. host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); + EXPECT_FALSE(did_request_animate_); + EXPECT_TRUE(did_request_redraw_); + did_request_redraw_ = false; + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + host_impl_->ScrollEnd(); - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); } TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { @@ -1682,28 +1707,28 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); EXPECT_FALSE(did_request_animate_); // If no scroll happened during a scroll gesture, it should have no effect. host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); host_impl_->ScrollEnd(); - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); EXPECT_FALSE(did_request_animate_); - EXPECT_TRUE(scrollbar_fade_start_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); // After a scroll, no fade animation should be scheduled. host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); host_impl_->ScrollEnd(); did_request_redraw_ = false; - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); EXPECT_FALSE(did_request_animate_); - requested_scrollbar_animation_delay_ = base::TimeDelta(); + requested_animation_delay_ = base::TimeDelta(); // We should not see any draw requests. fake_now += base::TimeDelta::FromMilliseconds(25); - EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); EXPECT_FALSE(did_request_animate_); // Make page scale > min so that subsequent scrolls will trigger fades. @@ -1714,11 +1739,10 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); host_impl_->ScrollEnd(); did_request_redraw_ = false; - EXPECT_LT(base::TimeDelta::FromMilliseconds(19), - requested_scrollbar_animation_delay_); + EXPECT_LT(base::TimeDelta::FromMilliseconds(19), requested_animation_delay_); EXPECT_FALSE(did_request_animate_); - requested_scrollbar_animation_delay_ = base::TimeDelta(); - scrollbar_fade_start_.Run(); + requested_animation_delay_ = base::TimeDelta(); + animation_task_.Run(); // After the fade begins, we should start getting redraws instead of a // scheduled animation. diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index f463db1fde54..2612a4de165f 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -104,7 +104,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, int priority_cutoff) override; bool IsInsideDraw() override; void RenewTreePriority() override {} - void PostDelayedScrollbarFadeOnImplThread(const base::Closure& start_fade, + void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, base::TimeDelta delay) override {} void DidActivateSyncTree() override; void DidPrepareTiles() override; diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index 109780585569..4efb4015c9e4 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -1362,10 +1362,10 @@ void ThreadProxy::RenewTreePriority() { } } -void ThreadProxy::PostDelayedScrollbarFadeOnImplThread( - const base::Closure& start_fade, +void ThreadProxy::PostDelayedAnimationTaskOnImplThread( + const base::Closure& task, base::TimeDelta delay) { - Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, start_fade, delay); + Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, task, delay); } void ThreadProxy::DidActivateSyncTree() { diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 8b4c3025ae95..c2dd348eb0ad 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -205,7 +205,7 @@ class CC_EXPORT ThreadProxy : public Proxy, int priority_cutoff) override; bool IsInsideDraw() override; void RenewTreePriority() override; - void PostDelayedScrollbarFadeOnImplThread(const base::Closure& start_fade, + void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, base::TimeDelta delay) override; void DidActivateSyncTree() override; void DidPrepareTiles() override; -- 2.11.4.GIT