Chromium Code Reviews| Index: Source/core/animation/AnimationPlayer.cpp |
| diff --git a/Source/core/animation/AnimationPlayer.cpp b/Source/core/animation/AnimationPlayer.cpp |
| index f10b029035b05a69060a171f67c2d32ce734e7b6..25e505ad635548f48369f9db34319474f24fd1d4 100644 |
| --- a/Source/core/animation/AnimationPlayer.cpp |
| +++ b/Source/core/animation/AnimationPlayer.cpp |
| @@ -61,6 +61,7 @@ PassRefPtrWillBeRawPtr<AnimationPlayer> AnimationPlayer::create(ExecutionContext |
| AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTimeline& timeline, AnimationNode* content) |
| : ActiveDOMObject(executionContext) |
| + , m_playState(Idle) |
| , m_playbackRate(1) |
| , m_startTime(nullValue()) |
| , m_holdTime(0) |
| @@ -75,7 +76,6 @@ AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTi |
| , m_compositorState(nullptr) |
| , m_compositorPending(true) |
| , m_currentTimePending(false) |
| - , m_idle(true) |
| { |
| if (m_content) { |
| if (m_content->player()) { |
| @@ -106,6 +106,19 @@ bool AnimationPlayer::limited(double currentTime) const |
| return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && currentTime >= sourceEnd()); |
| } |
| +void AnimationPlayer::setCurrentTime(double newCurrentTime) |
| +{ |
| + UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentTime); |
| + if (!std::isfinite(newCurrentTime)) |
| + return; |
| + |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| + setCompositorPending(); |
| + m_currentTimePending = false; |
| + setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); |
| +} |
| + |
| void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdateReason reason) |
| { |
| ASSERT(std::isfinite(newCurrentTime)); |
| @@ -126,7 +139,7 @@ void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdate |
| } else { |
| m_holdTime = nullValue(); |
| m_startTime = calculateStartTime(newCurrentTime); |
| - setFinished(false); |
| + m_finished = false; |
| outdated = true; |
| } |
| @@ -170,18 +183,23 @@ double AnimationPlayer::currentTime(bool& isNull) |
| double AnimationPlayer::currentTime() |
| { |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetCurrentTime); |
| - if (m_currentTimePending || m_idle) |
| + if (m_currentTimePending || playStateInternal() == Idle) |
| return std::numeric_limits<double>::quiet_NaN(); |
| + |
| return currentTimeInternal() * 1000; |
| } |
| -double AnimationPlayer::currentTimeInternal() |
| +double AnimationPlayer::currentTimeInternal() const |
| { |
| - updateCurrentTimingState(TimingUpdateOnDemand); |
| - if (m_held) |
| - return m_holdTime; |
| - return calculateCurrentTime(); |
| + double result = m_held ? m_holdTime : calculateCurrentTime(); |
| +#if ENABLE(ASSERT) |
|
shans
2014/10/15 03:38:00
is ASSERT stronger than DEBUG?
dstockwell
2014/10/15 08:30:04
ASSERT can be enabled outside of a debug build. Bu
|
| + const_cast<AnimationPlayer*>(this)->updateCurrentTimingState(TimingUpdateOnDemand); |
| + ASSERT(result == (m_held ? m_holdTime : calculateCurrentTime())); |
| +#endif |
| + return result; |
| } |
| void AnimationPlayer::preCommit(bool startOnCompositor) |
| @@ -191,6 +209,8 @@ void AnimationPlayer::preCommit(bool startOnCompositor) |
| return; |
| } |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate); |
| bool hardChange = m_compositorState && (m_compositorState->sourceChanged || (m_compositorState->startTime != m_startTime && !std::isnan(m_compositorState->startTime) && !std::isnan(m_startTime))); |
| @@ -218,6 +238,8 @@ void AnimationPlayer::preCommit(bool startOnCompositor) |
| void AnimationPlayer::postCommit(double timelineTime) |
| { |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| m_compositorPending = false; |
| if (!m_compositorState || m_compositorState->pendingAction == None) |
| @@ -244,6 +266,8 @@ void AnimationPlayer::postCommit(double timelineTime) |
| void AnimationPlayer::notifyCompositorStartTime(double timelineTime) |
| { |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| if (m_compositorState) { |
| ASSERT(m_compositorState->pendingAction == Start); |
| ASSERT(std::isnan(m_compositorState->startTime)); |
| @@ -304,21 +328,12 @@ double AnimationPlayer::calculateCurrentTime() const |
| return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate; |
| } |
| -void AnimationPlayer::setCurrentTime(double newCurrentTime) |
| -{ |
| - UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentTime); |
| - if (!std::isfinite(newCurrentTime)) |
| - return; |
| - |
| - setCompositorPending(); |
| - m_currentTimePending = false; |
| - setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); |
| -} |
| - |
| void AnimationPlayer::setStartTime(double startTime) |
| { |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetStartTime); |
| - if (m_paused || m_idle) |
| + if (m_paused || playStateInternal() == Idle) |
| return; |
| if (!std::isfinite(startTime)) |
| return; |
| @@ -351,6 +366,7 @@ void AnimationPlayer::setStartTimeInternal(double newStartTime) |
| } |
| setCurrentTimeInternal(currentTime, TimingUpdateOnDemand); |
| } |
| + updateCurrentTimingState(TimingUpdateOnDemand); |
| double newCurrentTime = currentTimeInternal(); |
| if (previousCurrentTime != newCurrentTime) { |
| @@ -367,6 +383,8 @@ void AnimationPlayer::setSource(AnimationNode* newSource) |
| if (m_content == newSource) |
| return; |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| setCompositorPending(true); |
| double storedCurrentTime = currentTimeInternal(); |
| @@ -385,9 +403,9 @@ void AnimationPlayer::setSource(AnimationNode* newSource) |
| setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); |
| } |
| -String AnimationPlayer::playState() |
| +const char* AnimationPlayer::playStateString(AnimationPlayState playState) |
| { |
| - switch (playStateInternal()) { |
| + switch (playState) { |
| case Idle: |
| return "idle"; |
| case Pending: |
| @@ -404,9 +422,14 @@ String AnimationPlayer::playState() |
| } |
| } |
| -AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal() |
| +AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal() const |
| { |
| - if (m_idle) |
| + return m_playState; |
| +} |
| + |
| +AnimationPlayer::AnimationPlayState AnimationPlayer::calculatePlayState() |
| +{ |
| + if (m_playState == Idle) |
| return Idle; |
| if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackRate != 0)) |
| return Pending; |
| @@ -421,6 +444,9 @@ void AnimationPlayer::pause() |
| { |
| if (m_paused) |
| return; |
| + |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| if (playing()) { |
| setCompositorPending(); |
| m_currentTimePending = true; |
| @@ -433,6 +459,9 @@ void AnimationPlayer::unpause() |
| { |
| if (!m_paused) |
| return; |
| + |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| setCompositorPending(); |
| m_currentTimePending = true; |
| unpauseInternal(); |
| @@ -448,6 +477,8 @@ void AnimationPlayer::unpauseInternal() |
| void AnimationPlayer::play() |
| { |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| if (!playing()) |
| m_startTime = nullValue(); |
| @@ -461,7 +492,7 @@ void AnimationPlayer::play() |
| setCurrentTimeInternal(0, TimingUpdateOnDemand); |
| else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd())) |
| setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand); |
| - setFinished(false); |
| + m_finished = false; |
| } |
| void AnimationPlayer::reverse() |
| @@ -477,7 +508,9 @@ void AnimationPlayer::reverse() |
| void AnimationPlayer::finish(ExceptionState& exceptionState) |
| { |
| - if (!m_playbackRate || m_idle) { |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| + if (!m_playbackRate || playStateInternal() == Idle) { |
| return; |
| } |
| if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infinity()) { |
| @@ -517,7 +550,9 @@ bool AnimationPlayer::hasPendingActivity() const |
| void AnimationPlayer::stop() |
| { |
| - setFinished(true); |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| + m_finished = true; |
| m_pendingFinishedEvent = nullptr; |
| } |
| @@ -542,6 +577,8 @@ void AnimationPlayer::setPlaybackRate(double playbackRate) |
| if (playbackRate == m_playbackRate) |
| return; |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| setPlaybackRateInternal(playbackRate); |
| } |
| @@ -556,7 +593,7 @@ void AnimationPlayer::setPlaybackRateInternal(double playbackRate) |
| double storedCurrentTime = currentTimeInternal(); |
| if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && playbackRate <= 0)) |
| - setFinished(false); |
| + m_finished = false; |
| m_playbackRate = playbackRate; |
| m_startTime = std::numeric_limits<double>::quiet_NaN(); |
| @@ -624,19 +661,21 @@ bool AnimationPlayer::update(TimingUpdateReason reason) |
| if (!m_timeline) |
| return false; |
| - updateCurrentTimingState(reason); |
| + PlayStateUpdateScope updateScope(*this, reason); |
| + |
| m_outdated = false; |
| + bool idle = playStateInternal() == Idle; |
| if (m_content) { |
| - double inheritedTime = m_idle || isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal(); |
| + double inheritedTime = idle || isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal(); |
| // Special case for end-exclusivity when playing backwards. |
| if (inheritedTime == 0 && m_playbackRate < 0) |
| inheritedTime = -1; |
| m_content->updateInheritedTime(inheritedTime, reason); |
| } |
| - if ((m_idle || finished()) && !m_finished) { |
| - if (reason == TimingUpdateForAnimationFrame && (m_idle || hasStartTime())) { |
| + if ((idle || finished()) && !m_finished) { |
| + if (reason == TimingUpdateForAnimationFrame && (idle || hasStartTime())) { |
| const AtomicString& eventType = EventTypeNames::finish; |
| if (executionContext() && hasEventListeners(eventType)) { |
| double eventCurrentTime = currentTimeInternal() * 1000; |
| @@ -645,7 +684,7 @@ bool AnimationPlayer::update(TimingUpdateReason reason) |
| m_pendingFinishedEvent->setCurrentTarget(this); |
| m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent); |
| } |
| - setFinished(true); |
| + m_finished = true; |
| } |
| } |
| ASSERT(!m_outdated); |
| @@ -664,29 +703,17 @@ double AnimationPlayer::timeToEffectChange() |
| return m_content->timeToReverseEffectChange() / -m_playbackRate; |
| } |
| -void AnimationPlayer::setFinished(bool finished) |
| -{ |
| - if (m_finished && !finished) { |
| - if (m_content) { |
| - TRACE_EVENT_ASYNC_BEGIN1("blink", "Animation", this, "Name", TRACE_STR_COPY(m_content->name().utf8().data())); |
| - } else { |
| - TRACE_EVENT_ASYNC_BEGIN0("blink", "Animation", this); |
| - } |
| - } |
| - if (!m_finished && finished) { |
| - TRACE_EVENT_ASYNC_END0("blink", "Animation", this); |
| - } |
| - m_finished = finished; |
| -} |
| - |
| void AnimationPlayer::cancel() |
| { |
| - if (m_idle) |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| + if (playStateInternal() == Idle) |
| return; |
| m_holdTime = currentTimeInternal(); |
| m_held = true; |
| - m_idle = true; |
| + // TODO |
| + m_playState = Idle; |
| m_startTime = nullValue(); |
| m_currentTimePending = false; |
| setCompositorPending(); |
| @@ -694,13 +721,56 @@ void AnimationPlayer::cancel() |
| void AnimationPlayer::uncancel() |
| { |
| - if (!m_idle) |
| + PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand); |
| + |
| + if (playStateInternal() != Idle) |
| return; |
| - m_idle = false; |
| + // We may not go into the pending state, but setting it to something other |
| + // than Idle here will force an update. |
| + ASSERT(isNull(m_startTime)); |
| + m_playState = Pending; |
| m_held = true; |
| m_holdTime = 0; |
| - setFinished(false); |
| + m_finished = false; |
| +} |
| + |
| +AnimationPlayer::PlayStateUpdateScope::PlayStateUpdateScope(AnimationPlayer& player, TimingUpdateReason reason) |
| + : m_player(player) |
| + , m_initial(player.playStateInternal()) |
| +{ |
| + m_player.updateCurrentTimingState(reason); |
| +} |
| + |
| +AnimationPlayer::PlayStateUpdateScope::~PlayStateUpdateScope() |
|
shans
2014/10/15 03:38:00
can we setCompositorPending in here too?
dstockwell
2014/10/15 08:30:04
Done, this required a few flags as it's not safe t
|
| +{ |
| + AnimationPlayState oldPlayState = m_initial; |
| + AnimationPlayState newPlayState = m_player.calculatePlayState(); |
| + if (oldPlayState != newPlayState) { |
| + bool wasActive = oldPlayState == Pending || oldPlayState == Running; |
| + bool isActive = newPlayState == Pending || newPlayState == Running; |
| + if (!wasActive && isActive) { |
| + if (m_player.m_content) { |
| + TRACE_EVENT_ASYNC_BEGIN1("blink", "Animation", &m_player, "Name", TRACE_STR_COPY(m_player.m_content->name().utf8().data())); |
| + } else { |
| + TRACE_EVENT_ASYNC_BEGIN0("blink", "Animation", &m_player); |
| + } |
| + } else if (wasActive && !isActive) { |
| + if (oldPlayState != Idle && oldPlayState != Finished) { |
| + TRACE_EVENT_ASYNC_END0("blink", "Animation", &m_player); |
| + } |
| + } |
| + if (isActive) { |
| + TRACE_EVENT_ASYNC_STEP_INTO0("blink", "Animation", &m_player, playStateString(newPlayState)); |
| + } |
| + } |
| + |
| + m_player.m_playState = newPlayState; |
| + |
| +#if ENABLE(ASSERT) |
| + // Verify that current time is up to date. |
| + m_player.currentTimeInternal(); |
| +#endif |
| } |