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

Side by Side Diff: ui/gfx/surface/accelerated_surface_win.cc

Issue 8867005: Win AcceleratedSurface no longer polls queries on separate thread. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 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 | Annotate | Revision Log
« no previous file with comments | « ui/gfx/surface/accelerated_surface_win.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 (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/gfx/surface/accelerated_surface_win.h" 5 #include "ui/gfx/surface/accelerated_surface_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include <list> 9 #include <list>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
15 #include "base/file_path.h"
15 #include "base/lazy_instance.h" 16 #include "base/lazy_instance.h"
16 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/weak_ptr.h" 18 #include "base/memory/weak_ptr.h"
18 #include "base/stringprintf.h" 19 #include "base/stringprintf.h"
19 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
20 #include "base/tracked_objects.h" 21 #include "base/tracked_objects.h"
21 #include "base/win/wrapped_window_proc.h" 22 #include "base/win/wrapped_window_proc.h"
22 #include "ipc/ipc_message.h" 23 #include "ipc/ipc_message.h"
23 #include "ui/base/win/hwnd_util.h" 24 #include "ui/base/win/hwnd_util.h"
24 #include "ui/gfx/gl/gl_switches.h" 25 #include "ui/gfx/gl/gl_switches.h"
25 26
26 #pragma comment(lib, "d3d9.lib")
27
28 namespace { 27 namespace {
29 28
30 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version, 29 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT sdk_version,
31 IDirect3D9Ex **d3d); 30 IDirect3D9Ex **d3d);
32 31
33 const int64 kPollQueryInterval = 1;
34
35 const wchar_t kD3D9ModuleName[] = L"d3d9.dll"; 32 const wchar_t kD3D9ModuleName[] = L"d3d9.dll";
36 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex"; 33 const char kCreate3D9DeviceExName[] = "Direct3DCreate9Ex";
37 34
38 class QuerySyncThread
39 : public base::Thread,
40 public base::RefCounted<QuerySyncThread> {
41 public:
42 explicit QuerySyncThread(const char* name);
43 virtual ~QuerySyncThread();
44
45 // Invoke the completion task when the query completes.
46 void AcknowledgeQuery(const base::win::ScopedComPtr<IDirect3DQuery9>& query,
47 const base::Closure& completion_task);
48
49 // Acknowledge all pending queries for the given device early then invoke
50 // the given task.
51 void AcknowledgeEarly(
52 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device,
53 const base::Closure& completion_task);
54
55 private:
56 void PollQueries();
57
58 struct PendingQuery {
59 base::win::ScopedComPtr<IDirect3DQuery9> query;
60 base::Closure completion_task;
61 };
62
63 typedef std::list<PendingQuery> PendingQueries;
64 PendingQueries pending_queries_;
65 base::WeakPtrFactory<QuerySyncThread> poll_factory_;
66
67 DISALLOW_COPY_AND_ASSIGN(QuerySyncThread);
68 };
69
70 class PresentThreadPool { 35 class PresentThreadPool {
71 public: 36 public:
72 static const int kNumPresentThreads = 4; 37 static const int kNumPresentThreads = 4;
73 38
74 PresentThreadPool(); 39 PresentThreadPool();
75 40
76 int NextThread(); 41 int NextThread();
77 42
78 void PostTask(int thread, 43 void PostTask(int thread,
79 const tracked_objects::Location& from_here, 44 const tracked_objects::Location& from_here,
80 const base::Closure& task); 45 const base::Closure& task);
81 46
82 void AcknowledgeQuery(const tracked_objects::Location& from_here,
83 const base::win::ScopedComPtr<IDirect3DQuery9>& query,
84 const base::Closure& completion_task);
85
86 void AcknowledgeEarly(
87 const tracked_objects::Location& from_here,
88 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device,
89 const base::Closure& completion_task);
90
91 private: 47 private:
92 int next_thread_; 48 int next_thread_;
93 scoped_ptr<base::Thread> present_threads_[kNumPresentThreads]; 49 scoped_ptr<base::Thread> present_threads_[kNumPresentThreads];
94 scoped_refptr<QuerySyncThread> query_sync_thread_;
95 50
96 DISALLOW_COPY_AND_ASSIGN(PresentThreadPool); 51 DISALLOW_COPY_AND_ASSIGN(PresentThreadPool);
97 }; 52 };
98 53
99 base::LazyInstance<PresentThreadPool> 54 base::LazyInstance<PresentThreadPool>
100 g_present_thread_pool = LAZY_INSTANCE_INITIALIZER; 55 g_present_thread_pool = LAZY_INSTANCE_INITIALIZER;
101 56
102 QuerySyncThread::QuerySyncThread(const char* name)
103 : base::Thread(name),
104 poll_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
105 }
106
107 QuerySyncThread::~QuerySyncThread() {
108 }
109
110 void QuerySyncThread::AcknowledgeQuery(
111 const base::win::ScopedComPtr<IDirect3DQuery9>& query,
112 const base::Closure& completion_task) {
113 PendingQuery pending_query;
114 pending_query.query = query;
115 pending_query.completion_task = completion_task;
116 pending_queries_.push_back(pending_query);
117
118 // Cancel any pending poll tasks. There should only ever be one pending at a
119 // time.
120 poll_factory_.InvalidateWeakPtrs();
121
122 PollQueries();
123 }
124
125 void QuerySyncThread::AcknowledgeEarly(
126 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device,
127 const base::Closure& completion_task) {
128 TRACE_EVENT0("surface", "AcknowledgeEarly");
129
130 PendingQueries::iterator it = pending_queries_.begin();
131 while (it != pending_queries_.end()) {
132 const PendingQuery& pending_query = *it;
133
134 base::win::ScopedComPtr<IDirect3DDevice9> query_device;
135 pending_query.query->GetDevice(query_device.Receive());
136
137 base::win::ScopedComPtr<IDirect3DDevice9Ex> query_device_ex;
138 query_device_ex.QueryFrom(query_device.get());
139
140 if (query_device_ex.get() != device.get()) {
141 ++it;
142 } else {
143 pending_query.completion_task.Run();
144 it = pending_queries_.erase(it);
145 }
146 }
147
148 if (!completion_task.is_null())
149 completion_task.Run();
150 }
151
152
153 void QuerySyncThread::PollQueries() {
154 TRACE_EVENT0("surface", "PollQueries");
155
156 PendingQueries::iterator it = pending_queries_.begin();
157 while (it != pending_queries_.end()) {
158 const PendingQuery& pending_query = *it;
159
160 HRESULT hr = pending_query.query->GetData(NULL, 0, D3DGETDATA_FLUSH);
161 if (hr == S_FALSE) {
162 ++it;
163 } else {
164 pending_query.completion_task.Run();
165 it = pending_queries_.erase(it);
166 }
167 }
168
169 // Try again later if there are incomplete queries. Otherwise don't poll again
170 // until AcknowledgeQuery is called with a new query.
171 if (!pending_queries_.empty()) {
172 message_loop()->PostDelayedTask(
173 FROM_HERE,
174 base::Bind(&QuerySyncThread::PollQueries, poll_factory_.GetWeakPtr()),
175 kPollQueryInterval);
176 }
177 }
178
179 PresentThreadPool::PresentThreadPool() : next_thread_(0) { 57 PresentThreadPool::PresentThreadPool() : next_thread_(0) {
180 for (int i = 0; i < kNumPresentThreads; ++i) { 58 for (int i = 0; i < kNumPresentThreads; ++i) {
181 present_threads_[i].reset(new base::Thread( 59 present_threads_[i].reset(new base::Thread(
182 base::StringPrintf("PresentThread #%d", i).c_str())); 60 base::StringPrintf("PresentThread #%d", i).c_str()));
183 present_threads_[i]->Start(); 61 present_threads_[i]->Start();
184 } 62 }
185
186 query_sync_thread_ = new QuerySyncThread("QuerySyncThread");
187 query_sync_thread_->Start();
188 } 63 }
189 64
190 int PresentThreadPool::NextThread() { 65 int PresentThreadPool::NextThread() {
191 next_thread_ = (next_thread_ + 1) % kNumPresentThreads; 66 next_thread_ = (next_thread_ + 1) % kNumPresentThreads;
192 return next_thread_; 67 return next_thread_;
193 } 68 }
194 69
195 void PresentThreadPool::PostTask(int thread, 70 void PresentThreadPool::PostTask(int thread,
196 const tracked_objects::Location& from_here, 71 const tracked_objects::Location& from_here,
197 const base::Closure& task) { 72 const base::Closure& task) {
198 DCHECK_GE(thread, 0); 73 DCHECK_GE(thread, 0);
199 DCHECK_LT(thread, kNumPresentThreads); 74 DCHECK_LT(thread, kNumPresentThreads);
200 75
201 present_threads_[thread]->message_loop()->PostTask(from_here, task); 76 present_threads_[thread]->message_loop()->PostTask(from_here, task);
202 } 77 }
203 78
204 void PresentThreadPool::AcknowledgeQuery(
205 const tracked_objects::Location& from_here,
206 const base::win::ScopedComPtr<IDirect3DQuery9>& query,
207 const base::Closure& completion_task) {
208 query_sync_thread_->message_loop()->PostTask(
209 from_here,
210 base::Bind(&QuerySyncThread::AcknowledgeQuery,
211 query_sync_thread_,
212 query,
213 completion_task));
214 }
215
216 void PresentThreadPool::AcknowledgeEarly(
217 const tracked_objects::Location& from_here,
218 const base::win::ScopedComPtr<IDirect3DDevice9Ex>& device,
219 const base::Closure& completion_task) {
220 query_sync_thread_->message_loop()->PostTask(
221 from_here,
222 base::Bind(&QuerySyncThread::AcknowledgeEarly,
223 query_sync_thread_,
224 device,
225 completion_task));
226 }
227
228 UINT GetPresentationInterval() { 79 UINT GetPresentationInterval() {
229 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) 80 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
230 return D3DPRESENT_INTERVAL_IMMEDIATE; 81 return D3DPRESENT_INTERVAL_IMMEDIATE;
231 else 82 else
232 return D3DPRESENT_INTERVAL_ONE; 83 return D3DPRESENT_INTERVAL_ONE;
233 } 84 }
234 85
235 } // namespace anonymous 86 } // namespace anonymous
236 87
237 AcceleratedSurface::AcceleratedSurface(HWND parent) 88 AcceleratedSurface::AcceleratedSurface(HWND parent)
238 : thread_affinity_(g_present_thread_pool.Pointer()->NextThread()), 89 : thread_affinity_(g_present_thread_pool.Pointer()->NextThread()),
239 window_(parent), 90 window_(parent),
240 num_pending_resizes_(0) { 91 num_pending_resizes_(0) {
241 } 92 }
242 93
243 AcceleratedSurface::~AcceleratedSurface() { 94 AcceleratedSurface::~AcceleratedSurface() {
244 // Destroy should have been called prior to the last reference going away. 95 // Destroy should have been called prior to the last reference going away.
245 DCHECK(!device_); 96 DCHECK(!device_);
246 } 97 }
247 98
248 void AcceleratedSurface::Initialize() { 99 void AcceleratedSurface::Initialize() {
249 g_present_thread_pool.Pointer()->PostTask( 100 g_present_thread_pool.Pointer()->PostTask(
250 thread_affinity_, 101 thread_affinity_,
251 FROM_HERE, 102 FROM_HERE,
252 base::Bind(&AcceleratedSurface::DoInitialize, this)); 103 base::Bind(&AcceleratedSurface::DoInitialize, this));
253 } 104 }
254 105
255 void AcceleratedSurface::Destroy() { 106 void AcceleratedSurface::Destroy() {
256 g_present_thread_pool.Pointer()->AcknowledgeEarly( 107 g_present_thread_pool.Pointer()->PostTask(
108 thread_affinity_,
257 FROM_HERE, 109 FROM_HERE,
258 device_, 110 base::Bind(&AcceleratedSurface::DoDestroy, this));
259 base::Bind(&AcceleratedSurface::QueriesDestroyed, this));
260 } 111 }
261 112
262 void AcceleratedSurface::AsyncPresentAndAcknowledge( 113 void AcceleratedSurface::AsyncPresentAndAcknowledge(
263 const gfx::Size& size, 114 const gfx::Size& size,
264 int64 surface_id, 115 int64 surface_id,
265 const base::Closure& completion_task) { 116 const base::Closure& completion_task) {
266 const int kRound = 64; 117 const int kRound = 64;
267 gfx::Size quantized_size( 118 gfx::Size quantized_size(
268 std::max(1, (size.width() + kRound - 1) / kRound * kRound), 119 std::max(1, (size.width() + kRound - 1) / kRound * kRound),
269 std::max(1, (size.height() + kRound - 1) / kRound * kRound)); 120 std::max(1, (size.height() + kRound - 1) / kRound * kRound));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 Sleep(0); 180 Sleep(0);
330 } while (hr == S_FALSE); 181 } while (hr == S_FALSE);
331 } 182 }
332 } 183 }
333 184
334 void AcceleratedSurface::DoInitialize() { 185 void AcceleratedSurface::DoInitialize() {
335 TRACE_EVENT0("surface", "DoInitialize"); 186 TRACE_EVENT0("surface", "DoInitialize");
336 187
337 HRESULT hr; 188 HRESULT hr;
338 189
339 HMODULE module = GetModuleHandle(kD3D9ModuleName); 190 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL));
340 if (!module)
341 return;
342 191
343 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( 192 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>(
344 GetProcAddress(module, kCreate3D9DeviceExName)); 193 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName));
345 if (!create_func) 194 if (!create_func)
346 return; 195 return;
347 196
348 base::win::ScopedComPtr<IDirect3D9Ex> d3d; 197 base::win::ScopedComPtr<IDirect3D9Ex> d3d;
349 hr = create_func(D3D_SDK_VERSION, d3d.Receive()); 198 hr = create_func(D3D_SDK_VERSION, d3d.Receive());
350 if (FAILED(hr)) 199 if (FAILED(hr))
351 return; 200 return;
352 201
353 D3DPRESENT_PARAMETERS parameters = { 0 }; 202 D3DPRESENT_PARAMETERS parameters = { 0 };
354 parameters.BackBufferWidth = 1; 203 parameters.BackBufferWidth = 1;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 query_ = NULL; 248 query_ = NULL;
400 } 249 }
401 250
402 void AcceleratedSurface::DoResize(const gfx::Size& size) { 251 void AcceleratedSurface::DoResize(const gfx::Size& size) {
403 TRACE_EVENT0("surface", "DoResize"); 252 TRACE_EVENT0("surface", "DoResize");
404 253
405 HRESULT hr; 254 HRESULT hr;
406 255
407 base::AtomicRefCountDec(&num_pending_resizes_); 256 base::AtomicRefCountDec(&num_pending_resizes_);
408 257
258 base::AutoLock locked(lock_);
259
260 if (!device_)
261 return;
262
409 D3DPRESENT_PARAMETERS parameters = { 0 }; 263 D3DPRESENT_PARAMETERS parameters = { 0 };
410 parameters.BackBufferWidth = size.width(); 264 parameters.BackBufferWidth = size.width();
411 parameters.BackBufferHeight = size.height(); 265 parameters.BackBufferHeight = size.height();
412 parameters.BackBufferCount = 1; 266 parameters.BackBufferCount = 1;
413 parameters.BackBufferFormat = D3DFMT_A8R8G8B8; 267 parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
414 parameters.hDeviceWindow = window_; 268 parameters.hDeviceWindow = window_;
415 parameters.Windowed = TRUE; 269 parameters.Windowed = TRUE;
416 parameters.Flags = 0; 270 parameters.Flags = 0;
417 parameters.PresentationInterval = GetPresentationInterval(); 271 parameters.PresentationInterval = GetPresentationInterval();
418 parameters.SwapEffect = D3DSWAPEFFECT_COPY; 272 parameters.SwapEffect = D3DSWAPEFFECT_COPY;
(...skipping 13 matching lines...) Expand all
432 const base::Closure& completion_task) { 286 const base::Closure& completion_task) {
433 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id); 287 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id);
434 288
435 HRESULT hr; 289 HRESULT hr;
436 290
437 base::AutoLock locked(lock_); 291 base::AutoLock locked(lock_);
438 292
439 // Ensure the task is always run and while the lock is taken. 293 // Ensure the task is always run and while the lock is taken.
440 base::ScopedClosureRunner scoped_completion_runner(completion_task); 294 base::ScopedClosureRunner scoped_completion_runner(completion_task);
441 295
296 if (!device_)
297 return;
298
442 if (!window_) 299 if (!window_)
443 return; 300 return;
444 301
445 HANDLE handle = reinterpret_cast<HANDLE>(surface_id); 302 HANDLE handle = reinterpret_cast<HANDLE>(surface_id);
446 if (!handle) 303 if (!handle)
447 return; 304 return;
448 305
449 base::win::ScopedComPtr<IDirect3DTexture9> source_texture; 306 base::win::ScopedComPtr<IDirect3DTexture9> source_texture;
450 { 307 {
451 TRACE_EVENT0("surface", "CreateTexture"); 308 TRACE_EVENT0("surface", "CreateTexture");
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 354
498 ::SetWindowPos( 355 ::SetWindowPos(
499 window_, 356 window_,
500 NULL, 357 NULL,
501 0, 0, 358 0, 0,
502 size.width(), size.height(), 359 size.width(), size.height(),
503 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER | 360 SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |SWP_NOOWNERZORDER |
504 SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING | 361 SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOSENDCHANGING |
505 SWP_ASYNCWINDOWPOS); 362 SWP_ASYNCWINDOWPOS);
506 363
364 // Wait for the StretchRect to complete before notifying the GPU process
365 // that it is safe to write to its backing store again.
366 {
367 TRACE_EVENT0("surface", "spin");
368 do {
369 hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
370
371 if (hr == S_FALSE)
372 Sleep(0);
373 } while (hr == S_FALSE);
Ken Russell (switch to Gerrit) 2011/12/08 01:55:07 As an FYI a problem in a similarly structured loop
374 }
375
507 scoped_completion_runner.Release(); 376 scoped_completion_runner.Release();
508 if (!completion_task.is_null()) { 377 if (!completion_task.is_null())
509 g_present_thread_pool.Pointer()->AcknowledgeQuery(FROM_HERE, 378 completion_task.Run();
510 query_,
511 completion_task);
512 }
513 379
514 { 380 {
515 TRACE_EVENT0("surface", "Present"); 381 TRACE_EVENT0("surface", "Present");
516 hr = device_->Present(&rect, &rect, NULL, NULL); 382 hr = device_->Present(&rect, &rect, NULL, NULL);
517 if (FAILED(hr)) 383 if (FAILED(hr))
518 return; 384 return;
519 } 385 }
520 } 386 }
OLDNEW
« no previous file with comments | « ui/gfx/surface/accelerated_surface_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698