Bug 1857618 - Ensure normal tasks get enough time to run, so try to avoid triggering RefreshDriver too often, r=bas

Based on testing we can simplify the current setup and also ensure that we don't trigger a RefreshDriver tick too soon
(so that we don't get two ticks when we expect only one).
This gets us even closer to Chrome's raf handling.

Differential Revision: https://phabricator.services.mozilla.com/D190361
This commit is contained in:
Olli Pettay 2023-10-10 22:45:47 +00:00
Родитель 5894d122aa
Коммит aba6665fc1
1 изменённых файлов: 23 добавлений и 40 удалений

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

@ -673,18 +673,20 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
// If pages aren't loading and there aren't other tasks to run,
// trigger the pending vsync notification.
static bool sHasPendingLowPrioTask = false;
static VsyncEvent sMostRecentSkippedVsync;
sMostRecentSkippedVsync = aVsyncEvent;
if (!sHasPendingLowPrioTask) {
sHasPendingLowPrioTask = true;
NS_DispatchToMainThreadQueue(
NS_NewRunnableFunction(
"NotifyVsyncOnMainThread[low priority]",
[self = RefPtr{this}, event = aVsyncEvent]() {
[self = RefPtr{this}]() {
sHasPendingLowPrioTask = false;
if (self->mRecentVsync == event.mTime &&
self->mRecentVsyncId == event.mId &&
if (self->mRecentVsync == sMostRecentSkippedVsync.mTime &&
self->mRecentVsyncId == sMostRecentSkippedVsync.mId &&
!self->ShouldGiveNonVsyncTasksMoreTime()) {
self->mSuspendVsyncPriorityTicksUntil = TimeStamp();
self->NotifyVsyncOnMainThread(event);
self->NotifyVsyncOnMainThread(sMostRecentSkippedVsync);
}
}),
EventQueuePriority::Low);
@ -828,8 +830,6 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
MOZ_ASSERT(aVsyncTimestamp <= tickStart);
#endif
bool shouldGiveNonVSyncTasksMoreTime = ShouldGiveNonVsyncTasksMoreTime();
// Set these variables before calling RunRefreshDrivers so that they are
// visible to any nested ticks.
mLastTickStart = tickStart;
@ -859,28 +859,24 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
// period).
TimeDuration gracePeriod = rate / int64_t(100);
if (shouldGiveNonVSyncTasksMoreTime) {
if (!mLastTickEnd.IsNull() && XRE_IsContentProcess() &&
// For RefreshDriver scheduling during page load there is currently
// idle priority based setup.
// XXX Consider to remove the page load specific code paths.
!IsAnyToplevelContentPageLoading()) {
// In case normal tasks are doing lots of work, we still want to paint
// every now and then, so only at maximum 4 * rate of work is counted
// here.
// If we're giving extra time for tasks outside a tick, try to
// ensure the next vsync after that period is handled, so subtract
// a grace period.
TimeDuration timeForOutsideTick = clamped(
tickStart - mLastTickEnd - gracePeriod, TimeDuration(), rate * 4);
mSuspendVsyncPriorityTicksUntil = aVsyncTimestamp + timeForOutsideTick +
(tickEnd - mostRecentTickStart);
} else {
mSuspendVsyncPriorityTicksUntil =
aVsyncTimestamp + gracePeriod + (tickEnd - mostRecentTickStart);
}
if (!mLastTickEnd.IsNull() && XRE_IsContentProcess() &&
// For RefreshDriver scheduling during page load there is currently
// idle priority based setup.
// XXX Consider to remove the page load specific code paths.
!IsAnyToplevelContentPageLoading()) {
// In case normal tasks are doing lots of work, we still want to paint
// every now and then, so only at maximum 4 * rate of work is counted
// here.
// If we're giving extra time for tasks outside a tick, try to
// ensure the next vsync after that period is handled, so subtract
// a grace period.
TimeDuration timeForOutsideTick = clamped(
tickStart - mLastTickEnd - gracePeriod, TimeDuration(), rate * 4);
mSuspendVsyncPriorityTicksUntil = aVsyncTimestamp + timeForOutsideTick +
(tickEnd - mostRecentTickStart);
} else {
mSuspendVsyncPriorityTicksUntil = aVsyncTimestamp + gracePeriod;
mSuspendVsyncPriorityTicksUntil =
aVsyncTimestamp + gracePeriod + (tickEnd - mostRecentTickStart);
}
mLastIdleTaskCount =
@ -2985,19 +2981,6 @@ void nsRefreshDriver::Thaw() {
}
void nsRefreshDriver::FinishedWaitingForTransaction() {
if (mSkippedPaints && !IsInRefresh() &&
(HasObservers() || HasImageRequests()) && CanDoCatchUpTick()) {
NS_DispatchToCurrentThreadQueue(
NS_NewRunnableFunction(
"nsRefreshDriver::FinishedWaitingForTransaction",
[self = RefPtr{this}]() {
if (self->CanDoCatchUpTick()) {
self->Tick(self->mActiveTimer->MostRecentRefreshVsyncId(),
self->mActiveTimer->MostRecentRefresh());
}
}),
EventQueuePriority::Vsync);
}
mWaitingForTransaction = false;
mSkippedPaints = false;
}