Bug 1036287 part 4 - Make GetLocalTime(At) get the current time automatically from the timeline; r=dholbert

This patch changes ElementAnimation::GetLocalTimeAt so that instead of taking
the current time as input, it uses the animation's mTimeline member to look up
the current time of the associated timeline. As a result of this, it is possible
to remove a few instances of querying the refresh driver for the current time.
Further instances are removed in subsequent patches.

Furthermore, in order to keep the use of time sources consistent, the mStartTime
of new transitions and animations is initialized with the current time from the
animation's timeline rather than with the latest refresh driver tick.
Since this time could, in future, be null, GetLocalTime(At) is updated to check
for a null start time.

GetLocalTimeAt is also renamed to GetLocalTime in the process.
This commit is contained in:
Brian Birtles 2014-07-16 09:02:32 +09:00
parent c368b36ded
commit c7feee4153
6 changed files with 46 additions and 41 deletions

View File

@ -433,8 +433,7 @@ ElementAnimation::CurrentTime() const
// have a *local* time. However, since we have a 1:1 correspondence between
// AnimationPlayers and Animations, and since the startTime of *Animations*
// (but not AnimationPlayers) is always 0, these are currently identical.
Nullable<TimeDuration> currentTime =
GetLocalTimeAt(mTimeline->GetCurrentTimeStamp());
Nullable<TimeDuration> currentTime = GetLocalTime();
// The current time is currently only going to be null when don't have a
// refresh driver (e.g. because we are in a display:none iframe).
@ -461,8 +460,7 @@ ElementAnimation::IsRunningAt(TimeStamp aTime) const
return false;
}
ComputedTiming computedTiming =
GetComputedTimingAt(GetLocalTimeAt(aTime), mTiming);
ComputedTiming computedTiming = GetComputedTimingAt(GetLocalTime(), mTiming);
return computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
}
@ -473,8 +471,7 @@ ElementAnimation::IsCurrentAt(TimeStamp aTime) const
return false;
}
ComputedTiming computedTiming =
GetComputedTimingAt(GetLocalTimeAt(aTime), mTiming);
ComputedTiming computedTiming = GetComputedTimingAt(GetLocalTime(), mTiming);
return computedTiming.mPhase == ComputedTiming::AnimationPhase_Before ||
computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
}
@ -847,9 +844,9 @@ ElementAnimationCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime,
continue;
}
// The GetLocalTimeAt() call here handles pausing. But:
// The GetLocalTime() call here handles pausing. But:
// FIXME: avoid recalculating every time when paused.
Nullable<TimeDuration> localTime = anim->GetLocalTimeAt(aRefreshTime);
Nullable<TimeDuration> localTime = anim->GetLocalTime();
ComputedTiming computedTiming =
ElementAnimation::GetComputedTimingAt(localTime, anim->mTiming);
@ -891,9 +888,9 @@ ElementAnimationCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime,
continue;
}
// The GetLocalTimeAt() call here handles pausing. But:
// The GetLocalTime() call here handles pausing. But:
// FIXME: avoid recalculating every time when paused.
Nullable<TimeDuration> localTime = anim->GetLocalTimeAt(aRefreshTime);
Nullable<TimeDuration> localTime = anim->GetLocalTime();
ComputedTiming computedTiming =
ElementAnimation::GetComputedTimingAt(localTime, anim->mTiming);

View File

@ -363,17 +363,23 @@ public:
bool IsRunningAt(mozilla::TimeStamp aTime) const;
bool IsCurrentAt(mozilla::TimeStamp aTime) const;
// Return the duration at aTime (or, if paused, mPauseStart) since
// the start of the delay period. May be negative.
// Returns a null value if and only if the passed-in TimeStamp IsNull().
Nullable<mozilla::TimeDuration>
GetLocalTimeAt(mozilla::TimeStamp aTime) const {
MOZ_ASSERT(aTime.IsNull() || !IsPaused() || aTime >= mPauseStart,
// Return the duration since the start of the delay period, taking into
// account the pause state. May be negative.
// Returns a null value if the timeline associated with this object has a
// current timestamp that is null or if the start time of this object is
// null.
Nullable<mozilla::TimeDuration> GetLocalTime() const {
const mozilla::TimeStamp& timelineTime = mTimeline->GetCurrentTimeStamp();
// FIXME: In order to support arbitrary timelines we will need to fix
// the pause logic to handle the timeline time going backwards.
MOZ_ASSERT(timelineTime.IsNull() || !IsPaused() ||
timelineTime >= mPauseStart,
"if paused, any non-null value of aTime must be at least"
" mPauseStart");
Nullable<mozilla::TimeDuration> result; // Initializes to null
if (!aTime.IsNull()) {
result.SetValue((IsPaused() ? mPauseStart : aTime) - mStartTime);
if (!timelineTime.IsNull() && !mStartTime.IsNull()) {
result.SetValue((IsPaused() ? mPauseStart : timelineTime) - mStartTime);
}
return result;
}

View File

@ -31,21 +31,21 @@ nsAnimationManager::UpdateStyleAndEvents(ElementAnimationCollection*
EnsureStyleRuleFlags aFlags)
{
aCollection->EnsureStyleRuleFor(aRefreshTime, aFlags);
GetEventsAt(aCollection, aRefreshTime, mPendingEvents);
GetEventsForCurrentTime(aCollection, mPendingEvents);
CheckNeedsRefresh();
}
void
nsAnimationManager::GetEventsAt(ElementAnimationCollection* aCollection,
TimeStamp aRefreshTime,
EventArray& aEventsToDispatch)
nsAnimationManager::GetEventsForCurrentTime(ElementAnimationCollection*
aCollection,
EventArray& aEventsToDispatch)
{
for (uint32_t animIdx = aCollection->mAnimations.Length(); animIdx-- != 0; ) {
ElementAnimation* anim = aCollection->mAnimations[animIdx];
Nullable<TimeDuration> localTime = anim->GetLocalTimeAt(aRefreshTime);
ComputedTiming computedTiming =
ElementAnimation::GetComputedTimingAt(localTime, anim->mTiming);
ElementAnimation::GetComputedTimingAt(anim->GetLocalTime(),
anim->mTiming);
switch (computedTiming.mPhase) {
case ComputedTiming::AnimationPhase_Null:
@ -253,8 +253,6 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
return nullptr;
}
TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
if (collection) {
collection->mStyleRule = nullptr;
collection->mStyleRuleRefreshTime = TimeStamp();
@ -306,7 +304,13 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
} else {
// Handle change in pause state by adjusting start
// time to unpause.
newAnim->mStartTime += refreshTime - oldAnim->mPauseStart;
const TimeStamp& now = timeline->GetCurrentTimeStamp();
if (!now.IsNull()) {
// FIXME: Once we store the start time and pause start as
// offsets (not timestamps) we should be able to update the
// start time to something more appropriate when now IsNull.
newAnim->mStartTime += now - oldAnim->mPauseStart;
}
}
}
}
@ -318,6 +322,7 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
collection->mAnimations.SwapElements(newAnimations);
collection->mNeedsRefreshes = true;
TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
UpdateStyleAndEvents(collection, refreshTime,
EnsureStyleRule_IsNotThrottled);
// We don't actually dispatch the mPendingEvents now. We'll either
@ -393,7 +398,8 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
ResolvedStyleCache resolvedStyles;
const nsStyleDisplay *disp = aStyleContext->StyleDisplay();
TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();
TimeStamp now = aTimeline->GetCurrentTimeStamp();
for (uint32_t animIdx = 0, animEnd = disp->mAnimationNameCount;
animIdx != animEnd; ++animIdx) {
const StyleAnimation& src = disp->mAnimations[animIdx];

View File

@ -79,9 +79,8 @@ public:
void UpdateStyleAndEvents(mozilla::ElementAnimationCollection* aEA,
mozilla::TimeStamp aRefreshTime,
mozilla::EnsureStyleRuleFlags aFlags);
void GetEventsAt(mozilla::ElementAnimationCollection* aEA,
mozilla::TimeStamp aRefreshTime,
EventArray &aEventsToDispatch);
void GetEventsForCurrentTime(mozilla::ElementAnimationCollection* aEA,
EventArray &aEventsToDispatch);
// nsIStyleRuleProcessor (parts)
virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE;

View File

@ -37,7 +37,7 @@ using namespace mozilla::layers;
using namespace mozilla::css;
double
ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const
ElementPropertyTransition::CurrentValuePortion() const
{
// It would be easy enough to handle finished transitions by using a time
// fraction of 1 but currently we should not be called for finished
@ -45,7 +45,7 @@ ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const
MOZ_ASSERT(!IsFinishedTransition(),
"Getting the value portion of a finished transition");
Nullable<TimeDuration> localTime = GetLocalTimeAt(aRefreshTime);
Nullable<TimeDuration> localTime = GetLocalTime();
MOZ_ASSERT(!localTime.IsNull(),
"Getting the value portion of an animation that's not being "
"sampled");
@ -491,9 +491,6 @@ nsTransitionManager::ConsiderStartingTransition(
return;
}
TimeStamp mostRecentRefresh =
presContext->RefreshDriver()->MostRecentRefresh();
const nsTimingFunction &tf = aTransition.GetTimingFunction();
float delay = aTransition.GetDelay();
float duration = aTransition.GetDuration();
@ -512,7 +509,7 @@ nsTransitionManager::ConsiderStartingTransition(
// Compute the appropriate negative transition-delay such that right
// now we'd end up at the current position.
double valuePortion =
oldPT->ValuePortionFor(mostRecentRefresh) * oldPT->mReversePortion +
oldPT->CurrentValuePortion() * oldPT->mReversePortion +
(1.0 - oldPT->mReversePortion);
// A timing function with negative y1 (or y2!) might make
// valuePortion negative. In this case, we still want to apply our
@ -553,7 +550,7 @@ nsTransitionManager::ConsiderStartingTransition(
segment.mToKey = 1;
segment.mTimingFunction.Init(tf);
pt->mStartTime = mostRecentRefresh;
pt->mStartTime = timeline->GetCurrentTimeStamp();
pt->mTiming.mIterationDuration = TimeDuration::FromMilliseconds(duration);
pt->mTiming.mDelay = TimeDuration::FromMilliseconds(delay);
pt->mTiming.mIterationCount = 1;
@ -823,7 +820,7 @@ nsTransitionManager::FlushTransitions(FlushFlags aFlags)
collection->mAnimations.RemoveElementAt(i);
}
} else {
Nullable<TimeDuration> localTime = anim->GetLocalTimeAt(now);
Nullable<TimeDuration> localTime = anim->GetLocalTime();
ComputedTiming computedTiming =
ElementAnimation::GetComputedTimingAt(localTime, anim->mTiming);
if (computedTiming.mPhase == ComputedTiming::AnimationPhase_After) {

View File

@ -54,9 +54,9 @@ struct ElementPropertyTransition : public mozilla::ElementAnimation
double mReversePortion;
// Compute the portion of the *value* space that we should be through
// at the given time. (The input to the transition timing function
// at the current time. (The input to the transition timing function
// has time units, the output has value units.)
double ValuePortionFor(mozilla::TimeStamp aRefreshTime) const;
double CurrentValuePortion() const;
};
} // namespace mozilla