Bug 1078122 part 1 - Move checks for animation throttling to AnimationPlayer; r=dholbert

This patch moves code from AnimationPlayerCollection to AnimationPlayer.

However, there is one subtle change in logic involved. Previously, we would test
if the player had finished by getting the computed time of its source content
and checking if it was in the after phase or not. In this patch, however, we
simply check the play state to see if it is finished or not.

These two approaches differ in the case where an animation is paused after it
has finished. The animation phase approach will indicate the player has
finished, but the play state approach will indicate the player has paused (since
the "paused" state trumps the "finished" state). This, however, should not
produce any observable effect because when an animation is paused
mIsRunningOnCompositor will be false (we don't put paused animations on the
compositor).
This commit is contained in:
Brian Birtles 2014-10-20 13:55:45 +09:00
parent 3727776b2f
commit 75670f2118
3 changed files with 38 additions and 26 deletions

View File

@ -180,6 +180,36 @@ AnimationPlayer::IsRunning() const
return computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
}
bool
AnimationPlayer::CanThrottle() const
{
if (!mSource ||
mSource->IsFinishedTransition() ||
mSource->Properties().IsEmpty()) {
return true;
}
if (!mIsRunningOnCompositor) {
return false;
}
if (PlayState() != AnimationPlayState::Finished) {
// Unfinished animations can be throttled.
return true;
}
// The animation has finished but, if this is the first sample since
// finishing, we need an unthrottled sample so we can apply the correct
// end-of-animation behavior on the main thread (either removing the
// animation style or applying the fill mode).
//
// XXX We shouldn't really be using LastNotification() below as a general
// indicator that the animation has finished, it should be reserved for
// events. If we use it differently in the future this use might need
// changing.
return mSource->LastNotification() == Animation::LAST_NOTIFICATION_END;
}
void
AnimationPlayer::FlushStyle() const
{

View File

@ -83,7 +83,6 @@ public:
}
bool IsPaused() const { return mIsPaused; }
bool IsRunning() const;
bool HasCurrentSource() const {
@ -93,6 +92,11 @@ public:
return GetSource() && GetSource()->IsInEffect();
}
// Returns true if this animation does not currently need to update
// style on the main thread (e.g. because it is empty, or is
// running on the compositor).
bool CanThrottle() const;
// The beginning of the delay period.
Nullable<TimeDuration> mStartTime; // Timeline timescale
bool mIsRunningOnCompositor;

View File

@ -489,33 +489,11 @@ AnimationPlayerCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime,
// most of the work in this method. But even if we are throttled, then we
// have to do the work if an animation is ending in order to get correct end
// of animation behaviour (the styles of the animation disappear, or the fill
// mode behaviour). This loop checks for any finishing animations and forces
// the style recalculation if we find any.
// mode behaviour). CanThrottle returns false for any finishing animations
// so we can force style recalculation in that case.
if (aFlags == EnsureStyleRule_IsThrottled) {
for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) {
AnimationPlayer* player = mPlayers[playerIdx];
// Skip player with no source content, finished transitions, or animations
// whose @keyframes rule is empty.
if (!player->GetSource() ||
player->GetSource()->IsFinishedTransition() ||
player->GetSource()->Properties().IsEmpty()) {
continue;
}
// The GetComputedTiming() call here handles pausing. But:
// FIXME: avoid recalculating every time when paused.
ComputedTiming computedTiming = player->GetSource()->GetComputedTiming();
// XXX We shouldn't really be using LastNotification() as a general
// indicator that the animation has finished, it should be reserved for
// events. If we use it differently in the future this use might need
// changing.
if (!player->mIsRunningOnCompositor ||
(computedTiming.mPhase == ComputedTiming::AnimationPhase_After &&
player->GetSource()->LastNotification()
!= Animation::LAST_NOTIFICATION_END))
{
if (!mPlayers[playerIdx]->CanThrottle()) {
aFlags = EnsureStyleRule_IsNotThrottled;
break;
}