Bug 1675614 - Try doing a 'catch-up' refresh driver tick if we get a paint request part way into a tick, and haven't yet painted that tick. r=mstange

Differential Revision: https://phabricator.services.mozilla.com/D109691
This commit is contained in:
Matt Woodrow 2021-03-26 04:19:45 +00:00
parent 452ae67807
commit 4d7b8ad1e7
2 changed files with 41 additions and 0 deletions

View File

@ -230,6 +230,7 @@ class RefreshDriverTimer {
}
TimeStamp MostRecentRefresh() const { return mLastFireTime; }
VsyncId MostRecentRefreshVsyncId() const { return mLastFireId; }
virtual TimeDuration GetTimerRate() = 0;
@ -332,6 +333,7 @@ class RefreshDriverTimer {
ScheduleNextTick(now);
mLastFireTime = now;
mLastFireId = aId;
LOG("[%p] ticking drivers...", this);
@ -346,6 +348,7 @@ class RefreshDriverTimer {
}
TimeStamp mLastFireTime;
VsyncId mLastFireId;
TimeStamp mTargetTime;
nsTArray<RefPtr<nsRefreshDriver>> mContentRefreshDrivers;
@ -393,6 +396,7 @@ class SimpleTimerBasedRefreshDriverTimer : public RefreshDriverTimer {
void StartTimer() override {
// pretend we just fired, and we schedule the next tick normally
mLastFireTime = TimeStamp::Now();
mLastFireId = VsyncId();
mTargetTime = mLastFireTime + mRateDuration;
@ -741,6 +745,7 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
MOZ_ASSERT(NS_IsMainThread());
mLastFireTime = TimeStamp::Now();
mLastFireId = VsyncId();
if (mVsyncDispatcher) {
mVsyncDispatcher->AddChildRefreshTimer(mVsyncObserver);
@ -876,6 +881,7 @@ class InactiveRefreshDriverTimer final
void StartTimer() override {
mLastFireTime = TimeStamp::Now();
mLastFireId = VsyncId();
mTargetTime = mLastFireTime + mRateDuration;
@ -919,6 +925,7 @@ class InactiveRefreshDriverTimer final
ScheduleNextTick(now);
mLastFireTime = now;
mLastFireId = VsyncId();
nsTArray<RefPtr<nsRefreshDriver>> drivers(mContentRefreshDrivers.Clone());
drivers.AppendElements(mRootRefreshDrivers);
@ -1385,6 +1392,20 @@ void nsRefreshDriver::RunDelayedEventsSoon() {
EnsureTimerStarted();
}
bool nsRefreshDriver::CanDoCatchUpTick() {
if (mTestControllingRefreshes || !mActiveTimer) {
return false;
}
// If we've already ticked for the current timer refresh (or more recently
// than that), then we don't need to do any catching up.
if (mMostRecentRefresh >= mActiveTimer->MostRecentRefresh()) {
return false;
}
return true;
}
void nsRefreshDriver::EnsureTimerStarted(EnsureTimerStartedFlags aFlags) {
// FIXME: Bug 1346065: We should also assert the case where we have
// STYLO_THREADS=1.
@ -1427,6 +1448,24 @@ void nsRefreshDriver::EnsureTimerStarted(EnsureTimerStartedFlags aFlags) {
if (mActiveTimer) mActiveTimer->RemoveRefreshDriver(this);
mActiveTimer = newTimer;
mActiveTimer->AddRefreshDriver(this);
// If the timer has ticked since we last ticked, consider doing a 'catch-up'
// tick immediately.
if (CanDoCatchUpTick()) {
RefPtr<nsRefreshDriver> self = this;
NS_DispatchToCurrentThreadQueue(
NS_NewRunnableFunction(
"RefreshDriver::EnsureTimerStarted::catch-up",
[self]() -> void {
// Re-check if we can still do a catch-up, in case anything
// changed while the runnable was pending.
if (self->CanDoCatchUpTick()) {
self->Tick(self->mActiveTimer->MostRecentRefreshVsyncId(),
self->mActiveTimer->MostRecentRefresh());
}
}),
EventQueuePriority::High);
}
}
// When switching from an inactive timer to an active timer, the root

View File

@ -478,6 +478,8 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
void FinishedWaitingForTransaction();
bool CanDoCatchUpTick();
mozilla::RefreshDriverTimer* ChooseTimer();
mozilla::RefreshDriverTimer* mActiveTimer;
RefPtr<mozilla::RefreshDriverTimer> mOwnTimer;