OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 { | 54 { |
55 RefPtrWillBeRawPtr<AnimationPlayer> player = adoptRefWillBeNoop(new Animatio
nPlayer(executionContext, timeline, content)); | 55 RefPtrWillBeRawPtr<AnimationPlayer> player = adoptRefWillBeNoop(new Animatio
nPlayer(executionContext, timeline, content)); |
56 player->uncancel(); | 56 player->uncancel(); |
57 timeline.document()->compositorPendingAnimations().add(player.get()); | 57 timeline.document()->compositorPendingAnimations().add(player.get()); |
58 player->suspendIfNeeded(); | 58 player->suspendIfNeeded(); |
59 return player.release(); | 59 return player.release(); |
60 } | 60 } |
61 | 61 |
62 AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTi
meline& timeline, AnimationNode* content) | 62 AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTi
meline& timeline, AnimationNode* content) |
63 : ActiveDOMObject(executionContext) | 63 : ActiveDOMObject(executionContext) |
| 64 , m_playState(Idle) |
64 , m_playbackRate(1) | 65 , m_playbackRate(1) |
65 , m_startTime(nullValue()) | 66 , m_startTime(nullValue()) |
66 , m_holdTime(0) | 67 , m_holdTime(0) |
67 , m_sequenceNumber(nextSequenceNumber()) | 68 , m_sequenceNumber(nextSequenceNumber()) |
68 , m_content(content) | 69 , m_content(content) |
69 , m_timeline(&timeline) | 70 , m_timeline(&timeline) |
70 , m_paused(false) | 71 , m_paused(false) |
71 , m_held(true) | 72 , m_held(true) |
72 , m_isPausedForTesting(false) | 73 , m_isPausedForTesting(false) |
73 , m_outdated(true) | 74 , m_outdated(true) |
74 , m_finished(true) | 75 , m_finished(true) |
75 , m_compositorState(nullptr) | 76 , m_compositorState(nullptr) |
76 , m_compositorPending(true) | 77 , m_compositorPending(true) |
77 , m_currentTimePending(false) | 78 , m_currentTimePending(false) |
78 , m_idle(true) | |
79 { | 79 { |
80 if (m_content) { | 80 if (m_content) { |
81 if (m_content->player()) { | 81 if (m_content->player()) { |
82 m_content->player()->cancel(); | 82 m_content->player()->cancel(); |
83 m_content->player()->setSource(0); | 83 m_content->player()->setSource(0); |
84 } | 84 } |
85 m_content->attach(this); | 85 m_content->attach(this); |
86 } | 86 } |
87 } | 87 } |
88 | 88 |
(...skipping 10 matching lines...) Expand all Loading... |
99 double AnimationPlayer::sourceEnd() const | 99 double AnimationPlayer::sourceEnd() const |
100 { | 100 { |
101 return m_content ? m_content->endTimeInternal() : 0; | 101 return m_content ? m_content->endTimeInternal() : 0; |
102 } | 102 } |
103 | 103 |
104 bool AnimationPlayer::limited(double currentTime) const | 104 bool AnimationPlayer::limited(double currentTime) const |
105 { | 105 { |
106 return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && cu
rrentTime >= sourceEnd()); | 106 return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && cu
rrentTime >= sourceEnd()); |
107 } | 107 } |
108 | 108 |
| 109 void AnimationPlayer::setCurrentTime(double newCurrentTime) |
| 110 { |
| 111 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentT
ime); |
| 112 if (!std::isfinite(newCurrentTime)) |
| 113 return; |
| 114 |
| 115 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 116 |
| 117 m_currentTimePending = false; |
| 118 setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); |
| 119 } |
| 120 |
109 void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdate
Reason reason) | 121 void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdate
Reason reason) |
110 { | 122 { |
111 ASSERT(std::isfinite(newCurrentTime)); | 123 ASSERT(std::isfinite(newCurrentTime)); |
112 | 124 |
113 bool oldHeld = m_held; | 125 bool oldHeld = m_held; |
114 bool outdated = false; | 126 bool outdated = false; |
115 bool isLimited = limited(newCurrentTime); | 127 bool isLimited = limited(newCurrentTime); |
116 m_held = m_paused || !m_playbackRate || isLimited || std::isnan(m_startTime)
; | 128 m_held = m_paused || !m_playbackRate || isLimited || std::isnan(m_startTime)
; |
117 if (m_held) { | 129 if (m_held) { |
118 if (!oldHeld || m_holdTime != newCurrentTime) | 130 if (!oldHeld || m_holdTime != newCurrentTime) |
119 outdated = true; | 131 outdated = true; |
120 m_holdTime = newCurrentTime; | 132 m_holdTime = newCurrentTime; |
121 if (m_paused || !m_playbackRate) { | 133 if (m_paused || !m_playbackRate) { |
122 m_startTime = nullValue(); | 134 m_startTime = nullValue(); |
123 } else if (isLimited && std::isnan(m_startTime) && reason == TimingUpdat
eForAnimationFrame) { | 135 } else if (isLimited && std::isnan(m_startTime) && reason == TimingUpdat
eForAnimationFrame) { |
124 m_startTime = calculateStartTime(newCurrentTime); | 136 m_startTime = calculateStartTime(newCurrentTime); |
125 } | 137 } |
126 } else { | 138 } else { |
127 m_holdTime = nullValue(); | 139 m_holdTime = nullValue(); |
128 m_startTime = calculateStartTime(newCurrentTime); | 140 m_startTime = calculateStartTime(newCurrentTime); |
129 setFinished(false); | 141 m_finished = false; |
130 outdated = true; | 142 outdated = true; |
131 } | 143 } |
132 | 144 |
133 if (outdated) { | 145 if (outdated) { |
134 setOutdated(); | 146 setOutdated(); |
135 } | 147 } |
136 } | 148 } |
137 | 149 |
138 // Update timing to reflect updated animation clock due to tick | 150 // Update timing to reflect updated animation clock due to tick |
139 void AnimationPlayer::updateCurrentTimingState(TimingUpdateReason reason) | 151 void AnimationPlayer::updateCurrentTimingState(TimingUpdateReason reason) |
(...skipping 23 matching lines...) Expand all Loading... |
163 | 175 |
164 double AnimationPlayer::currentTime(bool& isNull) | 176 double AnimationPlayer::currentTime(bool& isNull) |
165 { | 177 { |
166 double result = currentTime(); | 178 double result = currentTime(); |
167 isNull = std::isnan(result); | 179 isNull = std::isnan(result); |
168 return result; | 180 return result; |
169 } | 181 } |
170 | 182 |
171 double AnimationPlayer::currentTime() | 183 double AnimationPlayer::currentTime() |
172 { | 184 { |
| 185 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 186 |
173 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetCurrentT
ime); | 187 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetCurrentT
ime); |
174 if (m_currentTimePending || m_idle) | 188 if (m_currentTimePending || playStateInternal() == Idle) |
175 return std::numeric_limits<double>::quiet_NaN(); | 189 return std::numeric_limits<double>::quiet_NaN(); |
| 190 |
176 return currentTimeInternal() * 1000; | 191 return currentTimeInternal() * 1000; |
177 } | 192 } |
178 | 193 |
179 double AnimationPlayer::currentTimeInternal() | 194 double AnimationPlayer::currentTimeInternal() const |
180 { | 195 { |
181 updateCurrentTimingState(TimingUpdateOnDemand); | 196 double result = m_held ? m_holdTime : calculateCurrentTime(); |
182 if (m_held) | 197 #if ENABLE(ASSERT) |
183 return m_holdTime; | 198 const_cast<AnimationPlayer*>(this)->updateCurrentTimingState(TimingUpdateOnD
emand); |
184 return calculateCurrentTime(); | 199 ASSERT(result == (m_held ? m_holdTime : calculateCurrentTime())); |
| 200 #endif |
| 201 return result; |
185 } | 202 } |
186 | 203 |
187 void AnimationPlayer::preCommit(bool startOnCompositor) | 204 void AnimationPlayer::preCommit(bool startOnCompositor) |
188 { | 205 { |
189 if (m_compositorState && m_compositorState->pendingAction == Start) { | 206 if (m_compositorState && m_compositorState->pendingAction == Start) { |
190 // Still waiting for a start time. | 207 // Still waiting for a start time. |
191 return; | 208 return; |
192 } | 209 } |
193 | 210 |
| 211 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompos
itorPending); |
| 212 |
194 bool softChange = m_compositorState && (paused() || m_compositorState->playb
ackRate != m_playbackRate); | 213 bool softChange = m_compositorState && (paused() || m_compositorState->playb
ackRate != m_playbackRate); |
195 bool hardChange = m_compositorState && (m_compositorState->sourceChanged ||
(m_compositorState->startTime != m_startTime && !std::isnan(m_compositorState->s
tartTime) && !std::isnan(m_startTime))); | 214 bool hardChange = m_compositorState && (m_compositorState->sourceChanged ||
(m_compositorState->startTime != m_startTime && !std::isnan(m_compositorState->s
tartTime) && !std::isnan(m_startTime))); |
196 | 215 |
197 // FIXME: softChange && !hardChange should generate a Pause/ThenStart, | 216 // FIXME: softChange && !hardChange should generate a Pause/ThenStart, |
198 // not a Cancel, but we can't communicate these to the compositor yet. | 217 // not a Cancel, but we can't communicate these to the compositor yet. |
199 | 218 |
200 bool changed = softChange || hardChange; | 219 bool changed = softChange || hardChange; |
201 bool shouldCancel = (!playing() && m_compositorState) || changed; | 220 bool shouldCancel = (!playing() && m_compositorState) || changed; |
202 bool shouldStart = playing() && (!m_compositorState || changed); | 221 bool shouldStart = playing() && (!m_compositorState || changed); |
203 | 222 |
204 if (shouldCancel) { | 223 if (shouldCancel) { |
205 cancelAnimationOnCompositor(); | 224 cancelAnimationOnCompositor(); |
206 m_compositorState = nullptr; | 225 m_compositorState = nullptr; |
207 | |
208 } | 226 } |
209 | 227 |
210 if (!shouldStart) { | 228 if (!shouldStart) { |
211 m_currentTimePending = false; | 229 m_currentTimePending = false; |
212 } | 230 } |
213 | 231 |
214 if (shouldStart && startOnCompositor && maybeStartAnimationOnCompositor()) { | 232 if (shouldStart && startOnCompositor && maybeStartAnimationOnCompositor()) { |
215 m_compositorState = adoptPtr(new CompositorState(*this)); | 233 m_compositorState = adoptPtr(new CompositorState(*this)); |
216 } | 234 } |
217 } | 235 } |
218 | 236 |
219 void AnimationPlayer::postCommit(double timelineTime) | 237 void AnimationPlayer::postCommit(double timelineTime) |
220 { | 238 { |
| 239 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompos
itorPending); |
| 240 |
221 m_compositorPending = false; | 241 m_compositorPending = false; |
222 | 242 |
223 if (!m_compositorState || m_compositorState->pendingAction == None) | 243 if (!m_compositorState || m_compositorState->pendingAction == None) |
224 return; | 244 return; |
225 | 245 |
226 switch (m_compositorState->pendingAction) { | 246 switch (m_compositorState->pendingAction) { |
227 case Start: | 247 case Start: |
228 if (!std::isnan(m_compositorState->startTime)) { | 248 if (!std::isnan(m_compositorState->startTime)) { |
229 ASSERT(m_startTime == m_compositorState->startTime); | 249 ASSERT(m_startTime == m_compositorState->startTime); |
230 m_compositorState->pendingAction = None; | 250 m_compositorState->pendingAction = None; |
231 } | 251 } |
232 break; | 252 break; |
233 case Pause: | 253 case Pause: |
234 case PauseThenStart: | 254 case PauseThenStart: |
235 ASSERT(std::isnan(m_startTime)); | 255 ASSERT(std::isnan(m_startTime)); |
236 m_compositorState->pendingAction = None; | 256 m_compositorState->pendingAction = None; |
237 setCurrentTimeInternal((timelineTime - m_compositorState->startTime) * m
_playbackRate, TimingUpdateForAnimationFrame); | 257 setCurrentTimeInternal((timelineTime - m_compositorState->startTime) * m
_playbackRate, TimingUpdateForAnimationFrame); |
238 m_currentTimePending = false; | 258 m_currentTimePending = false; |
239 break; | 259 break; |
240 default: | 260 default: |
241 ASSERT_NOT_REACHED(); | 261 ASSERT_NOT_REACHED(); |
242 } | 262 } |
243 } | 263 } |
244 | 264 |
245 void AnimationPlayer::notifyCompositorStartTime(double timelineTime) | 265 void AnimationPlayer::notifyCompositorStartTime(double timelineTime) |
246 { | 266 { |
| 267 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 268 |
247 if (m_compositorState) { | 269 if (m_compositorState) { |
248 ASSERT(m_compositorState->pendingAction == Start); | 270 ASSERT(m_compositorState->pendingAction == Start); |
249 ASSERT(std::isnan(m_compositorState->startTime)); | 271 ASSERT(std::isnan(m_compositorState->startTime)); |
250 | 272 |
251 double initialCompositorHoldTime = m_compositorState->holdTime; | 273 double initialCompositorHoldTime = m_compositorState->holdTime; |
252 m_compositorState->pendingAction = None; | 274 m_compositorState->pendingAction = None; |
253 m_compositorState->startTime = timelineTime; | 275 m_compositorState->startTime = timelineTime; |
254 | 276 |
255 if (paused() || m_compositorState->playbackRate != m_playbackRate || m_c
ompositorState->sourceChanged) { | |
256 // Paused state, playback rate, or source changed while starting. | |
257 setCompositorPending(); | |
258 } | |
259 | |
260 if (m_startTime == timelineTime) { | 277 if (m_startTime == timelineTime) { |
261 // The start time was set to the incoming compositor start time. | 278 // The start time was set to the incoming compositor start time. |
262 // Unlikely, but possible. | 279 // Unlikely, but possible. |
263 // FIXME: Depending on what changed above this might still be pendin
g. | 280 // FIXME: Depending on what changed above this might still be pendin
g. |
264 // Maybe... | 281 // Maybe... |
265 m_currentTimePending = false; | 282 m_currentTimePending = false; |
266 return; | 283 return; |
267 } | 284 } |
268 | 285 |
269 if (!std::isnan(m_startTime) || currentTimeInternal() != initialComposit
orHoldTime) { | 286 if (!std::isnan(m_startTime) || currentTimeInternal() != initialComposit
orHoldTime) { |
270 // A new start time or current time was set while starting. | 287 // A new start time or current time was set while starting. |
271 setCompositorPending(); | 288 setCompositorPending(true); |
272 return; | 289 return; |
273 } | 290 } |
274 } | 291 } |
275 | 292 |
| 293 notifyStartTime(timelineTime); |
| 294 } |
| 295 |
| 296 void AnimationPlayer::notifyStartTime(double timelineTime) |
| 297 { |
276 if (playing()) { | 298 if (playing()) { |
277 ASSERT(std::isnan(m_startTime)); | 299 ASSERT(std::isnan(m_startTime)); |
278 ASSERT(m_held); | 300 ASSERT(m_held); |
279 | 301 |
280 if (m_playbackRate == 0) { | 302 if (m_playbackRate == 0) { |
281 setStartTimeInternal(timelineTime); | 303 setStartTimeInternal(timelineTime); |
282 } else { | 304 } else { |
283 setStartTimeInternal(timelineTime + currentTimeInternal() / -m_playb
ackRate); | 305 setStartTimeInternal(timelineTime + currentTimeInternal() / -m_playb
ackRate); |
284 } | 306 } |
285 | 307 |
(...skipping 11 matching lines...) Expand all Loading... |
297 } | 319 } |
298 | 320 |
299 double AnimationPlayer::calculateCurrentTime() const | 321 double AnimationPlayer::calculateCurrentTime() const |
300 { | 322 { |
301 ASSERT(!m_held); | 323 ASSERT(!m_held); |
302 if (isNull(m_startTime) || !m_timeline) | 324 if (isNull(m_startTime) || !m_timeline) |
303 return 0; | 325 return 0; |
304 return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate; | 326 return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate; |
305 } | 327 } |
306 | 328 |
307 void AnimationPlayer::setCurrentTime(double newCurrentTime) | |
308 { | |
309 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentT
ime); | |
310 if (!std::isfinite(newCurrentTime)) | |
311 return; | |
312 | |
313 setCompositorPending(); | |
314 m_currentTimePending = false; | |
315 setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); | |
316 } | |
317 | |
318 void AnimationPlayer::setStartTime(double startTime) | 329 void AnimationPlayer::setStartTime(double startTime) |
319 { | 330 { |
| 331 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 332 |
320 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetStartTim
e); | 333 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetStartTim
e); |
321 if (m_paused || m_idle) | 334 if (m_paused || playStateInternal() == Idle) |
322 return; | 335 return; |
323 if (!std::isfinite(startTime)) | 336 if (!std::isfinite(startTime)) |
324 return; | 337 return; |
325 if (startTime == m_startTime) | 338 if (startTime == m_startTime) |
326 return; | 339 return; |
327 | 340 |
328 setCompositorPending(); | |
329 m_currentTimePending = false; | 341 m_currentTimePending = false; |
330 setStartTimeInternal(startTime / 1000); | 342 setStartTimeInternal(startTime / 1000); |
331 } | 343 } |
332 | 344 |
333 void AnimationPlayer::setStartTimeInternal(double newStartTime) | 345 void AnimationPlayer::setStartTimeInternal(double newStartTime) |
334 { | 346 { |
335 ASSERT(!m_paused); | 347 ASSERT(!m_paused); |
336 ASSERT(std::isfinite(newStartTime)); | 348 ASSERT(std::isfinite(newStartTime)); |
337 ASSERT(newStartTime != m_startTime); | 349 ASSERT(newStartTime != m_startTime); |
338 | 350 |
339 bool hadStartTime = hasStartTime(); | 351 bool hadStartTime = hasStartTime(); |
340 double previousCurrentTime = currentTimeInternal(); | 352 double previousCurrentTime = currentTimeInternal(); |
341 m_startTime = newStartTime; | 353 m_startTime = newStartTime; |
342 if (m_held && m_playbackRate) { | 354 if (m_held && m_playbackRate) { |
343 // If held, the start time would still be derrived from the hold time. | 355 // If held, the start time would still be derrived from the hold time. |
344 // Force a new, limited, current time. | 356 // Force a new, limited, current time. |
345 m_held = false; | 357 m_held = false; |
346 double currentTime = calculateCurrentTime(); | 358 double currentTime = calculateCurrentTime(); |
347 if (m_playbackRate > 0 && currentTime > sourceEnd()) { | 359 if (m_playbackRate > 0 && currentTime > sourceEnd()) { |
348 currentTime = sourceEnd(); | 360 currentTime = sourceEnd(); |
349 } else if (m_playbackRate < 0 && currentTime < 0) { | 361 } else if (m_playbackRate < 0 && currentTime < 0) { |
350 currentTime = 0; | 362 currentTime = 0; |
351 } | 363 } |
352 setCurrentTimeInternal(currentTime, TimingUpdateOnDemand); | 364 setCurrentTimeInternal(currentTime, TimingUpdateOnDemand); |
353 } | 365 } |
| 366 updateCurrentTimingState(TimingUpdateOnDemand); |
354 double newCurrentTime = currentTimeInternal(); | 367 double newCurrentTime = currentTimeInternal(); |
355 | 368 |
356 if (previousCurrentTime != newCurrentTime) { | 369 if (previousCurrentTime != newCurrentTime) { |
357 setOutdated(); | 370 setOutdated(); |
358 } else if (!hadStartTime && m_timeline) { | 371 } else if (!hadStartTime && m_timeline) { |
359 // Even though this player is not outdated, time to effect change is | 372 // Even though this player is not outdated, time to effect change is |
360 // infinity until start time is set. | 373 // infinity until start time is set. |
361 m_timeline->wake(); | 374 m_timeline->wake(); |
362 } | 375 } |
363 } | 376 } |
364 | 377 |
365 void AnimationPlayer::setSource(AnimationNode* newSource) | 378 void AnimationPlayer::setSource(AnimationNode* newSource) |
366 { | 379 { |
367 if (m_content == newSource) | 380 if (m_content == newSource) |
368 return; | 381 return; |
369 | 382 |
370 setCompositorPending(true); | 383 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, SetCompositorP
endingWithSourceChanged); |
371 | 384 |
372 double storedCurrentTime = currentTimeInternal(); | 385 double storedCurrentTime = currentTimeInternal(); |
373 if (m_content) | 386 if (m_content) |
374 m_content->detach(); | 387 m_content->detach(); |
375 m_content = newSource; | 388 m_content = newSource; |
376 if (newSource) { | 389 if (newSource) { |
377 // FIXME: This logic needs to be updated once groups are implemented | 390 // FIXME: This logic needs to be updated once groups are implemented |
378 if (newSource->player()) { | 391 if (newSource->player()) { |
379 newSource->player()->cancel(); | 392 newSource->player()->cancel(); |
380 newSource->player()->setSource(0); | 393 newSource->player()->setSource(0); |
381 } | 394 } |
382 newSource->attach(this); | 395 newSource->attach(this); |
383 setOutdated(); | 396 setOutdated(); |
384 } | 397 } |
385 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); | 398 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); |
386 } | 399 } |
387 | 400 |
388 String AnimationPlayer::playState() | 401 const char* AnimationPlayer::playStateString(AnimationPlayState playState) |
389 { | 402 { |
390 switch (playStateInternal()) { | 403 switch (playState) { |
391 case Idle: | 404 case Idle: |
392 return "idle"; | 405 return "idle"; |
393 case Pending: | 406 case Pending: |
394 return "pending"; | 407 return "pending"; |
395 case Running: | 408 case Running: |
396 return "running"; | 409 return "running"; |
397 case Paused: | 410 case Paused: |
398 return "paused"; | 411 return "paused"; |
399 case Finished: | 412 case Finished: |
400 return "finished"; | 413 return "finished"; |
401 default: | 414 default: |
402 ASSERT_NOT_REACHED(); | 415 ASSERT_NOT_REACHED(); |
403 return ""; | 416 return ""; |
404 } | 417 } |
405 } | 418 } |
406 | 419 |
407 AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal() | 420 AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal() const |
408 { | 421 { |
409 if (m_idle) | 422 return m_playState; |
| 423 } |
| 424 |
| 425 AnimationPlayer::AnimationPlayState AnimationPlayer::calculatePlayState() |
| 426 { |
| 427 if (m_playState == Idle) |
410 return Idle; | 428 return Idle; |
411 if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackR
ate != 0)) | 429 if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackR
ate != 0)) |
412 return Pending; | 430 return Pending; |
413 if (m_paused) | 431 if (m_paused) |
414 return Paused; | 432 return Paused; |
415 if (finished()) | 433 if (finished()) |
416 return Finished; | 434 return Finished; |
417 return Running; | 435 return Running; |
418 } | 436 } |
419 | 437 |
420 void AnimationPlayer::pause() | 438 void AnimationPlayer::pause() |
421 { | 439 { |
422 if (m_paused) | 440 if (m_paused) |
423 return; | 441 return; |
| 442 |
| 443 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 444 |
424 if (playing()) { | 445 if (playing()) { |
425 setCompositorPending(); | |
426 m_currentTimePending = true; | 446 m_currentTimePending = true; |
427 } | 447 } |
428 m_paused = true; | 448 m_paused = true; |
429 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); | 449 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); |
430 } | 450 } |
431 | 451 |
432 void AnimationPlayer::unpause() | 452 void AnimationPlayer::unpause() |
433 { | 453 { |
434 if (!m_paused) | 454 if (!m_paused) |
435 return; | 455 return; |
436 setCompositorPending(); | 456 |
| 457 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 458 |
437 m_currentTimePending = true; | 459 m_currentTimePending = true; |
438 unpauseInternal(); | 460 unpauseInternal(); |
439 } | 461 } |
440 | 462 |
441 void AnimationPlayer::unpauseInternal() | 463 void AnimationPlayer::unpauseInternal() |
442 { | 464 { |
443 if (!m_paused) | 465 if (!m_paused) |
444 return; | 466 return; |
445 m_paused = false; | 467 m_paused = false; |
446 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); | 468 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); |
447 } | 469 } |
448 | 470 |
449 void AnimationPlayer::play() | 471 void AnimationPlayer::play() |
450 { | 472 { |
| 473 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 474 |
451 if (!playing()) | 475 if (!playing()) |
452 m_startTime = nullValue(); | 476 m_startTime = nullValue(); |
453 | 477 |
454 setCompositorPending(); | |
455 uncancel(); | 478 uncancel(); |
456 unpauseInternal(); | 479 unpauseInternal(); |
457 if (!m_content) | 480 if (!m_content) |
458 return; | 481 return; |
459 double currentTime = this->currentTimeInternal(); | 482 double currentTime = this->currentTimeInternal(); |
460 if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd())) | 483 if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd())) |
461 setCurrentTimeInternal(0, TimingUpdateOnDemand); | 484 setCurrentTimeInternal(0, TimingUpdateOnDemand); |
462 else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd(
))) | 485 else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd(
))) |
463 setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand); | 486 setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand); |
464 setFinished(false); | 487 m_finished = false; |
465 } | 488 } |
466 | 489 |
467 void AnimationPlayer::reverse() | 490 void AnimationPlayer::reverse() |
468 { | 491 { |
469 if (!m_playbackRate) { | 492 if (!m_playbackRate) { |
470 return; | 493 return; |
471 } | 494 } |
472 | 495 |
473 uncancel(); | 496 uncancel(); |
474 setPlaybackRateInternal(-m_playbackRate); | 497 setPlaybackRateInternal(-m_playbackRate); |
475 play(); | 498 play(); |
476 } | 499 } |
477 | 500 |
478 void AnimationPlayer::finish(ExceptionState& exceptionState) | 501 void AnimationPlayer::finish(ExceptionState& exceptionState) |
479 { | 502 { |
480 if (!m_playbackRate || m_idle) { | 503 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 504 |
| 505 if (!m_playbackRate || playStateInternal() == Idle) { |
481 return; | 506 return; |
482 } | 507 } |
483 if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infini
ty()) { | 508 if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infini
ty()) { |
484 exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has
source content whose end time is infinity."); | 509 exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has
source content whose end time is infinity."); |
485 return; | 510 return; |
486 } | 511 } |
487 if (playing()) { | |
488 setCompositorPending(); | |
489 } | |
490 | 512 |
491 uncancel(); | 513 uncancel(); |
492 | 514 |
493 double newCurrentTime = m_playbackRate < 0 ? 0 : sourceEnd(); | 515 double newCurrentTime = m_playbackRate < 0 ? 0 : sourceEnd(); |
494 setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand); | 516 setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand); |
495 if (!paused()) { | 517 if (!paused()) { |
496 m_startTime = calculateStartTime(newCurrentTime); | 518 m_startTime = calculateStartTime(newCurrentTime); |
497 } | 519 } |
498 | 520 |
499 m_currentTimePending = false; | 521 m_currentTimePending = false; |
(...skipping 10 matching lines...) Expand all Loading... |
510 return ActiveDOMObject::executionContext(); | 532 return ActiveDOMObject::executionContext(); |
511 } | 533 } |
512 | 534 |
513 bool AnimationPlayer::hasPendingActivity() const | 535 bool AnimationPlayer::hasPendingActivity() const |
514 { | 536 { |
515 return m_pendingFinishedEvent || (!m_finished && hasEventListeners(EventType
Names::finish)); | 537 return m_pendingFinishedEvent || (!m_finished && hasEventListeners(EventType
Names::finish)); |
516 } | 538 } |
517 | 539 |
518 void AnimationPlayer::stop() | 540 void AnimationPlayer::stop() |
519 { | 541 { |
520 setFinished(true); | 542 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 543 |
| 544 m_finished = true; |
521 m_pendingFinishedEvent = nullptr; | 545 m_pendingFinishedEvent = nullptr; |
522 } | 546 } |
523 | 547 |
524 bool AnimationPlayer::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) | 548 bool AnimationPlayer::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) |
525 { | 549 { |
526 if (m_pendingFinishedEvent == event) | 550 if (m_pendingFinishedEvent == event) |
527 m_pendingFinishedEvent = nullptr; | 551 m_pendingFinishedEvent = nullptr; |
528 return EventTargetWithInlineData::dispatchEvent(event); | 552 return EventTargetWithInlineData::dispatchEvent(event); |
529 } | 553 } |
530 | 554 |
531 double AnimationPlayer::playbackRate() const | 555 double AnimationPlayer::playbackRate() const |
532 { | 556 { |
533 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetPlayback
Rate); | 557 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetPlayback
Rate); |
534 return m_playbackRate; | 558 return m_playbackRate; |
535 } | 559 } |
536 | 560 |
537 void AnimationPlayer::setPlaybackRate(double playbackRate) | 561 void AnimationPlayer::setPlaybackRate(double playbackRate) |
538 { | 562 { |
539 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetPlayback
Rate); | 563 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetPlayback
Rate); |
540 if (!std::isfinite(playbackRate)) | 564 if (!std::isfinite(playbackRate)) |
541 return; | 565 return; |
542 if (playbackRate == m_playbackRate) | 566 if (playbackRate == m_playbackRate) |
543 return; | 567 return; |
544 | 568 |
| 569 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 570 |
545 setPlaybackRateInternal(playbackRate); | 571 setPlaybackRateInternal(playbackRate); |
546 } | 572 } |
547 | 573 |
548 void AnimationPlayer::setPlaybackRateInternal(double playbackRate) | 574 void AnimationPlayer::setPlaybackRateInternal(double playbackRate) |
549 { | 575 { |
550 ASSERT(std::isfinite(playbackRate)); | 576 ASSERT(std::isfinite(playbackRate)); |
551 ASSERT(playbackRate != m_playbackRate); | 577 ASSERT(playbackRate != m_playbackRate); |
552 | 578 |
553 setCompositorPending(); | |
554 if (!finished() && !paused() && hasStartTime()) | 579 if (!finished() && !paused() && hasStartTime()) |
555 m_currentTimePending = true; | 580 m_currentTimePending = true; |
556 | 581 |
557 double storedCurrentTime = currentTimeInternal(); | 582 double storedCurrentTime = currentTimeInternal(); |
558 if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && play
backRate <= 0)) | 583 if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && play
backRate <= 0)) |
559 setFinished(false); | 584 m_finished = false; |
560 | 585 |
561 m_playbackRate = playbackRate; | 586 m_playbackRate = playbackRate; |
562 m_startTime = std::numeric_limits<double>::quiet_NaN(); | 587 m_startTime = std::numeric_limits<double>::quiet_NaN(); |
563 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); | 588 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); |
564 } | 589 } |
565 | 590 |
566 void AnimationPlayer::setOutdated() | 591 void AnimationPlayer::setOutdated() |
567 { | 592 { |
568 m_outdated = true; | 593 m_outdated = true; |
569 if (m_timeline) | 594 if (m_timeline) |
(...skipping 20 matching lines...) Expand all Loading... |
590 } | 615 } |
591 return toAnimation(m_content.get())->maybeStartAnimationOnCompositor(startTi
me, timeOffset, m_playbackRate); | 616 return toAnimation(m_content.get())->maybeStartAnimationOnCompositor(startTi
me, timeOffset, m_playbackRate); |
592 } | 617 } |
593 | 618 |
594 void AnimationPlayer::setCompositorPending(bool sourceChanged) | 619 void AnimationPlayer::setCompositorPending(bool sourceChanged) |
595 { | 620 { |
596 // FIXME: Animation could notify this directly? | 621 // FIXME: Animation could notify this directly? |
597 if (!hasActiveAnimationsOnCompositor()) { | 622 if (!hasActiveAnimationsOnCompositor()) { |
598 m_compositorState.release(); | 623 m_compositorState.release(); |
599 } | 624 } |
600 if (!m_compositorPending) { | 625 if (sourceChanged && m_compositorState) { |
| 626 m_compositorState->sourceChanged = true; |
| 627 } |
| 628 if (m_compositorPending || m_isPausedForTesting) { |
| 629 return; |
| 630 } |
| 631 |
| 632 if (sourceChanged || !m_compositorState |
| 633 || !playing() || m_compositorState->playbackRate != m_playbackRate |
| 634 || m_compositorState->startTime != m_startTime) { |
601 m_compositorPending = true; | 635 m_compositorPending = true; |
602 if (sourceChanged && m_compositorState) | |
603 m_compositorState->sourceChanged = true; | |
604 timeline()->document()->compositorPendingAnimations().add(this); | 636 timeline()->document()->compositorPendingAnimations().add(this); |
605 } | 637 } |
606 } | 638 } |
607 | 639 |
608 bool AnimationPlayer::hasActiveAnimationsOnCompositor() | 640 bool AnimationPlayer::hasActiveAnimationsOnCompositor() |
609 { | 641 { |
610 if (!m_content || !m_content->isAnimation()) | 642 if (!m_content || !m_content->isAnimation()) |
611 return false; | 643 return false; |
612 | 644 |
613 return toAnimation(m_content.get())->hasActiveAnimationsOnCompositor(); | 645 return toAnimation(m_content.get())->hasActiveAnimationsOnCompositor(); |
614 } | 646 } |
615 | 647 |
616 void AnimationPlayer::cancelAnimationOnCompositor() | 648 void AnimationPlayer::cancelAnimationOnCompositor() |
617 { | 649 { |
618 if (hasActiveAnimationsOnCompositor()) | 650 if (hasActiveAnimationsOnCompositor()) |
619 toAnimation(m_content.get())->cancelAnimationOnCompositor(); | 651 toAnimation(m_content.get())->cancelAnimationOnCompositor(); |
620 } | 652 } |
621 | 653 |
622 bool AnimationPlayer::update(TimingUpdateReason reason) | 654 bool AnimationPlayer::update(TimingUpdateReason reason) |
623 { | 655 { |
624 if (!m_timeline) | 656 if (!m_timeline) |
625 return false; | 657 return false; |
626 | 658 |
627 updateCurrentTimingState(reason); | 659 PlayStateUpdateScope updateScope(*this, reason, DoNotSetCompositorPending); |
| 660 |
628 m_outdated = false; | 661 m_outdated = false; |
| 662 bool idle = playStateInternal() == Idle; |
629 | 663 |
630 if (m_content) { | 664 if (m_content) { |
631 double inheritedTime = m_idle || isNull(m_timeline->currentTimeInternal(
)) ? nullValue() : currentTimeInternal(); | 665 double inheritedTime = idle || isNull(m_timeline->currentTimeInternal())
? nullValue() : currentTimeInternal(); |
632 // Special case for end-exclusivity when playing backwards. | 666 // Special case for end-exclusivity when playing backwards. |
633 if (inheritedTime == 0 && m_playbackRate < 0) | 667 if (inheritedTime == 0 && m_playbackRate < 0) |
634 inheritedTime = -1; | 668 inheritedTime = -1; |
635 m_content->updateInheritedTime(inheritedTime, reason); | 669 m_content->updateInheritedTime(inheritedTime, reason); |
636 } | 670 } |
637 | 671 |
638 if ((m_idle || finished()) && !m_finished) { | 672 if ((idle || finished()) && !m_finished) { |
639 if (reason == TimingUpdateForAnimationFrame && (m_idle || hasStartTime()
)) { | 673 if (reason == TimingUpdateForAnimationFrame && (idle || hasStartTime()))
{ |
640 const AtomicString& eventType = EventTypeNames::finish; | 674 const AtomicString& eventType = EventTypeNames::finish; |
641 if (executionContext() && hasEventListeners(eventType)) { | 675 if (executionContext() && hasEventListeners(eventType)) { |
642 double eventCurrentTime = currentTimeInternal() * 1000; | 676 double eventCurrentTime = currentTimeInternal() * 1000; |
643 m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType,
eventCurrentTime, timeline()->currentTime()); | 677 m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType,
eventCurrentTime, timeline()->currentTime()); |
644 m_pendingFinishedEvent->setTarget(this); | 678 m_pendingFinishedEvent->setTarget(this); |
645 m_pendingFinishedEvent->setCurrentTarget(this); | 679 m_pendingFinishedEvent->setCurrentTarget(this); |
646 m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFini
shedEvent); | 680 m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFini
shedEvent); |
647 } | 681 } |
648 setFinished(true); | 682 m_finished = true; |
649 } | 683 } |
650 } | 684 } |
651 ASSERT(!m_outdated); | 685 ASSERT(!m_outdated); |
652 return !m_finished; | 686 return !m_finished; |
653 } | 687 } |
654 | 688 |
655 double AnimationPlayer::timeToEffectChange() | 689 double AnimationPlayer::timeToEffectChange() |
656 { | 690 { |
657 ASSERT(!m_outdated); | 691 ASSERT(!m_outdated); |
658 if (m_held || !hasStartTime()) | 692 if (m_held || !hasStartTime()) |
659 return std::numeric_limits<double>::infinity(); | 693 return std::numeric_limits<double>::infinity(); |
660 if (!m_content) | 694 if (!m_content) |
661 return -currentTimeInternal() / m_playbackRate; | 695 return -currentTimeInternal() / m_playbackRate; |
662 if (m_playbackRate > 0) | 696 if (m_playbackRate > 0) |
663 return m_content->timeToForwardsEffectChange() / m_playbackRate; | 697 return m_content->timeToForwardsEffectChange() / m_playbackRate; |
664 return m_content->timeToReverseEffectChange() / -m_playbackRate; | 698 return m_content->timeToReverseEffectChange() / -m_playbackRate; |
665 } | 699 } |
666 | 700 |
667 void AnimationPlayer::setFinished(bool finished) | |
668 { | |
669 if (m_finished && !finished) { | |
670 if (m_content) { | |
671 TRACE_EVENT_ASYNC_BEGIN1("blink", "Animation", this, "Name", TRACE_S
TR_COPY(m_content->name().utf8().data())); | |
672 } else { | |
673 TRACE_EVENT_ASYNC_BEGIN0("blink", "Animation", this); | |
674 } | |
675 } | |
676 if (!m_finished && finished) { | |
677 TRACE_EVENT_ASYNC_END0("blink", "Animation", this); | |
678 } | |
679 m_finished = finished; | |
680 } | |
681 | |
682 void AnimationPlayer::cancel() | 701 void AnimationPlayer::cancel() |
683 { | 702 { |
684 if (m_idle) | 703 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 704 |
| 705 if (playStateInternal() == Idle) |
685 return; | 706 return; |
686 | 707 |
687 m_holdTime = currentTimeInternal(); | 708 m_holdTime = currentTimeInternal(); |
688 m_held = true; | 709 m_held = true; |
689 m_idle = true; | 710 // TODO |
| 711 m_playState = Idle; |
690 m_startTime = nullValue(); | 712 m_startTime = nullValue(); |
691 m_currentTimePending = false; | 713 m_currentTimePending = false; |
692 setCompositorPending(); | |
693 } | 714 } |
694 | 715 |
695 void AnimationPlayer::uncancel() | 716 void AnimationPlayer::uncancel() |
696 { | 717 { |
697 if (!m_idle) | 718 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| 719 |
| 720 if (playStateInternal() != Idle) |
698 return; | 721 return; |
699 | 722 |
700 m_idle = false; | 723 // We may not go into the pending state, but setting it to something other |
| 724 // than Idle here will force an update. |
| 725 ASSERT(isNull(m_startTime)); |
| 726 m_playState = Pending; |
701 m_held = true; | 727 m_held = true; |
702 m_holdTime = 0; | 728 m_holdTime = 0; |
703 setFinished(false); | 729 m_finished = false; |
| 730 } |
| 731 |
| 732 AnimationPlayer::PlayStateUpdateScope::PlayStateUpdateScope(AnimationPlayer& pla
yer, TimingUpdateReason reason, CompositorPendingChange compositorPendingChange) |
| 733 : m_player(player) |
| 734 , m_initial(player.playStateInternal()) |
| 735 , m_compositorPendingChange(compositorPendingChange) |
| 736 { |
| 737 m_player.updateCurrentTimingState(reason); |
| 738 } |
| 739 |
| 740 AnimationPlayer::PlayStateUpdateScope::~PlayStateUpdateScope() |
| 741 { |
| 742 AnimationPlayState oldPlayState = m_initial; |
| 743 AnimationPlayState newPlayState = m_player.calculatePlayState(); |
| 744 if (oldPlayState != newPlayState) { |
| 745 bool wasActive = oldPlayState == Pending || oldPlayState == Running; |
| 746 bool isActive = newPlayState == Pending || newPlayState == Running; |
| 747 if (!wasActive && isActive) { |
| 748 if (m_player.m_content) { |
| 749 TRACE_EVENT_ASYNC_BEGIN1("blink", "Animation", &m_player, "Name"
, TRACE_STR_COPY(m_player.m_content->name().utf8().data())); |
| 750 } else { |
| 751 TRACE_EVENT_ASYNC_BEGIN0("blink", "Animation", &m_player); |
| 752 } |
| 753 } else if (wasActive && !isActive) { |
| 754 if (oldPlayState != Idle && oldPlayState != Finished) { |
| 755 TRACE_EVENT_ASYNC_END0("blink", "Animation", &m_player); |
| 756 } |
| 757 } |
| 758 if (isActive) { |
| 759 TRACE_EVENT_ASYNC_STEP_INTO0("blink", "Animation", &m_player, playSt
ateString(newPlayState)); |
| 760 } |
| 761 } |
| 762 |
| 763 m_player.m_playState = newPlayState; |
| 764 |
| 765 #if ENABLE(ASSERT) |
| 766 // Verify that current time is up to date. |
| 767 m_player.currentTimeInternal(); |
| 768 #endif |
| 769 |
| 770 switch (m_compositorPendingChange) { |
| 771 case SetCompositorPending: |
| 772 m_player.setCompositorPending(); |
| 773 break; |
| 774 case SetCompositorPendingWithSourceChanged: |
| 775 m_player.setCompositorPending(true); |
| 776 break; |
| 777 case DoNotSetCompositorPending: |
| 778 break; |
| 779 default: |
| 780 ASSERT_NOT_REACHED(); |
| 781 break; |
| 782 } |
704 } | 783 } |
705 | 784 |
706 | 785 |
707 #if !ENABLE(OILPAN) | 786 #if !ENABLE(OILPAN) |
708 bool AnimationPlayer::canFree() const | 787 bool AnimationPlayer::canFree() const |
709 { | 788 { |
710 ASSERT(m_content); | 789 ASSERT(m_content); |
711 return hasOneRef() && m_content->isAnimation() && m_content->hasOneRef(); | 790 return hasOneRef() && m_content->isAnimation() && m_content->hasOneRef(); |
712 } | 791 } |
713 #endif | 792 #endif |
(...skipping 17 matching lines...) Expand all Loading... |
731 | 810 |
732 void AnimationPlayer::trace(Visitor* visitor) | 811 void AnimationPlayer::trace(Visitor* visitor) |
733 { | 812 { |
734 visitor->trace(m_content); | 813 visitor->trace(m_content); |
735 visitor->trace(m_timeline); | 814 visitor->trace(m_timeline); |
736 visitor->trace(m_pendingFinishedEvent); | 815 visitor->trace(m_pendingFinishedEvent); |
737 EventTargetWithInlineData::trace(visitor); | 816 EventTargetWithInlineData::trace(visitor); |
738 } | 817 } |
739 | 818 |
740 } // namespace | 819 } // namespace |
OLD | NEW |