OLD | NEW |
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 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 "gpu/ipc/service/gpu_vsync_provider_win.h" | 5 #include "gpu/ipc/service/gpu_vsync_provider_win.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/atomicops.h" | 9 #include "base/atomicops.h" |
10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 void Reschedule(); | 77 void Reschedule(); |
78 void OpenAdapter(const wchar_t* device_name); | 78 void OpenAdapter(const wchar_t* device_name); |
79 void CloseAdapter(); | 79 void CloseAdapter(); |
80 NTSTATUS WaitForVBlankEvent(); | 80 NTSTATUS WaitForVBlankEvent(); |
81 | 81 |
82 void SendGpuVSyncUpdate(base::TimeTicks now, | 82 void SendGpuVSyncUpdate(base::TimeTicks now, |
83 base::TimeTicks timestamp, | 83 base::TimeTicks timestamp, |
84 base::TimeDelta interval); | 84 base::TimeDelta interval); |
85 void InvokeCallbackAndReschedule(base::TimeTicks timestamp, | 85 void InvokeCallbackAndReschedule(base::TimeTicks timestamp, |
86 base::TimeDelta interval); | 86 base::TimeDelta interval); |
| 87 void UseDelayBasedVSyncOnError(); |
87 void ScheduleDelayBasedVSync(base::TimeTicks timebase, | 88 void ScheduleDelayBasedVSync(base::TimeTicks timebase, |
88 base::TimeDelta interval); | 89 base::TimeDelta interval); |
89 | 90 |
90 // Specifies whether background tasks are running. | 91 // Specifies whether background tasks are running. |
91 // This can be set on background thread only. | 92 // This can be set on background thread only. |
92 bool running_ = false; | 93 bool running_ = false; |
93 | 94 |
94 // Specified whether the worker is enabled. This is accessed from both | 95 // Specified whether the worker is enabled. This is accessed from both |
95 // threads but can be changed on the main thread only. | 96 // threads but can be changed on the main thread only. |
96 base::subtle::AtomicWord enabled_ = false; | 97 base::subtle::AtomicWord enabled_ = false; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 } | 183 } |
183 } | 184 } |
184 | 185 |
185 void GpuVSyncWorker::WaitForVSyncOnThread() { | 186 void GpuVSyncWorker::WaitForVSyncOnThread() { |
186 DCHECK(BelongsToWorkerThread()); | 187 DCHECK(BelongsToWorkerThread()); |
187 | 188 |
188 TRACE_EVENT0("gpu", "GpuVSyncWorker::WaitForVSyncOnThread"); | 189 TRACE_EVENT0("gpu", "GpuVSyncWorker::WaitForVSyncOnThread"); |
189 | 190 |
190 HMONITOR monitor = | 191 HMONITOR monitor = |
191 MonitorFromWindow(surface_handle_, MONITOR_DEFAULTTONEAREST); | 192 MonitorFromWindow(surface_handle_, MONITOR_DEFAULTTONEAREST); |
192 MONITORINFOEX monitor_info; | 193 MONITORINFOEX monitor_info = {}; |
193 monitor_info.cbSize = sizeof(MONITORINFOEX); | 194 monitor_info.cbSize = sizeof(MONITORINFOEX); |
194 BOOL success = GetMonitorInfo(monitor, &monitor_info); | 195 BOOL success = GetMonitorInfo(monitor, &monitor_info); |
195 CHECK(success); | 196 if (!success) { |
| 197 // This is possible when a monitor is switched off or disconnected. |
| 198 CloseAdapter(); |
| 199 UseDelayBasedVSyncOnError(); |
| 200 return; |
| 201 } |
196 | 202 |
197 if (current_device_name_.compare(monitor_info.szDevice) != 0) { | 203 if (current_device_name_.compare(monitor_info.szDevice) != 0) { |
198 // Monitor changed. Close the current adapter handle and open a new one. | 204 // Monitor changed. Close the current adapter handle and open a new one. |
199 CloseAdapter(); | 205 CloseAdapter(); |
200 OpenAdapter(monitor_info.szDevice); | 206 OpenAdapter(monitor_info.szDevice); |
201 } | 207 } |
202 | 208 |
203 NTSTATUS wait_result = WaitForVBlankEvent(); | 209 NTSTATUS wait_result = WaitForVBlankEvent(); |
204 if (wait_result != STATUS_SUCCESS) { | 210 if (wait_result != STATUS_SUCCESS) { |
205 if (wait_result == STATUS_GRAPHICS_PRESENT_OCCLUDED) { | 211 if (wait_result == STATUS_GRAPHICS_PRESENT_OCCLUDED) { |
206 // This may be triggered by the monitor going into sleep. | 212 // This may be triggered by the monitor going into sleep. |
207 // Use timer based mechanism as a backup, start with getting VSync | 213 UseDelayBasedVSyncOnError(); |
208 // parameters to determine timebase and interval. | |
209 // TODO(stanisc): Consider a slower v-sync rate in this particular case. | |
210 vsync_provider_->GetVSyncParameters(base::Bind( | |
211 &GpuVSyncWorker::ScheduleDelayBasedVSync, base::Unretained(this))); | |
212 return; | 214 return; |
213 } else { | 215 } else { |
214 base::debug::Alias(&wait_result); | 216 base::debug::Alias(&wait_result); |
215 CHECK(false); | 217 CHECK(false); |
216 } | 218 } |
217 } | 219 } |
218 | 220 |
219 vsync_provider_->GetVSyncParameters( | 221 vsync_provider_->GetVSyncParameters( |
220 base::Bind(&GpuVSyncWorker::SendGpuVSyncUpdate, base::Unretained(this), | 222 base::Bind(&GpuVSyncWorker::SendGpuVSyncUpdate, base::Unretained(this), |
221 base::TimeTicks::Now())); | 223 base::TimeTicks::Now())); |
(...skipping 30 matching lines...) Expand all Loading... |
252 if (base::subtle::NoBarrier_Load(&enabled_)) { | 254 if (base::subtle::NoBarrier_Load(&enabled_)) { |
253 callback_.Run(timestamp, interval); | 255 callback_.Run(timestamp, interval); |
254 task_runner()->PostTask(FROM_HERE, | 256 task_runner()->PostTask(FROM_HERE, |
255 base::Bind(&GpuVSyncWorker::WaitForVSyncOnThread, | 257 base::Bind(&GpuVSyncWorker::WaitForVSyncOnThread, |
256 base::Unretained(this))); | 258 base::Unretained(this))); |
257 } else { | 259 } else { |
258 running_ = false; | 260 running_ = false; |
259 } | 261 } |
260 } | 262 } |
261 | 263 |
| 264 void GpuVSyncWorker::UseDelayBasedVSyncOnError() { |
| 265 // This is called in a case of an error. |
| 266 // Use timer based mechanism as a backup for one v-sync cycle, start with |
| 267 // getting VSync parameters to determine timebase and interval. |
| 268 // TODO(stanisc): Consider a slower v-sync rate in this particular case. |
| 269 vsync_provider_->GetVSyncParameters(base::Bind( |
| 270 &GpuVSyncWorker::ScheduleDelayBasedVSync, base::Unretained(this))); |
| 271 } |
| 272 |
262 void GpuVSyncWorker::ScheduleDelayBasedVSync(base::TimeTicks timebase, | 273 void GpuVSyncWorker::ScheduleDelayBasedVSync(base::TimeTicks timebase, |
263 base::TimeDelta interval) { | 274 base::TimeDelta interval) { |
264 // This is called only when WaitForVBlankEvent fails due to monitor going to | 275 // This is called only when WaitForVBlankEvent fails due to monitor going to |
265 // sleep. Use a delay based v-sync as a back-up. | 276 // sleep. Use a delay based v-sync as a back-up. |
266 if (interval.is_zero()) { | 277 if (interval.is_zero()) { |
267 interval = base::TimeDelta::FromMicroseconds(kDefaultTimerBasedInterval); | 278 interval = base::TimeDelta::FromMicroseconds(kDefaultTimerBasedInterval); |
268 } | 279 } |
269 | 280 |
270 base::TimeTicks now = base::TimeTicks::Now(); | 281 base::TimeTicks now = base::TimeTicks::Now(); |
271 base::TimeTicks next_vsync = now.SnappedToNextTick(timebase, interval); | 282 base::TimeTicks next_vsync = now.SnappedToNextTick(timebase, interval); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 void GpuVSyncProviderWin::OnVSync(base::TimeTicks timestamp, | 433 void GpuVSyncProviderWin::OnVSync(base::TimeTicks timestamp, |
423 base::TimeDelta interval) { | 434 base::TimeDelta interval) { |
424 DCHECK(vsync_worker_->BelongsToWorkerThread()); | 435 DCHECK(vsync_worker_->BelongsToWorkerThread()); |
425 | 436 |
426 message_filter_->Send( | 437 message_filter_->Send( |
427 base::MakeUnique<GpuCommandBufferMsg_UpdateVSyncParameters>( | 438 base::MakeUnique<GpuCommandBufferMsg_UpdateVSyncParameters>( |
428 message_filter_->route_id(), timestamp, interval)); | 439 message_filter_->route_id(), timestamp, interval)); |
429 } | 440 } |
430 | 441 |
431 } // namespace gpu | 442 } // namespace gpu |
OLD | NEW |