Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(876)

Side by Side Diff: ui/gl/vsync_provider_win.cc

Issue 2909943003: Removing useless Win7 checks + standardize its use (Closed)
Patch Set: Fix reversed conditionnal Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gl/vsync_provider_win.h" 5 #include "ui/gl/vsync_provider_win.h"
6 6
7 #include <dwmapi.h> 7 #include <dwmapi.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
11 #include "base/win/windows_version.h"
12 #include "ui/gfx/native_widget_types.h" 11 #include "ui/gfx/native_widget_types.h"
13 12
14 namespace gl { 13 namespace gl {
15 14
16 namespace {
17 bool g_use_dwm_vsync;
18 } // namespace
19
20 VSyncProviderWin::VSyncProviderWin(gfx::AcceleratedWidget window) 15 VSyncProviderWin::VSyncProviderWin(gfx::AcceleratedWidget window)
21 : window_(window) { 16 : window_(window) {
22 } 17 }
23 18
24 VSyncProviderWin::~VSyncProviderWin() {} 19 VSyncProviderWin::~VSyncProviderWin() {}
25 20
26 // static 21 // static
27 void VSyncProviderWin::InitializeOneOff() { 22 void VSyncProviderWin::InitializeOneOff() {
28 static bool initialized = false; 23 static bool initialized = false;
29 if (initialized) 24 if (initialized)
30 return; 25 return;
31 initialized = true; 26 initialized = true;
32 g_use_dwm_vsync = (base::win::GetVersion() >= base::win::VERSION_WIN7);
33 27
34 if (g_use_dwm_vsync) { 28 // Prewarm sandbox
35 // Prewarm sandbox 29 ::LoadLibrary(L"dwmapi.dll");
36 ::LoadLibrary(L"dwmapi.dll");
37 }
38 } 30 }
39 31
40 void VSyncProviderWin::GetVSyncParameters(const UpdateVSyncCallback& callback) { 32 void VSyncProviderWin::GetVSyncParameters(const UpdateVSyncCallback& callback) {
41 TRACE_EVENT0("gpu", "WinVSyncProvider::GetVSyncParameters"); 33 TRACE_EVENT0("gpu", "WinVSyncProvider::GetVSyncParameters");
42 34
43 base::TimeTicks timebase; 35 base::TimeTicks timebase;
44 base::TimeDelta interval; 36 base::TimeDelta interval;
45 bool dwm_active = false;
46 37
47 // Query the DWM timing info first if available. This will provide the most 38 // Query the DWM timing info first if available. This will provide the most
48 // precise values. 39 // precise values.
49 if (g_use_dwm_vsync) { 40 DWM_TIMING_INFO timing_info;
50 DWM_TIMING_INFO timing_info; 41 timing_info.cbSize = sizeof(timing_info);
51 timing_info.cbSize = sizeof(timing_info); 42 HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info);
52 HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info); 43 if (result == S_OK) {
53 if (result == S_OK) { 44 // Calculate an interval value using the rateRefresh numerator and
54 dwm_active = true; 45 // denominator.
46 base::TimeDelta rate_interval;
47 if (timing_info.rateRefresh.uiDenominator > 0 &&
48 timing_info.rateRefresh.uiNumerator > 0) {
49 // Swap the numerator/denominator to convert frequency to period.
50 rate_interval = base::TimeDelta::FromMicroseconds(
51 timing_info.rateRefresh.uiDenominator *
52 base::Time::kMicrosecondsPerSecond /
53 timing_info.rateRefresh.uiNumerator);
54 }
55 55
56 // Calculate an interval value using the rateRefresh numerator and 56 if (base::TimeTicks::IsHighResolution()) {
57 // denominator. 57 // qpcRefreshPeriod is very accurate but noisy, and must be used with
58 base::TimeDelta rate_interval; 58 // a high resolution timebase to avoid frequently missing Vsync.
59 if (timing_info.rateRefresh.uiDenominator > 0 && 59 timebase = base::TimeTicks::FromQPCValue(
60 timing_info.rateRefresh.uiNumerator > 0) { 60 static_cast<LONGLONG>(timing_info.qpcVBlank));
61 // Swap the numerator/denominator to convert frequency to period. 61 interval = base::TimeDelta::FromQPCValue(
62 rate_interval = base::TimeDelta::FromMicroseconds( 62 static_cast<LONGLONG>(timing_info.qpcRefreshPeriod));
63 timing_info.rateRefresh.uiDenominator * 63 // Check for interval values that are impossibly low. A 29 microsecond
64 base::Time::kMicrosecondsPerSecond / 64 // interval was seen (from a qpcRefreshPeriod of 60).
65 timing_info.rateRefresh.uiNumerator); 65 if (interval < base::TimeDelta::FromMilliseconds(1)) {
66 }
67
68 if (base::TimeTicks::IsHighResolution()) {
69 // qpcRefreshPeriod is very accurate but noisy, and must be used with
70 // a high resolution timebase to avoid frequently missing Vsync.
71 timebase = base::TimeTicks::FromQPCValue(
72 static_cast<LONGLONG>(timing_info.qpcVBlank));
73 interval = base::TimeDelta::FromQPCValue(
74 static_cast<LONGLONG>(timing_info.qpcRefreshPeriod));
75 // Check for interval values that are impossibly low. A 29 microsecond
76 // interval was seen (from a qpcRefreshPeriod of 60).
77 if (interval < base::TimeDelta::FromMilliseconds(1)) {
78 interval = rate_interval;
79 }
80 // Check for the qpcRefreshPeriod interval being improbably small
81 // compared to the rateRefresh calculated interval, as another
82 // attempt at detecting driver bugs.
83 if (!rate_interval.is_zero() && interval < rate_interval / 2) {
84 interval = rate_interval;
85 }
86 } else {
87 // If FrameTime is not high resolution, we do not want to translate
88 // the QPC value provided by DWM into the low-resolution timebase,
89 // which would be error prone and jittery. As a fallback, we assume
90 // the timebase is zero and use rateRefresh, which may be rounded but
91 // isn't noisy like qpcRefreshPeriod, instead. The fact that we don't
92 // have a timebase here may lead to brief periods of jank when our
93 // scheduling becomes offset from the hardware vsync.
94 interval = rate_interval; 66 interval = rate_interval;
95 } 67 }
68 // Check for the qpcRefreshPeriod interval being improbably small
69 // compared to the rateRefresh calculated interval, as another
70 // attempt at detecting driver bugs.
71 if (!rate_interval.is_zero() && interval < rate_interval / 2) {
72 interval = rate_interval;
73 }
74 } else {
75 // If FrameTime is not high resolution, we do not want to translate
76 // the QPC value provided by DWM into the low-resolution timebase,
77 // which would be error prone and jittery. As a fallback, we assume
78 // the timebase is zero and use rateRefresh, which may be rounded but
79 // isn't noisy like qpcRefreshPeriod, instead. The fact that we don't
80 // have a timebase here may lead to brief periods of jank when our
81 // scheduling becomes offset from the hardware vsync.
82 interval = rate_interval;
96 } 83 }
97 } 84 } else {
98
99 if (!dwm_active) {
100 // When DWM compositing is active all displays are normalized to the 85 // When DWM compositing is active all displays are normalized to the
101 // refresh rate of the primary display, and won't composite any faster. 86 // refresh rate of the primary display, and won't composite any faster.
102 // If DWM compositing is disabled, though, we can use the refresh rates 87 // If DWM compositing is disabled, though, we can use the refresh rates
103 // reported by each display, which will help systems that have mis-matched 88 // reported by each display, which will help systems that have mis-matched
104 // displays that run at different frequencies. 89 // displays that run at different frequencies.
105 HMONITOR monitor = MonitorFromWindow(window_, MONITOR_DEFAULTTONEAREST); 90 HMONITOR monitor = MonitorFromWindow(window_, MONITOR_DEFAULTTONEAREST);
106 MONITORINFOEX monitor_info; 91 MONITORINFOEX monitor_info;
107 monitor_info.cbSize = sizeof(MONITORINFOEX); 92 monitor_info.cbSize = sizeof(MONITORINFOEX);
108 BOOL result = GetMonitorInfo(monitor, &monitor_info); 93 BOOL result = GetMonitorInfo(monitor, &monitor_info);
109 if (result) { 94 if (result) {
110 DEVMODE display_info; 95 DEVMODE display_info;
111 display_info.dmSize = sizeof(DEVMODE); 96 display_info.dmSize = sizeof(DEVMODE);
112 display_info.dmDriverExtra = 0; 97 display_info.dmDriverExtra = 0;
113 result = EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS, 98 result = EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS,
114 &display_info); 99 &display_info);
115 if (result && display_info.dmDisplayFrequency > 1) { 100 if (result && display_info.dmDisplayFrequency > 1) {
116 interval = base::TimeDelta::FromMicroseconds( 101 interval = base::TimeDelta::FromMicroseconds(
117 (1.0 / static_cast<double>(display_info.dmDisplayFrequency)) * 102 (1.0 / static_cast<double>(display_info.dmDisplayFrequency)) *
118 base::Time::kMicrosecondsPerSecond); 103 base::Time::kMicrosecondsPerSecond);
119 } 104 }
120 } 105 }
121 } 106 }
122 107
123 if (interval.ToInternalValue() != 0) { 108 if (interval.ToInternalValue() != 0) {
124 callback.Run(timebase, interval); 109 callback.Run(timebase, interval);
125 } 110 }
126 } 111 }
127 112
128 } // namespace gl 113 } // namespace gl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698