Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(547)

Side by Side Diff: cc/animation/element_animations.cc

Issue 1904653002: CC Animation: Merge LayerAnimationController into ElementAnimations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor optimization: Don't init value observations if same host. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/animation/element_animations.h ('k') | cc/animation/element_animations_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/animation/element_animations.h" 5 #include "cc/animation/element_animations.h"
6 6
7 #include <stddef.h>
8
9 #include <algorithm>
10
7 #include "base/macros.h" 11 #include "base/macros.h"
8 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "cc/animation/animation_delegate.h"
9 #include "cc/animation/animation_host.h" 14 #include "cc/animation/animation_host.h"
10 #include "cc/animation/animation_player.h" 15 #include "cc/animation/animation_player.h"
16 #include "cc/animation/keyframed_animation_curve.h"
17 #include "cc/animation/scroll_offset_animation_curve.h"
18 #include "cc/output/filter_operations.h"
11 #include "cc/trees/mutator_host_client.h" 19 #include "cc/trees/mutator_host_client.h"
20 #include "ui/gfx/geometry/box_f.h"
12 21
13 namespace cc { 22 namespace cc {
14 23
15 scoped_refptr<ElementAnimations> ElementAnimations::Create( 24 scoped_refptr<ElementAnimations> ElementAnimations::Create() {
16 AnimationHost* host) { 25 return make_scoped_refptr(new ElementAnimations());
17 return make_scoped_refptr(new ElementAnimations(host));
18 } 26 }
19 27
20 ElementAnimations::ElementAnimations(AnimationHost* host) 28 ElementAnimations::ElementAnimations()
21 : players_list_(new PlayersList()), animation_host_(host) { 29 : players_list_(new PlayersList()),
22 DCHECK(animation_host_); 30 animation_host_(),
31 layer_id_(),
32 is_active_(false),
33 needs_active_value_observations_(false),
34 needs_pending_value_observations_(false),
35 needs_to_start_animations_(false),
36 scroll_offset_animation_was_interrupted_(false),
37 potentially_animating_transform_for_active_observers_(false),
38 potentially_animating_transform_for_pending_observers_(false) {}
39
40 ElementAnimations::~ElementAnimations() {}
41
42 void ElementAnimations::SetAnimationHost(AnimationHost* host) {
43 animation_host_ = host;
23 } 44 }
24 45
25 ElementAnimations::~ElementAnimations() { 46 void ElementAnimations::SetLayerId(int layer_id) {
26 DCHECK(!layer_animation_controller_); 47 layer_id_ = layer_id;
27 } 48 }
28 49
29 void ElementAnimations::CreateLayerAnimationController(int layer_id) { 50 void ElementAnimations::InitValueObservations() {
30 DCHECK(layer_id); 51 DCHECK(layer_id_);
31 DCHECK(!layer_animation_controller_);
32 DCHECK(animation_host_); 52 DCHECK(animation_host_);
33 53
34 layer_animation_controller_ = 54 UpdateActivation(FORCE_ACTIVATION);
35 animation_host_->GetAnimationControllerForId(layer_id);
36 layer_animation_controller_->SetAnimationHost(animation_host_);
37 layer_animation_controller_->set_layer_animation_delegate(this);
38 layer_animation_controller_->set_value_observer(this);
39 layer_animation_controller_->set_value_provider(this);
40 55
41 DCHECK(animation_host_->mutator_host_client()); 56 DCHECK(animation_host_->mutator_host_client());
42 if (animation_host_->mutator_host_client()->IsLayerInTree( 57 if (animation_host_->mutator_host_client()->IsLayerInTree(
43 layer_id, LayerTreeType::ACTIVE)) 58 layer_id_, LayerTreeType::ACTIVE)) {
44 CreateActiveValueObserver(); 59 set_needs_active_value_observations(true);
60 }
45 if (animation_host_->mutator_host_client()->IsLayerInTree( 61 if (animation_host_->mutator_host_client()->IsLayerInTree(
46 layer_id, LayerTreeType::PENDING)) 62 layer_id_, LayerTreeType::PENDING)) {
47 CreatePendingValueObserver(); 63 set_needs_pending_value_observations(true);
64 }
48 } 65 }
49 66
50 void ElementAnimations::DestroyLayerAnimationController() { 67 void ElementAnimations::ClearValueObservations() {
51 DCHECK(animation_host_); 68 DCHECK(animation_host_);
52 69
53 if (needs_active_value_observations()) 70 if (needs_active_value_observations())
54 OnTransformIsPotentiallyAnimatingChanged(LayerTreeType::ACTIVE, false); 71 OnTransformIsPotentiallyAnimatingChanged(LayerTreeType::ACTIVE, false);
72 set_needs_active_value_observations(false);
73
55 if (needs_pending_value_observations()) 74 if (needs_pending_value_observations())
56 OnTransformIsPotentiallyAnimatingChanged(LayerTreeType::PENDING, false); 75 OnTransformIsPotentiallyAnimatingChanged(LayerTreeType::PENDING, false);
76 set_needs_pending_value_observations(false);
57 77
58 DestroyPendingValueObserver(); 78 animation_host_->DidDeactivateElementAnimations(this);
59 DestroyActiveValueObserver(); 79 UpdateActivation(FORCE_ACTIVATION);
60
61 if (layer_animation_controller_) {
62 layer_animation_controller_->remove_value_provider(this);
63 layer_animation_controller_->set_value_observer(nullptr);
64 layer_animation_controller_->remove_layer_animation_delegate(this);
65 layer_animation_controller_->SetAnimationHost(nullptr);
66 layer_animation_controller_ = nullptr;
67 }
68 } 80 }
69 81
70 void ElementAnimations::LayerRegistered(int layer_id, LayerTreeType tree_type) { 82 void ElementAnimations::LayerRegistered(int layer_id, LayerTreeType tree_type) {
71 DCHECK(layer_animation_controller_); 83 DCHECK_EQ(layer_id_, layer_id);
72 DCHECK_EQ(layer_animation_controller_->id(), layer_id);
73 84
74 if (tree_type == LayerTreeType::ACTIVE) 85 if (tree_type == LayerTreeType::ACTIVE)
75 layer_animation_controller_->set_needs_active_value_observations(true); 86 set_needs_active_value_observations(true);
76 else 87 else
77 layer_animation_controller_->set_needs_pending_value_observations(true); 88 set_needs_pending_value_observations(true);
78 } 89 }
79 90
80 void ElementAnimations::LayerUnregistered(int layer_id, 91 void ElementAnimations::LayerUnregistered(int layer_id,
81 LayerTreeType tree_type) { 92 LayerTreeType tree_type) {
82 DCHECK_EQ(this->layer_id(), layer_id); 93 DCHECK_EQ(this->layer_id(), layer_id);
83 tree_type == LayerTreeType::ACTIVE ? DestroyActiveValueObserver() 94 if (tree_type == LayerTreeType::ACTIVE)
84 : DestroyPendingValueObserver(); 95 set_needs_active_value_observations(false);
96 else
97 set_needs_pending_value_observations(false);
85 } 98 }
86 99
87 void ElementAnimations::AddPlayer(AnimationPlayer* player) { 100 void ElementAnimations::AddPlayer(AnimationPlayer* player) {
88 players_list_->Append(player); 101 players_list_->Append(player);
89 } 102 }
90 103
91 void ElementAnimations::RemovePlayer(AnimationPlayer* player) { 104 void ElementAnimations::RemovePlayer(AnimationPlayer* player) {
92 for (PlayersListNode* node = players_list_->head(); 105 for (PlayersListNode* node = players_list_->head();
93 node != players_list_->end(); node = node->next()) { 106 node != players_list_->end(); node = node->next()) {
94 if (node->value() == player) { 107 if (node->value() == player) {
95 node->RemoveFromList(); 108 node->RemoveFromList();
96 return; 109 return;
97 } 110 }
98 } 111 }
99 } 112 }
100 113
101 bool ElementAnimations::IsEmpty() const { 114 bool ElementAnimations::IsEmpty() const {
102 return players_list_->empty(); 115 return players_list_->empty();
103 } 116 }
104 117
105 void ElementAnimations::PushPropertiesTo( 118 void ElementAnimations::PushPropertiesTo(
106 scoped_refptr<ElementAnimations> element_animations_impl) { 119 scoped_refptr<ElementAnimations> element_animations_impl) {
107 DCHECK(layer_animation_controller_); 120 DCHECK_NE(this, element_animations_impl);
108 DCHECK(element_animations_impl->layer_animation_controller_); 121 if (!has_any_animation() && !element_animations_impl->has_any_animation())
109 122 return;
110 layer_animation_controller_->PushAnimationUpdatesTo( 123 MarkAbortedAnimationsForDeletion(element_animations_impl.get());
111 element_animations_impl->layer_animation_controller_.get()); 124 PurgeAnimationsMarkedForDeletion();
125 PushNewAnimationsToImplThread(element_animations_impl.get());
126
127 // Remove finished impl side animations only after pushing,
128 // and only after the animations are deleted on the main thread
129 // this insures we will never push an animation twice.
130 RemoveAnimationsCompletedOnMainThread(element_animations_impl.get());
131
132 PushPropertiesToImplThread(element_animations_impl.get());
133 element_animations_impl->UpdateActivation(NORMAL_ACTIVATION);
134 UpdateActivation(NORMAL_ACTIVATION);
112 } 135 }
113 136
114 void ElementAnimations::AddAnimation(std::unique_ptr<Animation> animation) { 137 void ElementAnimations::AddAnimation(std::unique_ptr<Animation> animation) {
115 layer_animation_controller_->AddAnimation(std::move(animation)); 138 bool added_transform_animation =
139 animation->target_property() == TargetProperty::TRANSFORM;
140 animations_.push_back(std::move(animation));
141 needs_to_start_animations_ = true;
142 UpdateActivation(NORMAL_ACTIVATION);
143 if (added_transform_animation)
144 UpdatePotentiallyAnimatingTransform();
145 }
146
147 void ElementAnimations::Animate(base::TimeTicks monotonic_time) {
148 DCHECK(!monotonic_time.is_null());
149 if (!needs_active_value_observations() && !needs_pending_value_observations())
150 return;
151
152 if (needs_to_start_animations_)
153 StartAnimations(monotonic_time);
154 TickAnimations(monotonic_time);
155 last_tick_time_ = monotonic_time;
156 }
157
158 void ElementAnimations::AccumulatePropertyUpdates(
159 base::TimeTicks monotonic_time,
160 AnimationEvents* events) {
161 if (!events)
162 return;
163
164 for (size_t i = 0; i < animations_.size(); ++i) {
165 Animation* animation = animations_[i].get();
166 if (!animation->is_impl_only())
167 continue;
168
169 if (!animation->InEffect(monotonic_time))
170 continue;
171
172 base::TimeDelta trimmed =
173 animation->TrimTimeToCurrentIteration(monotonic_time);
174 switch (animation->target_property()) {
175 case TargetProperty::OPACITY: {
176 AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, layer_id_,
177 animation->group(), TargetProperty::OPACITY,
178 monotonic_time);
179 const FloatAnimationCurve* float_animation_curve =
180 animation->curve()->ToFloatAnimationCurve();
181 event.opacity = float_animation_curve->GetValue(trimmed);
182 event.is_impl_only = true;
183 events->events_.push_back(event);
184 break;
185 }
186
187 case TargetProperty::TRANSFORM: {
188 AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, layer_id_,
189 animation->group(), TargetProperty::TRANSFORM,
190 monotonic_time);
191 const TransformAnimationCurve* transform_animation_curve =
192 animation->curve()->ToTransformAnimationCurve();
193 event.transform = transform_animation_curve->GetValue(trimmed);
194 event.is_impl_only = true;
195 events->events_.push_back(event);
196 break;
197 }
198
199 case TargetProperty::FILTER: {
200 AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, layer_id_,
201 animation->group(), TargetProperty::FILTER,
202 monotonic_time);
203 const FilterAnimationCurve* filter_animation_curve =
204 animation->curve()->ToFilterAnimationCurve();
205 event.filters = filter_animation_curve->GetValue(trimmed);
206 event.is_impl_only = true;
207 events->events_.push_back(event);
208 break;
209 }
210
211 case TargetProperty::BACKGROUND_COLOR: {
212 break;
213 }
214
215 case TargetProperty::SCROLL_OFFSET: {
216 // Impl-side changes to scroll offset are already sent back to the
217 // main thread (e.g. for user-driven scrolling), so a PROPERTY_UPDATE
218 // isn't needed.
219 break;
220 }
221 }
222 }
223 }
224
225 void ElementAnimations::UpdateState(bool start_ready_animations,
226 AnimationEvents* events) {
227 if (!needs_active_value_observations())
228 return;
229
230 // Animate hasn't been called, this happens if an observer has been added
231 // between the Commit and Draw phases.
232 if (last_tick_time_ == base::TimeTicks())
233 return;
234
235 if (start_ready_animations)
236 PromoteStartedAnimations(last_tick_time_, events);
237
238 MarkFinishedAnimations(last_tick_time_);
239 MarkAnimationsForDeletion(last_tick_time_, events);
240
241 if (needs_to_start_animations_ && start_ready_animations) {
242 StartAnimations(last_tick_time_);
243 PromoteStartedAnimations(last_tick_time_, events);
244 }
245
246 AccumulatePropertyUpdates(last_tick_time_, events);
247
248 UpdateActivation(NORMAL_ACTIVATION);
249 }
250
251 void ElementAnimations::ActivateAnimations() {
252 bool changed_transform_animation = false;
253 for (size_t i = 0; i < animations_.size(); ++i) {
254 if (animations_[i]->affects_active_observers() !=
255 animations_[i]->affects_pending_observers() &&
256 animations_[i]->target_property() == TargetProperty::TRANSFORM)
257 changed_transform_animation = true;
258 animations_[i]->set_affects_active_observers(
259 animations_[i]->affects_pending_observers());
260 }
261 auto affects_no_observers = [](const std::unique_ptr<Animation>& animation) {
262 return !animation->affects_active_observers() &&
263 !animation->affects_pending_observers();
264 };
265 animations_.erase(std::remove_if(animations_.begin(), animations_.end(),
266 affects_no_observers),
267 animations_.end());
268 scroll_offset_animation_was_interrupted_ = false;
269 UpdateActivation(NORMAL_ACTIVATION);
270 if (changed_transform_animation)
271 UpdatePotentiallyAnimatingTransform();
272 }
273
274 void ElementAnimations::NotifyAnimationStarted(const AnimationEvent& event) {
275 if (event.is_impl_only) {
276 NotifyPlayersAnimationStarted(event.monotonic_time, event.target_property,
277 event.group_id);
278 return;
279 }
280
281 for (size_t i = 0; i < animations_.size(); ++i) {
282 if (animations_[i]->group() == event.group_id &&
283 animations_[i]->target_property() == event.target_property &&
284 animations_[i]->needs_synchronized_start_time()) {
285 animations_[i]->set_needs_synchronized_start_time(false);
286 if (!animations_[i]->has_set_start_time())
287 animations_[i]->set_start_time(event.monotonic_time);
288
289 NotifyPlayersAnimationStarted(event.monotonic_time, event.target_property,
290 event.group_id);
291
292 return;
293 }
294 }
295 }
296
297 void ElementAnimations::NotifyAnimationFinished(const AnimationEvent& event) {
298 if (event.is_impl_only) {
299 NotifyPlayersAnimationFinished(event.monotonic_time, event.target_property,
300 event.group_id);
301 return;
302 }
303
304 for (size_t i = 0; i < animations_.size(); ++i) {
305 if (animations_[i]->group() == event.group_id &&
306 animations_[i]->target_property() == event.target_property) {
307 animations_[i]->set_received_finished_event(true);
308 NotifyPlayersAnimationFinished(event.monotonic_time,
309 event.target_property, event.group_id);
310
311 return;
312 }
313 }
314 }
315
316 void ElementAnimations::NotifyAnimationTakeover(const AnimationEvent& event) {
317 DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
318 if (!players_list_->empty()) {
319 std::unique_ptr<AnimationCurve> animation_curve = event.curve->Clone();
320 NotifyPlayersAnimationTakeover(event.monotonic_time, event.target_property,
321 event.animation_start_time,
322 std::move(animation_curve));
323 }
324 }
325
326 void ElementAnimations::NotifyAnimationAborted(const AnimationEvent& event) {
327 bool aborted_transform_animation = false;
328 for (size_t i = 0; i < animations_.size(); ++i) {
329 if (animations_[i]->group() == event.group_id &&
330 animations_[i]->target_property() == event.target_property) {
331 animations_[i]->SetRunState(Animation::ABORTED, event.monotonic_time);
332 animations_[i]->set_received_finished_event(true);
333 NotifyPlayersAnimationAborted(event.monotonic_time, event.target_property,
334 event.group_id);
335 if (event.target_property == TargetProperty::TRANSFORM)
336 aborted_transform_animation = true;
337 break;
338 }
339 }
340 if (aborted_transform_animation)
341 UpdatePotentiallyAnimatingTransform();
342 }
343
344 void ElementAnimations::NotifyAnimationPropertyUpdate(
345 const AnimationEvent& event) {
346 bool notify_active_observers = true;
347 bool notify_pending_observers = true;
348 switch (event.target_property) {
349 case TargetProperty::OPACITY:
350 NotifyObserversOpacityAnimated(event.opacity, notify_active_observers,
351 notify_pending_observers);
352 break;
353 case TargetProperty::TRANSFORM:
354 NotifyObserversTransformAnimated(event.transform, notify_active_observers,
355 notify_pending_observers);
356 break;
357 default:
358 NOTREACHED();
359 }
360 }
361
362 bool ElementAnimations::HasFilterAnimationThatInflatesBounds() const {
363 for (size_t i = 0; i < animations_.size(); ++i) {
364 if (!animations_[i]->is_finished() &&
365 animations_[i]->target_property() == TargetProperty::FILTER &&
366 animations_[i]
367 ->curve()
368 ->ToFilterAnimationCurve()
369 ->HasFilterThatMovesPixels())
370 return true;
371 }
372
373 return false;
374 }
375
376 bool ElementAnimations::HasTransformAnimationThatInflatesBounds() const {
377 return IsCurrentlyAnimatingProperty(TargetProperty::TRANSFORM,
378 ObserverType::ACTIVE) ||
379 IsCurrentlyAnimatingProperty(TargetProperty::TRANSFORM,
380 ObserverType::PENDING);
381 }
382
383 bool ElementAnimations::FilterAnimationBoundsForBox(const gfx::BoxF& box,
384 gfx::BoxF* bounds) const {
385 // TODO(avallee): Implement.
386 return false;
387 }
388
389 bool ElementAnimations::TransformAnimationBoundsForBox(
390 const gfx::BoxF& box,
391 gfx::BoxF* bounds) const {
392 DCHECK(HasTransformAnimationThatInflatesBounds())
393 << "TransformAnimationBoundsForBox will give incorrect results if there "
394 << "are no transform animations affecting bounds, non-animated transform "
395 << "is not known";
396
397 // Compute bounds based on animations for which is_finished() is false.
398 // Do nothing if there are no such animations; in this case, it is assumed
399 // that callers will take care of computing bounds based on the owning layer's
400 // actual transform.
401 *bounds = gfx::BoxF();
402 for (size_t i = 0; i < animations_.size(); ++i) {
403 if (animations_[i]->is_finished() ||
404 animations_[i]->target_property() != TargetProperty::TRANSFORM)
405 continue;
406
407 const TransformAnimationCurve* transform_animation_curve =
408 animations_[i]->curve()->ToTransformAnimationCurve();
409 gfx::BoxF animation_bounds;
410 bool success =
411 transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
412 if (!success)
413 return false;
414 bounds->Union(animation_bounds);
415 }
416
417 return true;
418 }
419
420 bool ElementAnimations::HasAnimationThatAffectsScale() const {
421 for (size_t i = 0; i < animations_.size(); ++i) {
422 if (animations_[i]->is_finished() ||
423 animations_[i]->target_property() != TargetProperty::TRANSFORM)
424 continue;
425
426 const TransformAnimationCurve* transform_animation_curve =
427 animations_[i]->curve()->ToTransformAnimationCurve();
428 if (transform_animation_curve->AffectsScale())
429 return true;
430 }
431
432 return false;
433 }
434
435 bool ElementAnimations::HasOnlyTranslationTransforms(
436 ObserverType observer_type) const {
437 for (size_t i = 0; i < animations_.size(); ++i) {
438 if (animations_[i]->is_finished() ||
439 animations_[i]->target_property() != TargetProperty::TRANSFORM)
440 continue;
441
442 if ((observer_type == ObserverType::ACTIVE &&
443 !animations_[i]->affects_active_observers()) ||
444 (observer_type == ObserverType::PENDING &&
445 !animations_[i]->affects_pending_observers()))
446 continue;
447
448 const TransformAnimationCurve* transform_animation_curve =
449 animations_[i]->curve()->ToTransformAnimationCurve();
450 if (!transform_animation_curve->IsTranslation())
451 return false;
452 }
453
454 return true;
455 }
456
457 bool ElementAnimations::AnimationsPreserveAxisAlignment() const {
458 for (size_t i = 0; i < animations_.size(); ++i) {
459 if (animations_[i]->is_finished() ||
460 animations_[i]->target_property() != TargetProperty::TRANSFORM)
461 continue;
462
463 const TransformAnimationCurve* transform_animation_curve =
464 animations_[i]->curve()->ToTransformAnimationCurve();
465 if (!transform_animation_curve->PreservesAxisAlignment())
466 return false;
467 }
468
469 return true;
470 }
471
472 bool ElementAnimations::AnimationStartScale(ObserverType observer_type,
473 float* start_scale) const {
474 *start_scale = 0.f;
475 for (size_t i = 0; i < animations_.size(); ++i) {
476 if (animations_[i]->is_finished() ||
477 animations_[i]->target_property() != TargetProperty::TRANSFORM)
478 continue;
479
480 if ((observer_type == ObserverType::ACTIVE &&
481 !animations_[i]->affects_active_observers()) ||
482 (observer_type == ObserverType::PENDING &&
483 !animations_[i]->affects_pending_observers()))
484 continue;
485
486 bool forward_direction = true;
487 switch (animations_[i]->direction()) {
488 case Animation::DIRECTION_NORMAL:
489 case Animation::DIRECTION_ALTERNATE:
490 forward_direction = animations_[i]->playback_rate() >= 0.0;
491 break;
492 case Animation::DIRECTION_REVERSE:
493 case Animation::DIRECTION_ALTERNATE_REVERSE:
494 forward_direction = animations_[i]->playback_rate() < 0.0;
495 break;
496 }
497
498 const TransformAnimationCurve* transform_animation_curve =
499 animations_[i]->curve()->ToTransformAnimationCurve();
500 float animation_start_scale = 0.f;
501 if (!transform_animation_curve->AnimationStartScale(forward_direction,
502 &animation_start_scale))
503 return false;
504 *start_scale = std::max(*start_scale, animation_start_scale);
505 }
506 return true;
507 }
508
509 bool ElementAnimations::MaximumTargetScale(ObserverType observer_type,
510 float* max_scale) const {
511 *max_scale = 0.f;
512 for (size_t i = 0; i < animations_.size(); ++i) {
513 if (animations_[i]->is_finished() ||
514 animations_[i]->target_property() != TargetProperty::TRANSFORM)
515 continue;
516
517 if ((observer_type == ObserverType::ACTIVE &&
518 !animations_[i]->affects_active_observers()) ||
519 (observer_type == ObserverType::PENDING &&
520 !animations_[i]->affects_pending_observers()))
521 continue;
522
523 bool forward_direction = true;
524 switch (animations_[i]->direction()) {
525 case Animation::DIRECTION_NORMAL:
526 case Animation::DIRECTION_ALTERNATE:
527 forward_direction = animations_[i]->playback_rate() >= 0.0;
528 break;
529 case Animation::DIRECTION_REVERSE:
530 case Animation::DIRECTION_ALTERNATE_REVERSE:
531 forward_direction = animations_[i]->playback_rate() < 0.0;
532 break;
533 }
534
535 const TransformAnimationCurve* transform_animation_curve =
536 animations_[i]->curve()->ToTransformAnimationCurve();
537 float animation_scale = 0.f;
538 if (!transform_animation_curve->MaximumTargetScale(forward_direction,
539 &animation_scale))
540 return false;
541 *max_scale = std::max(*max_scale, animation_scale);
542 }
543
544 return true;
545 }
546
547 void ElementAnimations::PushNewAnimationsToImplThread(
548 ElementAnimations* element_animations_impl) const {
549 // Any new animations owned by the main thread's ElementAnimations are cloned
550 // and added to the impl thread's ElementAnimations.
551 for (size_t i = 0; i < animations_.size(); ++i) {
552 // If the animation is already running on the impl thread, there is no
553 // need to copy it over.
554 if (element_animations_impl->GetAnimationById(animations_[i]->id()))
555 continue;
556
557 if (animations_[i]->target_property() == TargetProperty::SCROLL_OFFSET &&
558 !animations_[i]
559 ->curve()
560 ->ToScrollOffsetAnimationCurve()
561 ->HasSetInitialValue()) {
562 gfx::ScrollOffset current_scroll_offset;
563 if (element_animations_impl->needs_active_value_observations()) {
564 current_scroll_offset =
565 element_animations_impl->ScrollOffsetForAnimation();
566 } else {
567 // The owning layer isn't yet in the active tree, so the main thread
568 // scroll offset will be up-to-date.
569 current_scroll_offset = ScrollOffsetForAnimation();
570 }
571 animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
572 current_scroll_offset);
573 }
574
575 // The new animation should be set to run as soon as possible.
576 Animation::RunState initial_run_state =
577 Animation::WAITING_FOR_TARGET_AVAILABILITY;
578 std::unique_ptr<Animation> to_add(
579 animations_[i]->CloneAndInitialize(initial_run_state));
580 DCHECK(!to_add->needs_synchronized_start_time());
581 to_add->set_affects_active_observers(false);
582 element_animations_impl->AddAnimation(std::move(to_add));
583 }
584 }
585
586 static bool IsCompleted(
587 Animation* animation,
588 const ElementAnimations* main_thread_element_animations) {
589 if (animation->is_impl_only()) {
590 return (animation->run_state() == Animation::WAITING_FOR_DELETION);
591 } else {
592 return !main_thread_element_animations->GetAnimationById(animation->id());
593 }
594 }
595
596 void ElementAnimations::RemoveAnimationsCompletedOnMainThread(
597 ElementAnimations* element_animations_impl) const {
598 bool removed_transform_animation = false;
599 // Animations removed on the main thread should no longer affect pending
600 // observers, and should stop affecting active observers after the next call
601 // to ActivateAnimations. If already WAITING_FOR_DELETION, they can be removed
602 // immediately.
603 auto& animations = element_animations_impl->animations_;
604 for (const auto& animation : animations) {
605 if (IsCompleted(animation.get(), this)) {
606 animation->set_affects_pending_observers(false);
607 if (animation->target_property() == TargetProperty::TRANSFORM)
608 removed_transform_animation = true;
609 }
610 }
611 auto affects_active_only_and_is_waiting_for_deletion =
612 [](const std::unique_ptr<Animation>& animation) {
613 return animation->run_state() == Animation::WAITING_FOR_DELETION &&
614 !animation->affects_pending_observers();
615 };
616 animations.erase(
617 std::remove_if(animations.begin(), animations.end(),
618 affects_active_only_and_is_waiting_for_deletion),
619 animations.end());
620
621 if (removed_transform_animation)
622 element_animations_impl->UpdatePotentiallyAnimatingTransform();
623 }
624
625 void ElementAnimations::PushPropertiesToImplThread(
626 ElementAnimations* element_animations_impl) {
627 for (size_t i = 0; i < animations_.size(); ++i) {
628 Animation* current_impl =
629 element_animations_impl->GetAnimationById(animations_[i]->id());
630 if (current_impl)
631 animations_[i]->PushPropertiesTo(current_impl);
632 }
633 element_animations_impl->scroll_offset_animation_was_interrupted_ =
634 scroll_offset_animation_was_interrupted_;
635 scroll_offset_animation_was_interrupted_ = false;
636 }
637
638 void ElementAnimations::StartAnimations(base::TimeTicks monotonic_time) {
639 DCHECK(needs_to_start_animations_);
640 needs_to_start_animations_ = false;
641 // First collect running properties affecting each type of observer.
642 TargetProperties blocked_properties_for_active_observers;
643 TargetProperties blocked_properties_for_pending_observers;
644 std::vector<size_t> animations_waiting_for_target;
645
646 animations_waiting_for_target.reserve(animations_.size());
647 for (size_t i = 0; i < animations_.size(); ++i) {
648 if (animations_[i]->run_state() == Animation::STARTING ||
649 animations_[i]->run_state() == Animation::RUNNING) {
650 if (animations_[i]->affects_active_observers()) {
651 blocked_properties_for_active_observers[animations_[i]
652 ->target_property()] = true;
653 }
654 if (animations_[i]->affects_pending_observers()) {
655 blocked_properties_for_pending_observers[animations_[i]
656 ->target_property()] =
657 true;
658 }
659 } else if (animations_[i]->run_state() ==
660 Animation::WAITING_FOR_TARGET_AVAILABILITY) {
661 animations_waiting_for_target.push_back(i);
662 }
663 }
664
665 for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) {
666 // Collect all properties for animations with the same group id (they
667 // should all also be in the list of animations).
668 size_t animation_index = animations_waiting_for_target[i];
669 Animation* animation_waiting_for_target =
670 animations_[animation_index].get();
671 // Check for the run state again even though the animation was waiting
672 // for target because it might have changed the run state while handling
673 // previous animation in this loop (if they belong to same group).
674 if (animation_waiting_for_target->run_state() ==
675 Animation::WAITING_FOR_TARGET_AVAILABILITY) {
676 TargetProperties enqueued_properties;
677 bool affects_active_observers =
678 animation_waiting_for_target->affects_active_observers();
679 bool affects_pending_observers =
680 animation_waiting_for_target->affects_pending_observers();
681 enqueued_properties[animation_waiting_for_target->target_property()] =
682 true;
683 for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
684 if (animation_waiting_for_target->group() == animations_[j]->group()) {
685 enqueued_properties[animations_[j]->target_property()] = true;
686 affects_active_observers |=
687 animations_[j]->affects_active_observers();
688 affects_pending_observers |=
689 animations_[j]->affects_pending_observers();
690 }
691 }
692
693 // Check to see if intersection of the list of properties affected by
694 // the group and the list of currently blocked properties is null, taking
695 // into account the type(s) of observers affected by the group. In any
696 // case, the group's target properties need to be added to the lists of
697 // blocked properties.
698 bool null_intersection = true;
699 static_assert(TargetProperty::FIRST_TARGET_PROPERTY == 0,
700 "TargetProperty must be 0-based enum");
701 for (int property = TargetProperty::FIRST_TARGET_PROPERTY;
702 property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) {
703 if (enqueued_properties[property]) {
704 if (affects_active_observers) {
705 if (blocked_properties_for_active_observers[property])
706 null_intersection = false;
707 else
708 blocked_properties_for_active_observers[property] = true;
709 }
710 if (affects_pending_observers) {
711 if (blocked_properties_for_pending_observers[property])
712 null_intersection = false;
713 else
714 blocked_properties_for_pending_observers[property] = true;
715 }
716 }
717 }
718
719 // If the intersection is null, then we are free to start the animations
720 // in the group.
721 if (null_intersection) {
722 animation_waiting_for_target->SetRunState(Animation::STARTING,
723 monotonic_time);
724 for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
725 if (animation_waiting_for_target->group() ==
726 animations_[j]->group()) {
727 animations_[j]->SetRunState(Animation::STARTING, monotonic_time);
728 }
729 }
730 } else {
731 needs_to_start_animations_ = true;
732 }
733 }
734 }
735 }
736
737 void ElementAnimations::PromoteStartedAnimations(base::TimeTicks monotonic_time,
738 AnimationEvents* events) {
739 for (size_t i = 0; i < animations_.size(); ++i) {
740 if (animations_[i]->run_state() == Animation::STARTING &&
741 animations_[i]->affects_active_observers()) {
742 animations_[i]->SetRunState(Animation::RUNNING, monotonic_time);
743 if (!animations_[i]->has_set_start_time() &&
744 !animations_[i]->needs_synchronized_start_time())
745 animations_[i]->set_start_time(monotonic_time);
746 if (events) {
747 base::TimeTicks start_time;
748 if (animations_[i]->has_set_start_time())
749 start_time = animations_[i]->start_time();
750 else
751 start_time = monotonic_time;
752 AnimationEvent started_event(
753 AnimationEvent::STARTED, layer_id_, animations_[i]->group(),
754 animations_[i]->target_property(), start_time);
755 started_event.is_impl_only = animations_[i]->is_impl_only();
756 if (started_event.is_impl_only)
757 NotifyAnimationStarted(started_event);
758 else
759 events->events_.push_back(started_event);
760 }
761 }
762 }
763 }
764
765 void ElementAnimations::MarkFinishedAnimations(base::TimeTicks monotonic_time) {
766 bool finished_transform_animation = false;
767 for (size_t i = 0; i < animations_.size(); ++i) {
768 if (!animations_[i]->is_finished() &&
769 animations_[i]->IsFinishedAt(monotonic_time)) {
770 animations_[i]->SetRunState(Animation::FINISHED, monotonic_time);
771 if (animations_[i]->target_property() == TargetProperty::TRANSFORM) {
772 finished_transform_animation = true;
773 }
774 }
775 }
776 if (finished_transform_animation)
777 UpdatePotentiallyAnimatingTransform();
778 }
779
780 void ElementAnimations::MarkAnimationsForDeletion(
781 base::TimeTicks monotonic_time,
782 AnimationEvents* events) {
783 bool marked_animations_for_deletions = false;
784 std::vector<size_t> animations_with_same_group_id;
785
786 animations_with_same_group_id.reserve(animations_.size());
787 // Non-aborted animations are marked for deletion after a corresponding
788 // AnimationEvent::FINISHED event is sent or received. This means that if
789 // we don't have an events vector, we must ensure that non-aborted animations
790 // have received a finished event before marking them for deletion.
791 for (size_t i = 0; i < animations_.size(); i++) {
792 int group_id = animations_[i]->group();
793 if (animations_[i]->run_state() == Animation::ABORTED) {
794 if (events && !animations_[i]->is_impl_only()) {
795 AnimationEvent aborted_event(
796 AnimationEvent::ABORTED, layer_id_, group_id,
797 animations_[i]->target_property(), monotonic_time);
798 events->events_.push_back(aborted_event);
799 }
800 // If on the compositor or on the main thread and received finish event,
801 // animation can be marked for deletion.
802 if (events || animations_[i]->received_finished_event()) {
803 animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
804 monotonic_time);
805 marked_animations_for_deletions = true;
806 }
807 continue;
808 }
809
810 // If running on the compositor and need to complete an aborted animation
811 // on the main thread.
812 if (events &&
813 animations_[i]->run_state() ==
814 Animation::ABORTED_BUT_NEEDS_COMPLETION) {
815 AnimationEvent aborted_event(AnimationEvent::TAKEOVER, layer_id_,
816 group_id, animations_[i]->target_property(),
817 monotonic_time);
818 aborted_event.animation_start_time =
819 (animations_[i]->start_time() - base::TimeTicks()).InSecondsF();
820 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
821 animations_[i]->curve()->ToScrollOffsetAnimationCurve();
822 aborted_event.curve = scroll_offset_animation_curve->Clone();
823 // Notify the compositor that the animation is finished.
824 NotifyPlayersAnimationFinished(aborted_event.monotonic_time,
825 aborted_event.target_property,
826 aborted_event.group_id);
827 // Notify main thread.
828 events->events_.push_back(aborted_event);
829
830 // Remove the animation from the compositor.
831 animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
832 monotonic_time);
833 marked_animations_for_deletions = true;
834 continue;
835 }
836
837 bool all_anims_with_same_id_are_finished = false;
838
839 // Since deleting an animation on the main thread leads to its deletion
840 // on the impl thread, we only mark a FINISHED main thread animation for
841 // deletion once it has received a FINISHED event from the impl thread.
842 bool animation_i_will_send_or_has_received_finish_event =
843 animations_[i]->is_controlling_instance() ||
844 animations_[i]->is_impl_only() ||
845 animations_[i]->received_finished_event();
846 // If an animation is finished, and not already marked for deletion,
847 // find out if all other animations in the same group are also finished.
848 if (animations_[i]->run_state() == Animation::FINISHED &&
849 animation_i_will_send_or_has_received_finish_event) {
850 // Clear the animations_with_same_group_id if it was added for
851 // the previous animation's iteration.
852 if (animations_with_same_group_id.size() > 0)
853 animations_with_same_group_id.clear();
854 all_anims_with_same_id_are_finished = true;
855 for (size_t j = 0; j < animations_.size(); ++j) {
856 bool animation_j_will_send_or_has_received_finish_event =
857 animations_[j]->is_controlling_instance() ||
858 animations_[j]->is_impl_only() ||
859 animations_[j]->received_finished_event();
860 if (group_id == animations_[j]->group()) {
861 if (!animations_[j]->is_finished() ||
862 (animations_[j]->run_state() == Animation::FINISHED &&
863 !animation_j_will_send_or_has_received_finish_event)) {
864 all_anims_with_same_id_are_finished = false;
865 break;
866 } else if (j >= i &&
867 animations_[j]->run_state() != Animation::ABORTED) {
868 // Mark down the animations which belong to the same group
869 // and is not yet aborted. If this current iteration finds that all
870 // animations with same ID are finished, then the marked
871 // animations below will be set to WAITING_FOR_DELETION in next
872 // iteration.
873 animations_with_same_group_id.push_back(j);
874 }
875 }
876 }
877 }
878 if (all_anims_with_same_id_are_finished) {
879 // We now need to remove all animations with the same group id as
880 // group_id (and send along animation finished notifications, if
881 // necessary).
882 for (size_t j = 0; j < animations_with_same_group_id.size(); j++) {
883 size_t animation_index = animations_with_same_group_id[j];
884 if (events) {
885 AnimationEvent finished_event(
886 AnimationEvent::FINISHED, layer_id_,
887 animations_[animation_index]->group(),
888 animations_[animation_index]->target_property(), monotonic_time);
889 finished_event.is_impl_only =
890 animations_[animation_index]->is_impl_only();
891 if (finished_event.is_impl_only)
892 NotifyAnimationFinished(finished_event);
893 else
894 events->events_.push_back(finished_event);
895 }
896 animations_[animation_index]->SetRunState(
897 Animation::WAITING_FOR_DELETION, monotonic_time);
898 }
899 marked_animations_for_deletions = true;
900 }
901 }
902 if (marked_animations_for_deletions)
903 NotifyObserversAnimationWaitingForDeletion();
904 }
905
906 void ElementAnimations::MarkAbortedAnimationsForDeletion(
907 ElementAnimations* element_animations_impl) const {
908 bool aborted_transform_animation = false;
909 auto& animations_impl = element_animations_impl->animations_;
910 for (const auto& animation_impl : animations_impl) {
911 // If the animation has been aborted on the main thread, mark it for
912 // deletion.
913 if (Animation* animation = GetAnimationById(animation_impl->id())) {
914 if (animation->run_state() == Animation::ABORTED) {
915 animation_impl->SetRunState(Animation::WAITING_FOR_DELETION,
916 element_animations_impl->last_tick_time_);
917 animation->SetRunState(Animation::WAITING_FOR_DELETION,
918 last_tick_time_);
919 if (animation_impl->target_property() == TargetProperty::TRANSFORM) {
920 aborted_transform_animation = true;
921 }
922 }
923 }
924 }
925
926 if (aborted_transform_animation)
927 element_animations_impl->UpdatePotentiallyAnimatingTransform();
928 }
929
930 void ElementAnimations::PurgeAnimationsMarkedForDeletion() {
931 animations_.erase(
932 std::remove_if(animations_.begin(), animations_.end(),
933 [](const std::unique_ptr<Animation>& animation) {
934 return animation->run_state() ==
935 Animation::WAITING_FOR_DELETION;
936 }),
937 animations_.end());
938 }
939
940 void ElementAnimations::TickAnimations(base::TimeTicks monotonic_time) {
941 for (size_t i = 0; i < animations_.size(); ++i) {
942 if (animations_[i]->run_state() == Animation::STARTING ||
943 animations_[i]->run_state() == Animation::RUNNING ||
944 animations_[i]->run_state() == Animation::PAUSED) {
945 if (!animations_[i]->InEffect(monotonic_time))
946 continue;
947
948 base::TimeDelta trimmed =
949 animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
950
951 switch (animations_[i]->target_property()) {
952 case TargetProperty::TRANSFORM: {
953 const TransformAnimationCurve* transform_animation_curve =
954 animations_[i]->curve()->ToTransformAnimationCurve();
955 const gfx::Transform transform =
956 transform_animation_curve->GetValue(trimmed);
957 NotifyObserversTransformAnimated(
958 transform, animations_[i]->affects_active_observers(),
959 animations_[i]->affects_pending_observers());
960 break;
961 }
962
963 case TargetProperty::OPACITY: {
964 const FloatAnimationCurve* float_animation_curve =
965 animations_[i]->curve()->ToFloatAnimationCurve();
966 const float opacity = std::max(
967 std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f);
968 NotifyObserversOpacityAnimated(
969 opacity, animations_[i]->affects_active_observers(),
970 animations_[i]->affects_pending_observers());
971 break;
972 }
973
974 case TargetProperty::FILTER: {
975 const FilterAnimationCurve* filter_animation_curve =
976 animations_[i]->curve()->ToFilterAnimationCurve();
977 const FilterOperations filter =
978 filter_animation_curve->GetValue(trimmed);
979 NotifyObserversFilterAnimated(
980 filter, animations_[i]->affects_active_observers(),
981 animations_[i]->affects_pending_observers());
982 break;
983 }
984
985 case TargetProperty::BACKGROUND_COLOR: {
986 // Not yet implemented.
987 break;
988 }
989
990 case TargetProperty::SCROLL_OFFSET: {
991 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
992 animations_[i]->curve()->ToScrollOffsetAnimationCurve();
993 const gfx::ScrollOffset scroll_offset =
994 scroll_offset_animation_curve->GetValue(trimmed);
995 NotifyObserversScrollOffsetAnimated(
996 scroll_offset, animations_[i]->affects_active_observers(),
997 animations_[i]->affects_pending_observers());
998 break;
999 }
1000 }
1001 }
1002 }
1003 }
1004
1005 void ElementAnimations::UpdateActivation(UpdateActivationType type) {
1006 bool force = type == FORCE_ACTIVATION;
1007 if (animation_host_) {
1008 bool was_active = is_active_;
1009 is_active_ = false;
1010 for (size_t i = 0; i < animations_.size(); ++i) {
1011 if (animations_[i]->run_state() != Animation::WAITING_FOR_DELETION) {
1012 is_active_ = true;
1013 break;
1014 }
1015 }
1016
1017 if (is_active_ && (!was_active || force))
1018 animation_host_->DidActivateElementAnimations(this);
1019 else if (!is_active_ && (was_active || force))
1020 animation_host_->DidDeactivateElementAnimations(this);
1021 }
1022 }
1023
1024 void ElementAnimations::NotifyObserversOpacityAnimated(
1025 float opacity,
1026 bool notify_active_observers,
1027 bool notify_pending_observers) {
1028 if (notify_active_observers && needs_active_value_observations())
1029 OnOpacityAnimated(LayerTreeType::ACTIVE, opacity);
1030 if (notify_pending_observers && needs_pending_value_observations())
1031 OnOpacityAnimated(LayerTreeType::PENDING, opacity);
1032 }
1033
1034 void ElementAnimations::NotifyObserversTransformAnimated(
1035 const gfx::Transform& transform,
1036 bool notify_active_observers,
1037 bool notify_pending_observers) {
1038 if (notify_active_observers && needs_active_value_observations())
1039 OnTransformAnimated(LayerTreeType::ACTIVE, transform);
1040 if (notify_pending_observers && needs_pending_value_observations())
1041 OnTransformAnimated(LayerTreeType::PENDING, transform);
1042 }
1043
1044 void ElementAnimations::NotifyObserversFilterAnimated(
1045 const FilterOperations& filters,
1046 bool notify_active_observers,
1047 bool notify_pending_observers) {
1048 if (notify_active_observers && needs_active_value_observations())
1049 OnFilterAnimated(LayerTreeType::ACTIVE, filters);
1050 if (notify_pending_observers && needs_pending_value_observations())
1051 OnFilterAnimated(LayerTreeType::PENDING, filters);
1052 }
1053
1054 void ElementAnimations::NotifyObserversScrollOffsetAnimated(
1055 const gfx::ScrollOffset& scroll_offset,
1056 bool notify_active_observers,
1057 bool notify_pending_observers) {
1058 if (notify_active_observers && needs_active_value_observations())
1059 OnScrollOffsetAnimated(LayerTreeType::ACTIVE, scroll_offset);
1060 if (notify_pending_observers && needs_pending_value_observations())
1061 OnScrollOffsetAnimated(LayerTreeType::PENDING, scroll_offset);
1062 }
1063
1064 void ElementAnimations::NotifyObserversAnimationWaitingForDeletion() {
1065 OnAnimationWaitingForDeletion();
1066 }
1067
1068 void ElementAnimations::NotifyObserversTransformIsPotentiallyAnimatingChanged(
1069 bool notify_active_observers,
1070 bool notify_pending_observers) {
1071 if (notify_active_observers && needs_active_value_observations())
1072 OnTransformIsPotentiallyAnimatingChanged(
1073 LayerTreeType::ACTIVE,
1074 potentially_animating_transform_for_active_observers_);
1075 if (notify_pending_observers && needs_pending_value_observations())
1076 OnTransformIsPotentiallyAnimatingChanged(
1077 LayerTreeType::PENDING,
1078 potentially_animating_transform_for_pending_observers_);
1079 }
1080
1081 void ElementAnimations::UpdatePotentiallyAnimatingTransform() {
1082 bool was_potentially_animating_transform_for_active_observers =
1083 potentially_animating_transform_for_active_observers_;
1084 bool was_potentially_animating_transform_for_pending_observers =
1085 potentially_animating_transform_for_pending_observers_;
1086
1087 potentially_animating_transform_for_active_observers_ = false;
1088 potentially_animating_transform_for_pending_observers_ = false;
1089
1090 for (const auto& animation : animations_) {
1091 if (!animation->is_finished() &&
1092 animation->target_property() == TargetProperty::TRANSFORM) {
1093 potentially_animating_transform_for_active_observers_ |=
1094 animation->affects_active_observers();
1095 potentially_animating_transform_for_pending_observers_ |=
1096 animation->affects_pending_observers();
1097 }
1098 }
1099
1100 bool changed_for_active_observers =
1101 was_potentially_animating_transform_for_active_observers !=
1102 potentially_animating_transform_for_active_observers_;
1103 bool changed_for_pending_observers =
1104 was_potentially_animating_transform_for_pending_observers !=
1105 potentially_animating_transform_for_pending_observers_;
1106
1107 if (!changed_for_active_observers && !changed_for_pending_observers)
1108 return;
1109
1110 NotifyObserversTransformIsPotentiallyAnimatingChanged(
1111 changed_for_active_observers, changed_for_pending_observers);
1112 }
1113
1114 bool ElementAnimations::HasActiveAnimation() const {
1115 for (size_t i = 0; i < animations_.size(); ++i) {
1116 if (!animations_[i]->is_finished())
1117 return true;
1118 }
1119 return false;
1120 }
1121
1122 bool ElementAnimations::IsPotentiallyAnimatingProperty(
1123 TargetProperty::Type target_property,
1124 ObserverType observer_type) const {
1125 for (size_t i = 0; i < animations_.size(); ++i) {
1126 if (!animations_[i]->is_finished() &&
1127 animations_[i]->target_property() == target_property) {
1128 if ((observer_type == ObserverType::ACTIVE &&
1129 animations_[i]->affects_active_observers()) ||
1130 (observer_type == ObserverType::PENDING &&
1131 animations_[i]->affects_pending_observers()))
1132 return true;
1133 }
1134 }
1135 return false;
1136 }
1137
1138 bool ElementAnimations::IsCurrentlyAnimatingProperty(
1139 TargetProperty::Type target_property,
1140 ObserverType observer_type) const {
1141 for (size_t i = 0; i < animations_.size(); ++i) {
1142 if (!animations_[i]->is_finished() &&
1143 animations_[i]->InEffect(last_tick_time_) &&
1144 animations_[i]->target_property() == target_property) {
1145 if ((observer_type == ObserverType::ACTIVE &&
1146 animations_[i]->affects_active_observers()) ||
1147 (observer_type == ObserverType::PENDING &&
1148 animations_[i]->affects_pending_observers()))
1149 return true;
1150 }
1151 }
1152 return false;
116 } 1153 }
117 1154
118 void ElementAnimations::PauseAnimation(int animation_id, 1155 void ElementAnimations::PauseAnimation(int animation_id,
119 base::TimeDelta time_offset) { 1156 base::TimeDelta time_offset) {
120 layer_animation_controller_->PauseAnimation(animation_id, time_offset); 1157 for (size_t i = 0; i < animations_.size(); ++i) {
1158 if (animations_[i]->id() == animation_id) {
1159 animations_[i]->SetRunState(Animation::PAUSED,
1160 time_offset + animations_[i]->start_time() +
1161 animations_[i]->time_offset());
1162 }
1163 }
121 } 1164 }
122 1165
123 void ElementAnimations::RemoveAnimation(int animation_id) { 1166 void ElementAnimations::RemoveAnimation(int animation_id) {
124 layer_animation_controller_->RemoveAnimation(animation_id); 1167 bool removed_transform_animation = false;
1168 // Since we want to use the animations that we're going to remove, we need to
1169 // use a stable_parition here instead of remove_if. Remove_if leaves the
1170 // removed items in an unspecified state.
1171 auto animations_to_remove = std::stable_partition(
1172 animations_.begin(), animations_.end(),
1173 [animation_id](const std::unique_ptr<Animation>& animation) {
1174 return animation->id() != animation_id;
1175 });
1176 for (auto it = animations_to_remove; it != animations_.end(); ++it) {
1177 if ((*it)->target_property() == TargetProperty::SCROLL_OFFSET) {
1178 scroll_offset_animation_was_interrupted_ = true;
1179 } else if ((*it)->target_property() == TargetProperty::TRANSFORM &&
1180 !(*it)->is_finished()) {
1181 removed_transform_animation = true;
1182 }
1183 }
1184
1185 animations_.erase(animations_to_remove, animations_.end());
1186 UpdateActivation(NORMAL_ACTIVATION);
1187 if (removed_transform_animation)
1188 UpdatePotentiallyAnimatingTransform();
125 } 1189 }
126 1190
127 void ElementAnimations::AbortAnimation(int animation_id) { 1191 void ElementAnimations::AbortAnimation(int animation_id) {
128 layer_animation_controller_->AbortAnimation(animation_id); 1192 bool aborted_transform_animation = false;
1193 if (Animation* animation = GetAnimationById(animation_id)) {
1194 if (!animation->is_finished()) {
1195 animation->SetRunState(Animation::ABORTED, last_tick_time_);
1196 if (animation->target_property() == TargetProperty::TRANSFORM)
1197 aborted_transform_animation = true;
1198 }
1199 }
1200 if (aborted_transform_animation)
1201 UpdatePotentiallyAnimatingTransform();
129 } 1202 }
130 1203
131 void ElementAnimations::AbortAnimations(TargetProperty::Type target_property, 1204 void ElementAnimations::AbortAnimations(TargetProperty::Type target_property,
132 bool needs_completion) { 1205 bool needs_completion) {
133 layer_animation_controller_->AbortAnimations(target_property, 1206 if (needs_completion)
134 needs_completion); 1207 DCHECK(target_property == TargetProperty::SCROLL_OFFSET);
1208
1209 bool aborted_transform_animation = false;
1210 for (size_t i = 0; i < animations_.size(); ++i) {
1211 if (animations_[i]->target_property() == target_property &&
1212 !animations_[i]->is_finished()) {
1213 // Currently only impl-only scroll offset animations can be completed on
1214 // the main thread.
1215 if (needs_completion && animations_[i]->is_impl_only()) {
1216 animations_[i]->SetRunState(Animation::ABORTED_BUT_NEEDS_COMPLETION,
1217 last_tick_time_);
1218 } else {
1219 animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_);
1220 }
1221 if (target_property == TargetProperty::TRANSFORM)
1222 aborted_transform_animation = true;
1223 }
1224 }
1225 if (aborted_transform_animation)
1226 UpdatePotentiallyAnimatingTransform();
135 } 1227 }
136 1228
137 Animation* ElementAnimations::GetAnimation( 1229 Animation* ElementAnimations::GetAnimation(
138 TargetProperty::Type target_property) const { 1230 TargetProperty::Type target_property) const {
139 return layer_animation_controller_->GetAnimation(target_property); 1231 for (size_t i = 0; i < animations_.size(); ++i) {
1232 size_t index = animations_.size() - i - 1;
1233 if (animations_[index]->target_property() == target_property)
1234 return animations_[index].get();
1235 }
1236 return nullptr;
140 } 1237 }
141 1238
142 Animation* ElementAnimations::GetAnimationById(int animation_id) const { 1239 Animation* ElementAnimations::GetAnimationById(int animation_id) const {
143 return layer_animation_controller_->GetAnimationById(animation_id); 1240 for (size_t i = 0; i < animations_.size(); ++i)
1241 if (animations_[i]->id() == animation_id)
1242 return animations_[i].get();
1243 return nullptr;
144 } 1244 }
145 1245
146 void ElementAnimations::OnFilterAnimated(LayerTreeType tree_type, 1246 void ElementAnimations::OnFilterAnimated(LayerTreeType tree_type,
147 const FilterOperations& filters) { 1247 const FilterOperations& filters) {
148 DCHECK(layer_id()); 1248 DCHECK(layer_id());
149 DCHECK(animation_host()); 1249 DCHECK(animation_host());
150 DCHECK(animation_host()->mutator_host_client()); 1250 DCHECK(animation_host()->mutator_host_client());
151 animation_host()->mutator_host_client()->SetLayerFilterMutated( 1251 animation_host()->mutator_host_client()->SetLayerFilterMutated(
152 layer_id(), tree_type, filters); 1252 layer_id(), tree_type, filters);
153 } 1253 }
(...skipping 22 matching lines...) Expand all
176 DCHECK(layer_id()); 1276 DCHECK(layer_id());
177 DCHECK(animation_host()); 1277 DCHECK(animation_host());
178 DCHECK(animation_host()->mutator_host_client()); 1278 DCHECK(animation_host()->mutator_host_client());
179 animation_host()->mutator_host_client()->SetLayerScrollOffsetMutated( 1279 animation_host()->mutator_host_client()->SetLayerScrollOffsetMutated(
180 layer_id(), tree_type, scroll_offset); 1280 layer_id(), tree_type, scroll_offset);
181 } 1281 }
182 1282
183 void ElementAnimations::OnAnimationWaitingForDeletion() { 1283 void ElementAnimations::OnAnimationWaitingForDeletion() {
184 // TODO(loyso): Invalidate AnimationHost::SetNeedsPushProperties here. 1284 // TODO(loyso): Invalidate AnimationHost::SetNeedsPushProperties here.
185 // But we always do PushProperties in AnimationHost for now. crbug.com/604280 1285 // But we always do PushProperties in AnimationHost for now. crbug.com/604280
1286 DCHECK(animation_host());
1287 animation_host()->OnAnimationWaitingForDeletion();
186 } 1288 }
187 1289
188 void ElementAnimations::OnTransformIsPotentiallyAnimatingChanged( 1290 void ElementAnimations::OnTransformIsPotentiallyAnimatingChanged(
189 LayerTreeType tree_type, 1291 LayerTreeType tree_type,
190 bool is_animating) { 1292 bool is_animating) {
191 DCHECK(layer_id()); 1293 DCHECK(layer_id());
192 DCHECK(animation_host()); 1294 DCHECK(animation_host());
193 DCHECK(animation_host()->mutator_host_client()); 1295 DCHECK(animation_host()->mutator_host_client());
194 animation_host() 1296 animation_host()
195 ->mutator_host_client() 1297 ->mutator_host_client()
196 ->LayerTransformIsPotentiallyAnimatingChanged(layer_id(), tree_type, 1298 ->LayerTransformIsPotentiallyAnimatingChanged(layer_id(), tree_type,
197 is_animating); 1299 is_animating);
198 } 1300 }
199 1301
200 void ElementAnimations::CreateActiveValueObserver() { 1302 void ElementAnimations::NotifyPlayersAnimationStarted(
201 DCHECK(layer_animation_controller_);
202 DCHECK(!needs_active_value_observations());
203 layer_animation_controller_->set_needs_active_value_observations(true);
204 }
205
206 void ElementAnimations::DestroyActiveValueObserver() {
207 if (layer_animation_controller_)
208 layer_animation_controller_->set_needs_active_value_observations(false);
209 }
210
211 void ElementAnimations::CreatePendingValueObserver() {
212 DCHECK(layer_animation_controller_);
213 DCHECK(!needs_pending_value_observations());
214 layer_animation_controller_->set_needs_pending_value_observations(true);
215 }
216
217 void ElementAnimations::DestroyPendingValueObserver() {
218 if (layer_animation_controller_)
219 layer_animation_controller_->set_needs_pending_value_observations(false);
220 }
221
222 void ElementAnimations::NotifyAnimationStarted(
223 base::TimeTicks monotonic_time, 1303 base::TimeTicks monotonic_time,
224 TargetProperty::Type target_property, 1304 TargetProperty::Type target_property,
225 int group) { 1305 int group) {
226 for (PlayersListNode* node = players_list_->head(); 1306 for (PlayersListNode* node = players_list_->head();
227 node != players_list_->end(); node = node->next()) { 1307 node != players_list_->end(); node = node->next()) {
228 AnimationPlayer* player = node->value(); 1308 AnimationPlayer* player = node->value();
229 player->NotifyAnimationStarted(monotonic_time, target_property, group); 1309 player->NotifyAnimationStarted(monotonic_time, target_property, group);
230 } 1310 }
231 } 1311 }
232 1312
233 void ElementAnimations::NotifyAnimationFinished( 1313 void ElementAnimations::NotifyPlayersAnimationFinished(
234 base::TimeTicks monotonic_time, 1314 base::TimeTicks monotonic_time,
235 TargetProperty::Type target_property, 1315 TargetProperty::Type target_property,
236 int group) { 1316 int group) {
237 for (PlayersListNode* node = players_list_->head(); 1317 for (PlayersListNode* node = players_list_->head();
238 node != players_list_->end(); node = node->next()) { 1318 node != players_list_->end(); node = node->next()) {
239 AnimationPlayer* player = node->value(); 1319 AnimationPlayer* player = node->value();
240 player->NotifyAnimationFinished(monotonic_time, target_property, group); 1320 player->NotifyAnimationFinished(monotonic_time, target_property, group);
241 } 1321 }
242 } 1322 }
243 1323
244 void ElementAnimations::NotifyAnimationAborted( 1324 void ElementAnimations::NotifyPlayersAnimationAborted(
245 base::TimeTicks monotonic_time, 1325 base::TimeTicks monotonic_time,
246 TargetProperty::Type target_property, 1326 TargetProperty::Type target_property,
247 int group) { 1327 int group) {
248 for (PlayersListNode* node = players_list_->head(); 1328 for (PlayersListNode* node = players_list_->head();
249 node != players_list_->end(); node = node->next()) { 1329 node != players_list_->end(); node = node->next()) {
250 AnimationPlayer* player = node->value(); 1330 AnimationPlayer* player = node->value();
251 player->NotifyAnimationAborted(monotonic_time, target_property, group); 1331 player->NotifyAnimationAborted(monotonic_time, target_property, group);
252 } 1332 }
253 } 1333 }
254 1334
255 void ElementAnimations::NotifyAnimationTakeover( 1335 void ElementAnimations::NotifyPlayersAnimationTakeover(
256 base::TimeTicks monotonic_time, 1336 base::TimeTicks monotonic_time,
257 TargetProperty::Type target_property, 1337 TargetProperty::Type target_property,
258 double animation_start_time, 1338 double animation_start_time,
259 std::unique_ptr<AnimationCurve> curve) { 1339 std::unique_ptr<AnimationCurve> curve) {
260 DCHECK(curve); 1340 DCHECK(curve);
261 for (PlayersListNode* node = players_list_->head(); 1341 for (PlayersListNode* node = players_list_->head();
262 node != players_list_->end(); node = node->next()) { 1342 node != players_list_->end(); node = node->next()) {
263 std::unique_ptr<AnimationCurve> animation_curve = curve->Clone(); 1343 std::unique_ptr<AnimationCurve> animation_curve = curve->Clone();
264 AnimationPlayer* player = node->value(); 1344 AnimationPlayer* player = node->value();
265 player->NotifyAnimationTakeover(monotonic_time, target_property, 1345 player->NotifyAnimationTakeover(monotonic_time, target_property,
266 animation_start_time, 1346 animation_start_time,
267 std::move(animation_curve)); 1347 std::move(animation_curve));
268 } 1348 }
269 } 1349 }
270 1350
271 gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const { 1351 gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const {
272 DCHECK(layer_animation_controller_);
273 if (animation_host()) { 1352 if (animation_host()) {
274 DCHECK(animation_host()->mutator_host_client()); 1353 DCHECK(animation_host()->mutator_host_client());
275 return animation_host()->mutator_host_client()->GetScrollOffsetForAnimation( 1354 return animation_host()->mutator_host_client()->GetScrollOffsetForAnimation(
276 layer_id()); 1355 layer_id());
277 } 1356 }
278 1357
279 return gfx::ScrollOffset(); 1358 return gfx::ScrollOffset();
280 } 1359 }
281 1360
282 } // namespace cc 1361 } // namespace cc
OLDNEW
« no previous file with comments | « cc/animation/element_animations.h ('k') | cc/animation/element_animations_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698