Bug 1190257. Use the previous vsync timestamp on Windows 10. r=jrmuizel

This commit is contained in:
Mason Chang 2015-08-12 09:20:00 -07:00
parent 12ea8e3272
commit fad3bcb082

View File

@ -2502,6 +2502,7 @@ public:
public:
D3DVsyncDisplay()
: mVsyncEnabledLock("D3DVsyncEnabledLock")
, mPrevVsync(TimeStamp::Now())
, mVsyncEnabled(false)
{
mVsyncThread = new base::Thread("WindowsVsyncThread");
@ -2561,6 +2562,35 @@ public:
delay.ToMilliseconds());
}
TimeStamp GetAdjustedVsyncTimeStamp(LARGE_INTEGER& aFrequency,
QPC_TIME& aQpcVblankTime)
{
TimeStamp vsync = TimeStamp::Now();
LARGE_INTEGER qpcNow;
QueryPerformanceCounter(&qpcNow);
const int microseconds = 1000000;
int64_t adjust = qpcNow.QuadPart - aQpcVblankTime;
int64_t usAdjust = (adjust * microseconds) / aFrequency.QuadPart;
vsync -= TimeDuration::FromMicroseconds((double) usAdjust);
if (IsWin10OrLater()) {
// On Windows 10 and on, DWMGetCompositionTimingInfo
// reports the upcoming vsync time, which is in the future.
// Since large parts of Gecko assume TimeStamps can't be in future
// return the previous vsync.
MOZ_ASSERT(usAdjust <= 0);
TimeStamp currentVsync = mPrevVsync;
mPrevVsync = vsync;
return currentVsync;
}
// On Windows 7 and 8, DwmFlush wakes up AFTER qpcVBlankTime
// from DWMGetCompositionTimingInfo. We can return the adjusted vsync.
MOZ_ASSERT(usAdjust >= 0);
return vsync;
}
void VBlankLoop()
{
MOZ_ASSERT(IsInVsyncThread());
@ -2570,12 +2600,9 @@ public:
// Make sure to init the cbSize, otherwise GetCompositionTiming will fail
vblankTime.cbSize = sizeof(DWM_TIMING_INFO);
LARGE_INTEGER qpcNow;
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
TimeStamp vsync = TimeStamp::Now();
TimeStamp previousVsync = vsync;
const int microseconds = 1000000;
for (;;) {
{ // scope lock
@ -2583,12 +2610,9 @@ public:
if (!mVsyncEnabled) return;
}
if (previousVsync > vsync) {
vsync = TimeStamp::Now();
NS_WARNING("Previous vsync timestamp is ahead of the calculated vsync timestamp.");
}
previousVsync = vsync;
// Large parts of gecko assume that the refresh driver timestamp
// must be <= Now() and cannot be in the future.
MOZ_ASSERT(vsync <= TimeStamp::Now());
Display::NotifyVsync(vsync);
// DwmComposition can be dynamically enabled/disabled
@ -2606,13 +2630,7 @@ public:
HRESULT hr = WinUtils::dwmGetCompositionTimingInfoPtr(0, &vblankTime);
vsync = TimeStamp::Now();
if (SUCCEEDED(hr)) {
QueryPerformanceCounter(&qpcNow);
// Adjust the timestamp to be the vsync timestamp since when
// DwmFlush wakes up and when the actual vsync occurred are not the
// same.
int64_t adjust = qpcNow.QuadPart - vblankTime.qpcVBlank;
int64_t usAdjust = (adjust * microseconds) / frequency.QuadPart;
vsync -= TimeDuration::FromMicroseconds((double) usAdjust);
vsync = GetAdjustedVsyncTimeStamp(frequency, vblankTime.qpcVBlank);
}
} // end for
}
@ -2632,6 +2650,7 @@ public:
}
TimeDuration mSoftwareVsyncRate;
TimeStamp mPrevVsync;
Monitor mVsyncEnabledLock;
base::Thread* mVsyncThread;
bool mVsyncEnabled;