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

Unified Diff: Source/core/animation/AnimationPlayer.cpp

Issue 638313002: Web Animations: Overhaul and trace play state in AnimationPlayer (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Don't set compositor pending when paused for testing Created 6 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/animation/AnimationPlayer.h ('k') | Source/core/animation/AnimationPlayerTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/animation/AnimationPlayer.cpp
diff --git a/Source/core/animation/AnimationPlayer.cpp b/Source/core/animation/AnimationPlayer.cpp
index f10b029035b05a69060a171f67c2d32ce734e7b6..b1760edf33644f03314a2a5db57e79a09200522d 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,18 @@ 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);
+
+ m_currentTimePending = false;
+ setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand);
+}
+
void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdateReason reason)
{
ASSERT(std::isfinite(newCurrentTime));
@@ -126,7 +138,7 @@ void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdate
} else {
m_holdTime = nullValue();
m_startTime = calculateStartTime(newCurrentTime);
- setFinished(false);
+ m_finished = false;
outdated = true;
}
@@ -170,18 +182,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)
+ const_cast<AnimationPlayer*>(this)->updateCurrentTimingState(TimingUpdateOnDemand);
+ ASSERT(result == (m_held ? m_holdTime : calculateCurrentTime()));
+#endif
+ return result;
}
void AnimationPlayer::preCommit(bool startOnCompositor)
@@ -191,6 +208,8 @@ void AnimationPlayer::preCommit(bool startOnCompositor)
return;
}
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);
+
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)));
@@ -204,7 +223,6 @@ void AnimationPlayer::preCommit(bool startOnCompositor)
if (shouldCancel) {
cancelAnimationOnCompositor();
m_compositorState = nullptr;
-
}
if (!shouldStart) {
@@ -218,6 +236,8 @@ void AnimationPlayer::preCommit(bool startOnCompositor)
void AnimationPlayer::postCommit(double timelineTime)
{
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);
+
m_compositorPending = false;
if (!m_compositorState || m_compositorState->pendingAction == None)
@@ -244,6 +264,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));
@@ -252,11 +274,6 @@ void AnimationPlayer::notifyCompositorStartTime(double timelineTime)
m_compositorState->pendingAction = None;
m_compositorState->startTime = timelineTime;
- if (paused() || m_compositorState->playbackRate != m_playbackRate || m_compositorState->sourceChanged) {
- // Paused state, playback rate, or source changed while starting.
- setCompositorPending();
- }
-
if (m_startTime == timelineTime) {
// The start time was set to the incoming compositor start time.
// Unlikely, but possible.
@@ -268,11 +285,16 @@ void AnimationPlayer::notifyCompositorStartTime(double timelineTime)
if (!std::isnan(m_startTime) || currentTimeInternal() != initialCompositorHoldTime) {
// A new start time or current time was set while starting.
- setCompositorPending();
+ setCompositorPending(true);
return;
}
}
+ notifyStartTime(timelineTime);
+}
+
+void AnimationPlayer::notifyStartTime(double timelineTime)
+{
if (playing()) {
ASSERT(std::isnan(m_startTime));
ASSERT(m_held);
@@ -304,28 +326,18 @@ 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;
if (startTime == m_startTime)
return;
- setCompositorPending();
m_currentTimePending = false;
setStartTimeInternal(startTime / 1000);
}
@@ -351,6 +363,7 @@ void AnimationPlayer::setStartTimeInternal(double newStartTime)
}
setCurrentTimeInternal(currentTime, TimingUpdateOnDemand);
}
+ updateCurrentTimingState(TimingUpdateOnDemand);
double newCurrentTime = currentTimeInternal();
if (previousCurrentTime != newCurrentTime) {
@@ -367,7 +380,7 @@ void AnimationPlayer::setSource(AnimationNode* newSource)
if (m_content == newSource)
return;
- setCompositorPending(true);
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, SetCompositorPendingWithSourceChanged);
double storedCurrentTime = currentTimeInternal();
if (m_content)
@@ -385,9 +398,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 +417,14 @@ String AnimationPlayer::playState()
}
}
-AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal()
+AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal() const
+{
+ return m_playState;
+}
+
+AnimationPlayer::AnimationPlayState AnimationPlayer::calculatePlayState()
{
- if (m_idle)
+ if (m_playState == Idle)
return Idle;
if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackRate != 0))
return Pending;
@@ -421,8 +439,10 @@ void AnimationPlayer::pause()
{
if (m_paused)
return;
+
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
+
if (playing()) {
- setCompositorPending();
m_currentTimePending = true;
}
m_paused = true;
@@ -433,7 +453,9 @@ void AnimationPlayer::unpause()
{
if (!m_paused)
return;
- setCompositorPending();
+
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
+
m_currentTimePending = true;
unpauseInternal();
}
@@ -448,10 +470,11 @@ void AnimationPlayer::unpauseInternal()
void AnimationPlayer::play()
{
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
+
if (!playing())
m_startTime = nullValue();
- setCompositorPending();
uncancel();
unpauseInternal();
if (!m_content)
@@ -461,7 +484,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,16 +500,15 @@ 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()) {
exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity.");
return;
}
- if (playing()) {
- setCompositorPending();
- }
uncancel();
@@ -517,7 +539,9 @@ bool AnimationPlayer::hasPendingActivity() const
void AnimationPlayer::stop()
{
- setFinished(true);
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
+
+ m_finished = true;
m_pendingFinishedEvent = nullptr;
}
@@ -542,6 +566,8 @@ void AnimationPlayer::setPlaybackRate(double playbackRate)
if (playbackRate == m_playbackRate)
return;
+ PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
+
setPlaybackRateInternal(playbackRate);
}
@@ -550,13 +576,12 @@ void AnimationPlayer::setPlaybackRateInternal(double playbackRate)
ASSERT(std::isfinite(playbackRate));
ASSERT(playbackRate != m_playbackRate);
- setCompositorPending();
if (!finished() && !paused() && hasStartTime())
m_currentTimePending = true;
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();
@@ -597,10 +622,17 @@ void AnimationPlayer::setCompositorPending(bool sourceChanged)
if (!hasActiveAnimationsOnCompositor()) {
m_compositorState.release();
}
- if (!m_compositorPending) {
+ if (sourceChanged && m_compositorState) {
+ m_compositorState->sourceChanged = true;
+ }
+ if (m_compositorPending || m_isPausedForTesting) {
+ return;
+ }
+
+ if (sourceChanged || !m_compositorState
+ || !playing() || m_compositorState->playbackRate != m_playbackRate
+ || m_compositorState->startTime != m_startTime) {
m_compositorPending = true;
- if (sourceChanged && m_compositorState)
- m_compositorState->sourceChanged = true;
timeline()->document()->compositorPendingAnimations().add(this);
}
}
@@ -624,19 +656,21 @@ bool AnimationPlayer::update(TimingUpdateReason reason)
if (!m_timeline)
return false;
- updateCurrentTimingState(reason);
+ PlayStateUpdateScope updateScope(*this, reason, DoNotSetCompositorPending);
+
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 +679,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,43 +698,88 @@ 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();
}
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, CompositorPendingChange compositorPendingChange)
+ : m_player(player)
+ , m_initial(player.playStateInternal())
+ , m_compositorPendingChange(compositorPendingChange)
+{
+ m_player.updateCurrentTimingState(reason);
+}
+
+AnimationPlayer::PlayStateUpdateScope::~PlayStateUpdateScope()
+{
+ 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
+
+ switch (m_compositorPendingChange) {
+ case SetCompositorPending:
+ m_player.setCompositorPending();
+ break;
+ case SetCompositorPendingWithSourceChanged:
+ m_player.setCompositorPending(true);
+ break;
+ case DoNotSetCompositorPending:
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
}
« no previous file with comments | « Source/core/animation/AnimationPlayer.h ('k') | Source/core/animation/AnimationPlayerTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698