diff options
author | ajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-23 01:54:16 +0000 |
---|---|---|
committer | ajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-23 01:54:16 +0000 |
commit | bf91227ca2796661a6b17176dc50f4db002a7b49 (patch) | |
tree | eb055c21ce79191091dfb52422b958d1118b3840 | |
parent | fe3b57cceb3381de3b8a9e83d52f6829c14317c0 (diff) | |
download | chromium_src-bf91227ca2796661a6b17176dc50f4db002a7b49.zip chromium_src-bf91227ca2796661a6b17176dc50f4db002a7b49.tar.gz chromium_src-bf91227ca2796661a6b17176dc50f4db002a7b49.tar.bz2 |
Thread ui opacity animations
BUG=164206
Review URL: https://chromiumcodereview.appspot.com/11896017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184254 0039d316-1c4b-4281-b951-d872f2087c98
28 files changed, 1461 insertions, 360 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index dd22c5b..e7f1b7e 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -573,6 +573,8 @@ 'ash_test_support', ], 'sources': [ + '../ui/compositor/test/layer_animator_test_controller.cc', + '../ui/compositor/test/layer_animator_test_controller.h', '../ui/views/test/test_views_delegate.cc', '../ui/views/test/test_views_delegate.h', 'accelerators/accelerator_controller_unittest.cc', diff --git a/ash/desktop_background/desktop_background_controller_unittest.cc b/ash/desktop_background/desktop_background_controller_unittest.cc index 7857231..237126e 100644 --- a/ash/desktop_background/desktop_background_controller_unittest.cc +++ b/ash/desktop_background/desktop_background_controller_unittest.cc @@ -9,6 +9,7 @@ #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ui/aura/root_window.h" +#include "ui/compositor/test/layer_animator_test_controller.h" using aura::RootWindow; using aura::Window; @@ -35,12 +36,13 @@ void RunAnimationForWidget(views::Widget* widget) { DCHECK(!ui::LayerAnimator::disable_animations_for_test()); ui::Layer* layer = widget->GetNativeView()->layer(); - ui::LayerAnimator* animator = layer->GetAnimator(); + ui::LayerAnimatorTestController controller(layer->GetAnimator()); ui::AnimationContainerElement* element = layer->GetAnimator(); // Multiple steps are required to complete complex animations. // TODO(vollick): This should not be necessary. crbug.com/154017 - while (animator->is_animating()) { - base::TimeTicks step_time = animator->last_step_time(); + while (controller.animator()->is_animating()) { + controller.StartThreadedAnimationsIfNeeded(); + base::TimeTicks step_time = controller.animator()->last_step_time(); element->Step(step_time + base::TimeDelta::FromMilliseconds(1000)); } } diff --git a/ash/rotator/screen_rotation.cc b/ash/rotator/screen_rotation.cc index 686bc89..2f0dc850 100644 --- a/ash/rotator/screen_rotation.cc +++ b/ash/rotator/screen_rotation.cc @@ -117,7 +117,7 @@ void ScreenRotation::OnGetTarget(TargetValue* target) const { target->transform = interpolated_transform_->Interpolate(1.0); } -void ScreenRotation::OnAbort() { +void ScreenRotation::OnAbort(ui::LayerAnimationDelegate* delegate) { } // static diff --git a/ash/rotator/screen_rotation.h b/ash/rotator/screen_rotation.h index 339b99f..2f9616a 100644 --- a/ash/rotator/screen_rotation.h +++ b/ash/rotator/screen_rotation.h @@ -43,7 +43,7 @@ class ASH_EXPORT ScreenRotation : public ui::LayerAnimationElement { virtual bool OnProgress(double t, ui::LayerAnimationDelegate* delegate) OVERRIDE; virtual void OnGetTarget(TargetValue* target) const OVERRIDE; - virtual void OnAbort() OVERRIDE; + virtual void OnAbort(ui::LayerAnimationDelegate* delegate) OVERRIDE; static const ui::LayerAnimationElement::AnimatableProperties& GetProperties(); diff --git a/cc/animation_id_provider.cc b/cc/animation_id_provider.cc new file mode 100644 index 0000000..bf30283 --- /dev/null +++ b/cc/animation_id_provider.cc @@ -0,0 +1,19 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/animation_id_provider.h" + +namespace cc { + +int AnimationIdProvider::NextAnimationId() { + static int next_animation_id = 1; + return next_animation_id++; +} + +int AnimationIdProvider::NextGroupId() { + static int next_group_id = 1; + return next_group_id++; +} + +} // namespace cc diff --git a/cc/animation_id_provider.h b/cc/animation_id_provider.h new file mode 100644 index 0000000..07a2452 --- /dev/null +++ b/cc/animation_id_provider.h @@ -0,0 +1,21 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_ANIMATION_ID_PROVIDER +#define CC_ANIMATION_ID_PROVIDER + +#include "cc/cc_export.h" + +namespace cc { + +class CC_EXPORT AnimationIdProvider { + public: + // These functions each return monotonically increasing values. + static int NextAnimationId(); + static int NextGroupId(); +}; + +} + +#endif // CC_ANIMATION_ID_PROVIDER @@ -10,6 +10,8 @@ 'animation_curve.cc', 'animation_curve.h', 'animation_events.h', + 'animation_id_provider.cc', + 'animation_id_provider.h', 'animation_registrar.cc', 'animation_registrar.h', 'append_quads_data.h', diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp index 13278f8..e8a6eae 100644 --- a/ui/compositor/compositor.gyp +++ b/ui/compositor/compositor.gyp @@ -118,6 +118,8 @@ 'layer_animator_unittest.cc', 'layer_unittest.cc', 'run_all_unittests.cc', + 'test/layer_animator_test_controller.cc', + 'test/layer_animator_test_controller.h', 'test/test_compositor_host.h', 'test/test_compositor_host_linux.cc', 'test/test_compositor_host_mac.mm', diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 6c7e075..b73419a 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc @@ -47,7 +47,6 @@ Layer::Layer() force_render_surface_(false), fills_bounds_opaquely_(true), layer_updated_externally_(false), - opacity_(1.0f), background_blur_radius_(0), layer_saturation_(0.0f), layer_brightness_(0.0f), @@ -75,7 +74,6 @@ Layer::Layer(LayerType type) force_render_surface_(false), fills_bounds_opaquely_(true), layer_updated_externally_(false), - opacity_(1.0f), background_blur_radius_(0), layer_saturation_(0.0f), layer_brightness_(0.0f), @@ -110,6 +108,7 @@ Layer::~Layer() { layer_mask_back_link_->SetMaskLayer(NULL); for (size_t i = 0; i < children_.size(); ++i) children_[i]->parent_ = NULL; + cc_layer_->removeLayerAnimationEventObserver(this); cc_layer_->removeFromParent(); } @@ -117,6 +116,10 @@ Compositor* Layer::GetCompositor() { return GetRoot(this)->compositor_; } +float Layer::opacity() const { + return cc_layer_->opacity(); +} + void Layer::SetCompositor(Compositor* compositor) { // This function must only be called to set the compositor on the root layer, // or to reset it. @@ -225,10 +228,10 @@ void Layer::SetOpacity(float opacity) { } float Layer::GetCombinedOpacity() const { - float opacity = opacity_; + float opacity = this->opacity(); Layer* current = this->parent_; while (current) { - opacity *= current->opacity_; + opacity *= current->opacity(); current = current->parent_; } return opacity; @@ -355,7 +358,7 @@ float Layer::GetTargetOpacity() const { if (animator_.get() && animator_->IsAnimatingProperty( LayerAnimationElement::OPACITY)) return animator_->GetTargetOpacity(); - return opacity_; + return opacity(); } void Layer::SetVisible(bool visible) { @@ -444,7 +447,10 @@ void Layer::SetExternalTexture(Texture* texture) { DCHECK(parent_->cc_layer_); parent_->cc_layer_->replaceChild(cc_layer_, new_layer); } + cc_layer_->removeLayerAnimationEventObserver(this); + new_layer->setOpacity(cc_layer_->opacity()); cc_layer_= new_layer; + cc_layer_->addLayerAnimationEventObserver(this); cc_layer_is_accelerated_ = layer_updated_externally_; for (size_t i = 0; i < children_.size(); ++i) { DCHECK(children_[i]->cc_layer_); @@ -452,7 +458,6 @@ void Layer::SetExternalTexture(Texture* texture) { } cc_layer_->setAnchorPoint(gfx::PointF()); cc_layer_->setContentsOpaque(fills_bounds_opaquely_); - cc_layer_->setOpacity(opacity_); cc_layer_->setForceRenderSurface(force_render_surface_); cc_layer_->setIsDrawable(IsDrawn()); RecomputeTransform(); @@ -564,6 +569,11 @@ void Layer::SetForceRenderSurface(bool force) { cc_layer_->setForceRenderSurface(force_render_surface_); } +void Layer::OnAnimationStarted(const cc::AnimationEvent& event) { + if (animator_) + animator_->OnThreadedAnimationStarted(event); +} + void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) { DCHECK_NE(child, other); DCHECK_EQ(this, child->parent()); @@ -656,8 +666,6 @@ void Layer::SetTransformImmediately(const gfx::Transform& transform) { } void Layer::SetOpacityImmediately(float opacity) { - opacity_ = opacity; - cc_layer_->setOpacity(opacity); ScheduleDraw(); } @@ -751,6 +759,16 @@ SkColor Layer::GetColorForAnimation() const { solid_color_layer_->backgroundColor() : SK_ColorBLACK; } +void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) { + DCHECK(cc_layer_); + cc_layer_->addAnimation(animation.Pass()); +} + +void Layer::RemoveThreadedAnimation(int animation_id) { + DCHECK(cc_layer_); + cc_layer_->removeAnimation(animation_id); +} + void Layer::CreateWebLayer() { if (type_ == LAYER_SOLID_COLOR) { solid_color_layer_ = cc::SolidColorLayer::create(); @@ -763,6 +781,7 @@ void Layer::CreateWebLayer() { cc_layer_->setAnchorPoint(gfx::PointF()); cc_layer_->setContentsOpaque(true); cc_layer_->setIsDrawable(type_ != LAYER_NOT_DRAWN); + cc_layer_->addLayerAnimationEventObserver(this); } void Layer::RecomputeTransform() { diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index 3bd460c2..2c322d0 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h @@ -12,7 +12,9 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" +#include "cc/animation_events.h" #include "cc/content_layer_client.h" +#include "cc/layer_animation_event_observer.h" #include "cc/texture_layer_client.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkRegion.h" @@ -52,7 +54,8 @@ class Texture; class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate, NON_EXPORTED_BASE(public cc::ContentLayerClient), - NON_EXPORTED_BASE(public cc::TextureLayerClient) { + NON_EXPORTED_BASE(public cc::TextureLayerClient), + NON_EXPORTED_BASE(public cc::LayerAnimationEventObserver) { public: Layer(); explicit Layer(LayerType type); @@ -134,7 +137,7 @@ class COMPOSITOR_EXPORT Layer // The opacity of the layer. The opacity is applied to each pixel of the // texture (resulting alpha = opacity * alpha). - float opacity() const { return opacity_; } + float opacity() const; void SetOpacity(float opacity); // Returns the actual opacity, which the opacity of this layer multipled by @@ -287,6 +290,9 @@ class COMPOSITOR_EXPORT Layer void SetForceRenderSurface(bool force); bool force_render_surface() const { return force_render_surface_; } + // LayerAnimationEventObserver + virtual void OnAnimationStarted(const cc::AnimationEvent& event) OVERRIDE; + private: // Stacks |child| above or below |other|. Helper method for StackAbove() and // StackBelow(). @@ -330,6 +336,9 @@ class COMPOSITOR_EXPORT Layer virtual float GetBrightnessForAnimation() const OVERRIDE; virtual float GetGrayscaleForAnimation() const OVERRIDE; virtual SkColor GetColorForAnimation() const OVERRIDE; + virtual void AddThreadedAnimation( + scoped_ptr<cc::Animation> animation) OVERRIDE; + virtual void RemoveThreadedAnimation(int animation_id) OVERRIDE; void CreateWebLayer(); void RecomputeTransform(); @@ -375,7 +384,6 @@ class COMPOSITOR_EXPORT Layer // compositor is ready to paint the content. SkRegion damaged_region_; - float opacity_; int background_blur_radius_; // Several variables which will change the visible representation of diff --git a/ui/compositor/layer_animation_delegate.h b/ui/compositor/layer_animation_delegate.h index 223eca2..8d144d3 100644 --- a/ui/compositor/layer_animation_delegate.h +++ b/ui/compositor/layer_animation_delegate.h @@ -5,6 +5,8 @@ #ifndef UI_COMPOSITOR_LAYER_ANIMATION_DELEGATE_H_ #define UI_COMPOSITOR_LAYER_ANIMATION_DELEGATE_H_ +#include "base/memory/scoped_ptr.h" +#include "cc/animation.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/compositor/compositor_export.h" #include "ui/gfx/rect.h" @@ -30,6 +32,8 @@ class COMPOSITOR_EXPORT LayerAnimationDelegate { virtual float GetBrightnessForAnimation() const = 0; virtual float GetGrayscaleForAnimation() const = 0; virtual SkColor GetColorForAnimation() const = 0; + virtual void AddThreadedAnimation(scoped_ptr<cc::Animation> animation) = 0; + virtual void RemoveThreadedAnimation(int animation_id) = 0; protected: virtual ~LayerAnimationDelegate() {} diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc index 6c9aa39..81aeca5 100644 --- a/ui/compositor/layer_animation_element.cc +++ b/ui/compositor/layer_animation_element.cc @@ -5,7 +5,10 @@ #include "ui/compositor/layer_animation_element.h" #include "base/compiler_specific.h" +#include "cc/animation.h" +#include "cc/animation_id_provider.h" #include "ui/base/animation/tween.h" +#include "ui/compositor/float_animation_curve_adapter.h" #include "ui/compositor/layer_animation_delegate.h" #include "ui/compositor/layer_animator.h" #include "ui/gfx/interpolated_transform.h" @@ -29,7 +32,7 @@ class Pause : public LayerAnimationElement { return false; } virtual void OnGetTarget(TargetValue* target) const OVERRIDE {} - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} DISALLOW_COPY_AND_ASSIGN(Pause); }; @@ -59,7 +62,7 @@ class TransformTransition : public LayerAnimationElement { target->transform = target_; } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -99,7 +102,7 @@ class InterpolatedTransformTransition : public LayerAnimationElement { target->transform = interpolated_transform_->Interpolate(1.0f); } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -137,7 +140,7 @@ class BoundsTransition : public LayerAnimationElement { target->bounds = target_; } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -177,7 +180,7 @@ class OpacityTransition : public LayerAnimationElement { target->opacity = target_; } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -217,7 +220,7 @@ class VisibilityTransition : public LayerAnimationElement { target->visibility = target_; } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -258,7 +261,7 @@ class BrightnessTransition : public LayerAnimationElement { target->brightness = target_; } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -299,7 +302,7 @@ class GrayscaleTransition : public LayerAnimationElement { target->grayscale = target_; } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -352,7 +355,7 @@ class ColorTransition : public LayerAnimationElement { target->color = target_; } - virtual void OnAbort() OVERRIDE {} + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE {} private: static AnimatableProperties GetProperties() { @@ -367,6 +370,120 @@ class ColorTransition : public LayerAnimationElement { DISALLOW_COPY_AND_ASSIGN(ColorTransition); }; +// ThreadedLayerAnimationElement ----------------------------------------------- + +class ThreadedLayerAnimationElement : public LayerAnimationElement { + public: + ThreadedLayerAnimationElement(const AnimatableProperties& properties, + base::TimeDelta duration) + : LayerAnimationElement(properties, duration) { + } + virtual ~ThreadedLayerAnimationElement() {} + + virtual bool IsThreaded() const OVERRIDE { + return (duration() != base::TimeDelta()); + } + + protected: + virtual bool OnProgress(double t, + LayerAnimationDelegate* delegate) OVERRIDE { + if (t < 1.0) + return false; + + if (Started()) { + delegate->RemoveThreadedAnimation(animation_id()); + } + + OnEnd(delegate); + return true; + } + + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE { + if (delegate && Started()) { + delegate->RemoveThreadedAnimation(animation_id()); + } + } + + virtual void RequestEffectiveStart( + LayerAnimationDelegate* delegate) OVERRIDE { + DCHECK(animation_group_id()); + if (duration() == base::TimeDelta()) { + set_effective_start_time(requested_start_time()); + return; + } + set_effective_start_time(base::TimeTicks()); + scoped_ptr<cc::Animation> animation = CreateCCAnimation(); + animation->setNeedsSynchronizedStartTime(true); + delegate->AddThreadedAnimation(animation.Pass()); + } + + virtual void OnEnd(LayerAnimationDelegate* delegate) = 0; + + virtual scoped_ptr<cc::Animation> CreateCCAnimation() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(ThreadedLayerAnimationElement); +}; + +// ThreadedOpacityTransition --------------------------------------------------- + +class ThreadedOpacityTransition : public ThreadedLayerAnimationElement { + public: + ThreadedOpacityTransition(float target, base::TimeDelta duration) + : ThreadedLayerAnimationElement(GetProperties(), duration), + start_(0.0f), + target_(target) { + } + virtual ~ThreadedOpacityTransition() {} + + protected: + virtual void OnStart(LayerAnimationDelegate* delegate) OVERRIDE { + start_ = delegate->GetOpacityForAnimation(); + } + + virtual void OnAbort(LayerAnimationDelegate* delegate) OVERRIDE { + if (delegate && Started()) { + ThreadedLayerAnimationElement::OnAbort(delegate); + delegate->SetOpacityFromAnimation( + Tween::ValueBetween(last_progressed_fraction(), start_, target_)); + } + } + + virtual void OnEnd(LayerAnimationDelegate* delegate) OVERRIDE { + delegate->SetOpacityFromAnimation(target_); + } + + virtual scoped_ptr<cc::Animation> CreateCCAnimation() OVERRIDE { + scoped_ptr<cc::AnimationCurve> animation_curve( + new FloatAnimationCurveAdapter(tween_type(), + start_, + target_, + duration())); + scoped_ptr<cc::Animation> animation( + cc::Animation::create(animation_curve.Pass(), + animation_id(), + animation_group_id(), + cc::Animation::Opacity)); + return animation.Pass(); + } + + virtual void OnGetTarget(TargetValue* target) const OVERRIDE { + target->opacity = target_; + } + + private: + static AnimatableProperties GetProperties() { + AnimatableProperties properties; + properties.insert(LayerAnimationElement::OPACITY); + return properties; + } + + float start_; + const float target_; + + DISALLOW_COPY_AND_ASSIGN(ThreadedOpacityTransition); +}; + } // namespace // LayerAnimationElement::TargetValue ------------------------------------------ @@ -399,31 +516,65 @@ LayerAnimationElement::LayerAnimationElement( : first_frame_(true), properties_(properties), duration_(GetEffectiveDuration(duration)), - tween_type_(Tween::LINEAR) { + tween_type_(Tween::LINEAR), + animation_id_(cc::AnimationIdProvider::NextAnimationId()), + animation_group_id_(0), + last_progressed_fraction_(0.0) { } LayerAnimationElement::~LayerAnimationElement() { } +void LayerAnimationElement::Start(LayerAnimationDelegate* delegate, + int animation_group_id) { + DCHECK(requested_start_time_ != base::TimeTicks()); + DCHECK(first_frame_); + animation_group_id_ = animation_group_id; + last_progressed_fraction_ = 0.0; + OnStart(delegate); + RequestEffectiveStart(delegate); + first_frame_ = false; +} + bool LayerAnimationElement::Progress(base::TimeTicks now, LayerAnimationDelegate* delegate) { - DCHECK(start_time_ != base::TimeTicks()); - base::TimeDelta elapsed = now - start_time_; - if (first_frame_) - OnStart(delegate); + DCHECK(requested_start_time_ != base::TimeTicks()); + DCHECK(!first_frame_); + + bool need_draw; double t = 1.0; + + if (effective_start_time_ == base::TimeTicks()) { + // This hasn't actually started yet. + need_draw = false; + last_progressed_fraction_ = 0.0; + return need_draw; + } + + base::TimeDelta elapsed = now - effective_start_time_; if ((duration_ > base::TimeDelta()) && (elapsed < duration_)) t = elapsed.InMillisecondsF() / duration_.InMillisecondsF(); - bool need_draw = OnProgress(Tween::CalculateValue(tween_type_, t), delegate); + need_draw = OnProgress(Tween::CalculateValue(tween_type_, t), delegate); first_frame_ = t == 1.0; + last_progressed_fraction_ = t; return need_draw; } bool LayerAnimationElement::IsFinished(base::TimeTicks time, base::TimeDelta* total_duration) { - base::TimeDelta elapsed = time - start_time_; - if (elapsed >= duration_) { - *total_duration = duration_; + // If an effective start has been requested but the effective start time + // hasn't yet been set, the animation is not finished, regardless of the + // value of |time|. + if (!first_frame_ && (effective_start_time_ == base::TimeTicks())) + return false; + + base::TimeDelta queueing_delay; + if (!first_frame_) + queueing_delay = effective_start_time_ - requested_start_time_; + + base::TimeDelta elapsed = time - requested_start_time_; + if (elapsed >= duration_ + queueing_delay) { + *total_duration = duration_ + queueing_delay; return true; } return false; @@ -433,6 +584,7 @@ bool LayerAnimationElement::ProgressToEnd(LayerAnimationDelegate* delegate) { if (first_frame_) OnStart(delegate); bool need_draw = OnProgress(1.0, delegate); + last_progressed_fraction_ = 1.0; first_frame_ = true; return need_draw; } @@ -441,9 +593,34 @@ void LayerAnimationElement::GetTargetValue(TargetValue* target) const { OnGetTarget(target); } -void LayerAnimationElement::Abort() { +bool LayerAnimationElement::IsThreaded() const { + return false; +} + +void LayerAnimationElement::Abort(LayerAnimationDelegate* delegate) { + OnAbort(delegate); first_frame_ = true; - OnAbort(); +} + +void LayerAnimationElement::RequestEffectiveStart( + LayerAnimationDelegate* delegate) { + DCHECK(requested_start_time_ != base::TimeTicks()); + effective_start_time_ = requested_start_time_; +} + +// static +LayerAnimationElement::AnimatableProperty +LayerAnimationElement::ToAnimatableProperty( + cc::Animation::TargetProperty property) { + switch (property) { + case cc::Animation::Transform: + return TRANSFORM; + case cc::Animation::Opacity: + return OPACITY; + default: + NOTREACHED(); + return AnimatableProperty(); + } } // static @@ -484,7 +661,7 @@ LayerAnimationElement* LayerAnimationElement::CreateBoundsElement( LayerAnimationElement* LayerAnimationElement::CreateOpacityElement( float opacity, base::TimeDelta duration) { - return new OpacityTransition(opacity, duration); + return new ThreadedOpacityTransition(opacity, duration); } // static diff --git a/ui/compositor/layer_animation_element.h b/ui/compositor/layer_animation_element.h index 9b65844..419092c 100644 --- a/ui/compositor/layer_animation_element.h +++ b/ui/compositor/layer_animation_element.h @@ -8,6 +8,8 @@ #include <set> #include "base/time.h" +#include "cc/animation.h" +#include "cc/animation_events.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/animation/tween.h" #include "ui/compositor/compositor_export.h" @@ -34,6 +36,9 @@ class COMPOSITOR_EXPORT LayerAnimationElement { COLOR, }; + static AnimatableProperty ToAnimatableProperty( + cc::Animation::TargetProperty property); + struct COMPOSITOR_EXPORT TargetValue { TargetValue(); // Initializes the target value to match the delegate. NULL may be supplied. @@ -114,10 +119,28 @@ class COMPOSITOR_EXPORT LayerAnimationElement { base::TimeDelta duration); // Sets the start time for the animation. This must be called before the first - // call to {Progress, IsFinished}. Once the animation is finished, this must + // call to {Start, IsFinished}. Once the animation is finished, this must // be called again in order to restart the animation. - void set_start_time(base::TimeTicks start_time) { start_time_ = start_time; } - base::TimeTicks start_time() const { return start_time_; } + void set_requested_start_time(base::TimeTicks start_time) { + requested_start_time_ = start_time; + } + base::TimeTicks requested_start_time() const { return requested_start_time_; } + + // Sets the actual start time for the animation, taking into account any + // queueing delays. + void set_effective_start_time(base::TimeTicks start_time) { + effective_start_time_ = start_time; + } + base::TimeTicks effective_start_time() const { return effective_start_time_; } + + // This must be called before the first call to Progress. If starting the + // animation involves dispatching to another thread, then this will proceed + // with that dispatch, ultimately resulting in the animation getting an + // effective start time (the time the animation starts on the other thread). + void Start(LayerAnimationDelegate* delegate, int animation_group_id); + + // Returns true if the animation has started but hasn't finished. + bool Started() { return !first_frame_; } // Updates the delegate to the appropriate value for |now|. Returns true // if a redraw is required. @@ -134,7 +157,7 @@ class COMPOSITOR_EXPORT LayerAnimationElement { // Called if the animation is not allowed to complete. This may be called // before OnStarted or Progress. - void Abort(); + void Abort(LayerAnimationDelegate* delegate); // Assigns the target value to |target|. void GetTargetValue(TargetValue* target) const; @@ -142,16 +165,35 @@ class COMPOSITOR_EXPORT LayerAnimationElement { // The properties that the element modifies. const AnimatableProperties& properties() const { return properties_; } + // Whether this element animates on the compositor thread. + virtual bool IsThreaded() const; + Tween::Type tween_type() const { return tween_type_; } void set_tween_type(Tween::Type tween_type) { tween_type_ = tween_type; } + // Each LayerAnimationElement has a unique animation_id. Elements belonging + // to sequences that are supposed to start together have the same + // animation_group_id. + int animation_id() const { return animation_id_; } + int animation_group_id() const { return animation_group_id_; } + void set_animation_group_id(int id) { animation_group_id_ = id; } + + // The fraction of the animation that has been completed after the last + // call made to {Progress, ProgressToEnd}. + double last_progressed_fraction() const { return last_progressed_fraction_; } + protected: // Called once each time the animation element is run before any call to // OnProgress. virtual void OnStart(LayerAnimationDelegate* delegate) = 0; virtual bool OnProgress(double t, LayerAnimationDelegate* delegate) = 0; virtual void OnGetTarget(TargetValue* target) const = 0; - virtual void OnAbort() = 0; + virtual void OnAbort(LayerAnimationDelegate* delegate) = 0; + + base::TimeDelta duration() const { return duration_; } + + // Actually start the animation, dispatching to another thread if needed. + virtual void RequestEffectiveStart(LayerAnimationDelegate* delegate); private: // For debugging purposes, we sometimes alter the duration we actually use. @@ -161,10 +203,18 @@ class COMPOSITOR_EXPORT LayerAnimationElement { bool first_frame_; const AnimatableProperties properties_; - base::TimeTicks start_time_; + base::TimeTicks requested_start_time_; + + // When the animation actually started, taking into account queueing delays. + base::TimeTicks effective_start_time_; const base::TimeDelta duration_; Tween::Type tween_type_; + const int animation_id_; + int animation_group_id_; + + double last_progressed_fraction_; + DISALLOW_COPY_AND_ASSIGN(LayerAnimationElement); }; diff --git a/ui/compositor/layer_animation_element_unittest.cc b/ui/compositor/layer_animation_element_unittest.cc index 5912023..9964436 100644 --- a/ui/compositor/layer_animation_element_unittest.cc +++ b/ui/compositor/layer_animation_element_unittest.cc @@ -34,14 +34,20 @@ TEST(LayerAnimationElementTest, TransformElement) { for (int i = 0; i < 2; ++i) { start_time += delta; - element->set_start_time(start_time); + element->set_requested_start_time(start_time); delegate.SetTransformFromAnimation(start_transform); + element->Start(&delegate, 1); element->Progress(start_time, &delegate); CheckApproximatelyEqual(start_transform, delegate.GetTransformForAnimation()); element->Progress(start_time + delta/2, &delegate); CheckApproximatelyEqual(middle_transform, delegate.GetTransformForAnimation()); + + base::TimeDelta element_duration; + EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); + EXPECT_EQ(delta, element_duration); + element->Progress(start_time + delta, &delegate); CheckApproximatelyEqual(target_transform, delegate.GetTransformForAnimation()); @@ -50,10 +56,6 @@ TEST(LayerAnimationElementTest, TransformElement) { LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); CheckApproximatelyEqual(target_transform, target_value.transform); - - base::TimeDelta element_duration; - EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); - EXPECT_EQ(delta, element_duration); } // Check that the bounds element progresses the delegate as expected and @@ -72,12 +74,18 @@ TEST(LayerAnimationElementTest, BoundsElement) { for (int i = 0; i < 2; ++i) { start_time += delta; - element->set_start_time(start_time); + element->set_requested_start_time(start_time); delegate.SetBoundsFromAnimation(start); + element->Start(&delegate, 1); element->Progress(start_time, &delegate); CheckApproximatelyEqual(start, delegate.GetBoundsForAnimation()); element->Progress(start_time + delta/2, &delegate); CheckApproximatelyEqual(middle, delegate.GetBoundsForAnimation()); + + base::TimeDelta element_duration; + EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); + EXPECT_EQ(delta, element_duration); + element->Progress(start_time + delta, &delegate); CheckApproximatelyEqual(target, delegate.GetBoundsForAnimation()); } @@ -85,10 +93,6 @@ TEST(LayerAnimationElementTest, BoundsElement) { LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); CheckApproximatelyEqual(target, target_value.bounds); - - base::TimeDelta element_duration; - EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); - EXPECT_EQ(delta, element_duration); } // Check that the opacity element progresses the delegate as expected and @@ -99,29 +103,38 @@ TEST(LayerAnimationElementTest, OpacityElement) { float middle = 0.5; float target = 1.0; base::TimeTicks start_time; + base::TimeTicks effective_start_time; base::TimeDelta delta = base::TimeDelta::FromSeconds(1); scoped_ptr<LayerAnimationElement> element( LayerAnimationElement::CreateOpacityElement(target, delta)); for (int i = 0; i < 2; ++i) { - start_time += delta; - element->set_start_time(start_time); + start_time = effective_start_time + delta; + element->set_requested_start_time(start_time); delegate.SetOpacityFromAnimation(start); + element->Start(&delegate, 1); element->Progress(start_time, &delegate); - EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation()); - element->Progress(start_time + delta/2, &delegate); - EXPECT_FLOAT_EQ(middle, delegate.GetOpacityForAnimation()); - element->Progress(start_time + delta, &delegate); + EXPECT_FLOAT_EQ(start, element->last_progressed_fraction()); + effective_start_time = start_time + delta; + element->set_effective_start_time(effective_start_time); + element->Progress(effective_start_time, &delegate); + EXPECT_FLOAT_EQ(start, element->last_progressed_fraction()); + element->Progress(effective_start_time + delta/2, &delegate); + EXPECT_FLOAT_EQ(middle, element->last_progressed_fraction()); + + base::TimeDelta element_duration; + EXPECT_TRUE(element->IsFinished(effective_start_time + delta, + &element_duration)); + EXPECT_EQ(2 * delta, element_duration); + + element->Progress(effective_start_time + delta, &delegate); + EXPECT_FLOAT_EQ(target, element->last_progressed_fraction()); EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation()); } LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); EXPECT_FLOAT_EQ(target, target_value.opacity); - - base::TimeDelta element_duration; - EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); - EXPECT_EQ(delta, element_duration); } // Check that the visibility element progresses the delegate as expected and @@ -137,12 +150,18 @@ TEST(LayerAnimationElementTest, VisibilityElement) { for (int i = 0; i < 2; ++i) { start_time += delta; - element->set_start_time(start_time); + element->set_requested_start_time(start_time); delegate.SetVisibilityFromAnimation(start); + element->Start(&delegate, 1); element->Progress(start_time, &delegate); EXPECT_TRUE(delegate.GetVisibilityForAnimation()); element->Progress(start_time + delta/2, &delegate); EXPECT_TRUE(delegate.GetVisibilityForAnimation()); + + base::TimeDelta element_duration; + EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); + EXPECT_EQ(delta, element_duration); + element->Progress(start_time + delta, &delegate); EXPECT_FALSE(delegate.GetVisibilityForAnimation()); } @@ -150,10 +169,6 @@ TEST(LayerAnimationElementTest, VisibilityElement) { LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); EXPECT_FALSE(target_value.visibility); - - base::TimeDelta element_duration; - EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); - EXPECT_EQ(delta, element_duration); } // Check that the Brightness element progresses the delegate as expected and @@ -170,12 +185,18 @@ TEST(LayerAnimationElementTest, BrightnessElement) { for (int i = 0; i < 2; ++i) { start_time += delta; - element->set_start_time(start_time); + element->set_requested_start_time(start_time); delegate.SetBrightnessFromAnimation(start); + element->Start(&delegate, 1); element->Progress(start_time, &delegate); EXPECT_FLOAT_EQ(start, delegate.GetBrightnessForAnimation()); element->Progress(start_time + delta/2, &delegate); EXPECT_FLOAT_EQ(middle, delegate.GetBrightnessForAnimation()); + + base::TimeDelta element_duration; + EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); + EXPECT_EQ(delta, element_duration); + element->Progress(start_time + delta, &delegate); EXPECT_FLOAT_EQ(target, delegate.GetBrightnessForAnimation()); } @@ -183,10 +204,6 @@ TEST(LayerAnimationElementTest, BrightnessElement) { LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); EXPECT_FLOAT_EQ(target, target_value.brightness); - - base::TimeDelta element_duration; - EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); - EXPECT_EQ(delta, element_duration); } // Check that the Grayscale element progresses the delegate as expected and @@ -203,12 +220,18 @@ TEST(LayerAnimationElementTest, GrayscaleElement) { for (int i = 0; i < 2; ++i) { start_time += delta; - element->set_start_time(start_time); + element->set_requested_start_time(start_time); delegate.SetGrayscaleFromAnimation(start); + element->Start(&delegate, 1); element->Progress(start_time, &delegate); EXPECT_FLOAT_EQ(start, delegate.GetGrayscaleForAnimation()); element->Progress(start_time + delta/2, &delegate); EXPECT_FLOAT_EQ(middle, delegate.GetGrayscaleForAnimation()); + + base::TimeDelta element_duration; + EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); + EXPECT_EQ(delta, element_duration); + element->Progress(start_time + delta, &delegate); EXPECT_FLOAT_EQ(target, delegate.GetGrayscaleForAnimation()); } @@ -216,10 +239,6 @@ TEST(LayerAnimationElementTest, GrayscaleElement) { LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); EXPECT_FLOAT_EQ(target, target_value.grayscale); - - base::TimeDelta element_duration; - EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); - EXPECT_EQ(delta, element_duration); } // Check that the pause element progresses the delegate as expected and @@ -241,7 +260,14 @@ TEST(LayerAnimationElementTest, PauseElement) { TestLayerAnimationDelegate copy = delegate; start_time += delta; - element->set_start_time(start_time); + element->set_requested_start_time(start_time); + element->Start(&delegate, 1); + + // Pause should last for |delta|. + base::TimeDelta element_duration; + EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); + EXPECT_EQ(delta, element_duration); + element->Progress(start_time + delta, &delegate); // Nothing should have changed. @@ -255,11 +281,6 @@ TEST(LayerAnimationElementTest, PauseElement) { copy.GetBrightnessForAnimation()); EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), copy.GetGrayscaleForAnimation()); - - // Pause should last for |delta|. - base::TimeDelta element_duration; - EXPECT_TRUE(element->IsFinished(start_time + delta, &element_duration)); - EXPECT_EQ(delta, element_duration); } } // namespace diff --git a/ui/compositor/layer_animation_sequence.cc b/ui/compositor/layer_animation_sequence.cc index a997c38..10ba702 100644 --- a/ui/compositor/layer_animation_sequence.cc +++ b/ui/compositor/layer_animation_sequence.cc @@ -16,12 +16,18 @@ namespace ui { LayerAnimationSequence::LayerAnimationSequence() : is_cyclic_(false), - last_element_(0) { + last_element_(0), + waiting_for_group_start_(false), + animation_group_id_(0), + last_progressed_fraction_(0.0) { } LayerAnimationSequence::LayerAnimationSequence(LayerAnimationElement* element) : is_cyclic_(false), - last_element_(0) { + last_element_(0), + waiting_for_group_start_(false), + animation_group_id_(0), + last_progressed_fraction_(0.0) { AddElement(element); } @@ -31,8 +37,19 @@ LayerAnimationSequence::~LayerAnimationSequence() { DetachedFromSequence(this, true)); } +void LayerAnimationSequence::Start(LayerAnimationDelegate* delegate) { + DCHECK(start_time_ != base::TimeTicks()); + last_progressed_fraction_ = 0.0; + if (elements_.empty()) + return; + + elements_[0]->set_requested_start_time(start_time_); + elements_[0]->Start(delegate, animation_group_id_); +} + void LayerAnimationSequence::Progress(base::TimeTicks now, LayerAnimationDelegate* delegate) { + DCHECK(start_time_ != base::TimeTicks()); bool redraw_required = false; if (elements_.empty()) @@ -44,21 +61,27 @@ void LayerAnimationSequence::Progress(base::TimeTicks now, size_t current_index = last_element_ % elements_.size(); base::TimeDelta element_duration; while (is_cyclic_ || last_element_ < elements_.size()) { - elements_[current_index]->set_start_time(last_start_); + elements_[current_index]->set_requested_start_time(last_start_); if (!elements_[current_index]->IsFinished(now, &element_duration)) break; // Let the element we're passing finish. - if (elements_[current_index]->Progress(now, delegate)) + if (elements_[current_index]->ProgressToEnd(delegate)) redraw_required = true; last_start_ += element_duration; ++last_element_; + last_progressed_fraction_ = + elements_[current_index]->last_progressed_fraction(); current_index = last_element_ % elements_.size(); } if (is_cyclic_ || last_element_ < elements_.size()) { + if (!elements_[current_index]->Started()) + elements_[current_index]->Start(delegate, animation_group_id_); if (elements_[current_index]->Progress(now, delegate)) redraw_required = true; + last_progressed_fraction_ = + elements_[current_index]->last_progressed_fraction(); } // Since the delegate may be deleted due to the notifications below, it is @@ -68,12 +91,14 @@ void LayerAnimationSequence::Progress(base::TimeTicks now, if (!is_cyclic_ && last_element_ == elements_.size()) { last_element_ = 0; + waiting_for_group_start_ = false; + animation_group_id_ = 0; NotifyEnded(); } } bool LayerAnimationSequence::IsFinished(base::TimeTicks time) { - if (is_cyclic_) + if (is_cyclic_ || waiting_for_group_start_) return false; if (elements_.empty()) @@ -86,7 +111,7 @@ bool LayerAnimationSequence::IsFinished(base::TimeTicks time) { size_t current_index = last_element_; base::TimeDelta element_duration; while (current_index < elements_.size()) { - elements_[current_index]->set_start_time(current_start); + elements_[current_index]->set_requested_start_time(current_start); if (!elements_[current_index]->IsFinished(time, &element_duration)) break; @@ -107,6 +132,8 @@ void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) { while (current_index < elements_.size()) { if (elements_[current_index]->ProgressToEnd(delegate)) redraw_required = true; + last_progressed_fraction_ = + elements_[current_index]->last_progressed_fraction(); ++current_index; ++last_element_; } @@ -116,6 +143,8 @@ void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) { if (!is_cyclic_) { last_element_ = 0; + waiting_for_group_start_ = false; + animation_group_id_ = 0; NotifyEnded(); } } @@ -129,13 +158,14 @@ void LayerAnimationSequence::GetTargetValue( elements_[i]->GetTargetValue(target); } -void LayerAnimationSequence::Abort() { +void LayerAnimationSequence::Abort(LayerAnimationDelegate* delegate) { size_t current_index = last_element_ % elements_.size(); while (current_index < elements_.size()) { - elements_[current_index]->Abort(); + elements_[current_index]->Abort(delegate); ++current_index; } last_element_ = 0; + waiting_for_group_start_ = false; NotifyAborted(); } @@ -156,6 +186,13 @@ bool LayerAnimationSequence::HasCommonProperty( return intersection.size() > 0; } +bool LayerAnimationSequence::IsFirstElementThreaded() const { + if (!elements_.empty()) + return elements_[0]->IsThreaded(); + + return false; +} + void LayerAnimationSequence::AddObserver(LayerAnimationObserver* observer) { if (!observers_.HasObserver(observer)) { observers_.AddObserver(observer); @@ -168,6 +205,22 @@ void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver* observer) { observer->DetachedFromSequence(this, true); } +void LayerAnimationSequence::OnThreadedAnimationStarted( + const cc::AnimationEvent& event) { + if (elements_.empty() || event.groupId != animation_group_id_) + return; + + size_t current_index = last_element_ % elements_.size(); + const LayerAnimationElement::AnimatableProperties& element_properties = + elements_[current_index]->properties(); + LayerAnimationElement::AnimatableProperty event_property = + LayerAnimationElement::ToAnimatableProperty(event.targetProperty); + DCHECK(element_properties.find(event_property) != element_properties.end()); + elements_[current_index]->set_effective_start_time( + base::TimeTicks::FromInternalValue( + event.monotonicTime * base::Time::kMicrosecondsPerSecond)); +} + void LayerAnimationSequence::OnScheduled() { NotifyScheduled(); } @@ -204,4 +257,12 @@ void LayerAnimationSequence::NotifyAborted() { OnLayerAnimationAborted(this)); } +LayerAnimationElement* LayerAnimationSequence::CurrentElement() { + if (elements_.empty()) + return NULL; + + size_t current_index = last_element_ % elements_.size(); + return elements_[current_index].get(); +} + } // namespace ui diff --git a/ui/compositor/layer_animation_sequence.h b/ui/compositor/layer_animation_sequence.h index 9691ee7..6f7c96e 100644 --- a/ui/compositor/layer_animation_sequence.h +++ b/ui/compositor/layer_animation_sequence.h @@ -42,11 +42,25 @@ class COMPOSITOR_EXPORT LayerAnimationSequence virtual ~LayerAnimationSequence(); // Sets the start time for the animation. This must be called before the - // first call to {Progress, IsFinished}. Once the animation is finished, this + // first call to {Start, IsFinished}. Once the animation is finished, this // must be called again in order to restart the animation. void set_start_time(base::TimeTicks start_time) { start_time_ = start_time; } base::TimeTicks start_time() const { return start_time_; } + // Sets a flag indicating that this sequence will start together with other + // sequences, and at least one of the sequences in this group has a threaded + // first element. + void set_waiting_for_group_start(bool waiting) { + waiting_for_group_start_ = waiting; + } + bool waiting_for_group_start() { return waiting_for_group_start_; } + + // This must be called before the first call to Progress. If starting the + // animation involves dispatching to another thread, then this will proceed + // with that dispatch, ultimately resulting in the animation getting an + // effective start time (the time the animation starts on the other thread). + void Start(LayerAnimationDelegate* delegate); + // Updates the delegate to the appropriate value for |now|. Requests a // redraw if it is required. void Progress(base::TimeTicks now, LayerAnimationDelegate* delegate); @@ -64,7 +78,7 @@ class COMPOSITOR_EXPORT LayerAnimationSequence void GetTargetValue(LayerAnimationElement::TargetValue* target) const; // Aborts the given animation. - void Abort(); + void Abort(LayerAnimationDelegate* delegate); // All properties modified by the sequence. const LayerAnimationElement::AnimatableProperties& properties() const { @@ -84,18 +98,34 @@ class COMPOSITOR_EXPORT LayerAnimationSequence bool HasCommonProperty( const LayerAnimationElement::AnimatableProperties& other) const; + // Returns true if the first element animates on the compositor thread. + bool IsFirstElementThreaded() const; + + // Used to identify groups of sequences that are supposed to start together. + int animation_group_id() const { return animation_group_id_; } + void set_animation_group_id(int id) { animation_group_id_ = id; } + // These functions are used for adding or removing observers from the observer // list. The observers are notified when animations end. void AddObserver(LayerAnimationObserver* observer); void RemoveObserver(LayerAnimationObserver* observer); + // Called when a threaded animation is actually started. + void OnThreadedAnimationStarted(const cc::AnimationEvent& event); + // Called when the animator schedules this sequence. void OnScheduled(); // Called when the animator is destroyed. void OnAnimatorDestroyed(); + // The last_progressed_fraction of the element most recently progressed by + // by this sequence. Returns 0.0 if no elements have been progressed. + double last_progressed_fraction() const { return last_progressed_fraction_; } + private: + friend class LayerAnimatorTestController; + typedef std::vector<linked_ptr<LayerAnimationElement> > Elements; FRIEND_TEST_ALL_PREFIXES(LayerAnimatorTest, @@ -110,6 +140,9 @@ class COMPOSITOR_EXPORT LayerAnimationSequence // Notifies the observers that this sequence has been aborted. void NotifyAborted(); + // The currently animating element. + LayerAnimationElement* CurrentElement(); + // The union of all the properties modified by all elements in the sequence. LayerAnimationElement::AnimatableProperties properties_; @@ -126,9 +159,20 @@ class COMPOSITOR_EXPORT LayerAnimationSequence // The start time of the current run of the sequence. base::TimeTicks start_time_; + // True if this sequence will start together with other sequences, and at + // least one of the sequences in this group has a threaded first element. + bool waiting_for_group_start_; + + // Identifies groups of sequences that are supposed to start together. + int animation_group_id_; + // These parties are notified when layer animations end. ObserverList<LayerAnimationObserver> observers_; + // Tracks the last_progressed_fraction() of the most recently progressed + // element. + double last_progressed_fraction_; + DISALLOW_COPY_AND_ASSIGN(LayerAnimationSequence); }; diff --git a/ui/compositor/layer_animation_sequence_unittest.cc b/ui/compositor/layer_animation_sequence_unittest.cc index a6bb402..e32e9b1 100644 --- a/ui/compositor/layer_animation_sequence_unittest.cc +++ b/ui/compositor/layer_animation_sequence_unittest.cc @@ -34,7 +34,7 @@ TEST(LayerAnimationSequenceTest, NoElement) { } // Check that the sequences progresses the delegate as expected when it contains -// a single element. +// a single non-threaded element. TEST(LayerAnimationSequenceTest, SingleElement) { LayerAnimationSequence sequence; TestLayerAnimationDelegate delegate; @@ -44,26 +44,70 @@ TEST(LayerAnimationSequenceTest, SingleElement) { base::TimeTicks start_time; base::TimeDelta delta = base::TimeDelta::FromSeconds(1); sequence.AddElement( - LayerAnimationElement::CreateOpacityElement(target, delta)); + LayerAnimationElement::CreateBrightnessElement(target, delta)); for (int i = 0; i < 2; ++i) { start_time += delta; sequence.set_start_time(start_time); - delegate.SetOpacityFromAnimation(start); + delegate.SetBrightnessFromAnimation(start); + sequence.Start(&delegate); sequence.Progress(start_time, &delegate); - EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation()); + EXPECT_FLOAT_EQ(start, delegate.GetBrightnessForAnimation()); sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(500), &delegate); - EXPECT_FLOAT_EQ(middle, delegate.GetOpacityForAnimation()); + EXPECT_FLOAT_EQ(middle, delegate.GetBrightnessForAnimation()); + EXPECT_TRUE(sequence.IsFinished(start_time + delta)); sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(1000), &delegate); + EXPECT_FLOAT_EQ(target, delegate.GetBrightnessForAnimation()); + } + + EXPECT_TRUE(sequence.properties().size() == 1); + EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::BRIGHTNESS) != + sequence.properties().end()); +} + +// Check that the sequences progresses the delegate as expected when it contains +// a single threaded element. +TEST(LayerAnimationSequenceTest, SingleThreadedElement) { + LayerAnimationSequence sequence; + TestLayerAnimationDelegate delegate; + float start = 0.0f; + float middle = 0.5f; + float target = 1.0f; + base::TimeTicks start_time; + base::TimeTicks effective_start; + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + sequence.AddElement( + LayerAnimationElement::CreateOpacityElement(target, delta)); + + for (int i = 0; i < 2; ++i) { + int group_id = 1; + sequence.set_animation_group_id(group_id); + start_time = effective_start + delta; + sequence.set_start_time(start_time); + delegate.SetOpacityFromAnimation(start); + sequence.Start(&delegate); + sequence.Progress(start_time, &delegate); + EXPECT_FLOAT_EQ(start, sequence.last_progressed_fraction()); + effective_start = start_time + delta; + sequence.OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + group_id, + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + sequence.Progress(effective_start + delta/2, &delegate); + EXPECT_FLOAT_EQ(middle, sequence.last_progressed_fraction()); + EXPECT_TRUE(sequence.IsFinished(effective_start + delta)); + sequence.Progress(effective_start + delta, &delegate); + EXPECT_FLOAT_EQ(target, sequence.last_progressed_fraction()); EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation()); } EXPECT_TRUE(sequence.properties().size() == 1); EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::OPACITY) != sequence.properties().end()); - EXPECT_TRUE(sequence.IsFinished(start_time + delta)); } // Check that the sequences progresses the delegate as expected when it contains @@ -72,9 +116,9 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { LayerAnimationSequence sequence; TestLayerAnimationDelegate delegate; float start_opacity = 0.0f; - float middle_opacity = 0.5f; float target_opacity = 1.0f; base::TimeTicks start_time; + base::TimeTicks effective_start; base::TimeDelta delta = base::TimeDelta::FromSeconds(1); sequence.AddElement( LayerAnimationElement::CreateOpacityElement(target_opacity, delta)); @@ -94,23 +138,34 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { LayerAnimationElement::CreateTransformElement(target_transform, delta)); for (int i = 0; i < 2; ++i) { - start_time += delta + delta + delta; + int group_id = 1; + sequence.set_animation_group_id(group_id); + start_time = effective_start + 3 * delta; sequence.set_start_time(start_time); delegate.SetOpacityFromAnimation(start_opacity); delegate.SetTransformFromAnimation(start_transform); + sequence.Start(&delegate); sequence.Progress(start_time, &delegate); - EXPECT_FLOAT_EQ(start_opacity, delegate.GetOpacityForAnimation()); - sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(500), - &delegate); - EXPECT_FLOAT_EQ(middle_opacity, delegate.GetOpacityForAnimation()); - sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(1000), - &delegate); + EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction()); + effective_start = start_time + delta; + sequence.OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + group_id, + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + sequence.Progress(effective_start + delta/2, &delegate); + EXPECT_FLOAT_EQ(0.5, sequence.last_progressed_fraction()); + sequence.Progress(effective_start + delta, &delegate); EXPECT_FLOAT_EQ(target_opacity, delegate.GetOpacityForAnimation()); + + // Now at the start of the pause. + EXPECT_FLOAT_EQ(0.0, sequence.last_progressed_fraction()); TestLayerAnimationDelegate copy = delegate; // In the middle of the pause -- nothing should have changed. - sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(1500), + sequence.Progress(effective_start + delta + delta/2, &delegate); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), copy.GetBoundsForAnimation()); @@ -120,16 +175,14 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { copy.GetOpacityForAnimation()); - sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(2000), - &delegate); + sequence.Progress(effective_start + 2 * delta, &delegate); CheckApproximatelyEqual(start_transform, delegate.GetTransformForAnimation()); - sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(2500), - &delegate); + sequence.Progress(effective_start + 2 * delta + delta/2, &delegate); CheckApproximatelyEqual(middle_transform, delegate.GetTransformForAnimation()); - sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(3000), - &delegate); + EXPECT_TRUE(sequence.IsFinished(effective_start + 3 * delta)); + sequence.Progress(effective_start + 3 * delta, &delegate); CheckApproximatelyEqual(target_transform, delegate.GetTransformForAnimation()); } @@ -141,41 +194,41 @@ TEST(LayerAnimationSequenceTest, MultipleElement) { sequence.properties().end()); EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::BOUNDS) != sequence.properties().end()); - EXPECT_TRUE(sequence.IsFinished(start_time + delta + delta + delta)); } // Check that a sequence can still be aborted if it has cycled many times. TEST(LayerAnimationSequenceTest, AbortingCyclicSequence) { LayerAnimationSequence sequence; TestLayerAnimationDelegate delegate; - float start_opacity = 0.0f; - float target_opacity = 1.0f; + float start_brightness = 0.0f; + float target_brightness = 1.0f; base::TimeTicks start_time; base::TimeDelta delta = base::TimeDelta::FromSeconds(1); sequence.AddElement( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta)); + LayerAnimationElement::CreateBrightnessElement(target_brightness, delta)); sequence.AddElement( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta)); + LayerAnimationElement::CreateBrightnessElement(start_brightness, delta)); sequence.set_is_cyclic(true); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); start_time += delta; sequence.set_start_time(start_time); + sequence.Start(&delegate); sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(101000), &delegate); - EXPECT_FLOAT_EQ(target_opacity, delegate.GetOpacityForAnimation()); - sequence.Abort(); + EXPECT_FLOAT_EQ(target_brightness, delegate.GetBrightnessForAnimation()); + sequence.Abort(&delegate); // Should be able to reuse the sequence after aborting. - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); start_time += base::TimeDelta::FromMilliseconds(101000); sequence.set_start_time(start_time); sequence.Progress(start_time + base::TimeDelta::FromMilliseconds(100000), &delegate); - EXPECT_FLOAT_EQ(start_opacity, delegate.GetOpacityForAnimation()); + EXPECT_FLOAT_EQ(start_brightness, delegate.GetBrightnessForAnimation()); } // Check that a sequence can be 'fast-forwarded' to the end and the target set. @@ -205,7 +258,7 @@ TEST(LayerAnimationSequenceTest, AddObserver) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); LayerAnimationSequence sequence; sequence.AddElement( - LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); for (int i = 0; i < 2; ++i) { start_time += delta; sequence.set_start_time(start_time); diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc index e6e663d..e18c796 100644 --- a/ui/compositor/layer_animator.cc +++ b/ui/compositor/layer_animator.cc @@ -7,6 +7,7 @@ #include "base/debug/trace_event.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "cc/animation_id_provider.h" #include "ui/base/animation/animation_container.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" @@ -202,9 +203,17 @@ void LayerAnimator::StartTogether( LayerAnimationElement::CreatePauseElement(animated_properties, base::TimeDelta()))); + bool wait_for_group_start = false; + for (iter = animations.begin(); iter != animations.end(); ++iter) + wait_for_group_start |= (*iter)->IsFirstElementThreaded(); + + int group_id = cc::AnimationIdProvider::NextGroupId(); + // These animations (provided they don't animate any common properties) will // now animate together if trivially scheduled. for (iter = animations.begin(); iter != animations.end(); ++iter) { + (*iter)->set_animation_group_id(group_id); + (*iter)->set_waiting_for_group_start(wait_for_group_start); ScheduleAnimation(*iter); } @@ -232,9 +241,17 @@ void LayerAnimator::ScheduleTogether( LayerAnimationElement::CreatePauseElement(animated_properties, base::TimeDelta()))); + bool wait_for_group_start = false; + for (iter = animations.begin(); iter != animations.end(); ++iter) + wait_for_group_start |= (*iter)->IsFirstElementThreaded(); + + int group_id = cc::AnimationIdProvider::NextGroupId(); + // These animations (provided they don't animate any common properties) will // now animate together if trivially scheduled. for (iter = animations.begin(); iter != animations.end(); ++iter) { + (*iter)->set_animation_group_id(group_id); + (*iter)->set_waiting_for_group_start(wait_for_group_start); ScheduleAnimation(*iter); } @@ -299,11 +316,50 @@ void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) { } } +void LayerAnimator::OnThreadedAnimationStarted( + const cc::AnimationEvent& event) { + LayerAnimationElement::AnimatableProperty property = + LayerAnimationElement::ToAnimatableProperty(event.targetProperty); + + RunningAnimation* running = GetRunningAnimation(property); + if (!running) + return; + DCHECK(running->is_sequence_alive()); + + if (running->sequence()->animation_group_id() != event.groupId) + return; + + running->sequence()->OnThreadedAnimationStarted(event); + if (!running->sequence()->waiting_for_group_start()) + return; + + base::TimeTicks start_time = base::TimeTicks::FromInternalValue( + event.monotonicTime * base::Time::kMicrosecondsPerSecond); + + running->sequence()->set_waiting_for_group_start(false); + + // The call to GetRunningAnimation made above already purged deleted + // animations, so we are guaranteed that all the animations we iterate + // over now are alive. + for (RunningAnimations::iterator iter = running_animations_.begin(); + iter != running_animations_.end(); ++iter) { + // Ensure that each sequence is only Started once, regardless of the + // number of sequences in the group that have threaded first elements. + if (((*iter).sequence()->animation_group_id() == event.groupId) && + !(*iter).sequence()->IsFirstElementThreaded() && + (*iter).sequence()->waiting_for_group_start()) { + (*iter).sequence()->set_start_time(start_time); + (*iter).sequence()->set_waiting_for_group_start(false); + (*iter).sequence()->Start(delegate()); + } + } +} + // LayerAnimator protected ----------------------------------------------------- void LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence, base::TimeTicks now) { - if (!delegate()) + if (!delegate() || sequence->waiting_for_group_start()) return; sequence->Progress(now, delegate()); @@ -399,11 +455,14 @@ LayerAnimationSequence* LayerAnimator::RemoveAnimation( LayerAnimationSequence* sequence) { linked_ptr<LayerAnimationSequence> to_return; + bool is_running = false; + // First remove from running animations for (RunningAnimations::iterator iter = running_animations_.begin(); iter != running_animations_.end(); ++iter) { if ((*iter).sequence() == sequence) { running_animations_.erase(iter); + is_running = true; break; } } @@ -418,6 +477,39 @@ LayerAnimationSequence* LayerAnimator::RemoveAnimation( } } + if (!to_return.get() || + !to_return->waiting_for_group_start() || + !to_return->IsFirstElementThreaded()) + return to_return.release(); + + // The removed sequence may have been responsible for making other sequences + // wait for a group start. If no other sequences in the group have a + // threaded first element, the group no longer needs the additional wait. + bool is_wait_still_needed = false; + int group_id = to_return->animation_group_id(); + for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); + queue_iter != animation_queue_.end(); ++queue_iter) { + if (((*queue_iter)->animation_group_id() == group_id) && + (*queue_iter)->IsFirstElementThreaded()) { + is_wait_still_needed = true; + break; + } + } + + if (is_wait_still_needed) + return to_return.release(); + + for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); + queue_iter != animation_queue_.end(); ++queue_iter) { + if ((*queue_iter)->animation_group_id() == group_id && + (*queue_iter)->waiting_for_group_start()) { + (*queue_iter)->set_waiting_for_group_start(false); + if (is_running) { + (*queue_iter)->set_start_time(last_step_time_); + (*queue_iter)->Start(delegate()); + } + } + } return to_return.release(); } @@ -426,7 +518,7 @@ void LayerAnimator::FinishAnimation( scoped_refptr<LayerAnimator> retain(this); scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence)); if (abort) - sequence->Abort(); + sequence->Abort(delegate()); else ProgressAnimationToEnd(sequence); ProcessQueue(); @@ -502,7 +594,7 @@ void LayerAnimator::RemoveAllAnimationsWithACommonProperty( scoped_ptr<LayerAnimationSequence> removed( SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i])); if (abort) - running_animations_copy[i].sequence()->Abort(); + running_animations_copy[i].sequence()->Abort(delegate()); else SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]); } @@ -522,7 +614,7 @@ void LayerAnimator::RemoveAllAnimationsWithACommonProperty( if (sequences[i]->HasCommonProperty(sequence->properties())) { scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequences[i])); if (abort) - sequences[i]->Abort(); + sequences[i]->Abort(delegate()); else ProgressAnimationToEnd(sequences[i]); } @@ -684,7 +776,13 @@ bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) { else start_time = base::TimeTicks::Now(); - sequence->set_start_time(start_time); + if (!sequence->animation_group_id()) + sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId()); + if (!sequence->waiting_for_group_start() || + sequence->IsFirstElementThreaded()) { + sequence->set_start_time(start_time); + sequence->Start(delegate()); + } running_animations_.push_back( RunningAnimation(sequence->AsWeakPtr())); @@ -733,7 +831,7 @@ void LayerAnimator::ClearAnimationsInternal() { scoped_ptr<LayerAnimationSequence> removed( RemoveAnimation(running_animations_copy[i].sequence())); if (removed.get()) - removed->Abort(); + removed->Abort(delegate()); } // This *should* have cleared the list of running animations. DCHECK(running_animations_.empty()); diff --git a/ui/compositor/layer_animator.h b/ui/compositor/layer_animator.h index bf8ee7c..27cb9db 100644 --- a/ui/compositor/layer_animator.h +++ b/ui/compositor/layer_animator.h @@ -113,14 +113,20 @@ class COMPOSITOR_EXPORT LayerAnimator // of this animation sequence. void ScheduleAnimation(LayerAnimationSequence* animation); - // Starts the animations to be run together. Obviously will not work if - // they animate any common properties. The animator takes ownership of the + // Starts the animations to be run together, ensuring that the first elements + // in these sequences have the same effective start time even when some of + // them start on the compositor thread (but there is no such guarantee for + // the effective start time of subsequent elements). Obviously will not work + // if they animate any common properties. The animator takes ownership of the // animation sequences. Takes PreemptionStrategy into account. void StartTogether(const std::vector<LayerAnimationSequence*>& animations); - // Schedules the animations to be run together. Obviously will not work if - // they animate any common properties. The animator takes ownership of the - // animation sequences. + // Schedules the animations to be run together, ensuring that the first + // elements in these sequences have the same effective start time even when + // some of them start on the compositor thread (but there is no such guarantee + // for the effective start time of subsequent elements). Obviously will not + // work if they animate any common properties. The animator takes ownership + // of the animation sequences. void ScheduleTogether(const std::vector<LayerAnimationSequence*>& animations); // Schedules a pause for length |duration| of all the specified properties. @@ -159,6 +165,9 @@ class COMPOSITOR_EXPORT LayerAnimator void AddObserver(LayerAnimationObserver* observer); void RemoveObserver(LayerAnimationObserver* observer); + // Called when a threaded animation is actually started. + void OnThreadedAnimationStarted(const cc::AnimationEvent& event); + // This determines how implicit animations will be tweened. This has no // effect on animations that are explicitly started or scheduled. The default // is Tween::LINEAR. @@ -216,6 +225,7 @@ class COMPOSITOR_EXPORT LayerAnimator private: friend class base::RefCounted<LayerAnimator>; friend class ScopedLayerAnimationSettings; + friend class LayerAnimatorTestController; class RunningAnimation { public: diff --git a/ui/compositor/layer_animator_unittest.cc b/ui/compositor/layer_animator_unittest.cc index c93d117..5ecb031 100644 --- a/ui/compositor/layer_animator_unittest.cc +++ b/ui/compositor/layer_animator_unittest.cc @@ -14,6 +14,7 @@ #include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/compositor/test/layer_animator_test_controller.h" #include "ui/compositor/test/test_layer_animation_delegate.h" #include "ui/compositor/test/test_layer_animation_observer.h" #include "ui/compositor/test/test_utils.h" @@ -155,10 +156,10 @@ TEST(LayerAnimatorTest, ImplicitAnimation) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); base::TimeTicks now = base::TimeTicks::Now(); - animator->SetOpacity(0.5); + animator->SetBrightness(0.5); EXPECT_TRUE(animator->is_animating()); element->Step(now + base::TimeDelta::FromSeconds(1)); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), 0.5); } // Checks that if the animator is a default animator, that implicit animations @@ -168,9 +169,9 @@ TEST(LayerAnimatorTest, NoImplicitAnimation) { animator->set_disable_timer_for_test(true); TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - animator->SetOpacity(0.5); + animator->SetBrightness(0.5); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), 0.5); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), 0.5); } // Checks that StopAnimatingProperty stops animation for that property, and also @@ -235,8 +236,8 @@ TEST(LayerAnimatorTest, AbortAllAnimations) { CheckApproximatelyEqual(initial_bounds, delegate.GetBoundsForAnimation()); } -// Schedule an animation that can run immediately. This is the trivial case and -// should result in the animation being started immediately. +// Schedule a non-threaded animation that can run immediately. This is the +// trivial case and should result in the animation being started immediately. TEST(LayerAnimatorTest, ScheduleAnimationThatCanRunImmediately) { scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); AnimationContainerElement* element = animator.get(); @@ -244,36 +245,85 @@ TEST(LayerAnimatorTest, ScheduleAnimationThatCanRunImmediately) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_brightness(0.0); + double middle_brightness(0.5); + double target_brightness(1.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); animator->ScheduleAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_FALSE(animator->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); +} + +// Schedule a threaded animation that can run immediately. +TEST(LayerAnimatorTest, ScheduleThreadedAnimationThatCanRunImmediately) { + LayerAnimatorTestController test_controller( + LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = test_controller.animator(); + test_controller.animator()->set_disable_timer_for_test(true); + TestLayerAnimationDelegate delegate; + test_controller.animator()->SetDelegate(&delegate); + + double start_opacity(0.0); + double target_opacity(1.0); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + + delegate.SetOpacityFromAnimation(start_opacity); + + test_controller.animator()->ScheduleAnimation( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + + base::TimeTicks start_time = test_controller.animator()->last_step_time(); + base::TimeTicks effective_start = start_time + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(effective_start + delta/2); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ( + 0.5, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + last_progressed_fraction()); + + element->Step(effective_start + delta); + + EXPECT_FALSE(test_controller.animator()->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); } -// Schedule two animations on separate properties. Both animations should -// start immediately and should progress in lock step. +// Schedule two non-threaded animations on separate properties. Both animations +// should start immediately and should progress in lock step. TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); AnimationContainerElement* element = animator.get(); @@ -281,9 +331,9 @@ TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_brightness(0.0); + double middle_brightness(0.5); + double target_brightness(1.0); gfx::Rect start_bounds, target_bounds, middle_bounds; start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50); @@ -292,19 +342,20 @@ TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); delegate.SetBoundsFromAnimation(start_bounds); animator->ScheduleAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); animator->ScheduleAnimation( new LayerAnimationSequence( LayerAnimationElement::CreateBoundsElement(target_bounds, delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); base::TimeTicks start_time = animator->last_step_time(); @@ -312,12 +363,77 @@ TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), middle_bounds); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_FALSE(animator->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); +} + +// Schedule a threaded and a non-threaded animation on separate properties. Both +// animations should progress in lock step. +TEST(LayerAnimatorTest, ScheduleThreadedAndNonThreadedAnimations) { + LayerAnimatorTestController test_controller( + LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = test_controller.animator(); + test_controller.animator()->set_disable_timer_for_test(true); + TestLayerAnimationDelegate delegate; + test_controller.animator()->SetDelegate(&delegate); + + double start_opacity(0.0); + double target_opacity(1.0); + + gfx::Rect start_bounds, target_bounds, middle_bounds; + start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50); + start_bounds.set_x(-90); + target_bounds.set_x(90); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + + delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBoundsFromAnimation(start_bounds); + + std::vector<LayerAnimationSequence*> animations; + animations.push_back( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + + animations.push_back( + new LayerAnimationSequence( + LayerAnimationElement::CreateBoundsElement(target_bounds, delta))); + + test_controller.animator()->ScheduleTogether(animations); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); + + base::TimeTicks start_time = test_controller.animator()->last_step_time(); + base::TimeTicks effective_start = start_time + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(effective_start + delta/2); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ( + 0.5, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + last_progressed_fraction()); + CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), middle_bounds); + + element->Step(effective_start + delta); + + EXPECT_FALSE(test_controller.animator()->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); } @@ -331,49 +447,51 @@ TEST(LayerAnimatorTest, ScheduleTwoAnimationsOnSameProperty) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_brightness(0.0); + double middle_brightness(0.5); + double target_brightness(1.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); animator->ScheduleAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); animator->ScheduleAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(start_brightness, + delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); } -// Schedule [{o}, {o,b}, {b}] and ensure that {b} doesn't run right away. That +// Schedule [{g}, {g,b}, {b}] and ensure that {b} doesn't run right away. That // is, ensure that all animations targetting a particular property are run in // order. TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { @@ -383,9 +501,9 @@ TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_grayscale(0.0); + double middle_grayscale(0.5); + double target_grayscale(1.0); gfx::Rect start_bounds, target_bounds, middle_bounds; start_bounds = target_bounds = middle_bounds = gfx::Rect(0, 0, 50, 50); @@ -394,28 +512,30 @@ TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetGrayscaleFromAnimation(start_grayscale); delegate.SetBoundsFromAnimation(start_bounds); animator->ScheduleAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateGrayscaleElement(target_grayscale, + delta))); - scoped_ptr<LayerAnimationSequence> bounds_and_opacity( + scoped_ptr<LayerAnimationSequence> bounds_and_grayscale( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + LayerAnimationElement::CreateGrayscaleElement(start_grayscale, + delta))); - bounds_and_opacity->AddElement( + bounds_and_grayscale->AddElement( LayerAnimationElement::CreateBoundsElement(target_bounds, delta)); - animator->ScheduleAnimation(bounds_and_opacity.release()); + animator->ScheduleAnimation(bounds_and_grayscale.release()); animator->ScheduleAnimation( new LayerAnimationSequence( LayerAnimationElement::CreateBoundsElement(start_bounds, delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); base::TimeTicks start_time = animator->last_step_time(); @@ -423,37 +543,37 @@ TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); element->Step(start_time + base::TimeDelta::FromMilliseconds(3000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); element->Step(start_time + base::TimeDelta::FromMilliseconds(4000)); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); } -// Schedule {o} and then schedule {o} and {b} together. In this case, since +// Schedule {g} and then schedule {g} and {b} together. In this case, since // ScheduleTogether is being used, the bounds animation should not start until -// the second opacity animation starts. +// the second grayscale animation starts. TEST(LayerAnimatorTest, ScheduleTogether) { scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); AnimationContainerElement* element = animator.get(); @@ -461,8 +581,8 @@ TEST(LayerAnimatorTest, ScheduleTogether) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double target_opacity(1.0); + double start_grayscale(0.0); + double target_grayscale(1.0); gfx::Rect start_bounds, target_bounds, middle_bounds; start_bounds = target_bounds = gfx::Rect(0, 0, 50, 50); @@ -471,23 +591,24 @@ TEST(LayerAnimatorTest, ScheduleTogether) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetGrayscaleFromAnimation(start_grayscale); delegate.SetBoundsFromAnimation(start_bounds); animator->ScheduleAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateGrayscaleElement(target_grayscale, + delta))); std::vector<LayerAnimationSequence*> sequences; sequences.push_back(new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta))); sequences.push_back(new LayerAnimationSequence( LayerAnimationElement::CreateBoundsElement(target_bounds, delta))); animator->ScheduleTogether(sequences); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); base::TimeTicks start_time = animator->last_step_time(); @@ -495,18 +616,18 @@ TEST(LayerAnimatorTest, ScheduleTogether) { element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), target_bounds); } -// Start animation (that can run immediately). This is the trivial case (see -// the trival case for ScheduleAnimation). +// Start non-threaded animation (that can run immediately). This is the trivial +// case (see the trival case for ScheduleAnimation). TEST(LayerAnimatorTest, StartAnimationThatCanRunImmediately) { scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); AnimationContainerElement* element = animator.get(); @@ -514,31 +635,79 @@ TEST(LayerAnimatorTest, StartAnimationThatCanRunImmediately) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_brightness(0.0); + double middle_brightness(0.5); + double target_brightness(1.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_FALSE(animator->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); +} + +// Start threaded animation (that can run immediately). +TEST(LayerAnimatorTest, StartThreadedAnimationThatCanRunImmediately) { + LayerAnimatorTestController test_controller( + LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = test_controller.animator(); + test_controller.animator()->set_disable_timer_for_test(true); + TestLayerAnimationDelegate delegate; + test_controller.animator()->SetDelegate(&delegate); + + double start_opacity(0.0); + double target_opacity(1.0); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + + delegate.SetOpacityFromAnimation(start_opacity); + + test_controller.animator()->StartAnimation( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + + base::TimeTicks start_time = test_controller.animator()->last_step_time(); + base::TimeTicks effective_start = start_time + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(effective_start + delta/2); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ( + 0.5, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + last_progressed_fraction()); + + element->Step(effective_start + delta); + EXPECT_FALSE(test_controller.animator()->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); } @@ -570,7 +739,7 @@ TEST(LayerAnimatorTest, PreemptBySettingNewTarget) { EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); } -// Preempt by animating to new target. +// Preempt by animating to new target, with a non-threaded animation. TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) { scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); AnimationContainerElement* element = animator.get(); @@ -578,20 +747,21 @@ TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_brightness(0.0); + double middle_brightness(0.5); + double target_brightness(1.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); animator->set_preemption_strategy( LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); base::TimeTicks start_time = animator->last_step_time(); @@ -599,26 +769,102 @@ TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) { animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(start_brightness, + delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(start_brightness, + delta))); EXPECT_TRUE(animator->is_animating()); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), - 0.5 * (start_opacity + middle_opacity)); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), + 0.5 * (start_brightness + middle_brightness)); element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); EXPECT_FALSE(animator->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); +} + +// Preempt by animating to new target, with a threaded animation. +TEST(LayerAnimatorTest, PreemptThreadedByImmediatelyAnimatingToNewTarget) { + LayerAnimatorTestController test_controller( + LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = test_controller.animator(); + test_controller.animator()->set_disable_timer_for_test(true); + TestLayerAnimationDelegate delegate; + test_controller.animator()->SetDelegate(&delegate); + + double start_opacity(0.0); + double middle_opacity(0.5); + double target_opacity(1.0); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + + delegate.SetOpacityFromAnimation(start_opacity); + + test_controller.animator()->set_preemption_strategy( + LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + + test_controller.animator()->StartAnimation( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + + base::TimeTicks start_time = test_controller.animator()->last_step_time(); + base::TimeTicks effective_start = start_time + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(effective_start + delta/2); + + test_controller.animator()->StartAnimation( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + + test_controller.animator()->StartAnimation( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + + base::TimeTicks second_effective_start = effective_start + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (second_effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(second_effective_start + delta/2); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ( + 0.5, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + last_progressed_fraction()); + + element->Step(second_effective_start + delta); + + EXPECT_FALSE(test_controller.animator()->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); } @@ -630,19 +876,20 @@ TEST(LayerAnimatorTest, PreemptEnqueueNewAnimation) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_brightness(0.0); + double middle_brightness(0.5); + double target_brightness(1.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION); animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); base::TimeTicks start_time = animator->last_step_time(); @@ -650,27 +897,28 @@ TEST(LayerAnimatorTest, PreemptEnqueueNewAnimation) { animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(start_brightness, + delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); EXPECT_TRUE(animator->is_animating()); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); } // Start an animation when there are sequences waiting in the queue. In this @@ -683,19 +931,20 @@ TEST(LayerAnimatorTest, PreemptyByReplacingQueuedAnimations) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_brightness(0.0); + double middle_brightness(0.5); + double target_brightness(1.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); animator->set_preemption_strategy(LayerAnimator::REPLACE_QUEUED_ANIMATIONS); animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); base::TimeTicks start_time = animator->last_step_time(); @@ -703,31 +952,33 @@ TEST(LayerAnimatorTest, PreemptyByReplacingQueuedAnimations) { animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(middle_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(middle_brightness, + delta))); // Queue should now have two animations. Starting a third should replace the // second. animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(start_brightness, + delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); } TEST(LayerAnimatorTest, StartTogetherSetsLastStepTime) { @@ -736,14 +987,14 @@ TEST(LayerAnimatorTest, StartTogetherSetsLastStepTime) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double target_opacity(1.0); + double start_grayscale(0.0); + double target_grayscale(1.0); double start_brightness(0.1); double target_brightness(0.9); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetGrayscaleFromAnimation(start_grayscale); delegate.SetBrightnessFromAnimation(start_brightness); animator->set_preemption_strategy( @@ -753,7 +1004,8 @@ TEST(LayerAnimatorTest, StartTogetherSetsLastStepTime) { animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(target_grayscale, + delta), LayerAnimationElement::CreateBrightnessElement(target_brightness, delta) )); @@ -813,9 +1065,9 @@ TEST(LayerAnimatorTest, MultiPreemptByImmediatelyAnimatingToNewTarget) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_grayscale(0.0); + double middle_grayscale(0.5); + double target_grayscale(1.0); double start_brightness(0.1); double middle_brightness(0.2); @@ -823,7 +1075,7 @@ TEST(LayerAnimatorTest, MultiPreemptByImmediatelyAnimatingToNewTarget) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetGrayscaleFromAnimation(start_grayscale); delegate.SetBrightnessFromAnimation(start_brightness); animator->set_preemption_strategy( @@ -831,7 +1083,8 @@ TEST(LayerAnimatorTest, MultiPreemptByImmediatelyAnimatingToNewTarget) { animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(target_grayscale, + delta), LayerAnimationElement::CreateBrightnessElement(target_brightness, delta) )); @@ -842,17 +1095,17 @@ TEST(LayerAnimatorTest, MultiPreemptByImmediatelyAnimatingToNewTarget) { animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta), LayerAnimationElement::CreateBrightnessElement(start_brightness, delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta), LayerAnimationElement::CreateBrightnessElement(start_brightness, delta))); @@ -861,14 +1114,104 @@ TEST(LayerAnimatorTest, MultiPreemptByImmediatelyAnimatingToNewTarget) { element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), - 0.5 * (start_opacity + middle_opacity)); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), + 0.5 * (start_grayscale + middle_grayscale)); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), 0.5 * (start_brightness + middle_brightness)); element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); EXPECT_FALSE(animator->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); +} + +// Preempt a threaded animation by animating to new target. +TEST(LayerAnimatorTest, MultiPreemptThreadedByImmediatelyAnimatingToNewTarget) { + LayerAnimatorTestController test_controller( + LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = test_controller.animator(); + test_controller.animator()->set_disable_timer_for_test(true); + TestLayerAnimationDelegate delegate; + test_controller.animator()->SetDelegate(&delegate); + + double start_opacity(0.0); + double middle_opacity(0.5); + double target_opacity(1.0); + + double start_brightness(0.1); + double middle_brightness(0.2); + double target_brightness(0.3); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + + delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); + + test_controller.animator()->set_preemption_strategy( + LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + + test_controller.animator()->StartTogether( + CreateMultiSequence( + LayerAnimationElement::CreateOpacityElement(target_opacity, delta), + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta) + )); + + base::TimeTicks start_time = test_controller.animator()->last_step_time(); + base::TimeTicks effective_start = start_time + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(effective_start + delta/2); + + test_controller.animator()->StartTogether( + CreateMultiSequence( + LayerAnimationElement::CreateOpacityElement(start_opacity, delta), + LayerAnimationElement::CreateBrightnessElement(start_brightness, + delta))); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); + + test_controller.animator()->StartTogether( + CreateMultiSequence( + LayerAnimationElement::CreateOpacityElement(start_opacity, delta), + LayerAnimationElement::CreateBrightnessElement(start_brightness, + delta))); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + + base::TimeTicks second_effective_start = effective_start + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (second_effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(second_effective_start + delta/2); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ( + 0.5, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + last_progressed_fraction()); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), + 0.5 * (start_brightness + middle_brightness)); + + element->Step(second_effective_start + delta); + + EXPECT_FALSE(test_controller.animator()->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); } @@ -881,9 +1224,9 @@ TEST(LayerAnimatorTest, MultiPreemptEnqueueNewAnimation) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_grayscale(0.0); + double middle_grayscale(0.5); + double target_grayscale(1.0); double start_brightness(0.1); double middle_brightness(0.2); @@ -891,14 +1234,15 @@ TEST(LayerAnimatorTest, MultiPreemptEnqueueNewAnimation) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetGrayscaleFromAnimation(start_grayscale); delegate.SetBrightnessFromAnimation(start_brightness); animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION); animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(target_grayscale, + delta), LayerAnimationElement::CreateBrightnessElement(target_brightness, delta))); @@ -908,12 +1252,12 @@ TEST(LayerAnimatorTest, MultiPreemptEnqueueNewAnimation) { animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta), LayerAnimationElement::CreateBrightnessElement(start_brightness, delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); EXPECT_TRUE(animator->is_animating()); @@ -921,19 +1265,19 @@ TEST(LayerAnimatorTest, MultiPreemptEnqueueNewAnimation) { element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); } @@ -947,9 +1291,9 @@ TEST(LayerAnimatorTest, MultiPreemptByReplacingQueuedAnimations) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double middle_opacity(0.5); - double target_opacity(1.0); + double start_grayscale(0.0); + double middle_grayscale(0.5); + double target_grayscale(1.0); double start_brightness(0.1); double middle_brightness(0.2); @@ -957,14 +1301,15 @@ TEST(LayerAnimatorTest, MultiPreemptByReplacingQueuedAnimations) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetGrayscaleFromAnimation(start_grayscale); delegate.SetBrightnessFromAnimation(start_brightness); animator->set_preemption_strategy(LayerAnimator::REPLACE_QUEUED_ANIMATIONS); animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(target_grayscale, + delta), LayerAnimationElement::CreateBrightnessElement(target_brightness, delta))); @@ -974,7 +1319,8 @@ TEST(LayerAnimatorTest, MultiPreemptByReplacingQueuedAnimations) { animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(middle_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(middle_grayscale, + delta), LayerAnimationElement::CreateBrightnessElement(middle_brightness, delta))); @@ -982,34 +1328,34 @@ TEST(LayerAnimatorTest, MultiPreemptByReplacingQueuedAnimations) { // second. animator->StartTogether( CreateMultiSequence( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta), + LayerAnimationElement::CreateGrayscaleElement(start_grayscale, delta), LayerAnimationElement::CreateBrightnessElement(start_brightness, delta))); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), target_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(1500)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), middle_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), middle_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), middle_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_FALSE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetGrayscaleForAnimation(), start_grayscale); EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); } //------------------------------------------------------- -// Test that cyclic sequences continue to animate. +// Test that non-threaded cyclic sequences continue to animate. TEST(LayerAnimatorTest, CyclicSequences) { scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); AnimationContainerElement* element = animator.get(); @@ -1017,19 +1363,20 @@ TEST(LayerAnimatorTest, CyclicSequences) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double target_opacity(1.0); + double start_brightness(0.0); + double target_brightness(1.0); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); scoped_ptr<LayerAnimationSequence> sequence( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + LayerAnimationElement::CreateBrightnessElement(target_brightness, + delta))); sequence->AddElement( - LayerAnimationElement::CreateOpacityElement(start_opacity, delta)); + LayerAnimationElement::CreateBrightnessElement(start_brightness, delta)); sequence->set_is_cyclic(true); @@ -1040,35 +1387,140 @@ TEST(LayerAnimatorTest, CyclicSequences) { element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(2000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); element->Step(start_time + base::TimeDelta::FromMilliseconds(3000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); // Skip ahead by a lot. element->Step(start_time + base::TimeDelta::FromMilliseconds(1000000000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), start_brightness); // Skip ahead by a lot. element->Step(start_time + base::TimeDelta::FromMilliseconds(1000001000)); EXPECT_TRUE(animator->is_animating()); - EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + EXPECT_FLOAT_EQ(delegate.GetBrightnessForAnimation(), target_brightness); - animator->StopAnimatingProperty(LayerAnimationElement::OPACITY); + animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS); EXPECT_FALSE(animator->is_animating()); } +// Test that threaded cyclic sequences continue to animate. +TEST(LayerAnimatorTest, ThreadedCyclicSequences) { + LayerAnimatorTestController test_controller( + LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = test_controller.animator(); + test_controller.animator()->set_disable_timer_for_test(true); + TestLayerAnimationDelegate delegate; + test_controller.animator()->SetDelegate(&delegate); + + double start_opacity(0.0); + double target_opacity(1.0); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + + delegate.SetOpacityFromAnimation(start_opacity); + + scoped_ptr<LayerAnimationSequence> sequence( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + + sequence->AddElement( + LayerAnimationElement::CreateOpacityElement(start_opacity, delta)); + + sequence->set_is_cyclic(true); + + test_controller.animator()->StartAnimation(sequence.release()); + + base::TimeTicks start_time = test_controller.animator()->last_step_time(); + base::TimeTicks effective_start = start_time + delta; + + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(effective_start + delta); + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + + base::TimeTicks second_effective_start = effective_start + 2 * delta; + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (second_effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(second_effective_start + delta); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + + base::TimeTicks third_effective_start = second_effective_start + 2 * delta; + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (third_effective_start - base::TimeTicks()).InSecondsF())); + + element->Step(third_effective_start + delta); + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + + base::TimeTicks fourth_effective_start = third_effective_start + 2 * delta; + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (fourth_effective_start - base::TimeTicks()).InSecondsF())); + + // Skip ahead by a lot. + element->Step(fourth_effective_start + 1000 * delta); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), target_opacity); + + base::TimeTicks fifth_effective_start = fourth_effective_start + 1001 * delta; + test_controller.animator()->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)-> + animation_group_id(), + cc::Animation::Opacity, + (fifth_effective_start - base::TimeTicks()).InSecondsF())); + + // Skip ahead by a lot. + element->Step(fifth_effective_start + 999 * delta); + + EXPECT_TRUE(test_controller.animator()->is_animating()); + EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); + + test_controller.animator()->StopAnimatingProperty( + LayerAnimationElement::OPACITY); + + EXPECT_FALSE(test_controller.animator()->is_animating()); +} + TEST(LayerAnimatorTest, AddObserverExplicit) { scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); AnimationContainerElement* element = animator.get(); @@ -1083,10 +1535,10 @@ TEST(LayerAnimatorTest, AddObserverExplicit) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - delegate.SetOpacityFromAnimation(0.0f); + delegate.SetBrightnessFromAnimation(0.0f); LayerAnimationSequence* sequence = new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); animator->StartAnimation(sequence); @@ -1100,7 +1552,7 @@ TEST(LayerAnimatorTest, AddObserverExplicit) { // |sequence| has been destroyed. Recreate it to test abort. sequence = new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); animator->StartAnimation(sequence); @@ -1120,19 +1572,19 @@ TEST(LayerAnimatorTest, ImplicitAnimationObservers) { animator->SetDelegate(&delegate); EXPECT_FALSE(observer.animations_completed()); - animator->SetOpacity(1.0f); + animator->SetBrightness(1.0f); { ScopedLayerAnimationSettings settings(animator.get()); settings.AddObserver(&observer); - animator->SetOpacity(0.0f); + animator->SetBrightness(0.0f); } EXPECT_FALSE(observer.animations_completed()); base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(observer.animations_completed()); - EXPECT_FLOAT_EQ(0.0f, delegate.GetOpacityForAnimation()); + EXPECT_FLOAT_EQ(0.0f, delegate.GetBrightnessForAnimation()); } // Tests that an observer added to a scoped settings object is still notified @@ -1145,20 +1597,20 @@ TEST(LayerAnimatorTest, InterruptedImplicitAnimationObservers) { animator->SetDelegate(&delegate); EXPECT_FALSE(observer.animations_completed()); - animator->SetOpacity(1.0f); + animator->SetBrightness(1.0f); { ScopedLayerAnimationSettings settings(animator.get()); settings.AddObserver(&observer); - animator->SetOpacity(0.0f); + animator->SetBrightness(0.0f); } EXPECT_FALSE(observer.animations_completed()); // This should interrupt the implicit animation causing the observer to be // notified immediately. - animator->SetOpacity(1.0f); + animator->SetBrightness(1.0f); EXPECT_TRUE(observer.animations_completed()); - EXPECT_FLOAT_EQ(1.0f, delegate.GetOpacityForAnimation()); + EXPECT_FLOAT_EQ(1.0f, delegate.GetBrightnessForAnimation()); } // Tests that an observer added to a scoped settings object is not notified @@ -1174,13 +1626,13 @@ TEST(LayerAnimatorTest, ImplicitObserversAtAnimatorDestruction) { EXPECT_FALSE(observer_notify.animations_completed()); EXPECT_FALSE(observer_do_not_notify.animations_completed()); - animator->SetOpacity(1.0f); + animator->SetBrightness(1.0f); { ScopedLayerAnimationSettings settings(animator.get()); settings.AddObserver(&observer_notify); settings.AddObserver(&observer_do_not_notify); - animator->SetOpacity(0.0f); + animator->SetBrightness(0.0f); } EXPECT_FALSE(observer_notify.animations_completed()); @@ -1203,7 +1655,7 @@ TEST(LayerAnimatorTest, RemoveObserverShouldRemoveFromSequences) { base::TimeDelta delta = base::TimeDelta::FromSeconds(1); LayerAnimationSequence* sequence = new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); sequence->AddObserver(&observer); sequence->AddObserver(&removed_observer); @@ -1227,12 +1679,12 @@ TEST(LayerAnimatorTest, RemoveObserverShouldRemoveFromSequences) { } TEST(LayerAnimatorTest, ObserverReleasedBeforeAnimationSequenceEnds) { + TestLayerAnimationDelegate delegate; scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); animator->set_disable_timer_for_test(true); scoped_ptr<TestLayerAnimationObserver> observer( new TestLayerAnimationObserver); - TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); animator->AddObserver(observer.get()); @@ -1263,14 +1715,14 @@ TEST(LayerAnimatorTest, ObserverAttachedAfterAnimationStarted) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - delegate.SetOpacityFromAnimation(0.0f); + delegate.SetBrightnessFromAnimation(0.0f); { ScopedLayerAnimationSettings setter(animator.get()); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); LayerAnimationSequence* sequence = new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); animator->StartAnimation(sequence); base::TimeTicks start_time = animator->last_step_time(); @@ -1296,10 +1748,10 @@ TEST(LayerAnimatorTest, ObserverDetachedBeforeAnimationFinished) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - delegate.SetOpacityFromAnimation(0.0f); + delegate.SetBrightnessFromAnimation(0.0f); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); LayerAnimationSequence* sequence = new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); { ScopedLayerAnimationSettings setter(animator.get()); @@ -1331,16 +1783,16 @@ TEST(LayerAnimatorTest, ObserverDeletesAnimations) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - double start_opacity(0.0); - double target_opacity(1.0); + double start_brightness(0.0); + double target_brightness(1.0); gfx::Rect start_bounds(0, 0, 50, 50); gfx::Rect target_bounds(5, 5, 5, 5); - delegate.SetOpacityFromAnimation(start_opacity); + delegate.SetBrightnessFromAnimation(start_brightness); delegate.SetBoundsFromAnimation(start_bounds); - base::TimeDelta opacity_delta = base::TimeDelta::FromSeconds(1); + base::TimeDelta brightness_delta = base::TimeDelta::FromSeconds(1); base::TimeDelta halfway_delta = base::TimeDelta::FromSeconds(2); base::TimeDelta bounds_delta = base::TimeDelta::FromSeconds(3); @@ -1354,8 +1806,8 @@ TEST(LayerAnimatorTest, ObserverDeletesAnimations) { animator->StartAnimation( new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement( - target_opacity, opacity_delta))); + LayerAnimationElement::CreateBrightnessElement( + target_brightness, brightness_delta))); animator->StartAnimation(to_delete); @@ -1435,10 +1887,10 @@ TEST(LayerAnimatorTest, ImmediatelySettingNewTargetDoesNotLeak) { // Verifies GetTargetOpacity() works when multiple sequences are scheduled. TEST(LayerAnimatorTest, GetTargetOpacity) { + TestLayerAnimationDelegate delegate; scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); animator->set_preemption_strategy(LayerAnimator::ENQUEUE_NEW_ANIMATION); animator->set_disable_timer_for_test(true); - TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); delegate.SetOpacityFromAnimation(0.0); @@ -1641,7 +2093,7 @@ TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterFinishingAnimation) { TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); - delegate.SetOpacityFromAnimation(0.0f); + delegate.SetBrightnessFromAnimation(0.0f); gfx::Rect start_bounds(0, 0, 50, 50); gfx::Rect target_bounds(10, 10, 100, 100); @@ -1649,9 +2101,9 @@ TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterFinishingAnimation) { delegate.SetBoundsFromAnimation(start_bounds); base::TimeDelta delta = base::TimeDelta::FromSeconds(1); - LayerAnimationSequence* opacity_sequence = new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement(1.0f, delta)); - animator->StartAnimation(opacity_sequence); + LayerAnimationSequence* brightness_sequence = new LayerAnimationSequence( + LayerAnimationElement::CreateBrightnessElement(1.0f, delta)); + animator->StartAnimation(brightness_sequence); delta = base::TimeDelta::FromSeconds(2); LayerAnimationSequence* bounds_sequence = new LayerAnimationSequence( @@ -1698,11 +2150,11 @@ TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterStoppingAnimating) { TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterScheduling) { bool observer_was_deleted = false; + TestLayerAnimationDelegate delegate; DeletingObserver* observer = new DeletingObserver(&observer_was_deleted); observer->set_delete_on_animation_scheduled(true); LayerAnimator* animator = observer->animator(); animator->set_disable_timer_for_test(true); - TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); delegate.SetOpacityFromAnimation(0.0f); @@ -1730,12 +2182,12 @@ TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterScheduling) { TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterAborted) { bool observer_was_deleted = false; DeletingObserver* observer = new DeletingObserver(&observer_was_deleted); + TestLayerAnimationDelegate delegate; observer->set_delete_on_animation_aborted(true); LayerAnimator* animator = observer->animator(); animator->set_preemption_strategy( LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); animator->set_disable_timer_for_test(true); - TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); delegate.SetOpacityFromAnimation(0.0f); @@ -1767,10 +2219,10 @@ TEST(LayerAnimatorTest, ObserverDeletesAnimatorAfterAborted) { TEST(LayerAnimatorTest, TestSetterRespectEnqueueStrategy) { + TestLayerAnimationDelegate delegate; scoped_refptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); animator->set_disable_timer_for_test(true); - TestLayerAnimationDelegate delegate; animator->SetDelegate(&delegate); float start_opacity = 0.0f; diff --git a/ui/compositor/test/layer_animator_test_controller.cc b/ui/compositor/test/layer_animator_test_controller.cc new file mode 100644 index 0000000..5721cce --- /dev/null +++ b/ui/compositor/test/layer_animator_test_controller.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/compositor/test/layer_animator_test_controller.h" +#include "ui/compositor/layer_animation_sequence.h" + +namespace ui { + +LayerAnimatorTestController::LayerAnimatorTestController( + scoped_refptr<LayerAnimator> animator) + : animator_(animator) { +} + +LayerAnimatorTestController::~LayerAnimatorTestController() { +} + +LayerAnimationSequence* LayerAnimatorTestController::GetRunningSequence( + LayerAnimationElement::AnimatableProperty property) { + LayerAnimator::RunningAnimation* running_animation = + animator_->GetRunningAnimation(property); + if (running_animation) + return running_animation->sequence(); + else + return NULL; +} + +void LayerAnimatorTestController::StartThreadedAnimationsIfNeeded() { + LayerAnimationSequence* sequence = + GetRunningSequence(LayerAnimationElement::OPACITY); + + if (!sequence) + return; + + LayerAnimationElement* element = sequence->CurrentElement(); + if (element->properties().find(LayerAnimationElement::OPACITY) == + element->properties().end()) + return; + + if (!element->Started() || + element->effective_start_time() != base::TimeTicks()) + return; + + animator_->OnThreadedAnimationStarted(cc::AnimationEvent( + cc::AnimationEvent::Started, + 0, + element->animation_group_id(), + cc::Animation::Opacity, + (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF())); +} + +} // namespace ui diff --git a/ui/compositor/test/layer_animator_test_controller.h b/ui/compositor/test/layer_animator_test_controller.h new file mode 100644 index 0000000..0f8d1e8 --- /dev/null +++ b/ui/compositor/test/layer_animator_test_controller.h @@ -0,0 +1,34 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_COMPOSITOR_TEST_LAYER_ANIMATOR_TEST_CONTROLLER_H_ +#define UI_COMPOSITOR_TEST_LAYER_ANIMATOR_TEST_CONTROLLER_H_ + +#include "ui/compositor/layer_animator.h" + +namespace ui { + +// Allows tests to access sequences owned by the animator. +class LayerAnimatorTestController { + public: + LayerAnimatorTestController(scoped_refptr<LayerAnimator> animator); + + ~LayerAnimatorTestController(); + + LayerAnimator* animator() { return animator_.get(); } + + // Returns the running sequence animating the given property, if any. + LayerAnimationSequence* GetRunningSequence( + LayerAnimationElement::AnimatableProperty property); + + // Starts threaded animations that are waiting for an effective start time. + void StartThreadedAnimationsIfNeeded(); + + private: + scoped_refptr<LayerAnimator> animator_; +}; + +} // namespace ui + +#endif // UI_COMPOSITOR_TEST_LAYER_ANIMATOR_TEST_CONTROLLER_H_ diff --git a/ui/compositor/test/test_layer_animation_delegate.cc b/ui/compositor/test/test_layer_animation_delegate.cc index a3d7f67..d452fc0 100644 --- a/ui/compositor/test/test_layer_animation_delegate.cc +++ b/ui/compositor/test/test_layer_animation_delegate.cc @@ -88,4 +88,11 @@ SkColor TestLayerAnimationDelegate::GetColorForAnimation() const { return color_; } +void TestLayerAnimationDelegate::AddThreadedAnimation( + scoped_ptr<cc::Animation> animation) { +} + +void TestLayerAnimationDelegate::RemoveThreadedAnimation(int animation_id) { +} + } // namespace ui diff --git a/ui/compositor/test/test_layer_animation_delegate.h b/ui/compositor/test/test_layer_animation_delegate.h index 2c21aa5..3370f72 100644 --- a/ui/compositor/test/test_layer_animation_delegate.h +++ b/ui/compositor/test/test_layer_animation_delegate.h @@ -35,6 +35,9 @@ class TestLayerAnimationDelegate : public LayerAnimationDelegate { virtual float GetBrightnessForAnimation() const OVERRIDE; virtual float GetGrayscaleForAnimation() const OVERRIDE; virtual SkColor GetColorForAnimation() const OVERRIDE; + virtual void AddThreadedAnimation( + scoped_ptr<cc::Animation> animation) OVERRIDE; + virtual void RemoveThreadedAnimation(int animation_id) OVERRIDE; private: gfx::Rect bounds_; diff --git a/webkit/compositor_bindings/compositor_bindings.gyp b/webkit/compositor_bindings/compositor_bindings.gyp index df98e44..51d2575 100644 --- a/webkit/compositor_bindings/compositor_bindings.gyp +++ b/webkit/compositor_bindings/compositor_bindings.gyp @@ -7,8 +7,6 @@ 'webkit_compositor_bindings_sources': [ 'web_animation_curve_common.cc', 'web_animation_curve_common.h', - 'web_animation_id_provider.cc', - 'web_animation_id_provider.h', 'web_animation_impl.cc', 'web_animation_impl.h', 'web_compositor_support_software_output_device.cc', diff --git a/webkit/compositor_bindings/web_animation_id_provider.cc b/webkit/compositor_bindings/web_animation_id_provider.cc deleted file mode 100644 index efd3f0f..0000000 --- a/webkit/compositor_bindings/web_animation_id_provider.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "webkit/compositor_bindings/web_animation_id_provider.h" - -namespace webkit { - -int WebAnimationIdProvider::NextAnimationId() { - static int next_animation_id = 1; - return next_animation_id++; -} - -int WebAnimationIdProvider::NextGroupId() { - static int next_group_id = 1; - return next_group_id++; -} - -} // namespace webkit diff --git a/webkit/compositor_bindings/web_animation_id_provider.h b/webkit/compositor_bindings/web_animation_id_provider.h deleted file mode 100644 index 631785c..0000000 --- a/webkit/compositor_bindings/web_animation_id_provider.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef WEBKIT_COMPOSITOR_BINDINGS_WEB_ANIMATION_ID_PROVIDER -#define WEBKIT_COMPOSITOR_BINDINGS_WEB_ANIMATION_ID_PROVIDER - -namespace webkit { - -class WebAnimationIdProvider { - public: - // These functions each return monotonically increasing values. - static int NextAnimationId(); - static int NextGroupId(); -}; - -} - -#endif // WEBKIT_COMPOSITOR_BINDINGS_WEB_ANIMATION_ID_PROVIDER diff --git a/webkit/compositor_bindings/web_animation_impl.cc b/webkit/compositor_bindings/web_animation_impl.cc index 21b0bc8..961df4d 100644 --- a/webkit/compositor_bindings/web_animation_impl.cc +++ b/webkit/compositor_bindings/web_animation_impl.cc @@ -6,23 +6,23 @@ #include "cc/animation.h" #include "cc/animation_curve.h" +#include "cc/animation_id_provider.h" #include "third_party/WebKit/Source/Platform/chromium/public/WebAnimationCurve.h" #include "third_party/WebKit/Source/Platform/chromium/public/WebAnimation.h" -#include "webkit/compositor_bindings/web_animation_id_provider.h" #include "webkit/compositor_bindings/web_float_animation_curve_impl.h" #include "webkit/compositor_bindings/web_transform_animation_curve_impl.h" using cc::Animation; -using webkit::WebAnimationIdProvider; +using cc::AnimationIdProvider; namespace WebKit { WebAnimationImpl::WebAnimationImpl(const WebAnimationCurve& webCurve, TargetProperty targetProperty, int animationId, int groupId) { if (!animationId) - animationId = WebAnimationIdProvider::NextAnimationId(); + animationId = AnimationIdProvider::NextAnimationId(); if (!groupId) - groupId = WebAnimationIdProvider::NextGroupId(); + groupId = AnimationIdProvider::NextGroupId(); WebAnimationCurve::AnimationCurveType curveType = webCurve.type(); scoped_ptr<cc::AnimationCurve> curve; |