Delete unused downloads page asset.
[chromium-blink-merge.git] / cc / animation / animation_host.cc
bloba9515be20aae6b20ab150c703853e27c5e70f649
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"
7 #include <algorithm>
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"
20 namespace cc {
22 class AnimationHost::ScrollOffsetAnimations : public AnimationDelegate {
23 public:
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);
79 if (!animation) {
80 scroll_offset_animation_player_->DetachLayer();
81 return false;
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(),
94 new_target);
96 return true;
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();
111 private:
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
117 // any given time.
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;
140 ClearTimelines();
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();
149 return nullptr;
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) {
159 auto& timeline = *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)
177 continue;
179 EraseTimelines(iter, iter + 1);
180 break;
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) {
200 DCHECK(layer_id);
201 DCHECK(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) {
220 DCHECK(layer_id);
221 DCHECK(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)
237 return;
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());
257 if (timeline_impl)
258 continue;
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_;
269 auto to_erase =
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());
285 if (timeline_impl)
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)
304 return nullptr;
306 return element_animations->layer_animation_controller();
309 ElementAnimations* AnimationHost::GetElementAnimationsForLayerId(
310 int layer_id) const {
311 DCHECK(layer_id);
312 auto iter = layer_to_element_animations_map_.find(layer_id);
313 return iter == layer_to_element_animations_map_.end() ? nullptr
314 : iter->second;
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,
342 events);
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()
357 : false;
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);
370 return controller
371 ? controller->IsCurrentlyAnimatingProperty(
372 Animation::FILTER, ObserverTypeFromTreeType(tree_type))
373 : false;
376 bool AnimationHost::IsAnimatingOpacityProperty(int layer_id,
377 LayerTreeType tree_type) const {
378 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
379 return controller
380 ? controller->IsCurrentlyAnimatingProperty(
381 Animation::OPACITY, ObserverTypeFromTreeType(tree_type))
382 : false;
385 bool AnimationHost::IsAnimatingTransformProperty(
386 int layer_id,
387 LayerTreeType tree_type) const {
388 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
389 return controller
390 ? controller->IsCurrentlyAnimatingProperty(
391 Animation::TRANSFORM, ObserverTypeFromTreeType(tree_type))
392 : false;
395 bool AnimationHost::HasPotentiallyRunningFilterAnimation(
396 int layer_id,
397 LayerTreeType tree_type) const {
398 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
399 return controller
400 ? controller->IsPotentiallyAnimatingProperty(
401 Animation::FILTER, ObserverTypeFromTreeType(tree_type))
402 : false;
405 bool AnimationHost::HasPotentiallyRunningOpacityAnimation(
406 int layer_id,
407 LayerTreeType tree_type) const {
408 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
409 return controller
410 ? controller->IsPotentiallyAnimatingProperty(
411 Animation::OPACITY, ObserverTypeFromTreeType(tree_type))
412 : false;
415 bool AnimationHost::HasPotentiallyRunningTransformAnimation(
416 int layer_id,
417 LayerTreeType tree_type) const {
418 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
419 return controller
420 ? controller->IsPotentiallyAnimatingProperty(
421 Animation::TRANSFORM, ObserverTypeFromTreeType(tree_type))
422 : false;
425 bool AnimationHost::HasAnyAnimationTargetingProperty(
426 int layer_id,
427 Animation::TargetProperty property) const {
428 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
429 if (!controller)
430 return false;
432 return !!controller->GetAnimation(property);
435 bool AnimationHost::FilterIsAnimatingOnImplOnly(int layer_id) const {
436 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
437 if (!controller)
438 return false;
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);
446 if (!controller)
447 return false;
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);
455 if (!controller)
456 return false;
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()
465 : false;
468 bool AnimationHost::HasTransformAnimationThatInflatesBounds(
469 int layer_id) const {
470 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
471 return controller ? controller->HasTransformAnimationThatInflatesBounds()
472 : false;
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)
485 : false;
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)
494 : true;
497 bool AnimationHost::HasOnlyTranslationTransforms(
498 int layer_id,
499 LayerTreeType tree_type) const {
500 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
501 return controller
502 ? controller->HasOnlyTranslationTransforms(
503 ObserverTypeFromTreeType(tree_type))
504 : true;
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 {
515 *max_scale = 0.f;
516 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
517 return controller
518 ? controller->MaximumTargetScale(
519 ObserverTypeFromTreeType(tree_type), max_scale)
520 : true;
523 bool AnimationHost::AnimationStartScale(int layer_id,
524 LayerTreeType tree_type,
525 float* start_scale) const {
526 *start_scale = 0.f;
527 LayerAnimationController* controller = GetControllerForLayerId(layer_id);
528 return controller
529 ? controller->AnimationStartScale(
530 ObserverTypeFromTreeType(tree_type), start_scale)
531 : true;
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(
545 int layer_id,
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,
550 current_offset);
553 bool AnimationHost::ImplOnlyScrollAnimationUpdateTarget(
554 int layer_id,
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);
563 } // namespace cc