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

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 if (device_)
99 return;
100
101 TRACE_EVENT0("surface", "PresentThread::Init");
102 d3d_module_.Reset(base::LoadNativeLibrary(FilePath(kD3D9ModuleName), NULL));
103 ResetDevice();
104 }
105
97 void PresentThread::ResetDevice() { 106 void PresentThread::ResetDevice() {
98 TRACE_EVENT0("surface", "PresentThread::ResetDevice"); 107 TRACE_EVENT0("surface", "PresentThread::ResetDevice");
99 108
100 // This will crash some Intel drivers but we can't render anything without 109 // This will crash some Intel drivers but we can't render anything without
101 // reseting the device, which would be disappointing. 110 // reseting the device, which would be disappointing.
102 query_ = NULL; 111 query_ = NULL;
103 device_ = NULL; 112 device_ = NULL;
104 113
105 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>( 114 Direct3DCreate9ExFunc create_func = reinterpret_cast<Direct3DCreate9ExFunc>(
106 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName)); 115 d3d_module_.GetFunctionPointer(kCreate3D9DeviceExName));
(...skipping 30 matching lines...) Expand all
137 NULL, 146 NULL,
138 device_.Receive()); 147 device_.Receive());
139 if (FAILED(hr)) 148 if (FAILED(hr))
140 return; 149 return;
141 150
142 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); 151 hr = device_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive());
143 if (FAILED(hr)) 152 if (FAILED(hr))
144 device_ = NULL; 153 device_ = NULL;
145 } 154 }
146 155
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() { 156 void PresentThread::CleanUp() {
154 // The D3D device and query are leaked because destroying the associated D3D 157 // The D3D device and query are leaked because destroying the associated D3D
155 // query crashes some Intel drivers. 158 // query crashes some Intel drivers.
156 device_.Detach(); 159 device_.Detach();
157 query_.Detach(); 160 query_.Detach();
158 } 161 }
159 162
160 PresentThreadPool::PresentThreadPool() : next_thread_(0) { 163 PresentThreadPool::PresentThreadPool() : next_thread_(0) {
164 // Do this in the constructor so present_threads_ is initialized before any
165 // other thread sees it. See LazyInstance documentation.
166 for (int i = 0; i < kNumPresentThreads; ++i) {
167 present_threads_[i].reset(new PresentThread(
168 base::StringPrintf("PresentThread #%d", i).c_str()));
169 present_threads_[i]->Start();
170 }
161 } 171 }
162 172
163 PresentThread* PresentThreadPool::NextThread() { 173 PresentThread* PresentThreadPool::NextThread() {
164 next_thread_ = (next_thread_ + 1) % kNumPresentThreads; 174 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(); 175 return present_threads_[next_thread_].get();
171 } 176 }
172 177
173 AcceleratedPresenter::AcceleratedPresenter() 178 AcceleratedPresenter::AcceleratedPresenter()
174 : present_thread_(g_present_thread_pool.Pointer()->NextThread()) { 179 : present_thread_(g_present_thread_pool.Pointer()->NextThread()) {
175 } 180 }
176 181
177 void AcceleratedPresenter::AsyncPresentAndAcknowledge( 182 void AcceleratedPresenter::AsyncPresentAndAcknowledge(
178 gfx::NativeWindow window, 183 gfx::NativeWindow window,
179 const gfx::Size& size, 184 const gfx::Size& size,
180 int64 surface_id, 185 int64 surface_id,
181 const base::Callback<void(bool)>& completion_task) { 186 const base::Callback<void(bool)>& completion_task) {
182 present_thread_->message_loop()->PostTask( 187 present_thread_->message_loop()->PostTask(
183 FROM_HERE, 188 FROM_HERE,
184 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge, 189 base::Bind(&AcceleratedPresenter::DoPresentAndAcknowledge,
185 this, 190 this,
186 window, 191 window,
187 size, 192 size,
188 surface_id, 193 surface_id,
189 completion_task)); 194 completion_task));
190 } 195 }
191 196
192 bool AcceleratedPresenter::Present(gfx::NativeWindow window) { 197 bool AcceleratedPresenter::Present(gfx::NativeWindow window) {
193 TRACE_EVENT0("surface", "Present"); 198 TRACE_EVENT0("surface", "Present");
194 199
195 HRESULT hr; 200 HRESULT hr;
196 201
197 base::AutoLock locked(lock_); 202 base::AutoLock locked(lock_);
198 203
199 // Signal the caller to recomposite if the presenter has been suspended. 204 // Signal the caller to recomposite if the presenter has been suspended or no
205 // surface has ever been presented.
200 if (!swap_chain_) 206 if (!swap_chain_)
201 return false; 207 return false;
202 208
203 RECT rect = { 209 RECT rect = {
204 0, 0, 210 0, 0,
205 size_.width(), size_.height() 211 size_.width(), size_.height()
206 }; 212 };
207 213
208 { 214 {
209 TRACE_EVENT0("surface", "PresentEx"); 215 TRACE_EVENT0("surface", "PresentEx");
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 gfx::NativeWindow window, 265 gfx::NativeWindow window,
260 const gfx::Size& size, 266 const gfx::Size& size,
261 int64 surface_id, 267 int64 surface_id,
262 const base::Callback<void(bool)>& completion_task) { 268 const base::Callback<void(bool)>& completion_task) {
263 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id); 269 TRACE_EVENT1("surface", "DoPresentAndAcknowledge", "surface_id", surface_id);
264 270
265 HRESULT hr; 271 HRESULT hr;
266 272
267 base::AutoLock locked(lock_); 273 base::AutoLock locked(lock_);
268 274
275 // Initialize the device lazily since calling Direct3D can crash bots.
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