#include "ui/gl/vsync_provider_win.h"
#include <dwmapi.h>
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/native_widget_types.h"
namespace gl {
VSyncProviderWin::VSyncProviderWin(gfx::AcceleratedWidget window)
: window_(window) {
}
VSyncProviderWin::~VSyncProviderWin() {}
void VSyncProviderWin::InitializeOneOff() {
static bool initialized = false;
if (initialized)
return;
initialized = true;
::LoadLibrary(L"dwmapi.dll");
}
void VSyncProviderWin::GetVSyncParameters(UpdateVSyncCallback callback) {
base::TimeTicks timebase;
base::TimeDelta interval;
if (GetVSyncParametersIfAvailable(&timebase, &interval))
std::move(callback).Run(timebase, interval);
}
bool VSyncProviderWin::GetVSyncParametersIfAvailable(
base::TimeTicks* out_timebase,
base::TimeDelta* out_interval) {
TRACE_EVENT0("gpu", "WinVSyncProvider::GetVSyncParameters");
base::TimeTicks timebase;
base::TimeDelta interval;
DWM_TIMING_INFO timing_info;
timing_info.cbSize = sizeof(timing_info);
HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info);
if (result == S_OK) {
base::TimeDelta rate_interval;
if (timing_info.rateRefresh.uiDenominator > 0 &&
timing_info.rateRefresh.uiNumerator > 0) {
rate_interval = base::Microseconds(timing_info.rateRefresh.uiDenominator *
base::Time::kMicrosecondsPerSecond /
timing_info.rateRefresh.uiNumerator);
}
if (base::TimeTicks::IsHighResolution()) {
timebase = base::TimeTicks::FromQPCValue(
static_cast<LONGLONG>(timing_info.qpcVBlank));
interval = base::TimeDelta::FromQPCValue(
static_cast<LONGLONG>(timing_info.qpcRefreshPeriod));
if (interval < base::Milliseconds(1)) {
interval = rate_interval;
}
if (!rate_interval.is_zero() && interval < rate_interval / 2) {
interval = rate_interval;
}
} else {
interval = rate_interval;
}
} else {
HMONITOR monitor = MonitorFromWindow(window_, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
if (GetMonitorInfo(monitor, &monitor_info)) {
DEVMODE display_info;
display_info.dmSize = sizeof(DEVMODE);
display_info.dmDriverExtra = 0;
if (EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS,
&display_info) &&
display_info.dmDisplayFrequency > 1) {
interval = base::Microseconds(
(1.0 / static_cast<double>(display_info.dmDisplayFrequency)) *
base::Time::kMicrosecondsPerSecond);
}
}
}
if (interval.is_zero())
return false;
*out_timebase = timebase;
*out_interval = interval;
return true;
}
bool VSyncProviderWin::SupportGetVSyncParametersIfAvailable() const {
return true;
}
bool VSyncProviderWin::IsHWClock() const {
return true;
}
}