author | Mason Chang <mchang@mozilla.com> |
Thu, 13 Aug 2015 08:22:28 -0700 | |
changeset 257590 | bbc8646e83432bd74a37b6a6950a53c9e5a4644d |
parent 257589 | a5c25038d81e9de97b939f9380c20773b10ace46 |
child 257591 | be020690f03288bbbcf8e061a2f0bc80de498195 |
push id | 29223 |
push user | kwierso@gmail.com |
push date | Thu, 13 Aug 2015 22:18:08 +0000 |
treeherder | mozilla-central@4b35236fc76e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 1144946 |
milestone | 43.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/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -516,134 +516,16 @@ protected: // then schedule the timer LOG("[%p] scheduling callback for %d ms (2)", this, delay); mTimer->InitWithFuncCallback(TimerTick, this, delay, nsITimer::TYPE_ONE_SHOT); mTargetTime = newTarget; } }; -#ifdef XP_WIN -/* - * Uses vsync timing on windows with DWM. Falls back dynamically to fixed rate if required. - */ -class PreciseRefreshDriverTimerWindowsDwmVsync : - public PreciseRefreshDriverTimer -{ -public: - // Checks if the vsync API is accessible. - static bool IsSupported() - { - return WinUtils::dwmGetCompositionTimingInfoPtr != nullptr; - } - - PreciseRefreshDriverTimerWindowsDwmVsync(double aRate, bool aPreferHwTiming = false) - : PreciseRefreshDriverTimer(aRate) - , mPreferHwTiming(aPreferHwTiming) - { - } - -protected: - // Indicates we should try to adjust to the HW's timing (get rate from the OS or use vsync) - // This is typically true if the default refresh-rate value was not modified by the user. - bool mPreferHwTiming; - - nsresult GetVBlankInfo(mozilla::TimeStamp &aLastVBlank, mozilla::TimeDuration &aInterval) - { - MOZ_ASSERT(WinUtils::dwmGetCompositionTimingInfoPtr, - "DwmGetCompositionTimingInfoPtr is unavailable (windows vsync)"); - - DWM_TIMING_INFO timingInfo; - timingInfo.cbSize = sizeof(DWM_TIMING_INFO); - HRESULT hr = WinUtils::dwmGetCompositionTimingInfoPtr(0, &timingInfo); // For the desktop window instead of a specific one. - - if (FAILED(hr)) { - // This happens first time this is called. - return NS_ERROR_NOT_INITIALIZED; - } - - LARGE_INTEGER time, freq; - ::QueryPerformanceCounter(&time); - ::QueryPerformanceFrequency(&freq); - aLastVBlank = TimeStamp::Now(); - double secondsPassed = double(time.QuadPart - timingInfo.qpcVBlank) / double(freq.QuadPart); - - aLastVBlank -= TimeDuration::FromSeconds(secondsPassed); - aInterval = TimeDuration::FromSeconds(double(timingInfo.qpcRefreshPeriod) / double(freq.QuadPart)); - - return NS_OK; - } - - virtual void ScheduleNextTick(TimeStamp aNowTime) - { - static const TimeDuration kMinSaneInterval = TimeDuration::FromMilliseconds(3); // 330Hz - static const TimeDuration kMaxSaneInterval = TimeDuration::FromMilliseconds(44); // 23Hz - static const TimeDuration kNegativeMaxSaneInterval = TimeDuration::FromMilliseconds(-44); // Saves conversions for abs interval - TimeStamp lastVblank; - TimeDuration vblankInterval; - - if (!mPreferHwTiming || - NS_OK != GetVBlankInfo(lastVblank, vblankInterval) || - vblankInterval > kMaxSaneInterval || - vblankInterval < kMinSaneInterval || - (aNowTime - lastVblank) > kMaxSaneInterval || - (aNowTime - lastVblank) < kNegativeMaxSaneInterval) { - // Use the default timing without vsync - PreciseRefreshDriverTimer::ScheduleNextTick(aNowTime); - return; - } - - TimeStamp newTarget = lastVblank + vblankInterval; // Base target - - // However, timer callback might return early (or late, but that wouldn't bother us), and vblankInterval - // appears to be slightly (~1%) different on each call (probably the OS measuring recent actual interval[s]) - // and since we don't want to re-target the same vsync, we keep advancing in vblank intervals until we find the - // next safe target (next vsync, but not within 10% interval of previous target). - // This is typically 0 or 1 iteration: - // If we're too early, next vsync would be the one we've already targeted (1 iteration). - // If the timer returned late, no iteration will be required. - - const double kSameVsyncThreshold = 0.1; - while (newTarget <= mTargetTime + vblankInterval.MultDouble(kSameVsyncThreshold)) { - newTarget += vblankInterval; - } - - // To make sure we always hit the same "side" of the signal: - // round the delay up (by adding 1, since we later floor) and add a little (10% by default). - // Note that newTarget doesn't change (and is the next vblank) as a reference when we're back. - static const double kDefaultPhaseShiftPercent = 10; - static const double phaseShiftFactor = 0.01 * - (Preferences::GetInt("layout.frame_rate.vsync.phasePercentage", kDefaultPhaseShiftPercent) % 100); - - double phaseDelay = 1.0 + vblankInterval.ToMilliseconds() * phaseShiftFactor; - - // ms until the next time we should tick - double delayMs = (newTarget - aNowTime).ToMilliseconds() + phaseDelay; - - // Make sure the delay is never negative. - uint32_t delay = static_cast<uint32_t>(delayMs < 0 ? 0 : delayMs); - - // log info & lateness - LOG("[%p] precise dwm-vsync timer last tick late by %f ms, next tick in %d ms", - this, - (aNowTime - mTargetTime).ToMilliseconds(), - delay); -#ifndef ANDROID /* bug 1142079 */ - Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_FRAME_DELAY_MS, (aNowTime - mTargetTime).ToMilliseconds()); -#endif - - // then schedule the timer - LOG("[%p] scheduling callback for %d ms (2)", this, delay); - mTimer->InitWithFuncCallback(TimerTick, this, delay, nsITimer::TYPE_ONE_SHOT); - - mTargetTime = newTarget; - } -}; -#endif - /* * A RefreshDriverTimer for inactive documents. When a new refresh driver is * added, the rate is reset to the base (normally 1s/1fps). Every time * it ticks, a single refresh driver is poked. Once they have all been poked, * the duration between ticks doubles, up to mDisableAfterMilliseconds. At that point, * the timer is quiet and doesn't tick (until something is added to it again). * * When a timer is removed, there is a possibility of another timer @@ -1002,21 +884,16 @@ nsRefreshDriver::ChooseTimer() const if (!sRegularRateTimer) { bool isDefault = true; double rate = GetRegularTimerInterval(&isDefault); // Try to use vsync-base refresh timer first for sRegularRateTimer. CreateVsyncRefreshTimer(); -#ifdef XP_WIN - if (!sRegularRateTimer && PreciseRefreshDriverTimerWindowsDwmVsync::IsSupported()) { - sRegularRateTimer = new PreciseRefreshDriverTimerWindowsDwmVsync(rate, isDefault); - } -#endif if (!sRegularRateTimer) { sRegularRateTimer = new PreciseRefreshDriverTimer(rate); } } return sRegularRateTimer; } nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext)