| 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 |