diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 257da80e7427..e54e58c59d94 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -155,6 +155,8 @@ class AutoRecordPhase { namespace mozilla { +static TimeStamp sMostRecentHighRateVsync; + /* * The base class for all global refresh driver timers. It takes care * of managing the list of refresh drivers attached to them and @@ -780,6 +782,12 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer { TimeStamp tickStart = TimeStamp::Now(); + TimeDuration rate = GetTimerRate(); + if (TimeDuration::FromMilliseconds(nsRefreshDriver::DefaultInterval() / 2) > + rate) { + sMostRecentHighRateVsync = tickStart; + } + // On 32-bit Windows we sometimes get times where TimeStamp::Now() is not // monotonic because the underlying system apis produce non-monontonic // results. (bug 1306896) @@ -812,7 +820,6 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer { // (aVsyncTimestamp) and the next tick needs to be at least the amount of // work normal tasks and RefreshDrivers did together (minus short grace // period). - TimeDuration rate = GetTimerRate(); TimeDuration gracePeriod = rate / int64_t(100); if (shouldGiveNonVSyncTasksMoreTime) { @@ -1187,6 +1194,23 @@ int32_t nsRefreshDriver::DefaultInterval() { return NSToIntRound(1000.0 / gfxPlatform::GetDefaultFrameRate()); } +/* static */ +bool nsRefreshDriver::IsInHighRateMode() { + // We're in high rate mode if we've gotten a fast rate during the last + // DefaultInterval(). + bool inHighRateMode = + !gfxPlatform::IsInLayoutAsapMode() && + StaticPrefs::layout_expose_high_rate_mode_from_refreshdriver() && + !sMostRecentHighRateVsync.IsNull() && + (sMostRecentHighRateVsync + + TimeDuration::FromMilliseconds(DefaultInterval())) > TimeStamp::Now(); + if (!inHighRateMode) { + // Clear the timestamp so that the next call is faster. + sMostRecentHighRateVsync = TimeStamp(); + } + return inHighRateMode; +} + // Compute the interval to use for the refresh driver timer, in milliseconds. // outIsDefault indicates that rate was not explicitly set by the user // so we might choose other, more appropriate rates (e.g. vsync, etc) diff --git a/layout/base/nsRefreshDriver.h b/layout/base/nsRefreshDriver.h index e41bea586b4a..4d9af9f4530d 100644 --- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -322,6 +322,12 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator, */ static int32_t DefaultInterval(); + /** + * Returns true if a recent vsync interval has been less than a half of + * DefaultInterval. + */ + static bool IsInHighRateMode(); + bool IsInRefresh() { return mInRefresh; } void SetIsResizeSuppressed() { mResizeSuppressed = true; } diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 76a050fb81ce..d4dde2157e3a 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -8382,6 +8382,12 @@ value: true mirror: always +# Controls whether nsRefreshDriver::IsInHighRateMode() may ever return true. +- name: layout.expose_high_rate_mode_from_refreshdriver + type: bool + value: true + mirror: always + #--------------------------------------------------------------------------- # Prefs starting with "mathml." #---------------------------------------------------------------------------