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

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

Issue 9694015: Ensure that PresentThreadPool is initialized on the UI thread. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 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 | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // A PresentThread is a thread that is dedicated to presenting surfaces to a 43 // A PresentThread is a thread that is dedicated to presenting surfaces to a
44 // window. It owns a Direct3D device and a Direct3D query for this purpose. 44 // window. It owns a Direct3D device and a Direct3D query for this purpose.
45 class PresentThread : public base::Thread { 45 class PresentThread : public base::Thread {
46 public: 46 public:
47 PresentThread(const char* name); 47 PresentThread(const char* name);
48 ~PresentThread(); 48 ~PresentThread();
49 49
50 IDirect3DDevice9* device() { return device_.get(); } 50 IDirect3DDevice9* device() { return device_.get(); }
51 IDirect3DQuery9* query() { return query_.get(); } 51 IDirect3DQuery9* query() { return query_.get(); }
52 52
53 void InitDevice();
53 void ResetDevice(); 54 void ResetDevice();
54 55
55 protected: 56 protected:
56 virtual void Init();
57 virtual void CleanUp(); 57 virtual void CleanUp();
58 58
59 private: 59 private:
60 base::ScopedNativeLibrary d3d_module_; 60 base::ScopedNativeLibrary d3d_module_;
61 base::win::ScopedComPtr<IDirect3DDevice9Ex> device_; 61 base::win::ScopedComPtr<IDirect3DDevice9Ex> device_;
62 62
63 // This query is used to wait until a certain amount of progress has been 63 // This query is used to wait until a certain amount of progress has been
64 // made by the GPU and it is safe for the producer to modify its shared 64 // made by the GPU and it is safe for the producer to modify its shared
65 // texture again. 65 // texture again.
66 base::win::ScopedComPtr<IDirect3DQuery9> query_; 66 base::win::ScopedComPtr<IDirect3DQuery9> query_;
(...skipping 20 matching lines...) Expand all
87 base::LazyInstance<PresentThreadPool> 87 base::LazyInstance<PresentThreadPool>
88 g_present_thread_pool = LAZY_INSTANCE_INITIALIZER; 88 g_present_thread_pool = LAZY_INSTANCE_INITIALIZER;
89 89
90 PresentThread::PresentThread(const char* name) : base::Thread(name) { 90 PresentThread::PresentThread(const char* name) : base::Thread(name) {
91 } 91 }
92 92
93 PresentThread::~PresentThread() { 93 PresentThread::~PresentThread() {
94 Stop(); 94 Stop();
95 } 95 }
96 96
97 void PresentThread::InitDevice() {
98 // Initialize the device lazily since calling Direct3D can crash bots.
vangelis 2012/03/13 22:09:37 This comment probably makes more sense at the call
apatrick_chromium 2012/03/13 22:22:02 Done.
99 if (device_)
100 return;
101
102 TRACE_EVENT0("surface", "PresentThread::Init");
103 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL));
104 ResetDevice();
105 }
106
97 void PresentThread::ResetDevice() { 107 void PresentThread::ResetDevice() {
98 TRACE_EVENT0("surface", "PresentThread::ResetDevice"); 108 TRACE_EVENT0("surface", "PresentThread::ResetDevice");
99 109
100 // This will crash some Intel drivers but we can't render anything without 110 // This will crash some Intel drivers but we can't render anything without
101 // reseting the device, which would be disappointing. 111 // reseting the device, which would be disappointing.
102 query_ = NULL; 112 query_ = NULL;
103 device_ = NULL; 113 device_ = NULL;
104 114
105 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( 115 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>(
106 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName)); 116 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName));
(...skipping 30 matching lines...) Expand all
137 NULL, 147 NULL,
138 device_.Receive()); 148 device_.Receive());
139 if (FAILED(hr)) 149 if (FAILED(hr))
140 return; 150 return;
141 151
142 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); 152 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
143 if (FAILED(hr)) 153 if (FAILED(hr))
144 device_ = NULL; 154 device_ = NULL;
145 } 155 }
146 156
147 void PresentThread::Init() {
148 TRACE_EVENT0("surface", "PresentThread::Init");
149 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL));
150 ResetDevice();
151 }
152
153 void PresentThread::CleanUp() { 157 void PresentThread::CleanUp() {
154 // The D3D device and query are leaked because destroying the associated D3D 158 // The D3D device and query are leaked because destroying the associated D3D
155 // query crashes some Intel drivers. 159 // query crashes some Intel drivers.
156 device_.Detach(); 160 device_.Detach();
157 query_.Detach(); 161 query_.Detach();
158 } 162 }
159 163
160 PresentThreadPool::PresentThreadPool() : next_thread_(0) { 164 PresentThreadPool::PresentThreadPool() : next_thread_(0) {
165 // Do this in the constructor so present_threads_ is initialized before any
166 // other thread sees it. See LazyInstance documentation.
167 for (int i = 0; i < kNumPresentThreads; ++i) {
168 present_threads_[i].reset(new PresentThread(
169 base::StringPrintf("PresentThread #%d", i).c_str()));
170 present_threads_[i]->Start();
171 }
161 } 172 }
162 173
163 PresentThread* PresentThreadPool::NextThread() { 174 PresentThread* PresentThreadPool::NextThread() {
164 next_thread_ = (next_thread_ + 1) % kNumPresentThreads; 175 next_thread_ = (next_thread_ + 1) % kNumPresentThreads;
165 if (!present_threads_[next_thread_].get()) {
166 present_threads_[next_thread_].reset(new PresentThread(
167 base::StringPrintf("PresentThread #%d", next_thread_).c_str()));
168 present_threads_[next_thread_]->Start();
169 }
170 return present_threads_[next_thread_].get(); 176 return present_threads_[next_thread_].get();
171 } 177 }
172 178
173 AcceleratedPresenter::AcceleratedPresenter() 179 AcceleratedPresenter::AcceleratedPresenter()
174 : present_thread_(g_present_thread_pool.Pointer()->NextThread()) { 180 : present_thread_(g_present_thread_pool.Pointer()->NextThread()) {
175 } 181 }
176 182
177 void AcceleratedPresenter::AsyncPresentAndAcknowledge( 183 void AcceleratedPresenter::AsyncPresentAndAcknowledge(
178 gfx::NativeWindow window, 184 gfx::NativeWindow window,
179 const gfx::Size& size, 185 const gfx::Size& size,
180 int64 surface_id, 186 int64 surface_id,
181 const base::Callback<void(bool)>& completion_task) { 187 const base::Callback<void(bool)>& completion_task) {
182 present_thread_->message_loop()->PostTask( 188 present_thread_->message_loop()->PostTask(
183 FROM_HERE, 189 FROM_HERE,
184 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, 190 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge,
185 this, 191 this,
186 window, 192 window,
187 size, 193 size,
188 surface_id, 194 surface_id,
189 completion_task)); 195 completion_task));
190 } 196 }
191 197
192 bool AcceleratedPresenter::Present(gfx::NativeWindow window) { 198 bool AcceleratedPresenter::Present(gfx::NativeWindow window) {
193 TRACE_EVENT0("surface", "Present"); 199 TRACE_EVENT0("surface", "Present");
194 200
195 HRESULT hr; 201 HRESULT hr;
196 202
197 base::AutoLock locked(lock_); 203 base::AutoLock locked(lock_);
198 204
199 // Signal the caller to recomposite if the presenter has been suspended. 205 // Signal the caller to recomposite if the presenter has been suspended or no
206 // surface has ever been presented.
200 if (!swap_chain_) 207 if (!swap_chain_)
201 return false; 208 return false;
202 209
203 RECT rect = { 210 RECT rect = {
204 0, 0, 211 0, 0,
205 size_.width(), size_.height() 212 size_.width(), size_.height()
206 }; 213 };
207 214
208 { 215 {
209 TRACE_EVENT0("surface", "PresentEx"); 216 TRACE_EVENT0("surface", "PresentEx");
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 gfx::NativeWindow window, 266 gfx::NativeWindow window,
260 const gfx::Size& size, 267 const gfx::Size& size,
261 int64 surface_id, 268 int64 surface_id,
262 const base::Callback<void(bool)>& completion_task) { 269 const base::Callback<void(bool)>& completion_task) {
263 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id); 270 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id);
264 271
265 HRESULT hr; 272 HRESULT hr;
266 273
267 base::AutoLock locked(lock_); 274 base::AutoLock locked(lock_);
268 275
276 present_thread_->InitDevice();
277
278 // A surface with ID zero is presented even when shared surfaces are not in
279 // use for synchronization purposes. In that case, just acknowledge.
280 if (!surface_id) {
281 if (!completion_task.is_null())
282 completion_task.Run(true);
283 return;
284 }
285
269 if (!present_thread_->device()) { 286 if (!present_thread_->device()) {
270 if (!completion_task.is_null()) 287 if (!completion_task.is_null())
271 completion_task.Run(false); 288 completion_task.Run(false);
272 return; 289 return;
273 } 290 }
274 291
275 // Ensure the task is always run and while the lock is taken. 292 // Ensure the task is always run and while the lock is taken.
276 base::ScopedClosureRunner scoped_completion_runner(base::Bind(completion_task, 293 base::ScopedClosureRunner scoped_completion_runner(base::Bind(completion_task,
277 true)); 294 true));
278 295
(...skipping 22 matching lines...) Expand all
301 parameters.SwapEffect = D3DSWAPEFFECT_COPY; 318 parameters.SwapEffect = D3DSWAPEFFECT_COPY;
302 319
303 swap_chain_ = NULL; 320 swap_chain_ = NULL;
304 HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain( 321 HRESULT hr = present_thread_->device()->CreateAdditionalSwapChain(
305 &parameters, 322 &parameters,
306 swap_chain_.Receive()); 323 swap_chain_.Receive());
307 if (FAILED(hr)) 324 if (FAILED(hr))
308 return; 325 return;
309 } 326 }
310 327
311 HANDLE handle = reinterpret_cast<HANDLE>(surface_id);
312 if (!handle)
313 return;
314
315 base::win::ScopedComPtr<IDirect3DTexture9> source_texture; 328 base::win::ScopedComPtr<IDirect3DTexture9> source_texture;
316 { 329 {
317 TRACE_EVENT0("surface", "CreateTexture"); 330 TRACE_EVENT0("surface", "CreateTexture");
331 HANDLE handle = reinterpret_cast<HANDLE>(surface_id);
318 hr = present_thread_->device()->CreateTexture(size.width(), 332 hr = present_thread_->device()->CreateTexture(size.width(),
319 size.height(), 333 size.height(),
320 1, 334 1,
321 D3DUSAGE_RENDERTARGET, 335 D3DUSAGE_RENDERTARGET,
322 D3DFMT_A8R8G8B8, 336 D3DFMT_A8R8G8B8,
323 D3DPOOL_DEFAULT, 337 D3DPOOL_DEFAULT,
324 source_texture.Receive(), 338 source_texture.Receive(),
325 &handle); 339 &handle);
326 if (FAILED(hr)) 340 if (FAILED(hr))
327 return; 341 return;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 if (FAILED(hr)) 408 if (FAILED(hr))
395 present_thread_->ResetDevice(); 409 present_thread_->ResetDevice();
396 } 410 }
397 } 411 }
398 412
399 void AcceleratedPresenter::DoSuspend() { 413 void AcceleratedPresenter::DoSuspend() {
400 base::AutoLock locked(lock_); 414 base::AutoLock locked(lock_);
401 swap_chain_ = NULL; 415 swap_chain_ = NULL;
402 } 416 }
403 417
404 AcceleratedSurface::AcceleratedSurface(){ 418 AcceleratedSurface::AcceleratedSurface()
419 : presenter_(new AcceleratedPresenter) {
405 } 420 }
406 421
407 AcceleratedSurface::~AcceleratedSurface() { 422 AcceleratedSurface::~AcceleratedSurface() {
408 if (presenter_) { 423 // Ensure that the swap chain is destroyed on the PresentThread in case
409 // Ensure that the swap chain is destroyed on the PresentThread in case 424 // there are still pending presents.
410 // there are still pending presents. 425 presenter_->Suspend();
411 presenter_->Suspend(); 426 presenter_->WaitForPendingTasks();
412 presenter_->WaitForPendingTasks();
413 }
414 } 427 }
415 428
416 void AcceleratedSurface::AsyncPresentAndAcknowledge( 429 void AcceleratedSurface::AsyncPresentAndAcknowledge(
417 HWND window, 430 HWND window,
418 const gfx::Size& size, 431 const gfx::Size& size,
419 int64 surface_id, 432 int64 surface_id,
420 const base::Callback<void(bool)>& completion_task) { 433 const base::Callback<void(bool)>& completion_task) {
421 if (!surface_id) 434 if (!surface_id)
422 return; 435 return;
423 436
424 if (!presenter_)
425 presenter_ = new AcceleratedPresenter;
426
427 presenter_->AsyncPresentAndAcknowledge(window, 437 presenter_->AsyncPresentAndAcknowledge(window,
428 size, 438 size,
429 surface_id, 439 surface_id,
430 completion_task); 440 completion_task);
431 } 441 }
432 442
433 bool AcceleratedSurface::Present(HWND window) { 443 bool AcceleratedSurface::Present(HWND window) {
434 if (presenter_) 444 return presenter_->Present(window);
435 return presenter_->Present(window);
436 else
437 return false;
438 } 445 }
439 446
440 void AcceleratedSurface::Suspend() { 447 void AcceleratedSurface::Suspend() {
441 if (presenter_) 448 presenter_->Suspend();
442 presenter_->Suspend();
443 } 449 }
444 450
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