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

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

Issue 2411803003: Route DXGI Frame Statistics to VSyncProvider (Closed)
Patch Set: Build error fix Created 4 years, 2 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
« no previous file with comments | « ui/gl/sync_control_vsync_provider.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/sync_control_vsync_provider.h" 5 #include "ui/gl/sync_control_vsync_provider.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
11 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
12 #include "build/build_config.h" 12 #include "build/build_config.h"
13 13
14 #if defined(OS_LINUX) 14 #if defined(OS_LINUX) || defined(OS_WIN)
15 // These constants define a reasonable range for a calculated refresh interval. 15 // These constants define a reasonable range for a calculated refresh interval.
16 // Calculating refreshes out of this range will be considered a fatal error. 16 // Calculating refreshes out of this range will be considered a fatal error.
17 const int64_t kMinVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 400; 17 const int64_t kMinVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 400;
18 const int64_t kMaxVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 10; 18 const int64_t kMaxVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 10;
19 19
20 // How much noise we'll tolerate between successive computed intervals before 20 // How much noise we'll tolerate between successive computed intervals before
21 // we think the latest computed interval is invalid (noisey due to 21 // we think the latest computed interval is invalid (noisey due to
22 // monitor configuration change, moving a window between monitors, etc.). 22 // monitor configuration change, moving a window between monitors, etc.).
23 const double kRelativeIntervalDifferenceThreshold = 0.05; 23 const double kRelativeIntervalDifferenceThreshold = 0.05;
24 #endif 24 #endif // defined(OS_LINUX) || defined(OS_WIN)
25 25
26 namespace gl { 26 namespace gl {
27 27
28 SyncControlVSyncProvider::SyncControlVSyncProvider() : gfx::VSyncProvider() { 28 SyncControlVSyncProvider::SyncControlVSyncProvider() : gfx::VSyncProvider() {
29 #if defined(OS_LINUX) 29 #if defined(OS_LINUX) || defined(OS_WIN)
30 // On platforms where we can't get an accurate reading on the refresh 30 // On platforms where we can't get an accurate reading on the refresh
31 // rate we fall back to the assumption that we're displaying 60 frames 31 // rate we fall back to the assumption that we're displaying 60 frames
32 // per second. 32 // per second.
33 last_good_interval_ = base::TimeDelta::FromSeconds(1) / 60; 33 last_good_interval_ = base::TimeDelta::FromSeconds(1) / 60;
34 #endif 34 #endif // defined(OS_LINUX) || defined(OS_WIN)
35 } 35 }
36 36
37 SyncControlVSyncProvider::~SyncControlVSyncProvider() {} 37 SyncControlVSyncProvider::~SyncControlVSyncProvider() {}
38 38
39 void SyncControlVSyncProvider::GetVSyncParameters( 39 void SyncControlVSyncProvider::GetVSyncParameters(
40 const UpdateVSyncCallback& callback) { 40 const UpdateVSyncCallback& callback) {
41 TRACE_EVENT0("gpu", "SyncControlVSyncProvider::GetVSyncParameters"); 41 TRACE_EVENT0("gpu", "SyncControlVSyncProvider::GetVSyncParameters");
42 #if defined(OS_LINUX) 42 #if defined(OS_LINUX) || defined(OS_WIN)
43 base::TimeTicks timebase; 43 base::TimeTicks timebase;
44 44
45 // The actual clock used for the system time returned by glXGetSyncValuesOML
46 // is unspecified. In practice, the clock used is likely to be either
47 // CLOCK_REALTIME or CLOCK_MONOTONIC, so we compare the returned time to the
48 // current time according to both clocks, and assume that the returned time
49 // was produced by the clock whose current time is closest to it, subject
50 // to the restriction that the returned time must not be in the future
51 // (since it is the time of a vblank that has already occurred).
52 int64_t system_time; 45 int64_t system_time;
53 int64_t media_stream_counter; 46 int64_t media_stream_counter;
54 int64_t swap_buffer_counter; 47 int64_t swap_buffer_counter;
55 if (!GetSyncValues(&system_time, &media_stream_counter, &swap_buffer_counter)) 48 if (!GetSyncValues(&system_time, &media_stream_counter, &swap_buffer_counter))
56 return; 49 return;
57 50
58 // Both Intel and Mali drivers will return TRUE for GetSyncValues 51 // Perform platform specific adjustment of |system_time| and
59 // but a value of 0 for MSC if they cannot access the CRTC data structure 52 // |media_stream_counter|.
60 // associated with the surface. crbug.com/231945 53 if (!AdjustSyncValues(&system_time, &media_stream_counter))
61 bool prev_invalid_msc = invalid_msc_;
62 invalid_msc_ = (media_stream_counter == 0);
63 if (invalid_msc_) {
64 LOG_IF(ERROR, !prev_invalid_msc) << "glXGetSyncValuesOML "
65 "should not return TRUE with a media stream counter of 0.";
66 return;
67 }
68
69 struct timespec real_time;
70 struct timespec monotonic_time;
71 clock_gettime(CLOCK_REALTIME, &real_time);
72 clock_gettime(CLOCK_MONOTONIC, &monotonic_time);
73
74 int64_t real_time_in_microseconds =
75 real_time.tv_sec * base::Time::kMicrosecondsPerSecond +
76 real_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
77 int64_t monotonic_time_in_microseconds =
78 monotonic_time.tv_sec * base::Time::kMicrosecondsPerSecond +
79 monotonic_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
80
81 // We need the time according to CLOCK_MONOTONIC, so if we've been given
82 // a time from CLOCK_REALTIME, we need to convert.
83 bool time_conversion_needed =
84 llabs(system_time - real_time_in_microseconds) <
85 llabs(system_time - monotonic_time_in_microseconds);
86
87 if (time_conversion_needed)
88 system_time += monotonic_time_in_microseconds - real_time_in_microseconds;
89
90 // Return if |system_time| is more than 1 frames in the future.
91 int64_t interval_in_microseconds = last_good_interval_.InMicroseconds();
92 if (system_time > monotonic_time_in_microseconds + interval_in_microseconds)
93 return;
94
95 // If |system_time| is slightly in the future, adjust it to the previous
96 // frame and use the last frame counter to prevent issues in the callback.
97 if (system_time > monotonic_time_in_microseconds) {
98 system_time -= interval_in_microseconds;
99 media_stream_counter--;
100 }
101 if (monotonic_time_in_microseconds - system_time >
102 base::Time::kMicrosecondsPerSecond)
103 return; 54 return;
104 55
105 timebase = base::TimeTicks::FromInternalValue(system_time); 56 timebase = base::TimeTicks::FromInternalValue(system_time);
106 57
107 // Only need the previous calculated interval for our filtering. 58 // Only need the previous calculated interval for our filtering.
108 while (last_computed_intervals_.size() > 1) 59 while (last_computed_intervals_.size() > 1)
109 last_computed_intervals_.pop(); 60 last_computed_intervals_.pop();
110 61
111 int32_t numerator, denominator; 62 int32_t numerator, denominator;
112 if (GetMscRate(&numerator, &denominator) && numerator) { 63 if (GetMscRate(&numerator, &denominator) && numerator) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 << ", media_stream_counter=" << media_stream_counter; 99 << ", media_stream_counter=" << media_stream_counter;
149 } else { 100 } else {
150 last_good_interval_ = new_interval; 101 last_good_interval_ = new_interval;
151 } 102 }
152 } 103 }
153 } 104 }
154 105
155 last_timebase_ = timebase; 106 last_timebase_ = timebase;
156 last_media_stream_counter_ = media_stream_counter; 107 last_media_stream_counter_ = media_stream_counter;
157 callback.Run(timebase, last_good_interval_); 108 callback.Run(timebase, last_good_interval_);
158 #endif // defined(OS_LINUX) 109 #endif // defined(OS_LINUX) || defined(OS_WIN)
159 } 110 }
160 111
112 #if defined(OS_LINUX)
113 bool SyncControlVSyncProvider::AdjustSyncValues(int64_t* system_time,
114 int64_t* media_stream_counter) {
115 // The actual clock used for the system time returned by glXGetSyncValuesOML
116 // is unspecified. In practice, the clock used is likely to be either
117 // CLOCK_REALTIME or CLOCK_MONOTONIC, so we compare the returned time to the
118 // current time according to both clocks, and assume that the returned time
119 // was produced by the clock whose current time is closest to it, subject
120 // to the restriction that the returned time must not be in the future
121 // (since it is the time of a vblank that has already occurred).
122
123 // Both Intel and Mali drivers will return TRUE for GetSyncValues
124 // but a value of 0 for MSC if they cannot access the CRTC data structure
125 // associated with the surface. crbug.com/231945
126 bool prev_invalid_msc = invalid_msc_;
127 invalid_msc_ = (*media_stream_counter == 0);
128 if (invalid_msc_) {
129 LOG_IF(ERROR, !prev_invalid_msc)
130 << "glXGetSyncValuesOML "
131 "should not return TRUE with a media stream counter of 0.";
132 return false;
133 }
134
135 struct timespec real_time;
136 struct timespec monotonic_time;
137 clock_gettime(CLOCK_REALTIME, &real_time);
138 clock_gettime(CLOCK_MONOTONIC, &monotonic_time);
139
140 int64_t real_time_in_microseconds =
141 real_time.tv_sec * base::Time::kMicrosecondsPerSecond +
142 real_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
143 int64_t monotonic_time_in_microseconds =
144 monotonic_time.tv_sec * base::Time::kMicrosecondsPerSecond +
145 monotonic_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
146
147 // We need the time according to CLOCK_MONOTONIC, so if we've been given
148 // a time from CLOCK_REALTIME, we need to convert.
149 bool time_conversion_needed =
150 llabs(*system_time - real_time_in_microseconds) <
151 llabs(*system_time - monotonic_time_in_microseconds);
152
153 if (time_conversion_needed)
154 *system_time += monotonic_time_in_microseconds - real_time_in_microseconds;
155
156 // Return if |*system_time| is more than 1 frames in the future.
157 int64_t interval_in_microseconds = last_good_interval_.InMicroseconds();
158 if (*system_time > monotonic_time_in_microseconds + interval_in_microseconds)
159 return false;
160
161 // If |system_time| is slightly in the future, adjust it to the previous
162 // frame and use the last frame counter to prevent issues in the callback.
163 if (*system_time > monotonic_time_in_microseconds) {
164 *system_time -= interval_in_microseconds;
165 (*media_stream_counter)--;
166 }
167 if (monotonic_time_in_microseconds - *system_time >
168 base::Time::kMicrosecondsPerSecond)
169 return false;
170
171 return true;
172 }
173 #endif // defined(OS_LINUX)
174
175 #if defined(OS_WIN)
176 bool SyncControlVSyncProvider::AdjustSyncValues(int64_t* system_time,
177 int64_t* media_stream_counter) {
178 // The actual clock used for the system time returned by glXGetSyncValuesEGL
179 // is unspecified. In practice, the clock comes from QueryPerformanceCounter.
180
181 LARGE_INTEGER perf_counter_now = {};
182 ::QueryPerformanceCounter(&perf_counter_now);
183 int64_t qpc_now =
184 base::TimeDelta::FromQPCValue(perf_counter_now.QuadPart).InMicroseconds();
185
186 // Return if |system_time| is more than 1 frames in the future.
187 int64_t interval_in_microseconds = last_good_interval_.InMicroseconds();
188 if (*system_time > qpc_now + interval_in_microseconds)
189 return false;
190
191 // If |system_time| is slightly in the future, adjust it to the previous
192 // frame and use the last frame counter to prevent issues in the callback.
193 if (*system_time > qpc_now) {
194 *system_time -= interval_in_microseconds;
195 (*media_stream_counter)--;
196 }
197 if (qpc_now - *system_time > base::Time::kMicrosecondsPerSecond)
198 return false;
199
200 return true;
201 }
202 #endif // defined(OS_WIN)
203
161 } // namespace gl 204 } // namespace gl
OLDNEW
« no previous file with comments | « ui/gl/sync_control_vsync_provider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698