Use Histogram algorithm to calculate DNS timeout.
[chromium-blink-merge.git] / ui / compositor / layer_animation_sequence.cc
blob371e54092194557b4933c0d038b2be131609a51c
1 // Copyright (c) 2012 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 "ui/compositor/layer_animation_sequence.h"
7 #include <algorithm>
8 #include <iterator>
10 #include "base/debug/trace_event.h"
11 #include "ui/compositor/layer_animation_delegate.h"
12 #include "ui/compositor/layer_animation_element.h"
13 #include "ui/compositor/layer_animation_observer.h"
15 namespace ui {
17 LayerAnimationSequence::LayerAnimationSequence()
18 : is_cyclic_(false),
19 last_element_(0),
20 waiting_for_group_start_(false),
21 animation_group_id_(0),
22 last_progressed_fraction_(0.0) {
25 LayerAnimationSequence::LayerAnimationSequence(LayerAnimationElement* element)
26 : is_cyclic_(false),
27 last_element_(0),
28 waiting_for_group_start_(false),
29 animation_group_id_(0),
30 last_progressed_fraction_(0.0) {
31 AddElement(element);
34 LayerAnimationSequence::~LayerAnimationSequence() {
35 FOR_EACH_OBSERVER(LayerAnimationObserver,
36 observers_,
37 DetachedFromSequence(this, true));
40 void LayerAnimationSequence::Start(LayerAnimationDelegate* delegate) {
41 DCHECK(start_time_ != base::TimeTicks());
42 last_progressed_fraction_ = 0.0;
43 if (elements_.empty())
44 return;
46 elements_[0]->set_requested_start_time(start_time_);
47 elements_[0]->Start(delegate, animation_group_id_);
50 void LayerAnimationSequence::Progress(base::TimeTicks now,
51 LayerAnimationDelegate* delegate) {
52 DCHECK(start_time_ != base::TimeTicks());
53 bool redraw_required = false;
55 if (elements_.empty())
56 return;
58 if (last_element_ == 0)
59 last_start_ = start_time_;
61 size_t current_index = last_element_ % elements_.size();
62 base::TimeDelta element_duration;
63 while (is_cyclic_ || last_element_ < elements_.size()) {
64 elements_[current_index]->set_requested_start_time(last_start_);
65 if (!elements_[current_index]->IsFinished(now, &element_duration))
66 break;
68 // Let the element we're passing finish.
69 if (elements_[current_index]->ProgressToEnd(delegate))
70 redraw_required = true;
71 last_start_ += element_duration;
72 ++last_element_;
73 last_progressed_fraction_ =
74 elements_[current_index]->last_progressed_fraction();
75 current_index = last_element_ % elements_.size();
78 if (is_cyclic_ || last_element_ < elements_.size()) {
79 if (!elements_[current_index]->Started())
80 elements_[current_index]->Start(delegate, animation_group_id_);
81 if (elements_[current_index]->Progress(now, delegate))
82 redraw_required = true;
83 last_progressed_fraction_ =
84 elements_[current_index]->last_progressed_fraction();
87 // Since the delegate may be deleted due to the notifications below, it is
88 // important that we schedule a draw before sending them.
89 if (redraw_required)
90 delegate->ScheduleDrawForAnimation();
92 if (!is_cyclic_ && last_element_ == elements_.size()) {
93 last_element_ = 0;
94 waiting_for_group_start_ = false;
95 animation_group_id_ = 0;
96 NotifyEnded();
100 bool LayerAnimationSequence::IsFinished(base::TimeTicks time) {
101 if (is_cyclic_ || waiting_for_group_start_)
102 return false;
104 if (elements_.empty())
105 return true;
107 if (last_element_ == 0)
108 last_start_ = start_time_;
110 base::TimeTicks current_start = last_start_;
111 size_t current_index = last_element_;
112 base::TimeDelta element_duration;
113 while (current_index < elements_.size()) {
114 elements_[current_index]->set_requested_start_time(current_start);
115 if (!elements_[current_index]->IsFinished(time, &element_duration))
116 break;
118 current_start += element_duration;
119 ++current_index;
122 return (current_index == elements_.size());
125 void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) {
126 bool redraw_required = false;
128 if (elements_.empty())
129 return;
131 size_t current_index = last_element_ % elements_.size();
132 while (current_index < elements_.size()) {
133 if (elements_[current_index]->ProgressToEnd(delegate))
134 redraw_required = true;
135 last_progressed_fraction_ =
136 elements_[current_index]->last_progressed_fraction();
137 ++current_index;
138 ++last_element_;
141 if (redraw_required)
142 delegate->ScheduleDrawForAnimation();
144 if (!is_cyclic_) {
145 last_element_ = 0;
146 waiting_for_group_start_ = false;
147 animation_group_id_ = 0;
148 NotifyEnded();
152 void LayerAnimationSequence::GetTargetValue(
153 LayerAnimationElement::TargetValue* target) const {
154 if (is_cyclic_)
155 return;
157 for (size_t i = last_element_; i < elements_.size(); ++i)
158 elements_[i]->GetTargetValue(target);
161 void LayerAnimationSequence::Abort(LayerAnimationDelegate* delegate) {
162 size_t current_index = last_element_ % elements_.size();
163 while (current_index < elements_.size()) {
164 elements_[current_index]->Abort(delegate);
165 ++current_index;
167 last_element_ = 0;
168 waiting_for_group_start_ = false;
169 NotifyAborted();
172 void LayerAnimationSequence::AddElement(LayerAnimationElement* element) {
173 properties_.insert(element->properties().begin(),
174 element->properties().end());
175 elements_.push_back(make_linked_ptr(element));
178 bool LayerAnimationSequence::HasConflictingProperty(
179 const LayerAnimationElement::AnimatableProperties& other) const {
180 LayerAnimationElement::AnimatableProperties intersection;
181 std::insert_iterator<LayerAnimationElement::AnimatableProperties> ii(
182 intersection, intersection.begin());
183 std::set_intersection(properties_.begin(), properties_.end(),
184 other.begin(), other.end(),
185 ii);
186 return (intersection.size() > 0);
189 bool LayerAnimationSequence::IsFirstElementThreaded() const {
190 if (!elements_.empty())
191 return elements_[0]->IsThreaded();
193 return false;
196 void LayerAnimationSequence::AddObserver(LayerAnimationObserver* observer) {
197 if (!observers_.HasObserver(observer)) {
198 observers_.AddObserver(observer);
199 observer->AttachedToSequence(this);
203 void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver* observer) {
204 observers_.RemoveObserver(observer);
205 observer->DetachedFromSequence(this, true);
208 void LayerAnimationSequence::OnThreadedAnimationStarted(
209 const cc::AnimationEvent& event) {
210 if (elements_.empty() || event.group_id != animation_group_id_)
211 return;
213 size_t current_index = last_element_ % elements_.size();
214 const LayerAnimationElement::AnimatableProperties& element_properties =
215 elements_[current_index]->properties();
216 LayerAnimationElement::AnimatableProperty event_property =
217 LayerAnimationElement::ToAnimatableProperty(event.target_property);
218 DCHECK(element_properties.find(event_property) != element_properties.end());
219 elements_[current_index]->set_effective_start_time(
220 base::TimeTicks::FromInternalValue(
221 event.monotonic_time * base::Time::kMicrosecondsPerSecond));
224 void LayerAnimationSequence::OnScheduled() {
225 NotifyScheduled();
228 void LayerAnimationSequence::OnAnimatorDestroyed() {
229 if (observers_.might_have_observers()) {
230 ObserverListBase<LayerAnimationObserver>::Iterator it(observers_);
231 LayerAnimationObserver* obs;
232 while ((obs = it.GetNext()) != NULL) {
233 if (!obs->RequiresNotificationWhenAnimatorDestroyed()) {
234 // Remove the observer, but do not allow notifications to be sent.
235 observers_.RemoveObserver(obs);
236 obs->DetachedFromSequence(this, false);
242 void LayerAnimationSequence::NotifyScheduled() {
243 FOR_EACH_OBSERVER(LayerAnimationObserver,
244 observers_,
245 OnLayerAnimationScheduled(this));
248 void LayerAnimationSequence::NotifyEnded() {
249 FOR_EACH_OBSERVER(LayerAnimationObserver,
250 observers_,
251 OnLayerAnimationEnded(this));
254 void LayerAnimationSequence::NotifyAborted() {
255 FOR_EACH_OBSERVER(LayerAnimationObserver,
256 observers_,
257 OnLayerAnimationAborted(this));
260 LayerAnimationElement* LayerAnimationSequence::CurrentElement() {
261 if (elements_.empty())
262 return NULL;
264 size_t current_index = last_element_ % elements_.size();
265 return elements_[current_index].get();
268 } // namespace ui