// Copyright 2017 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_KEYFRAME_EFFECT_H_ #define CC_ANIMATION_KEYFRAME_EFFECT_H_ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/animation/animation_events.h" #include "cc/animation/animation_export.h" #include "cc/animation/element_animations.h" #include "cc/trees/element_id.h" #include "cc/trees/mutator_host_client.h" #include "cc/trees/target_property.h" #include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/scroll_offset.h" #include #include namespace cc { class Animation; class KeyframeModel; struct PropertyAnimationState; typedef size_t KeyframeEffectId; // An KeyframeEffect owns a group of KeyframeModels for a single target // (identified by a ElementId). It is responsible for managing the // KeyframeModels' running states (starting, running, paused, etc), as well as // ticking the KeyframeModels when it is requested to produce new outputs for a // given time. // // Note that a single KeyframeEffect may not own all the KeyframeModels for a // given target. KeyframeEffect is only a grouping mechanism for related // KeyframeModels. The commonality between keyframe models on the same target // is found via ElementAnimations - there is only one ElementAnimations for a // given target. class CC_ANIMATION_EXPORT KeyframeEffect { public: class AnimationTimeProvider { public: virtual base::TimeTicks GetTimeForKeyframeModel( const KeyframeModel&) const = 0; }; explicit KeyframeEffect(KeyframeEffectId id); ~KeyframeEffect(); static std::unique_ptr Create(KeyframeEffectId id); std::unique_ptr CreateImplInstance() const; // ElementAnimations object where this controller is listed. scoped_refptr element_animations() const { return element_animations_; } bool has_bound_element_animations() const { return !!element_animations_; } bool has_attached_element() const { return !!element_id_; } ElementId element_id() const { return element_id_; } // Returns true if there are any KeyframeModels at all to process. bool has_any_keyframe_model() const { return !keyframe_models_.empty(); } // When a scroll animation is removed on the main thread, its compositor // thread counterpart continues producing scroll deltas until activation. // These scroll deltas need to be cleared at activation, so that the active // element's scroll offset matches the offset provided by the main thread // rather than a combination of this offset and scroll deltas produced by the // removed animation. This is to provide the illusion of synchronicity to JS // that simultaneously removes an animation and sets the scroll offset. bool scroll_offset_animation_was_interrupted() const { return scroll_offset_animation_was_interrupted_; } bool needs_push_properties() const { return needs_push_properties_; } void SetNeedsPushProperties(); void BindElementAnimations(ElementAnimations* element_animations); void UnbindElementAnimations(); void AttachElement(ElementId element_id); void DetachElement(); void Tick(base::TimeTicks monotonic_time, const AnimationTimeProvider* tick_provider); static void TickKeyframeModel(base::TimeTicks monotonic_time, KeyframeModel* keyframe_model, AnimationTarget* target); void RemoveFromTicking(); bool is_ticking() const { return is_ticking_; } void UpdateState(bool start_ready_keyframe_models, AnimationEvents* events); void UpdateTickingState(UpdateTickingType type); void AddKeyframeModel(std::unique_ptr keyframe_model); void PauseKeyframeModel(int keyframe_model_id, double time_offset); void RemoveKeyframeModel(int keyframe_model_id); void AbortKeyframeModel(int keyframe_model_id); void AbortKeyframeModels(TargetProperty::Type target_property, bool needs_completion); void ActivateKeyframeEffects(); void KeyframeModelAdded(); // The following methods should be called to notify the KeyframeEffect that // an animation event has been received for the same target (ElementId) as // this keyframe_effect. If the event matches a KeyframeModel owned by this // KeyframeEffect the call will return true, else it will return false. bool NotifyKeyframeModelStarted(const AnimationEvent& event); bool NotifyKeyframeModelFinished(const AnimationEvent& event); void NotifyKeyframeModelTakeover(const AnimationEvent& event); bool NotifyKeyframeModelAborted(const AnimationEvent& event); // Returns true if there are any KeyframeModels that have neither finished // nor aborted. bool HasTickingKeyframeModel() const; size_t TickingKeyframeModelsCount() const; bool HasNonDeletedKeyframeModel() const; bool HasOnlyTranslationTransforms(ElementListType list_type) const; bool AnimationsPreserveAxisAlignment() const; // Sets |start_scale| to the maximum of starting keyframe_model scale along // any dimension at any destination in active KeyframeModels. Returns false // if the starting scale cannot be computed. bool AnimationStartScale(ElementListType, float* start_scale) const; // Sets |max_scale| to the maximum scale along any dimension at any // destination in active KeyframeModels. Returns false if the maximum scale // cannot be computed. bool MaximumTargetScale(ElementListType, float* max_scale) const; // Returns true if there is a keyframe_model that is either currently // animating the given property or scheduled to animate this property in the // future, and that affects the given tree type. bool IsPotentiallyAnimatingProperty(TargetProperty::Type target_property, ElementListType list_type) const; // Returns true if there is a keyframe_model that is currently animating the // given property and that affects the given tree type. bool IsCurrentlyAnimatingProperty(TargetProperty::Type target_property, ElementListType list_type) const; KeyframeModel* GetKeyframeModel(TargetProperty::Type target_property) const; KeyframeModel* GetKeyframeModelById(int keyframe_model_id) const; void GetPropertyAnimationState(PropertyAnimationState* pending_state, PropertyAnimationState* active_state) const; void MarkAbortedKeyframeModelsForDeletion( KeyframeEffect* element_keyframe_effect_impl); void PurgeKeyframeModelsMarkedForDeletion(bool impl_only); void PushNewKeyframeModelsToImplThread( KeyframeEffect* element_keyframe_effect_impl) const; void RemoveKeyframeModelsCompletedOnMainThread( KeyframeEffect* element_keyframe_effect_impl) const; void PushPropertiesTo(KeyframeEffect* keyframe_effect_impl); void SetAnimation(Animation* animation); std::string KeyframeModelsToString() const; KeyframeEffectId id() const { return id_; } private: void StartKeyframeModels(base::TimeTicks monotonic_time); void PromoteStartedKeyframeModels(AnimationEvents* events); void MarkKeyframeModelsForDeletion(base::TimeTicks, AnimationEvents* events); void MarkFinishedKeyframeModels(base::TimeTicks monotonic_time); bool HasElementInActiveList() const; gfx::ScrollOffset ScrollOffsetForAnimation() const; void GenerateEvent(AnimationEvents* events, const KeyframeModel& keyframe_model, AnimationEvent::Type type, base::TimeTicks monotonic_time); void GenerateTakeoverEventForScrollAnimation( AnimationEvents* events, const KeyframeModel& keyframe_model, base::TimeTicks monotonic_time); std::vector> keyframe_models_; Animation* animation_; KeyframeEffectId id_; ElementId element_id_; // element_animations_ is non-null if controller is attached to an element. scoped_refptr element_animations_; // Only try to start KeyframeModels when new keyframe models are added or // when the previous attempt at starting KeyframeModels failed to start all // KeyframeModels. bool needs_to_start_keyframe_models_; bool scroll_offset_animation_was_interrupted_; bool is_ticking_; base::TimeTicks last_tick_time_; bool needs_push_properties_; DISALLOW_COPY_AND_ASSIGN(KeyframeEffect); }; } // namespace cc #endif // CC_ANIMATION_KEYFRAME_EFFECT_H_