Commit 9570bc95 authored by Olga Gerchikov's avatar Olga Gerchikov Committed by Commit Bot

Use timeline, animation, keyframe, keyframe model ids for targeting animation events.

Implemented common mechanism for targeting animation events initiated by animations and
worklet animations. Changes made:

- AnimationHost::SetAnimationEvents consults animation timeline to find a target animation.
- Moved animation events routing logic from cc:ElementAnimations to cc:Animation.
- Directly route to the target keyframe model using keyframe id and model id instead of using
  element id and group id to identify the target keyframe model.

Bug: 1013727
Change-Id: I28613b0e708258e6433a45e828710caa3e73e280
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1872486
Commit-Queue: Olga Gerchikov <gerchiko@microsoft.com>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719388}
parent 3f3d9cc5
...@@ -271,36 +271,55 @@ void Animation::RemoveFromTicking() { ...@@ -271,36 +271,55 @@ void Animation::RemoveFromTicking() {
animation_host_->RemoveFromTicking(this); animation_host_->RemoveFromTicking(this);
} }
void Animation::NotifyKeyframeModelStarted(const AnimationEvent& event) { void Animation::DispatchAndDelegateAnimationEvent(const AnimationEvent& event) {
if (animation_delegate_) { if (event.ShouldDispatchToKeyframeEffectAndModel()) {
animation_delegate_->NotifyAnimationStarted( KeyframeEffect* keyframe_effect =
event.monotonic_time, event.target_property, event.group_id); GetKeyframeEffectById(event.uid.effect_id);
} if (!keyframe_effect ||
} !keyframe_effect->DispatchAnimationEventToKeyframeModel(event)) {
// If we fail to dispatch the event, it is to clean up an obsolete
void Animation::NotifyKeyframeModelFinished(const AnimationEvent& event) { // animation and should not notify the delegate.
if (animation_delegate_) { // TODO(gerchiko): Determine when we expect the referenced animations not
animation_delegate_->NotifyAnimationFinished( // to exist.
event.monotonic_time, event.target_property, event.group_id); return;
} }
}
void Animation::NotifyKeyframeModelAborted(const AnimationEvent& event) {
if (animation_delegate_) {
animation_delegate_->NotifyAnimationAborted(
event.monotonic_time, event.target_property, event.group_id);
} }
DelegateAnimationEvent(event);
} }
void Animation::NotifyKeyframeModelTakeover(const AnimationEvent& event) { void Animation::DelegateAnimationEvent(const AnimationEvent& event) {
DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
if (animation_delegate_) { if (animation_delegate_) {
DCHECK(event.curve); switch (event.type) {
std::unique_ptr<AnimationCurve> animation_curve = event.curve->Clone(); case AnimationEvent::STARTED:
animation_delegate_->NotifyAnimationTakeover( animation_delegate_->NotifyAnimationStarted(
event.monotonic_time, event.target_property, event.animation_start_time, event.monotonic_time, event.target_property, event.group_id);
std::move(animation_curve)); break;
case AnimationEvent::FINISHED:
animation_delegate_->NotifyAnimationFinished(
event.monotonic_time, event.target_property, event.group_id);
break;
case AnimationEvent::ABORTED:
animation_delegate_->NotifyAnimationAborted(
event.monotonic_time, event.target_property, event.group_id);
break;
case AnimationEvent::TAKEOVER:
// TODO(crbug.com/1018213): Routing TAKEOVER events is broken.
DCHECK(!event.is_impl_only);
DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
DCHECK(event.curve);
animation_delegate_->NotifyAnimationTakeover(
event.monotonic_time, event.target_property,
event.animation_start_time, event.curve->Clone());
break;
case AnimationEvent::TIME_UPDATED:
DCHECK(!event.is_impl_only);
animation_delegate_->NotifyLocalTimeUpdated(event.local_time);
break;
}
} }
} }
......
...@@ -102,11 +102,12 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { ...@@ -102,11 +102,12 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> {
void AddToTicking(); void AddToTicking();
void RemoveFromTicking(); void RemoveFromTicking();
// AnimationDelegate routing. // Dispatches animation event to the animation keyframe effect and model when
void NotifyKeyframeModelStarted(const AnimationEvent& event); // appropriate, based on the event characteristics.
void NotifyKeyframeModelFinished(const AnimationEvent& event); // Delegates animation event that was successfully dispatched or doesn't need
void NotifyKeyframeModelAborted(const AnimationEvent& event); // to be dispatched.
void NotifyKeyframeModelTakeover(const AnimationEvent& event); void DispatchAndDelegateAnimationEvent(const AnimationEvent& event);
size_t TickingKeyframeModelsCount() const; size_t TickingKeyframeModelsCount() const;
bool AffectsCustomProperty() const; bool AffectsCustomProperty() const;
...@@ -147,6 +148,9 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { ...@@ -147,6 +148,9 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> {
void PushAttachedKeyframeEffectsToImplThread(Animation* animation_impl) const; void PushAttachedKeyframeEffectsToImplThread(Animation* animation_impl) const;
void PushPropertiesToImplThread(Animation* animation_impl); void PushPropertiesToImplThread(Animation* animation_impl);
// Delegates animation event
void DelegateAnimationEvent(const AnimationEvent& event);
protected: protected:
explicit Animation(int id); explicit Animation(int id);
virtual ~Animation(); virtual ~Animation();
......
...@@ -7,24 +7,27 @@ ...@@ -7,24 +7,27 @@
namespace cc { namespace cc {
AnimationEvent::AnimationEvent(AnimationEvent::Type type, AnimationEvent::AnimationEvent(AnimationEvent::Type type,
ElementId element_id, UniqueKeyframeModelId uid,
int group_id, int group_id,
int target_property, int target_property,
base::TimeTicks monotonic_time) base::TimeTicks monotonic_time)
: type(type), : type(type),
element_id(element_id), uid(uid),
worklet_animation_id(),
group_id(group_id), group_id(group_id),
target_property(target_property), target_property(target_property),
monotonic_time(monotonic_time), monotonic_time(monotonic_time),
is_impl_only(false), is_impl_only(false),
local_time() {} local_time() {}
AnimationEvent::AnimationEvent(WorkletAnimationId worklet_animation_id, AnimationEvent::AnimationEvent(int timeline_id,
int animation_id,
base::Optional<base::TimeDelta> local_time) base::Optional<base::TimeDelta> local_time)
: type(TIME_UPDATED), : type(TIME_UPDATED),
element_id(), // Initializing model_id with an invalid value (0).
worklet_animation_id(worklet_animation_id), // Also initializing keyframe_id with 0 which in its case is a valid
// value. However this is safe since keyframe_id and model_id are not used
// when routing a TIME_UPDATED event.
uid({timeline_id, animation_id, 0, 0}),
group_id(), group_id(),
target_property(), target_property(),
monotonic_time(), monotonic_time(),
...@@ -33,7 +36,7 @@ AnimationEvent::AnimationEvent(WorkletAnimationId worklet_animation_id, ...@@ -33,7 +36,7 @@ AnimationEvent::AnimationEvent(WorkletAnimationId worklet_animation_id,
AnimationEvent::AnimationEvent(const AnimationEvent& other) { AnimationEvent::AnimationEvent(const AnimationEvent& other) {
type = other.type; type = other.type;
element_id = other.element_id; uid = other.uid;
group_id = other.group_id; group_id = other.group_id;
target_property = other.target_property; target_property = other.target_property;
monotonic_time = other.monotonic_time; monotonic_time = other.monotonic_time;
...@@ -41,13 +44,12 @@ AnimationEvent::AnimationEvent(const AnimationEvent& other) { ...@@ -41,13 +44,12 @@ AnimationEvent::AnimationEvent(const AnimationEvent& other) {
animation_start_time = other.animation_start_time; animation_start_time = other.animation_start_time;
if (other.curve) if (other.curve)
curve = other.curve->Clone(); curve = other.curve->Clone();
worklet_animation_id = other.worklet_animation_id;
local_time = other.local_time; local_time = other.local_time;
} }
AnimationEvent& AnimationEvent::operator=(const AnimationEvent& other) { AnimationEvent& AnimationEvent::operator=(const AnimationEvent& other) {
type = other.type; type = other.type;
element_id = other.element_id; uid = other.uid;
group_id = other.group_id; group_id = other.group_id;
target_property = other.target_property; target_property = other.target_property;
monotonic_time = other.monotonic_time; monotonic_time = other.monotonic_time;
...@@ -55,7 +57,6 @@ AnimationEvent& AnimationEvent::operator=(const AnimationEvent& other) { ...@@ -55,7 +57,6 @@ AnimationEvent& AnimationEvent::operator=(const AnimationEvent& other) {
animation_start_time = other.animation_start_time; animation_start_time = other.animation_start_time;
if (other.curve) if (other.curve)
curve = other.curve->Clone(); curve = other.curve->Clone();
worklet_animation_id = other.worklet_animation_id;
local_time = other.local_time; local_time = other.local_time;
return *this; return *this;
} }
...@@ -70,4 +71,13 @@ bool AnimationEvents::IsEmpty() const { ...@@ -70,4 +71,13 @@ bool AnimationEvents::IsEmpty() const {
return events_.empty(); return events_.empty();
} }
bool AnimationEvent::ShouldDispatchToKeyframeEffectAndModel() const {
// TIME_UPDATED events are used to synchronize effect time between cc and
// main thread worklet animations. Keyframe models are not involved in
// this process.
// is_impl_only events are not dispatched because they don't have
// corresponding main thread components.
return type != TIME_UPDATED && !is_impl_only;
}
} // namespace cc } // namespace cc
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include "cc/animation/animation_curve.h" #include "cc/animation/animation_curve.h"
#include "cc/animation/animation_export.h" #include "cc/animation/animation_export.h"
#include "cc/animation/keyframe_model.h"
#include "cc/paint/element_id.h"
#include "cc/trees/mutator_host.h" #include "cc/trees/mutator_host.h"
namespace cc { namespace cc {
...@@ -19,14 +17,23 @@ namespace cc { ...@@ -19,14 +17,23 @@ namespace cc {
struct CC_ANIMATION_EXPORT AnimationEvent { struct CC_ANIMATION_EXPORT AnimationEvent {
enum Type { STARTED, FINISHED, ABORTED, TAKEOVER, TIME_UPDATED }; enum Type { STARTED, FINISHED, ABORTED, TAKEOVER, TIME_UPDATED };
typedef size_t KeyframeEffectId;
struct UniqueKeyframeModelId {
int timeline_id;
int animation_id;
KeyframeEffectId effect_id;
int model_id;
};
AnimationEvent(Type type, AnimationEvent(Type type,
ElementId element_id, UniqueKeyframeModelId uid,
int group_id, int group_id,
int target_property, int target_property,
base::TimeTicks monotonic_time); base::TimeTicks monotonic_time);
// Constructs AnimationEvent of TIME_UPDATED type. // Constructs AnimationEvent of TIME_UPDATED type.
AnimationEvent(WorkletAnimationId worklet_animation_id, AnimationEvent(int timeline_id,
int animation_id,
base::Optional<base::TimeDelta> local_time); base::Optional<base::TimeDelta> local_time);
AnimationEvent(const AnimationEvent& other); AnimationEvent(const AnimationEvent& other);
...@@ -34,13 +41,10 @@ struct CC_ANIMATION_EXPORT AnimationEvent { ...@@ -34,13 +41,10 @@ struct CC_ANIMATION_EXPORT AnimationEvent {
~AnimationEvent(); ~AnimationEvent();
bool ShouldDispatchToKeyframeEffectAndModel() const;
Type type; Type type;
// Either element_id or worklet_animation_id are set. worklet_animation_id is UniqueKeyframeModelId uid;
// set for TIME_UPDATED event types, element_id is set for other events.
// TODO(http://crbug.com/1013727): Make all animation events use animation id
// to do targeting;
ElementId element_id;
WorkletAnimationId worklet_animation_id;
int group_id; int group_id;
int target_property; int target_property;
base::TimeTicks monotonic_time; base::TimeTicks monotonic_time;
......
...@@ -483,32 +483,6 @@ std::unique_ptr<MutatorEvents> AnimationHost::CreateEvents() { ...@@ -483,32 +483,6 @@ std::unique_ptr<MutatorEvents> AnimationHost::CreateEvents() {
return std::make_unique<AnimationEvents>(); return std::make_unique<AnimationEvents>();
} }
void DispatchAnimationEventToElementAnimations(ElementAnimations* animations,
const AnimationEvent& event) {
switch (event.type) {
case AnimationEvent::STARTED:
animations->NotifyAnimationStarted(event);
break;
case AnimationEvent::FINISHED:
animations->NotifyAnimationFinished(event);
break;
case AnimationEvent::ABORTED:
animations->NotifyAnimationAborted(event);
break;
case AnimationEvent::TAKEOVER:
animations->NotifyAnimationTakeover(event);
break;
case AnimationEvent::TIME_UPDATED:
// Worklet animations are looked up in ticking animations.
NOTREACHED();
break;
}
}
void AnimationHost::SetAnimationEvents( void AnimationHost::SetAnimationEvents(
std::unique_ptr<MutatorEvents> mutator_events) { std::unique_ptr<MutatorEvents> mutator_events) {
auto events = auto events =
...@@ -517,25 +491,11 @@ void AnimationHost::SetAnimationEvents( ...@@ -517,25 +491,11 @@ void AnimationHost::SetAnimationEvents(
for (size_t event_index = 0; event_index < events->events_.size(); for (size_t event_index = 0; event_index < events->events_.size();
++event_index) { ++event_index) {
AnimationEvent& event = events->events_[event_index]; AnimationEvent& event = events->events_[event_index];
AnimationTimeline* timeline = GetTimelineById(event.uid.timeline_id);
// TODO(http://crbug.com/1013727): Make all animation events use animation if (timeline) {
// id to do targeting; Animation* animation = timeline->GetAnimationById(event.uid.animation_id);
if (event.worklet_animation_id) {
DCHECK(event.type == AnimationEvent::TIME_UPDATED);
// Look up worklet animation in ticking animations.
WorkletAnimation* animation =
FindWorkletAnimation(event.worklet_animation_id);
if (animation) if (animation)
animation->NotifyLocalTimeUpdated(event); animation->DispatchAndDelegateAnimationEvent(event);
} else {
// Use the map of all ElementAnimations, not just ticking animations,
// since non-ticking animations may still receive events for impl-only
// animations.
const ElementToAnimationsMap& all_element_animations =
element_to_animations_map_;
auto iter = all_element_animations.find(event.element_id);
if (iter != all_element_animations.end())
DispatchAnimationEventToElementAnimations((*iter).second.get(), event);
} }
} }
} }
......
...@@ -175,41 +175,6 @@ void ElementAnimations::RemoveKeyframeEffectsFromTicking() const { ...@@ -175,41 +175,6 @@ void ElementAnimations::RemoveKeyframeEffectsFromTicking() const {
keyframe_effect.RemoveFromTicking(); keyframe_effect.RemoveFromTicking();
} }
void ElementAnimations::NotifyAnimationStarted(const AnimationEvent& event) {
DCHECK(!event.is_impl_only);
for (auto& keyframe_effect : keyframe_effects_list_) {
if (keyframe_effect.NotifyKeyframeModelStarted(event))
break;
}
}
void ElementAnimations::NotifyAnimationFinished(const AnimationEvent& event) {
DCHECK(!event.is_impl_only);
for (auto& keyframe_effect : keyframe_effects_list_) {
if (keyframe_effect.NotifyKeyframeModelFinished(event))
break;
}
}
void ElementAnimations::NotifyAnimationTakeover(const AnimationEvent& event) {
DCHECK(!event.is_impl_only);
DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
for (auto& keyframe_effect : keyframe_effects_list_)
keyframe_effect.NotifyKeyframeModelTakeover(event);
}
void ElementAnimations::NotifyAnimationAborted(const AnimationEvent& event) {
DCHECK(!event.is_impl_only);
for (auto& keyframe_effect : keyframe_effects_list_) {
if (keyframe_effect.NotifyKeyframeModelAborted(event))
break;
}
UpdateClientAnimationState();
}
bool ElementAnimations::AnimationsPreserveAxisAlignment() const { bool ElementAnimations::AnimationsPreserveAxisAlignment() const {
for (auto& keyframe_effect : keyframe_effects_list_) { for (auto& keyframe_effect : keyframe_effects_list_) {
if (!keyframe_effect.AnimationsPreserveAxisAlignment()) if (!keyframe_effect.AnimationsPreserveAxisAlignment())
......
...@@ -26,7 +26,6 @@ class FilterOperations; ...@@ -26,7 +26,6 @@ class FilterOperations;
class KeyframeEffect; class KeyframeEffect;
class TransformOperations; class TransformOperations;
enum class ElementListType; enum class ElementListType;
struct AnimationEvent;
// An ElementAnimations owns a list of all KeyframeEffects attached to a single // An ElementAnimations owns a list of all KeyframeEffects attached to a single
// target (represented by an ElementId). // target (represented by an ElementId).
...@@ -89,11 +88,6 @@ class CC_ANIMATION_EXPORT ElementAnimations ...@@ -89,11 +88,6 @@ class CC_ANIMATION_EXPORT ElementAnimations
bool IsCurrentlyAnimatingProperty(TargetProperty::Type target_property, bool IsCurrentlyAnimatingProperty(TargetProperty::Type target_property,
ElementListType list_type) const; ElementListType list_type) const;
void NotifyAnimationStarted(const AnimationEvent& event);
void NotifyAnimationFinished(const AnimationEvent& event);
void NotifyAnimationAborted(const AnimationEvent& event);
void NotifyAnimationTakeover(const AnimationEvent& event);
bool has_element_in_active_list() const { bool has_element_in_active_list() const {
return has_element_in_active_list_; return has_element_in_active_list_;
} }
......
This diff is collapsed.
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "cc/animation/animation.h" #include "cc/animation/animation.h"
#include "cc/animation/animation_curve.h" #include "cc/animation/animation_curve.h"
#include "cc/animation/animation_host.h" #include "cc/animation/animation_host.h"
#include "cc/animation/animation_timeline.h"
#include "cc/animation/keyframe_model.h" #include "cc/animation/keyframe_model.h"
#include "cc/animation/scroll_offset_animation_curve.h" #include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/transform_operations.h" #include "cc/animation/transform_operations.h"
...@@ -394,62 +395,65 @@ void KeyframeEffect::KeyframeModelAdded() { ...@@ -394,62 +395,65 @@ void KeyframeEffect::KeyframeModelAdded() {
element_animations_->UpdateClientAnimationState(); element_animations_->UpdateClientAnimationState();
} }
bool KeyframeEffect::NotifyKeyframeModelStarted(const AnimationEvent& event) { bool KeyframeEffect::DispatchAnimationEventToKeyframeModel(
const AnimationEvent& event) {
DCHECK(!event.is_impl_only); DCHECK(!event.is_impl_only);
for (auto& keyframe_model : keyframe_models_) { KeyframeModel* keyframe_model = GetKeyframeModelById(event.uid.model_id);
if (keyframe_model->group() == event.group_id && bool dispatched = false;
keyframe_model->target_property_id() == event.target_property && switch (event.type) {
keyframe_model->needs_synchronized_start_time()) { case AnimationEvent::STARTED:
keyframe_model->set_needs_synchronized_start_time(false); if (keyframe_model && keyframe_model->needs_synchronized_start_time()) {
if (!keyframe_model->has_set_start_time()) keyframe_model->set_needs_synchronized_start_time(false);
keyframe_model->set_start_time(event.monotonic_time); if (!keyframe_model->has_set_start_time())
animation_->NotifyKeyframeModelStarted(event); keyframe_model->set_start_time(event.monotonic_time);
return true; dispatched = true;
} }
} break;
return false;
}
bool KeyframeEffect::NotifyKeyframeModelFinished(const AnimationEvent& event) {
DCHECK(!event.is_impl_only);
for (auto& keyframe_model : keyframe_models_) {
if (keyframe_model->group() == event.group_id &&
keyframe_model->target_property_id() == event.target_property) {
keyframe_model->set_received_finished_event(true);
animation_->NotifyKeyframeModelFinished(event);
return true;
}
}
// This is for the case when a keyframe_model is already removed on main
// thread, but the impl version of it sent a finished event and is now waiting
// for deletion. We would need to delete that keyframe_model during push
// properties.
SetNeedsPushProperties();
return false;
}
void KeyframeEffect::NotifyKeyframeModelTakeover(const AnimationEvent& event) { case AnimationEvent::FINISHED:
DCHECK(!event.is_impl_only); if (keyframe_model) {
keyframe_model->set_received_finished_event(true);
dispatched = true;
} else {
// This is for the case when a keyframe_model is already removed on main
// thread, but the impl version of it sent a finished event and is now
// waiting for deletion. We would need to delete that keyframe_model
// during push properties.
SetNeedsPushProperties();
}
break;
// We need to purge KeyframeModels marked for deletion on CT. case AnimationEvent::ABORTED:
SetNeedsPushProperties(); if (keyframe_model) {
keyframe_model->SetRunState(KeyframeModel::ABORTED,
event.monotonic_time);
keyframe_model->set_received_finished_event(true);
dispatched = true;
ElementAnimations* element_animations =
animation_->animation_host()
->GetElementAnimationsForElementId(element_id())
.get();
if (element_animations)
element_animations->UpdateClientAnimationState();
}
break;
animation_->NotifyKeyframeModelTakeover(event); case AnimationEvent::TAKEOVER:
} // TODO(crbug.com/1018213): Routing TAKEOVER events is broken.
// We need to purge KeyframeModels marked for deletion on CT.
SetNeedsPushProperties();
dispatched = true;
break;
bool KeyframeEffect::NotifyKeyframeModelAborted(const AnimationEvent& event) { case AnimationEvent::TIME_UPDATED:
DCHECK(!event.is_impl_only); // TIME_UPDATED events are used to synchronize effect time between cc and
for (auto& keyframe_model : keyframe_models_) { // main thread worklet animations. Keyframe models are not involved in
if (keyframe_model->group() == event.group_id && // this process.
keyframe_model->target_property_id() == event.target_property) { NOTREACHED();
keyframe_model->SetRunState(KeyframeModel::ABORTED, event.monotonic_time); break;
keyframe_model->set_received_finished_event(true);
animation_->NotifyKeyframeModelAborted(event);
return true;
}
} }
return false; return dispatched;
} }
bool KeyframeEffect::HasTickingKeyframeModel() const { bool KeyframeEffect::HasTickingKeyframeModel() const {
...@@ -1082,7 +1086,10 @@ void KeyframeEffect::GenerateEvent(AnimationEvents* events, ...@@ -1082,7 +1086,10 @@ void KeyframeEffect::GenerateEvent(AnimationEvents* events,
if (!events) if (!events)
return; return;
AnimationEvent event(type, element_id_, keyframe_model.group(), AnimationEvent event(type,
{animation_->animation_timeline()->id(),
animation_->id(), id(), keyframe_model.id()},
keyframe_model.group(),
keyframe_model.target_property_id(), monotonic_time); keyframe_model.target_property_id(), monotonic_time);
event.is_impl_only = keyframe_model.is_impl_only(); event.is_impl_only = keyframe_model.is_impl_only();
if (!event.is_impl_only) { if (!event.is_impl_only) {
...@@ -1090,23 +1097,7 @@ void KeyframeEffect::GenerateEvent(AnimationEvents* events, ...@@ -1090,23 +1097,7 @@ void KeyframeEffect::GenerateEvent(AnimationEvents* events,
return; return;
} }
// For impl only animations notify delegate directly, do not record the event. // For impl only animations notify delegate directly, do not record the event.
switch (type) { animation_->DispatchAndDelegateAnimationEvent(event);
case AnimationEvent::FINISHED:
animation_->NotifyKeyframeModelFinished(event);
break;
case AnimationEvent::STARTED:
animation_->NotifyKeyframeModelStarted(event);
break;
case AnimationEvent::ABORTED:
animation_->NotifyKeyframeModelAborted(event);
break;
case AnimationEvent::TAKEOVER:
case AnimationEvent::TIME_UPDATED:
// We never expect to receive a TAKEOVER or TIME_UPDATED
// notifications on impl only animations.
NOTREACHED();
break;
}
} }
void KeyframeEffect::GenerateTakeoverEventForScrollAnimation( void KeyframeEffect::GenerateTakeoverEventForScrollAnimation(
...@@ -1117,17 +1108,28 @@ void KeyframeEffect::GenerateTakeoverEventForScrollAnimation( ...@@ -1117,17 +1108,28 @@ void KeyframeEffect::GenerateTakeoverEventForScrollAnimation(
if (!events) if (!events)
return; return;
AnimationEvent takeover_event( AnimationEvent takeover_event(AnimationEvent::TAKEOVER,
AnimationEvent::TAKEOVER, element_id_, keyframe_model.group(), {animation_->animation_timeline()->id(),
keyframe_model.target_property_id(), monotonic_time); animation_->id(), id(), keyframe_model.id()},
keyframe_model.group(),
keyframe_model.target_property_id(),
monotonic_time);
takeover_event.animation_start_time = keyframe_model.start_time(); takeover_event.animation_start_time = keyframe_model.start_time();
const ScrollOffsetAnimationCurve* scroll_offset_animation_curve = const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
keyframe_model.curve()->ToScrollOffsetAnimationCurve(); keyframe_model.curve()->ToScrollOffsetAnimationCurve();
takeover_event.curve = scroll_offset_animation_curve->Clone(); takeover_event.curve = scroll_offset_animation_curve->Clone();
// Notify the compositor that the animation is finished.
animation_->NotifyKeyframeModelFinished(takeover_event);
// Notify main thread. // Notify main thread.
events->events_.push_back(takeover_event); events->events_.push_back(takeover_event);
AnimationEvent finished_event(AnimationEvent::FINISHED,
{animation_->animation_timeline()->id(),
animation_->id(), id(), keyframe_model.id()},
keyframe_model.group(),
keyframe_model.target_property_id(),
monotonic_time);
// Notify the compositor that the animation is finished.
finished_event.is_impl_only = true;
animation_->DispatchAndDelegateAnimationEvent(finished_event);
} }
} // namespace cc } // namespace cc
...@@ -105,14 +105,9 @@ class CC_ANIMATION_EXPORT KeyframeEffect { ...@@ -105,14 +105,9 @@ class CC_ANIMATION_EXPORT KeyframeEffect {
void KeyframeModelAdded(); void KeyframeModelAdded();
// The following methods should be called to notify the KeyframeEffect that // Dispatches animation event to a keyframe model specified as part of the
// an animation event has been received for the same target (ElementId) as // event. Returns true if the event is dispatched, false otherwise.
// this keyframe_effect. If the event matches a KeyframeModel owned by this bool DispatchAnimationEventToKeyframeModel(const AnimationEvent& event);
// 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 // Returns true if there are any KeyframeModels that have neither finished
// nor aborted. // nor aborted.
......
...@@ -95,13 +95,16 @@ void SingleKeyframeEffectAnimation::AbortKeyframeModel(int keyframe_model_id) { ...@@ -95,13 +95,16 @@ void SingleKeyframeEffectAnimation::AbortKeyframeModel(int keyframe_model_id) {
GetKeyframeEffect()->id()); GetKeyframeEffect()->id());
} }
bool SingleKeyframeEffectAnimation::NotifyKeyframeModelFinishedForTesting( void SingleKeyframeEffectAnimation::NotifyKeyframeModelFinishedForTesting(
int timeline_id,
int keyframe_model_id,
TargetProperty::Type target_property, TargetProperty::Type target_property,
int group_id) { int group_id) {
AnimationEvent event(AnimationEvent::FINISHED, AnimationEvent event(
GetKeyframeEffect()->element_id(), group_id, AnimationEvent::FINISHED,
target_property, base::TimeTicks()); {timeline_id, id(), GetKeyframeEffect()->id(), keyframe_model_id},
return GetKeyframeEffect()->NotifyKeyframeModelFinished(event); group_id, target_property, base::TimeTicks());
DispatchAndDelegateAnimationEvent(event);
} }
KeyframeModel* SingleKeyframeEffectAnimation::GetKeyframeModel( KeyframeModel* SingleKeyframeEffectAnimation::GetKeyframeModel(
......
...@@ -50,7 +50,9 @@ class CC_ANIMATION_EXPORT SingleKeyframeEffectAnimation : public Animation { ...@@ -50,7 +50,9 @@ class CC_ANIMATION_EXPORT SingleKeyframeEffectAnimation : public Animation {
virtual void RemoveKeyframeModel(int keyframe_model_id); virtual void RemoveKeyframeModel(int keyframe_model_id);
void AbortKeyframeModel(int keyframe_model_id); void AbortKeyframeModel(int keyframe_model_id);
bool NotifyKeyframeModelFinishedForTesting( void NotifyKeyframeModelFinishedForTesting(
int timeline_id,
int keyframe_model_id,
TargetProperty::Type target_property, TargetProperty::Type target_property,
int group_id); int group_id);
KeyframeModel* GetKeyframeModel(TargetProperty::Type target_property) const; KeyframeModel* GetKeyframeModel(TargetProperty::Type target_property) const;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <utility> #include <utility>
#include "cc/animation/animation_delegate.h" #include "cc/animation/animation_delegate.h"
#include "cc/animation/animation_id_provider.h" #include "cc/animation/animation_id_provider.h"
#include "cc/animation/animation_timeline.h"
#include "cc/animation/keyframe_effect.h" #include "cc/animation/keyframe_effect.h"
#include "cc/animation/scroll_timeline.h" #include "cc/animation/scroll_timeline.h"
#include "cc/trees/animation_effect_timings.h" #include "cc/trees/animation_effect_timings.h"
...@@ -113,7 +114,7 @@ void WorkletAnimation::UpdateState(bool start_ready_animations, ...@@ -113,7 +114,7 @@ void WorkletAnimation::UpdateState(bool start_ready_animations,
AnimationEvents* events) { AnimationEvents* events) {
Animation::UpdateState(start_ready_animations, events); Animation::UpdateState(start_ready_animations, events);
if (last_synced_local_time_ != local_time_) { if (last_synced_local_time_ != local_time_) {
AnimationEvent event(worklet_animation_id_, local_time_); AnimationEvent event(animation_timeline()->id(), id_, local_time_);
// TODO(http://crbug.com/1013654): Instead of pushing multiple events per // TODO(http://crbug.com/1013654): Instead of pushing multiple events per
// single main frame, push just the recent one to be handled by next main // single main frame, push just the recent one to be handled by next main
// frame. // frame.
...@@ -201,11 +202,6 @@ void WorkletAnimation::SetOutputState( ...@@ -201,11 +202,6 @@ void WorkletAnimation::SetOutputState(
local_time_ = state.local_times[0]; local_time_ = state.local_times[0];
} }
void WorkletAnimation::NotifyLocalTimeUpdated(const AnimationEvent& event) {
if (animation_delegate_)
animation_delegate_->NotifyLocalTimeUpdated(event.local_time);
}
void WorkletAnimation::SetPlaybackRate(double playback_rate) { void WorkletAnimation::SetPlaybackRate(double playback_rate) {
if (playback_rate == playback_rate_) if (playback_rate == playback_rate_)
return; return;
......
...@@ -92,7 +92,6 @@ class CC_ANIMATION_EXPORT WorkletAnimation final ...@@ -92,7 +92,6 @@ class CC_ANIMATION_EXPORT WorkletAnimation final
} }
void RemoveKeyframeModel(int keyframe_model_id) override; void RemoveKeyframeModel(int keyframe_model_id) override;
void NotifyLocalTimeUpdated(const AnimationEvent& event);
void ReleasePendingTreeLock() { has_pending_tree_lock_ = false; } void ReleasePendingTreeLock() { has_pending_tree_lock_ = false; }
......
...@@ -129,7 +129,7 @@ TEST_F(WorkletAnimationTest, AnimationEventLocalTimeUpdate) { ...@@ -129,7 +129,7 @@ TEST_F(WorkletAnimationTest, AnimationEventLocalTimeUpdate) {
EXPECT_EQ(1u, animation_events->events_.size()); EXPECT_EQ(1u, animation_events->events_.size());
AnimationEvent event = animation_events->events_[0]; AnimationEvent event = animation_events->events_[0];
EXPECT_EQ(AnimationEvent::TIME_UPDATED, event.type); EXPECT_EQ(AnimationEvent::TIME_UPDATED, event.type);
EXPECT_EQ(worklet_animation_id_, event.worklet_animation_id); EXPECT_EQ(worklet_animation_->id(), event.uid.animation_id);
EXPECT_EQ(local_time, event.local_time); EXPECT_EQ(local_time, event.local_time);
// If the state is not updated no more events is generated. // If the state is not updated no more events is generated.
......
...@@ -880,7 +880,9 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationTakeover ...@@ -880,7 +880,9 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationTakeover
scoped_refptr<FakePictureLayer> scroll_layer_; scoped_refptr<FakePictureLayer> scroll_layer_;
}; };
MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationTakeover); // TODO(crbug.com/1018213): [BlinkGenPropertyTrees] Scroll Animation should be
// taken over from cc when scroll is unpromoted.
// MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationTakeover);
// Verifies that an impl-only scroll offset animation gets updated when the // Verifies that an impl-only scroll offset animation gets updated when the
// scroll offset is adjusted on the main thread. // scroll offset is adjusted on the main thread.
......
...@@ -56,27 +56,32 @@ TEST_F(CompositorAnimationTest, NullDelegate) { ...@@ -56,27 +56,32 @@ TEST_F(CompositorAnimationTest, NullDelegate) {
std::unique_ptr<CompositorAnimationDelegateForTesting> delegate( std::unique_ptr<CompositorAnimationDelegateForTesting> delegate(
new CompositorAnimationDelegateForTesting); new CompositorAnimationDelegateForTesting);
std::unique_ptr<CompositorAnimation> animation = auto timeline = std::make_unique<CompositorAnimationTimeline>();
CompositorAnimation::Create(); std::unique_ptr<CompositorAnimationTestClient> client(
new CompositorAnimationTestClient);
CompositorAnimation* animation = client->GetCompositorAnimation();
cc::SingleKeyframeEffectAnimation* cc_animation = animation->CcAnimation(); cc::SingleKeyframeEffectAnimation* cc_animation = animation->CcAnimation();
timeline->AnimationAttached(*client);
int timeline_id = cc_animation->animation_timeline()->id();
auto curve = std::make_unique<CompositorFloatAnimationCurve>(); auto curve = std::make_unique<CompositorFloatAnimationCurve>();
auto keyframe_model = std::make_unique<CompositorKeyframeModel>( auto keyframe_model = std::make_unique<CompositorKeyframeModel>(
*curve, compositor_target_property::TRANSFORM, 0, 1); *curve, compositor_target_property::TRANSFORM, 0, 1);
int keyframe_model_id = keyframe_model->Id();
animation->AddKeyframeModel(std::move(keyframe_model)); animation->AddKeyframeModel(std::move(keyframe_model));
animation->SetAnimationDelegate(delegate.get()); animation->SetAnimationDelegate(delegate.get());
EXPECT_FALSE(delegate->finished_); EXPECT_FALSE(delegate->finished_);
cc_animation->NotifyKeyframeModelFinishedForTesting( cc_animation->NotifyKeyframeModelFinishedForTesting(
compositor_target_property::TRANSFORM, 1); timeline_id, keyframe_model_id, compositor_target_property::TRANSFORM, 1);
EXPECT_TRUE(delegate->finished_); EXPECT_TRUE(delegate->finished_);
delegate->ResetFlags(); delegate->ResetFlags();
animation->SetAnimationDelegate(nullptr); animation->SetAnimationDelegate(nullptr);
cc_animation->NotifyKeyframeModelFinishedForTesting( cc_animation->NotifyKeyframeModelFinishedForTesting(
compositor_target_property::TRANSFORM, 1); timeline_id, keyframe_model_id, compositor_target_property::TRANSFORM, 1);
EXPECT_FALSE(delegate->finished_); EXPECT_FALSE(delegate->finished_);
} }
...@@ -84,30 +89,35 @@ TEST_F(CompositorAnimationTest, NotifyFromCCAfterCompositorAnimationDeletion) { ...@@ -84,30 +89,35 @@ TEST_F(CompositorAnimationTest, NotifyFromCCAfterCompositorAnimationDeletion) {
std::unique_ptr<CompositorAnimationDelegateForTesting> delegate( std::unique_ptr<CompositorAnimationDelegateForTesting> delegate(
new CompositorAnimationDelegateForTesting); new CompositorAnimationDelegateForTesting);
std::unique_ptr<CompositorAnimation> animation = auto timeline = std::make_unique<CompositorAnimationTimeline>();
CompositorAnimation::Create(); std::unique_ptr<CompositorAnimationTestClient> client(
new CompositorAnimationTestClient);
CompositorAnimation* animation = client->GetCompositorAnimation();
scoped_refptr<cc::SingleKeyframeEffectAnimation> cc_animation = scoped_refptr<cc::SingleKeyframeEffectAnimation> cc_animation =
animation->CcAnimation(); animation->CcAnimation();
timeline->AnimationAttached(*client);
int timeline_id = cc_animation->animation_timeline()->id();
auto curve = std::make_unique<CompositorFloatAnimationCurve>(); auto curve = std::make_unique<CompositorFloatAnimationCurve>();
auto keyframe_model = std::make_unique<CompositorKeyframeModel>( auto keyframe_model = std::make_unique<CompositorKeyframeModel>(
*curve, compositor_target_property::OPACITY, 0, 1); *curve, compositor_target_property::OPACITY, 0, 1);
int keyframe_model_id = keyframe_model->Id();
animation->AddKeyframeModel(std::move(keyframe_model)); animation->AddKeyframeModel(std::move(keyframe_model));
animation->SetAnimationDelegate(delegate.get()); animation->SetAnimationDelegate(delegate.get());
EXPECT_FALSE(delegate->finished_); EXPECT_FALSE(delegate->finished_);
cc_animation->NotifyKeyframeModelFinishedForTesting( cc_animation->NotifyKeyframeModelFinishedForTesting(
compositor_target_property::OPACITY, 1); timeline_id, keyframe_model_id, compositor_target_property::OPACITY, 1);
EXPECT_TRUE(delegate->finished_); EXPECT_TRUE(delegate->finished_);
delegate->finished_ = false; delegate->finished_ = false;
// Delete CompositorAnimation. ccAnimation stays alive. // Delete CompositorAnimation. ccAnimation stays alive.
animation = nullptr; client = nullptr;
// No notifications. Doesn't crash. // No notifications. Doesn't crash.
cc_animation->NotifyKeyframeModelFinishedForTesting( cc_animation->NotifyKeyframeModelFinishedForTesting(
compositor_target_property::OPACITY, 1); timeline_id, keyframe_model_id, compositor_target_property::OPACITY, 1);
EXPECT_FALSE(delegate->finished_); EXPECT_FALSE(delegate->finished_);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment