Bug 1112480 part 6 - Make PendingPlayerTracker call StartOnNextTick; r=jwatt

This patch switches on the new, "actually start the player in the next refresh
driver tick" behavior. It updates PendingPlayerTracker, adding
a StartPendingPlayersOnNextTick method which calls the appropriate method on
AnimationPlayer. The existing StartPendingPlayers is renamed to
StartPendingPlayersNow and is used for testing only.

Furthermore, since we now expect AnimationPlayer::StartOnNextTick to be
functional, AnimationPlayer::DoPlay is updated to use it when there is no
document available. This should make playing an animation player always
asynchronous, that is, always transition to the pending state temporarily
(unless we are already playing).
This commit is contained in:
Brian Birtles 2015-01-09 07:57:58 +09:00
Родитель 9eb65d26c7
Коммит ac47cd0a02
5 изменённых файлов: 35 добавлений и 31 удалений

Просмотреть файл

@ -270,14 +270,7 @@ AnimationPlayer::DoPlay()
nsIDocument* doc = GetRenderedDocument();
if (!doc) {
// If we have no rendered document (e.g. because the source content's
// target element is orphaned), then treat the animation as ready and
// start it immediately. It is probably preferable to make playing
// *always* asynchronous (e.g. by setting some additional state that
// marks this player as pending and queueing a runnable to resolve the
// start time). That situation, however, is currently rare enough that
// we don't bother for now.
StartNow();
StartOnNextTick(Nullable<TimeDuration>());
return;
}

Просмотреть файл

@ -46,30 +46,42 @@ StartPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
void* aReadyTime)
{
dom::AnimationPlayer* player = aKey->GetKey();
// For animations that are waiting until their first frame has rendered
// before starting, we record the moment when they finish painting
// as the "ready time" and make any pending layer animations start at
// that time.
//
// Here we fast-forward the player's timeline to the same "ready time" and
// then tell the player to start at the timeline's current time.
//
// Redundant calls to FastForward with the same ready time are ignored by
// AnimationTimeline.
dom::AnimationTimeline* timeline = player->Timeline();
timeline->FastForward(*static_cast<const TimeStamp*>(aReadyTime));
player->StartNow();
// When the timeline's refresh driver is under test control, its values
// have no correspondance to wallclock times so we shouldn't try to convert
// aReadyTime (which is a wallclock time) to a timeline value. Instead, the
// animation player will be started when the refresh driver is next
// advanced since this will trigger a call to StartPendingPlayersNow.
if (timeline->IsUnderTestControl()) {
return PL_DHASH_NEXT;
}
Nullable<TimeDuration> readyTime =
timeline->ToTimelineTime(*static_cast<const TimeStamp*>(aReadyTime));
player->StartOnNextTick(readyTime);
return PL_DHASH_REMOVE;
}
void
PendingPlayerTracker::StartPendingPlayersOnNextTick(const TimeStamp& aReadyTime)
{
mPlayPendingSet.EnumerateEntries(StartPlayerAtTime,
const_cast<TimeStamp*>(&aReadyTime));
}
PLDHashOperator
StartPlayerNow(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, void*)
{
aKey->GetKey()->StartNow();
return PL_DHASH_NEXT;
}
void
PendingPlayerTracker::StartPendingPlayers(const TimeStamp& aReadyTime)
PendingPlayerTracker::StartPendingPlayersNow()
{
mPlayPendingSet.EnumerateEntries(StartPlayerAtTime,
const_cast<TimeStamp*>(&aReadyTime));
mPlayPendingSet.EnumerateEntries(StartPlayerNow, nullptr);
mPlayPendingSet.Clear();
}

Просмотреть файл

@ -29,9 +29,8 @@ public:
void RemovePlayPending(dom::AnimationPlayer& aPlayer);
bool IsWaitingToPlay(dom::AnimationPlayer const& aPlayer) const;
// Causes any pending players to resume at |aReadyTime| by first
// fast-forwarding their timeline to the corresponding time.
void StartPendingPlayers(const TimeStamp& aReadyTime);
void StartPendingPlayersOnNextTick(const TimeStamp& aReadyTime);
void StartPendingPlayersNow();
bool HasPendingPlayers() const { return mPlayPendingSet.Count() > 0; }
private:

Просмотреть файл

@ -2675,8 +2675,6 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
// Before we advance the time, we should trigger any animations that are
// waiting to start. This is because there are many tests that call this
// which expect animations to start immediately. Ideally, we should make
@ -2689,10 +2687,11 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
if (doc) {
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
if (tracker) {
tracker->StartPendingPlayers(driver->MostRecentRefresh());
tracker->StartPendingPlayersNow();
}
}
nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
driver->AdvanceTimeAndRefresh(aMilliseconds);
RefPtr<LayerTransactionChild> transaction = GetLayerTransaction();

Просмотреть файл

@ -1465,7 +1465,8 @@ StartPendingAnimationsOnSubDocuments(nsIDocument* aDocument, void* aReadyTime)
// If paint-suppression is in effect then we haven't finished painting
// this document yet so we shouldn't start animations
if (!shell || !shell->IsPaintingSuppressed()) {
tracker->StartPendingPlayers(*static_cast<TimeStamp*>(aReadyTime));
const TimeStamp& readyTime = *static_cast<TimeStamp*>(aReadyTime);
tracker->StartPendingPlayersOnNextTick(readyTime);
}
}
aDocument->EnumerateSubDocuments(StartPendingAnimationsOnSubDocuments,