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

Side by Side Diff: gpu/ipc/service/gpu_vsync_provider_win.cc

Issue 2596123002: GpuVSyncProvider with unit test (Closed)
Patch Set: Fixed build failure on posix. Created 4 years 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "gpu/ipc/service/gpu_vsync_provider.h"
6
7 #include "base/bind.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/trace_event/trace_event.h"
10
11 #include <windows.h>
12
13 namespace gpu {
14
15 namespace {
16 // from <D3dkmthk.h>
17 typedef LONG NTSTATUS;
18 typedef UINT D3DKMT_HANDLE;
19 typedef UINT D3DDDI_VIDEO_PRESENT_SOURCE_ID;
20
21 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
22
23 typedef struct _D3DKMT_OPENADAPTERFROMHDC {
24 HDC hDc;
25 D3DKMT_HANDLE hAdapter;
26 LUID AdapterLuid;
27 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId;
28 } D3DKMT_OPENADAPTERFROMHDC;
29
30 typedef struct _D3DKMT_CLOSEADAPTER {
31 D3DKMT_HANDLE hAdapter;
32 } D3DKMT_CLOSEADAPTER;
33
34 typedef struct _D3DKMT_WAITFORVERTICALBLANKEVENT {
35 D3DKMT_HANDLE hAdapter;
36 D3DKMT_HANDLE hDevice;
37 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId;
38 } D3DKMT_WAITFORVERTICALBLANKEVENT;
39
40 typedef NTSTATUS(APIENTRY* PFND3DKMTOPENADAPTERFROMHDC)(
41 D3DKMT_OPENADAPTERFROMHDC*);
42 typedef NTSTATUS(APIENTRY* PFND3DKMTCLOSEADAPTER)(D3DKMT_CLOSEADAPTER*);
43 typedef NTSTATUS(APIENTRY* PFND3DKMTWAITFORVERTICALBLANKEVENT)(
44 D3DKMT_WAITFORVERTICALBLANKEVENT*);
45 } // namespace
46
47 /* static */
48 std::unique_ptr<GpuVSyncProvider> GpuVSyncProvider::Create(
49 const VSyncCallback& callback,
50 SurfaceHandle surface_handle) {
51 std::unique_ptr<GpuVSyncProvider> provider(
52 new GpuVSyncProvider(callback, surface_handle));
53 // Start the thread.
54 base::Thread::Options options;
55 // TODO(stanisc): might consider even higher priority - REALTIME_AUDIO.
56 options.priority = base::ThreadPriority::DISPLAY;
57 provider->StartWithOptions(options);
58 return provider;
59 }
60
61 GpuVSyncProvider::GpuVSyncProvider(const VSyncCallback& callback,
62 SurfaceHandle surface_handle)
63 : base::Thread(base::StringPrintf("VSync-%d", surface_handle)),
64 callback_(callback),
65 surface_handle_(surface_handle) {}
66
67 GpuVSyncProvider::~GpuVSyncProvider() {
68 Stop();
69 }
70
71 void GpuVSyncProvider::EnableVSync(bool enabled) {
72 if (enabled_ == enabled)
73 return;
74
75 enabled_ = enabled;
76
77 if (enabled_)
78 task_runner()->PostTask(
79 FROM_HERE, base::Bind(&GpuVSyncProvider::StartRunningVSyncOnThread,
80 base::Unretained(this)));
81 }
82
83 void GpuVSyncProvider::StartRunningVSyncOnThread() {
84 DCHECK(base::PlatformThread::CurrentId() == GetThreadId());
85
86 if (!running_) {
87 running_ = true;
88 WaitForVSyncOnThread();
89 }
90 }
91
92 void GpuVSyncProvider::WaitForVSyncOnThread() {
brucedawson 2016/12/22 21:49:16 Do we really want this to do the whole init/de-ini
stanisc 2016/12/22 22:59:31 One reason I've done it this way is because I want
stanisc 2017/01/04 22:33:04 OK. Cached function pointers, but keep opening/clo
93 DCHECK(base::PlatformThread::CurrentId() == GetThreadId());
94
95 TRACE_EVENT0("gpu", "GpuVSyncProvider::WaitForVSyncOnThread");
96
97 // TODO: implement this
brucedawson 2016/12/22 21:49:16 I don't understand this comment.
stanisc 2016/12/22 22:59:31 Forgot to remove this one. Will remove it in the n
stanisc 2017/01/04 22:33:04 Done.
98 HMODULE gdi32 = GetModuleHandle(L"gdi32");
99 if (!gdi32) {
100 NOTREACHED() << "Can't open gdi32.dll";
101 return;
102 }
103
104 auto open_adapter_from_hdc_ptr =
105 reinterpret_cast<PFND3DKMTOPENADAPTERFROMHDC>(
106 ::GetProcAddress(gdi32, "D3DKMTOpenAdapterFromHdc"));
107 if (!open_adapter_from_hdc_ptr) {
108 NOTREACHED() << "Can't find D3DKMTOpenAdapterFromHdc in gdi32.dll";
109 return;
110 }
111
112 auto close_adapter_ptr = reinterpret_cast<PFND3DKMTCLOSEADAPTER>(
113 ::GetProcAddress(gdi32, "D3DKMTCloseAdapter"));
114 if (!close_adapter_ptr) {
115 NOTREACHED() << "Can't find D3DKMTCloseAdapter in gdi32.dll";
116 return;
117 }
118
119 auto wait_for_vertical_blank_event_ptr =
120 reinterpret_cast<PFND3DKMTWAITFORVERTICALBLANKEVENT>(
121 ::GetProcAddress(gdi32, "D3DKMTWaitForVerticalBlankEvent"));
122 if (!wait_for_vertical_blank_event_ptr) {
123 NOTREACHED() << "Can't find D3DKMTWaitForVerticalBlankEvent in gdi32.dll";
124 return;
125 }
126
127 HMONITOR monitor =
128 MonitorFromWindow(surface_handle_, MONITOR_DEFAULTTONEAREST);
129 MONITORINFOEX monitor_info;
130 monitor_info.cbSize = sizeof(MONITORINFOEX);
131 BOOL success = GetMonitorInfo(monitor, &monitor_info);
132 CHECK(success);
133
134 HDC hdc = CreateDC(NULL, monitor_info.szDevice, NULL, NULL);
135
136 D3DKMT_OPENADAPTERFROMHDC open_adapter_data;
137 open_adapter_data.hDc = hdc;
138
139 NTSTATUS result = open_adapter_from_hdc_ptr(&open_adapter_data);
140 DeleteDC(hdc);
141
142 CHECK(result == STATUS_SUCCESS);
143
144 D3DKMT_WAITFORVERTICALBLANKEVENT wait_for_vertical_blank_event_data;
145 wait_for_vertical_blank_event_data.hAdapter = open_adapter_data.hAdapter;
146 wait_for_vertical_blank_event_data.hDevice = 0;
147 wait_for_vertical_blank_event_data.VidPnSourceId =
148 open_adapter_data.VidPnSourceId;
149
150 result =
151 wait_for_vertical_blank_event_ptr(&wait_for_vertical_blank_event_data);
152 if (result == STATUS_SUCCESS) {
153 // Note: this sends update from the background thread.
154 SendVSyncUpdate(base::TimeTicks::Now());
155 }
156
157 D3DKMT_CLOSEADAPTER close_adapter_data;
158 close_adapter_data.hAdapter = open_adapter_data.hAdapter;
159
160 result = close_adapter_ptr(&close_adapter_data);
161 CHECK(result == STATUS_SUCCESS);
162
163 // Restart the task if still enabled.
164 if (enabled_) {
165 task_runner()->PostTask(FROM_HERE,
166 base::Bind(&GpuVSyncProvider::WaitForVSyncOnThread,
167 base::Unretained(this)));
168 } else {
169 running_ = false;
170 }
171 }
172
173 void GpuVSyncProvider::SendVSyncUpdate(base::TimeTicks now) {
174 TRACE_EVENT0("gpu", "GpuVSyncProvider::SendVSync");
stanisc 2016/12/22 21:35:08 Need to change this to SendVSyncUpdate
175 if (enabled_) {
176 callback_.Run(now);
177 }
178 }
179
180 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698