1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/animation/animation_host.h"
9 #include "cc/animation/animation_delegate.h"
10 #include "cc/animation/animation_id_provider.h"
11 #include "cc/animation/animation_player.h"
12 #include "cc/animation/animation_registrar.h"
13 #include "cc/animation/animation_timeline.h"
14 #include "cc/animation/element_animations.h"
15 #include "cc/animation/scroll_offset_animation_curve.h"
16 #include "cc/animation/timing_function.h"
17 #include "ui/gfx/geometry/box_f.h"
18 #include "ui/gfx/geometry/scroll_offset.h"
22 class AnimationHost::ScrollOffsetAnimations
: public AnimationDelegate
{
24 explicit ScrollOffsetAnimations(AnimationHost
* animation_host
)
25 : animation_host_(animation_host
),
26 scroll_offset_timeline_(
27 AnimationTimeline::Create(AnimationIdProvider::NextTimelineId())),
28 scroll_offset_animation_player_(
29 AnimationPlayer::Create(AnimationIdProvider::NextPlayerId())) {
30 scroll_offset_timeline_
->set_is_impl_only(true);
31 scroll_offset_animation_player_
->set_layer_animation_delegate(this);
33 animation_host_
->AddAnimationTimeline(scroll_offset_timeline_
.get());
34 scroll_offset_timeline_
->AttachPlayer(
35 scroll_offset_animation_player_
.get());
38 ~ScrollOffsetAnimations() override
{
39 scroll_offset_timeline_
->DetachPlayer(
40 scroll_offset_animation_player_
.get());
41 animation_host_
->RemoveAnimationTimeline(scroll_offset_timeline_
.get());
44 void ScrollAnimationCreate(int layer_id
,
45 const gfx::ScrollOffset
& target_offset
,
46 const gfx::ScrollOffset
& current_offset
) {
47 scoped_ptr
<ScrollOffsetAnimationCurve
> curve
=
48 ScrollOffsetAnimationCurve::Create(target_offset
,
49 EaseInOutTimingFunction::Create());
50 curve
->SetInitialValue(current_offset
);
52 scoped_ptr
<Animation
> animation
= Animation::Create(
53 curve
.Pass(), AnimationIdProvider::NextAnimationId(),
54 AnimationIdProvider::NextGroupId(), Animation::SCROLL_OFFSET
);
55 animation
->set_is_impl_only(true);
57 DCHECK(scroll_offset_animation_player_
);
58 DCHECK(scroll_offset_animation_player_
->animation_timeline());
60 if (scroll_offset_animation_player_
->layer_id() != layer_id
) {
61 if (scroll_offset_animation_player_
->layer_id())
62 scroll_offset_animation_player_
->DetachLayer();
63 scroll_offset_animation_player_
->AttachLayer(layer_id
);
66 scroll_offset_animation_player_
->AddAnimation(animation
.Pass());
69 bool ScrollAnimationUpdateTarget(int layer_id
,
70 const gfx::Vector2dF
& scroll_delta
,
71 const gfx::ScrollOffset
& max_scroll_offset
,
72 base::TimeTicks frame_monotonic_time
) {
73 DCHECK(scroll_offset_animation_player_
);
74 DCHECK_EQ(layer_id
, scroll_offset_animation_player_
->layer_id());
76 Animation
* animation
= scroll_offset_animation_player_
->element_animations()
77 ->layer_animation_controller()
78 ->GetAnimation(Animation::SCROLL_OFFSET
);
80 scroll_offset_animation_player_
->DetachLayer();
84 ScrollOffsetAnimationCurve
* curve
=
85 animation
->curve()->ToScrollOffsetAnimationCurve();
87 gfx::ScrollOffset new_target
=
88 gfx::ScrollOffsetWithDelta(curve
->target_value(), scroll_delta
);
89 new_target
.SetToMax(gfx::ScrollOffset());
90 new_target
.SetToMin(max_scroll_offset
);
92 curve
->UpdateTarget(animation
->TrimTimeToCurrentIteration(
93 frame_monotonic_time
).InSecondsF(),
99 // AnimationDelegate implementation.
100 void NotifyAnimationStarted(base::TimeTicks monotonic_time
,
101 Animation::TargetProperty target_property
,
102 int group
) override
{}
103 void NotifyAnimationFinished(base::TimeTicks monotonic_time
,
104 Animation::TargetProperty target_property
,
105 int group
) override
{
106 DCHECK_EQ(target_property
, Animation::SCROLL_OFFSET
);
107 DCHECK(animation_host_
->mutator_host_client());
108 animation_host_
->mutator_host_client()->ScrollOffsetAnimationFinished();
112 AnimationHost
* animation_host_
;
113 scoped_refptr
<AnimationTimeline
> scroll_offset_timeline_
;
115 // We have just one player for impl-only scroll offset animations.
116 // I.e. only one layer can have an impl-only scroll offset animation at
118 scoped_refptr
<AnimationPlayer
> scroll_offset_animation_player_
;
120 DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimations
);
123 scoped_ptr
<AnimationHost
> AnimationHost::Create(
124 ThreadInstance thread_instance
) {
125 return make_scoped_ptr(new AnimationHost(thread_instance
));
128 AnimationHost::AnimationHost(ThreadInstance thread_instance
)
129 : animation_registrar_(AnimationRegistrar::Create()),
130 mutator_host_client_(nullptr),
131 thread_instance_(thread_instance
) {
132 if (thread_instance_
== ThreadInstance::IMPL
)
133 scroll_offset_animations_
=
134 make_scoped_ptr(new ScrollOffsetAnimations(this));
137 AnimationHost::~AnimationHost() {
138 scroll_offset_animations_
= nullptr;
141 DCHECK(!mutator_host_client());
142 DCHECK(layer_to_element_animations_map_
.empty());
145 AnimationTimeline
* AnimationHost::GetTimelineById(int timeline_id
) const {
146 for (auto& timeline
: timelines_
)
147 if (timeline
->id() == timeline_id
)
148 return timeline
.get();
152 void AnimationHost::ClearTimelines() {
153 EraseTimelines(timelines_
.begin(), timelines_
.end());
156 void AnimationHost::EraseTimelines(AnimationTimelineList::iterator begin
,
157 AnimationTimelineList::iterator end
) {
158 for (auto i
= begin
; i
!= end
; ++i
) {
160 timeline
->ClearPlayers();
161 timeline
->SetAnimationHost(nullptr);
164 timelines_
.erase(begin
, end
);
167 void AnimationHost::AddAnimationTimeline(
168 scoped_refptr
<AnimationTimeline
> timeline
) {
169 timeline
->SetAnimationHost(this);
170 timelines_
.push_back(timeline
);
173 void AnimationHost::RemoveAnimationTimeline(
174 scoped_refptr
<AnimationTimeline
> timeline
) {
175 for (auto iter
= timelines_
.begin(); iter
!= timelines_
.end(); ++iter
) {
176 if (iter
->get() != timeline
)
179 EraseTimelines(iter
, iter
+ 1);
184 void AnimationHost::RegisterLayer(int layer_id
, LayerTreeType tree_type
) {
185 ElementAnimations
* element_animations
=
186 GetElementAnimationsForLayerId(layer_id
);
187 if (element_animations
)
188 element_animations
->LayerRegistered(layer_id
, tree_type
);
191 void AnimationHost::UnregisterLayer(int layer_id
, LayerTreeType tree_type
) {
192 ElementAnimations
* element_animations
=
193 GetElementAnimationsForLayerId(layer_id
);
194 if (element_animations
)
195 element_animations
->LayerUnregistered(layer_id
, tree_type
);
198 void AnimationHost::RegisterPlayerForLayer(int layer_id
,
199 AnimationPlayer
* player
) {
203 ElementAnimations
* element_animations
=
204 GetElementAnimationsForLayerId(layer_id
);
205 if (!element_animations
) {
206 auto new_element_animations
= ElementAnimations::Create(this);
207 element_animations
= new_element_animations
.get();
209 layer_to_element_animations_map_
.add(layer_id
,
210 new_element_animations
.Pass());
211 element_animations
->CreateLayerAnimationController(layer_id
);
214 DCHECK(element_animations
);
215 element_animations
->AddPlayer(player
);
218 void AnimationHost::UnregisterPlayerForLayer(int layer_id
,
219 AnimationPlayer
* player
) {
223 ElementAnimations
* element_animations
=
224 GetElementAnimationsForLayerId(layer_id
);
225 DCHECK(element_animations
);
226 element_animations
->RemovePlayer(player
);
228 if (element_animations
->IsEmpty()) {
229 element_animations
->DestroyLayerAnimationController();
230 layer_to_element_animations_map_
.erase(layer_id
);
231 element_animations
= nullptr;
235 void AnimationHost::SetMutatorHostClient(MutatorHostClient
* client
) {
236 if (mutator_host_client_
== client
)
239 mutator_host_client_
= client
;
242 void AnimationHost::SetNeedsCommit() {
243 DCHECK(mutator_host_client_
);
244 mutator_host_client_
->SetMutatorsNeedCommit();
247 void AnimationHost::PushPropertiesTo(AnimationHost
* host_impl
) {
248 PushTimelinesToImplThread(host_impl
);
249 RemoveTimelinesFromImplThread(host_impl
);
250 PushPropertiesToImplThread(host_impl
);
253 void AnimationHost::PushTimelinesToImplThread(AnimationHost
* host_impl
) const {
254 for (auto& timeline
: timelines_
) {
255 AnimationTimeline
* timeline_impl
=
256 host_impl
->GetTimelineById(timeline
->id());
260 scoped_refptr
<AnimationTimeline
> to_add
= timeline
->CreateImplInstance();
261 host_impl
->AddAnimationTimeline(to_add
.get());
265 void AnimationHost::RemoveTimelinesFromImplThread(
266 AnimationHost
* host_impl
) const {
267 AnimationTimelineList
& timelines_impl
= host_impl
->timelines_
;
270 std::partition(timelines_impl
.begin(), timelines_impl
.end(),
271 [this](AnimationTimelineList::value_type timeline_impl
) {
272 return timeline_impl
->is_impl_only() ||
273 GetTimelineById(timeline_impl
->id());
276 host_impl
->EraseTimelines(to_erase
, timelines_impl
.end());
279 void AnimationHost::PushPropertiesToImplThread(AnimationHost
* host_impl
) {
280 // Firstly, sync all players with impl thread to create ElementAnimations and
281 // layer animation controllers.
282 for (auto& timeline
: timelines_
) {
283 AnimationTimeline
* timeline_impl
=
284 host_impl
->GetTimelineById(timeline
->id());
286 timeline
->PushPropertiesTo(timeline_impl
);
289 // Secondly, sync properties for created layer animation controllers.
290 for (auto& kv
: layer_to_element_animations_map_
) {
291 ElementAnimations
* element_animations
= kv
.second
;
292 ElementAnimations
* element_animations_impl
=
293 host_impl
->GetElementAnimationsForLayerId(kv
.first
);
294 if (element_animations_impl
)
295 element_animations
->PushPropertiesTo(element_animations_impl
);
299 LayerAnimationController
* AnimationHost::GetControllerForLayerId(
300 int layer_id
) const {
301 const ElementAnimations
* element_animations
=
302 GetElementAnimationsForLayerId(layer_id
);
303 if (!element_animations
)
306 return element_animations
->layer_animation_controller();
309 ElementAnimations
* AnimationHost::GetElementAnimationsForLayerId(
310 int layer_id
) const {
312 auto iter
= layer_to_element_animations_map_
.find(layer_id
);
313 return iter
== layer_to_element_animations_map_
.end() ? nullptr
317 void AnimationHost::SetSupportsScrollAnimations(
318 bool supports_scroll_animations
) {
319 animation_registrar_
->set_supports_scroll_animations(
320 supports_scroll_animations
);
323 bool AnimationHost::SupportsScrollAnimations() const {
324 return animation_registrar_
->supports_scroll_animations();
327 bool AnimationHost::NeedsAnimateLayers() const {
328 return animation_registrar_
->needs_animate_layers();
331 bool AnimationHost::ActivateAnimations() {
332 return animation_registrar_
->ActivateAnimations();
335 bool AnimationHost::AnimateLayers(base::TimeTicks monotonic_time
) {
336 return animation_registrar_
->AnimateLayers(monotonic_time
);
339 bool AnimationHost::UpdateAnimationState(bool start_ready_animations
,
340 AnimationEventsVector
* events
) {
341 return animation_registrar_
->UpdateAnimationState(start_ready_animations
,
345 scoped_ptr
<AnimationEventsVector
> AnimationHost::CreateEvents() {
346 return animation_registrar_
->CreateEvents();
349 void AnimationHost::SetAnimationEvents(
350 scoped_ptr
<AnimationEventsVector
> events
) {
351 return animation_registrar_
->SetAnimationEvents(events
.Pass());
354 bool AnimationHost::ScrollOffsetAnimationWasInterrupted(int layer_id
) const {
355 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
356 return controller
? controller
->scroll_offset_animation_was_interrupted()
360 static LayerAnimationController::ObserverType
ObserverTypeFromTreeType(
361 LayerTreeType tree_type
) {
362 return tree_type
== LayerTreeType::ACTIVE
363 ? LayerAnimationController::ObserverType::ACTIVE
364 : LayerAnimationController::ObserverType::PENDING
;
367 bool AnimationHost::IsAnimatingFilterProperty(int layer_id
,
368 LayerTreeType tree_type
) const {
369 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
371 ? controller
->IsCurrentlyAnimatingProperty(
372 Animation::FILTER
, ObserverTypeFromTreeType(tree_type
))
376 bool AnimationHost::IsAnimatingOpacityProperty(int layer_id
,
377 LayerTreeType tree_type
) const {
378 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
380 ? controller
->IsCurrentlyAnimatingProperty(
381 Animation::OPACITY
, ObserverTypeFromTreeType(tree_type
))
385 bool AnimationHost::IsAnimatingTransformProperty(
387 LayerTreeType tree_type
) const {
388 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
390 ? controller
->IsCurrentlyAnimatingProperty(
391 Animation::TRANSFORM
, ObserverTypeFromTreeType(tree_type
))
395 bool AnimationHost::HasPotentiallyRunningFilterAnimation(
397 LayerTreeType tree_type
) const {
398 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
400 ? controller
->IsPotentiallyAnimatingProperty(
401 Animation::FILTER
, ObserverTypeFromTreeType(tree_type
))
405 bool AnimationHost::HasPotentiallyRunningOpacityAnimation(
407 LayerTreeType tree_type
) const {
408 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
410 ? controller
->IsPotentiallyAnimatingProperty(
411 Animation::OPACITY
, ObserverTypeFromTreeType(tree_type
))
415 bool AnimationHost::HasPotentiallyRunningTransformAnimation(
417 LayerTreeType tree_type
) const {
418 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
420 ? controller
->IsPotentiallyAnimatingProperty(
421 Animation::TRANSFORM
, ObserverTypeFromTreeType(tree_type
))
425 bool AnimationHost::HasAnyAnimationTargetingProperty(
427 Animation::TargetProperty property
) const {
428 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
432 return !!controller
->GetAnimation(property
);
435 bool AnimationHost::FilterIsAnimatingOnImplOnly(int layer_id
) const {
436 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
440 Animation
* animation
= controller
->GetAnimation(Animation::FILTER
);
441 return animation
&& animation
->is_impl_only();
444 bool AnimationHost::OpacityIsAnimatingOnImplOnly(int layer_id
) const {
445 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
449 Animation
* animation
= controller
->GetAnimation(Animation::OPACITY
);
450 return animation
&& animation
->is_impl_only();
453 bool AnimationHost::TransformIsAnimatingOnImplOnly(int layer_id
) const {
454 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
458 Animation
* animation
= controller
->GetAnimation(Animation::TRANSFORM
);
459 return animation
&& animation
->is_impl_only();
462 bool AnimationHost::HasFilterAnimationThatInflatesBounds(int layer_id
) const {
463 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
464 return controller
? controller
->HasFilterAnimationThatInflatesBounds()
468 bool AnimationHost::HasTransformAnimationThatInflatesBounds(
469 int layer_id
) const {
470 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
471 return controller
? controller
->HasTransformAnimationThatInflatesBounds()
475 bool AnimationHost::HasAnimationThatInflatesBounds(int layer_id
) const {
476 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
477 return controller
? controller
->HasAnimationThatInflatesBounds() : false;
480 bool AnimationHost::FilterAnimationBoundsForBox(int layer_id
,
481 const gfx::BoxF
& box
,
482 gfx::BoxF
* bounds
) const {
483 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
484 return controller
? controller
->FilterAnimationBoundsForBox(box
, bounds
)
488 bool AnimationHost::TransformAnimationBoundsForBox(int layer_id
,
489 const gfx::BoxF
& box
,
490 gfx::BoxF
* bounds
) const {
491 *bounds
= gfx::BoxF();
492 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
493 return controller
? controller
->TransformAnimationBoundsForBox(box
, bounds
)
497 bool AnimationHost::HasOnlyTranslationTransforms(
499 LayerTreeType tree_type
) const {
500 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
502 ? controller
->HasOnlyTranslationTransforms(
503 ObserverTypeFromTreeType(tree_type
))
507 bool AnimationHost::AnimationsPreserveAxisAlignment(int layer_id
) const {
508 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
509 return controller
? controller
->AnimationsPreserveAxisAlignment() : true;
512 bool AnimationHost::MaximumTargetScale(int layer_id
,
513 LayerTreeType tree_type
,
514 float* max_scale
) const {
516 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
518 ? controller
->MaximumTargetScale(
519 ObserverTypeFromTreeType(tree_type
), max_scale
)
523 bool AnimationHost::AnimationStartScale(int layer_id
,
524 LayerTreeType tree_type
,
525 float* start_scale
) const {
527 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
529 ? controller
->AnimationStartScale(
530 ObserverTypeFromTreeType(tree_type
), start_scale
)
534 bool AnimationHost::HasAnyAnimation(int layer_id
) const {
535 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
536 return controller
? controller
->has_any_animation() : false;
539 bool AnimationHost::HasActiveAnimation(int layer_id
) const {
540 LayerAnimationController
* controller
= GetControllerForLayerId(layer_id
);
541 return controller
? controller
->HasActiveAnimation() : false;
544 void AnimationHost::ImplOnlyScrollAnimationCreate(
546 const gfx::ScrollOffset
& target_offset
,
547 const gfx::ScrollOffset
& current_offset
) {
548 DCHECK(scroll_offset_animations_
);
549 scroll_offset_animations_
->ScrollAnimationCreate(layer_id
, target_offset
,
553 bool AnimationHost::ImplOnlyScrollAnimationUpdateTarget(
555 const gfx::Vector2dF
& scroll_delta
,
556 const gfx::ScrollOffset
& max_scroll_offset
,
557 base::TimeTicks frame_monotonic_time
) {
558 DCHECK(scroll_offset_animations_
);
559 return scroll_offset_animations_
->ScrollAnimationUpdateTarget(
560 layer_id
, scroll_delta
, max_scroll_offset
, frame_monotonic_time
);