OLD | NEW |
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 "content/browser/gpu/browser_gpu_channel_host_factory.h" | 5 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "base/synchronization/waitable_event.h" | 9 #include "base/synchronization/waitable_event.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
11 #include "content/browser/gpu/gpu_data_manager_impl.h" | 11 #include "content/browser/gpu/gpu_data_manager_impl.h" |
12 #include "content/browser/gpu/gpu_process_host.h" | 12 #include "content/browser/gpu/gpu_process_host.h" |
13 #include "content/browser/gpu/gpu_surface_tracker.h" | 13 #include "content/browser/gpu/gpu_surface_tracker.h" |
14 #include "content/common/child_process_host_impl.h" | 14 #include "content/common/child_process_host_impl.h" |
15 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" | 15 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" |
16 #include "content/common/gpu/gpu_messages.h" | 16 #include "content/common/gpu/gpu_messages.h" |
17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/gpu_data_manager.h" | 18 #include "content/public/browser/gpu_data_manager.h" |
19 #include "content/public/common/content_client.h" | 19 #include "content/public/common/content_client.h" |
20 #include "ipc/ipc_channel_handle.h" | 20 #include "ipc/ipc_channel_handle.h" |
21 #include "ipc/ipc_forwarding_message_filter.h" | 21 #include "ipc/ipc_forwarding_message_filter.h" |
22 #include "ipc/message_filter.h" | 22 #include "ipc/message_filter.h" |
23 | 23 |
24 namespace content { | 24 namespace content { |
25 | 25 |
26 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; | 26 BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; |
27 | 27 |
28 struct BrowserGpuChannelHostFactory::CreateRequest { | 28 struct BrowserGpuChannelHostFactory::CreateRequest { |
29 CreateRequest() | 29 CreateRequest(int32 route_id) |
30 : event(true, false), gpu_host_id(0), route_id(MSG_ROUTING_NONE), | 30 : event(true, false), |
| 31 gpu_host_id(0), |
| 32 route_id(route_id), |
31 result(CREATE_COMMAND_BUFFER_FAILED) {} | 33 result(CREATE_COMMAND_BUFFER_FAILED) {} |
32 ~CreateRequest() {} | 34 ~CreateRequest() {} |
33 base::WaitableEvent event; | 35 base::WaitableEvent event; |
34 int gpu_host_id; | 36 int gpu_host_id; |
35 int32 route_id; | 37 int32 route_id; |
36 CreateCommandBufferResult result; | 38 CreateCommandBufferResult result; |
37 }; | 39 }; |
38 | 40 |
| 41 struct BrowserGpuChannelHostFactory::AllocateGpuMemoryBufferRequest { |
| 42 AllocateGpuMemoryBufferRequest(size_t width, |
| 43 size_t height, |
| 44 unsigned internalformat, |
| 45 unsigned usage) |
| 46 : event(true, false), |
| 47 width(width), |
| 48 height(height), |
| 49 internalformat(internalformat), |
| 50 usage(usage) {} |
| 51 ~AllocateGpuMemoryBufferRequest() {} |
| 52 base::WaitableEvent event; |
| 53 size_t width; |
| 54 size_t height; |
| 55 unsigned internalformat; |
| 56 unsigned usage; |
| 57 scoped_ptr<gfx::GpuMemoryBuffer> result; |
| 58 }; |
| 59 |
39 class BrowserGpuChannelHostFactory::EstablishRequest | 60 class BrowserGpuChannelHostFactory::EstablishRequest |
40 : public base::RefCountedThreadSafe<EstablishRequest> { | 61 : public base::RefCountedThreadSafe<EstablishRequest> { |
41 public: | 62 public: |
42 static scoped_refptr<EstablishRequest> Create(CauseForGpuLaunch cause, | 63 static scoped_refptr<EstablishRequest> Create(CauseForGpuLaunch cause, |
43 int gpu_client_id, | 64 int gpu_client_id, |
44 int gpu_host_id); | 65 int gpu_host_id); |
45 void Wait(); | 66 void Wait(); |
46 void Cancel(); | 67 void Cancel(); |
47 | 68 |
48 int gpu_host_id() { return gpu_host_id_; } | 69 int gpu_host_id() { return gpu_host_id_; } |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 void BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO( | 292 void BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO( |
272 CreateRequest* request, CreateCommandBufferResult result) { | 293 CreateRequest* request, CreateCommandBufferResult result) { |
273 request->result = result; | 294 request->result = result; |
274 request->event.Signal(); | 295 request->event.Signal(); |
275 } | 296 } |
276 | 297 |
277 CreateCommandBufferResult BrowserGpuChannelHostFactory::CreateViewCommandBuffer( | 298 CreateCommandBufferResult BrowserGpuChannelHostFactory::CreateViewCommandBuffer( |
278 int32 surface_id, | 299 int32 surface_id, |
279 const GPUCreateCommandBufferConfig& init_params, | 300 const GPUCreateCommandBufferConfig& init_params, |
280 int32 route_id) { | 301 int32 route_id) { |
281 CreateRequest request; | 302 CreateRequest request(route_id); |
282 request.route_id = route_id; | |
283 GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind( | 303 GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind( |
284 &BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO, | 304 &BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO, |
285 base::Unretained(this), | 305 base::Unretained(this), |
286 &request, | 306 &request, |
287 surface_id, | 307 surface_id, |
288 init_params)); | 308 init_params)); |
289 // We're blocking the UI thread, which is generally undesirable. | 309 // We're blocking the UI thread, which is generally undesirable. |
290 // In this case we need to wait for this before we can show any UI /anyway/, | 310 // In this case we need to wait for this before we can show any UI /anyway/, |
291 // so it won't cause additional jank. | 311 // so it won't cause additional jank. |
292 // TODO(piman): Make this asynchronous (http://crbug.com/125248). | 312 // TODO(piman): Make this asynchronous (http://crbug.com/125248). |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 established_callbacks_[n].Run(); | 376 established_callbacks_[n].Run(); |
357 | 377 |
358 established_callbacks_.clear(); | 378 established_callbacks_.clear(); |
359 } | 379 } |
360 | 380 |
361 scoped_ptr<gfx::GpuMemoryBuffer> | 381 scoped_ptr<gfx::GpuMemoryBuffer> |
362 BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer(size_t width, | 382 BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer(size_t width, |
363 size_t height, | 383 size_t height, |
364 unsigned internalformat, | 384 unsigned internalformat, |
365 unsigned usage) { | 385 unsigned usage) { |
366 if (!GpuMemoryBufferImpl::IsFormatValid(internalformat) || | 386 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); |
367 !GpuMemoryBufferImpl::IsUsageValid(usage)) | |
368 return scoped_ptr<gfx::GpuMemoryBuffer>(); | |
369 | 387 |
370 return GpuMemoryBufferImpl::Create(gfx::Size(width, height), | 388 AllocateGpuMemoryBufferRequest request(width, height, internalformat, usage); |
371 internalformat, | 389 GetIOLoopProxy()->PostTask( |
372 usage).PassAs<gfx::GpuMemoryBuffer>(); | 390 FROM_HERE, |
| 391 base::Bind(&BrowserGpuChannelHostFactory::AllocateGpuMemoryBufferOnIO, |
| 392 base::Unretained(&request))); |
| 393 |
| 394 // We're blocking the UI thread, which is generally undesirable. |
| 395 TRACE_EVENT0("browser", |
| 396 "BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer"); |
| 397 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
| 398 request.event.Wait(); |
| 399 return request.result.Pass(); |
| 400 } |
| 401 |
| 402 void BrowserGpuChannelHostFactory::DeleteGpuMemoryBuffer( |
| 403 scoped_ptr<gfx::GpuMemoryBuffer> buffer) { |
| 404 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 405 |
| 406 GetIOLoopProxy()->PostTask( |
| 407 FROM_HERE, |
| 408 base::Bind(&BrowserGpuChannelHostFactory::DeleteGpuMemoryBufferOnIO, |
| 409 base::Passed(&buffer))); |
| 410 } |
| 411 |
| 412 void BrowserGpuChannelHostFactory::CreateGpuMemoryBuffer( |
| 413 const gfx::GpuMemoryBufferHandle& handle, |
| 414 const gfx::Size& size, |
| 415 unsigned internalformat, |
| 416 unsigned usage, |
| 417 const CreateGpuMemoryBufferCallback& callback) { |
| 418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 419 |
| 420 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); |
| 421 if (!host) { |
| 422 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 423 return; |
| 424 } |
| 425 |
| 426 uint32 request_id = next_create_gpu_memory_buffer_request_id_++; |
| 427 create_gpu_memory_buffer_requests_[request_id] = callback; |
| 428 |
| 429 host->CreateGpuMemoryBuffer( |
| 430 handle, |
| 431 size, |
| 432 internalformat, |
| 433 usage, |
| 434 base::Bind(&BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated, |
| 435 base::Unretained(this), |
| 436 request_id)); |
| 437 } |
| 438 |
| 439 void BrowserGpuChannelHostFactory::DestroyGpuMemoryBuffer( |
| 440 const gfx::GpuMemoryBufferHandle& handle, |
| 441 int32 sync_point) { |
| 442 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 443 |
| 444 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); |
| 445 if (!host) |
| 446 return; |
| 447 |
| 448 host->DestroyGpuMemoryBuffer(handle, sync_point); |
373 } | 449 } |
374 | 450 |
375 // static | 451 // static |
376 void BrowserGpuChannelHostFactory::AddFilterOnIO( | 452 void BrowserGpuChannelHostFactory::AddFilterOnIO( |
377 int host_id, | 453 int host_id, |
378 scoped_refptr<IPC::MessageFilter> filter) { | 454 scoped_refptr<IPC::MessageFilter> filter) { |
379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 455 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
380 | 456 |
381 GpuProcessHost* host = GpuProcessHost::FromID(host_id); | 457 GpuProcessHost* host = GpuProcessHost::FromID(host_id); |
382 if (host) | 458 if (host) |
(...skipping 16 matching lines...) Expand all Loading... |
399 target_task_runner); | 475 target_task_runner); |
400 filter->AddRoute(MSG_ROUTING_CONTROL, handler); | 476 filter->AddRoute(MSG_ROUTING_CONTROL, handler); |
401 | 477 |
402 GetIOLoopProxy()->PostTask( | 478 GetIOLoopProxy()->PostTask( |
403 FROM_HERE, | 479 FROM_HERE, |
404 base::Bind(&BrowserGpuChannelHostFactory::AddFilterOnIO, | 480 base::Bind(&BrowserGpuChannelHostFactory::AddFilterOnIO, |
405 gpu_host_id_, | 481 gpu_host_id_, |
406 filter)); | 482 filter)); |
407 } | 483 } |
408 | 484 |
409 void BrowserGpuChannelHostFactory::CreateGpuMemoryBuffer( | 485 // static |
410 const gfx::GpuMemoryBufferHandle& handle, | 486 void BrowserGpuChannelHostFactory::AllocateGpuMemoryBufferOnIO( |
411 const gfx::Size& size, | 487 AllocateGpuMemoryBufferRequest* request) { |
412 unsigned internalformat, | 488 if (!GpuMemoryBufferImpl::IsFormatValid(request->internalformat) || |
413 unsigned usage, | 489 !GpuMemoryBufferImpl::IsUsageValid(request->usage)) { |
414 const CreateGpuMemoryBufferCallback& callback) { | 490 request->result = scoped_ptr<gfx::GpuMemoryBuffer>(); |
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 491 request->event.Signal(); |
416 uint32 request_id = next_create_gpu_memory_buffer_request_id_++; | |
417 create_gpu_memory_buffer_requests_[request_id] = callback; | |
418 GetIOLoopProxy()->PostTask( | |
419 FROM_HERE, | |
420 base::Bind(&BrowserGpuChannelHostFactory::CreateGpuMemoryBufferOnIO, | |
421 base::Unretained(this), | |
422 handle, | |
423 size, | |
424 internalformat, | |
425 usage, | |
426 request_id)); | |
427 } | |
428 | |
429 void BrowserGpuChannelHostFactory::DestroyGpuMemoryBuffer( | |
430 const gfx::GpuMemoryBufferHandle& handle, | |
431 int32 sync_point) { | |
432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
433 GetIOLoopProxy()->PostTask( | |
434 FROM_HERE, | |
435 base::Bind(&BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO, | |
436 base::Unretained(this), | |
437 handle, | |
438 sync_point)); | |
439 } | |
440 | |
441 void BrowserGpuChannelHostFactory::CreateGpuMemoryBufferOnIO( | |
442 const gfx::GpuMemoryBufferHandle& handle, | |
443 const gfx::Size& size, | |
444 unsigned internalformat, | |
445 unsigned usage, | |
446 uint32 request_id) { | |
447 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); | |
448 if (!host) { | |
449 GpuMemoryBufferCreatedOnIO(request_id, gfx::GpuMemoryBufferHandle()); | |
450 return; | 492 return; |
451 } | 493 } |
452 | 494 |
453 host->CreateGpuMemoryBuffer( | 495 request->result = GpuMemoryBufferImpl::Create( |
454 handle, | 496 gfx::Size(request->width, request->height), |
455 size, | 497 request->internalformat, |
456 internalformat, | 498 request->usage).PassAs<gfx::GpuMemoryBuffer>(); |
457 usage, | 499 request->event.Signal(); |
458 base::Bind(&BrowserGpuChannelHostFactory::GpuMemoryBufferCreatedOnIO, | |
459 base::Unretained(this), | |
460 request_id)); | |
461 } | 500 } |
462 | 501 |
463 void BrowserGpuChannelHostFactory::GpuMemoryBufferCreatedOnIO( | 502 // static |
464 uint32 request_id, | 503 void BrowserGpuChannelHostFactory::DeleteGpuMemoryBufferOnIO( |
465 const gfx::GpuMemoryBufferHandle& handle) { | 504 scoped_ptr<gfx::GpuMemoryBuffer> buffer) { |
466 BrowserThread::PostTask( | |
467 BrowserThread::UI, | |
468 FROM_HERE, | |
469 base::Bind(&BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated, | |
470 base::Unretained(this), | |
471 request_id, | |
472 handle)); | |
473 } | 505 } |
474 | 506 |
475 void BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated( | 507 void BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated( |
476 uint32 request_id, | 508 uint32 request_id, |
477 const gfx::GpuMemoryBufferHandle& handle) { | 509 const gfx::GpuMemoryBufferHandle& handle) { |
| 510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 511 |
478 CreateGpuMemoryBufferCallbackMap::iterator iter = | 512 CreateGpuMemoryBufferCallbackMap::iterator iter = |
479 create_gpu_memory_buffer_requests_.find(request_id); | 513 create_gpu_memory_buffer_requests_.find(request_id); |
480 DCHECK(iter != create_gpu_memory_buffer_requests_.end()); | 514 DCHECK(iter != create_gpu_memory_buffer_requests_.end()); |
481 iter->second.Run(handle); | 515 iter->second.Run(handle); |
482 create_gpu_memory_buffer_requests_.erase(iter); | 516 create_gpu_memory_buffer_requests_.erase(iter); |
483 } | 517 } |
484 | 518 |
485 void BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO( | |
486 const gfx::GpuMemoryBufferHandle& handle, | |
487 int32 sync_point) { | |
488 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); | |
489 if (!host) | |
490 return; | |
491 | |
492 host->DestroyGpuMemoryBuffer(handle, sync_point); | |
493 } | |
494 | |
495 } // namespace content | 519 } // namespace content |
OLD | NEW |