author | Brian Birtles <birtles@gmail.com> |
Tue, 06 Jan 2015 10:56:02 +0900 | |
changeset 222169 | 3b5b53b73e1531425a366c408873d152ed3086cd |
parent 222168 | b2c5a67125d6457a50d3fed0df8681d7c359ca8c |
child 222170 | 78d67ab239d260e9d05b8718603c3bac4d1174b2 |
push id | 28059 |
push user | ryanvm@gmail.com |
push date | Tue, 06 Jan 2015 15:53:01 +0000 |
treeherder | mozilla-central@4d91c33b351c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | vlad |
bugs | 1113413 |
milestone | 37.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/animation/AnimationTimeline.cpp +++ b/dom/animation/AnimationTimeline.cpp @@ -55,24 +55,18 @@ AnimationTimeline::FastForward(const Tim // nsDOMWindowUtils::AdvanceTimeAndRefresh automatically starts any // pending animation players so we don't need to fast-forward the timeline // anyway. nsRefreshDriver* refreshDriver = GetRefreshDriver(); if (refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled()) { return; } - // Bug 1113413: If the refresh driver has just been restored from test - // control it's possible that aTimeStamp could be before the most recent - // refresh. - if (refreshDriver && - aTimeStamp < refreshDriver->MostRecentRefresh()) { - mFastForwardTime = refreshDriver->MostRecentRefresh(); - return; - } + MOZ_ASSERT(!refreshDriver || aTimeStamp >= refreshDriver->MostRecentRefresh(), + "aTimeStamp must be >= the refresh driver time"); // FIXME: For all animations attached to this timeline, we should mark // their target elements as needing restyling. Otherwise, tasks that run // in between now and the next refresh driver tick might see inconsistencies // between the timing of an animation and the computed style of its target. mFastForwardTime = aTimeStamp; }
--- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -756,43 +756,43 @@ nsRefreshDriver::AdvanceTimeAndRefresh(i mozilla::dom::AutoNoJSAPI nojsapi; DoTick(); } void nsRefreshDriver::RestoreNormalRefresh() { mTestControllingRefreshes = false; - EnsureTimerStarted(false); + EnsureTimerStarted(eAllowTimeToGoBackwards); mCompletedTransaction = mPendingTransaction; } TimeStamp nsRefreshDriver::MostRecentRefresh() const { - const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted(false); + const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted(); return mMostRecentRefresh; } int64_t nsRefreshDriver::MostRecentRefreshEpochTime() const { - const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted(false); + const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted(); return mMostRecentRefreshEpochTime; } bool nsRefreshDriver::AddRefreshObserver(nsARefreshObserver* aObserver, mozFlushType aFlushType) { ObserverArray& array = ArrayFor(aFlushType); bool success = array.AppendElement(aObserver) != nullptr; - EnsureTimerStarted(false); + EnsureTimerStarted(); return success; } bool nsRefreshDriver::RemoveRefreshObserver(nsARefreshObserver* aObserver, mozFlushType aFlushType) { ObserverArray& array = ArrayFor(aFlushType); @@ -823,17 +823,17 @@ nsRefreshDriver::AddImageRequest(imgIReq ImageStartData* start = mStartTable.Get(delay); if (!start) { start = new ImageStartData(); mStartTable.Put(delay, start); } start->mEntries.PutEntry(aRequest); } - EnsureTimerStarted(false); + EnsureTimerStarted(); return true; } void nsRefreshDriver::RemoveImageRequest(imgIRequest* aRequest) { // Try to remove from both places, just in case, because we can't tell @@ -844,23 +844,23 @@ nsRefreshDriver::RemoveImageRequest(imgI ImageStartData* start = mStartTable.Get(delay); if (start) { start->mEntries.RemoveEntry(aRequest); } } } void -nsRefreshDriver::EnsureTimerStarted(bool aAdjustingTimer) +nsRefreshDriver::EnsureTimerStarted(EnsureTimerStartedFlags aFlags) { if (mTestControllingRefreshes) return; // will it already fire, and no other changes needed? - if (mActiveTimer && !aAdjustingTimer) + if (mActiveTimer && !(aFlags & eAdjustingTimer)) return; if (IsFrozen() || !mPresContext) { // If we don't want to start it now, or we've been disconnected. StopTimer(); return; } @@ -886,21 +886,29 @@ nsRefreshDriver::EnsureTimerStarted(bool mActiveTimer = newTimer; mActiveTimer->AddRefreshDriver(this); } // Since the different timers are sampled at different rates, when switching // timers, the most recent refresh of the new timer may be *before* the // most recent refresh of the old timer. However, the refresh driver time // should not go backwards so we clamp the most recent refresh time. + // + // The one exception to this is when we are restoring the refresh driver + // from test control in which case the time is expected to go backwards + // (see bug 1043078). mMostRecentRefresh = - std::max(mActiveTimer->MostRecentRefresh(), mMostRecentRefresh); + aFlags & eAllowTimeToGoBackwards + ? mActiveTimer->MostRecentRefresh() + : std::max(mActiveTimer->MostRecentRefresh(), mMostRecentRefresh); mMostRecentRefreshEpochTime = - std::max(mActiveTimer->MostRecentRefreshEpochTime(), - mMostRecentRefreshEpochTime); + aFlags & eAllowTimeToGoBackwards + ? mActiveTimer->MostRecentRefreshEpochTime() + : std::max(mActiveTimer->MostRecentRefreshEpochTime(), + mMostRecentRefreshEpochTime); } void nsRefreshDriver::StopTimer() { if (!mActiveTimer) return; @@ -1498,17 +1506,17 @@ nsRefreshDriver::Thaw() if (mFreezeCount == 0) { if (ObserverCount() || ImageRequestCount()) { // FIXME: This isn't quite right, since our EnsureTimerStarted call // updates our mMostRecentRefresh, but the DoRefresh call won't run // and notify our observers until we get back to the event loop. // Thus MostRecentRefresh() will lie between now and the DoRefresh. NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, &nsRefreshDriver::DoRefresh)); - EnsureTimerStarted(false); + EnsureTimerStarted(); } } } void nsRefreshDriver::FinishedWaitingForTransaction() { mWaitingForTransaction = false; @@ -1626,17 +1634,17 @@ nsRefreshDriver::IsWaitingForPaint(mozil void nsRefreshDriver::SetThrottled(bool aThrottled) { if (aThrottled != mThrottled) { mThrottled = aThrottled; if (mActiveTimer) { // We want to switch our timer type here, so just stop and // restart the timer. - EnsureTimerStarted(true); + EnsureTimerStarted(eAdjustingTimer); } } } void nsRefreshDriver::DoRefresh() { // Don't do a refresh unless we're in a state where we should be refreshing. @@ -1656,30 +1664,30 @@ nsRefreshDriver::IsRefreshObserver(nsARe #endif void nsRefreshDriver::ScheduleViewManagerFlush() { NS_ASSERTION(mPresContext->IsRoot(), "Should only schedule view manager flush on root prescontexts"); mViewManagerFlushIsPending = true; - EnsureTimerStarted(false); + EnsureTimerStarted(); } void nsRefreshDriver::ScheduleFrameRequestCallbacks(nsIDocument* aDocument) { NS_ASSERTION(mFrameRequestCallbackDocs.IndexOf(aDocument) == mFrameRequestCallbackDocs.NoIndex, "Don't schedule the same document multiple times"); mFrameRequestCallbackDocs.AppendElement(aDocument); // make sure that the timer is running ConfigureHighPrecision(); - EnsureTimerStarted(false); + EnsureTimerStarted(); } void nsRefreshDriver::RevokeFrameRequestCallbacks(nsIDocument* aDocument) { mFrameRequestCallbackDocs.RemoveElement(aDocument); ConfigureHighPrecision(); // No need to worry about restarting our timer in slack mode if it's already
--- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -154,17 +154,17 @@ public: // We only get the cause for the first observer each frame because capturing // a stack is expensive. This is still useful if (1) you're trying to remove // all flushes for a particial frame or (2) the costly flush is triggered // near the call site where the first observer is triggered. if (!mStyleCause) { mStyleCause = profiler_get_backtrace(); } bool appended = mStyleFlushObservers.AppendElement(aShell) != nullptr; - EnsureTimerStarted(false); + EnsureTimerStarted(); return appended; } void RemoveStyleFlushObserver(nsIPresShell* aShell) { mStyleFlushObservers.RemoveElement(aShell); } bool AddLayoutFlushObserver(nsIPresShell* aShell) { NS_ASSERTION(!IsLayoutFlushObserver(aShell), @@ -172,30 +172,30 @@ public: // We only get the cause for the first observer each frame because capturing // a stack is expensive. This is still useful if (1) you're trying to remove // all flushes for a particial frame or (2) the costly flush is triggered // near the call site where the first observer is triggered. if (!mReflowCause) { mReflowCause = profiler_get_backtrace(); } bool appended = mLayoutFlushObservers.AppendElement(aShell) != nullptr; - EnsureTimerStarted(false); + EnsureTimerStarted(); return appended; } void RemoveLayoutFlushObserver(nsIPresShell* aShell) { mLayoutFlushObservers.RemoveElement(aShell); } bool IsLayoutFlushObserver(nsIPresShell* aShell) { return mLayoutFlushObservers.Contains(aShell); } bool AddPresShellToInvalidateIfHidden(nsIPresShell* aShell) { NS_ASSERTION(!mPresShellsToInvalidateIfHidden.Contains(aShell), "Double-adding style flush observer"); bool appended = mPresShellsToInvalidateIfHidden.AppendElement(aShell) != nullptr; - EnsureTimerStarted(false); + EnsureTimerStarted(); return appended; } void RemovePresShellToInvalidateIfHidden(nsIPresShell* aShell) { mPresShellsToInvalidateIfHidden.RemoveElement(aShell); } /** * Remember whether our presshell's view manager needs a flush @@ -293,17 +293,22 @@ private: mozilla::Maybe<mozilla::TimeStamp> mStartTime; RequestTable mEntries; }; typedef nsClassHashtable<nsUint32HashKey, ImageStartData> ImageStartTable; void Tick(int64_t aNowEpoch, mozilla::TimeStamp aNowTime); - void EnsureTimerStarted(bool aAdjustingTimer); + enum EnsureTimerStartedFlags { + eNone = 0, + eAdjustingTimer = 1 << 0, + eAllowTimeToGoBackwards = 1 << 1 + }; + void EnsureTimerStarted(EnsureTimerStartedFlags aFlags = eNone); void StopTimer(); uint32_t ObserverCount() const; uint32_t ImageRequestCount() const; static PLDHashOperator ImageRequestEnumerator(nsISupportsHashKey* aEntry, void* aUserArg); static PLDHashOperator StartTableRequestCounter(const uint32_t& aKey, ImageStartData* aEntry,