| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_memory_buffer_manager.h" | 5 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 for (auto& usage : kGPUReadWriteUsages) { | 120 for (auto& usage : kGPUReadWriteUsages) { |
| 121 if (IsNativeGpuMemoryBufferFactoryConfigurationSupported(format, usage)) | 121 if (IsNativeGpuMemoryBufferFactoryConfigurationSupported(format, usage)) |
| 122 configurations.insert(std::make_pair(format, usage)); | 122 configurations.insert(std::make_pair(format, usage)); |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 | 126 |
| 127 return configurations; | 127 return configurations; |
| 128 } | 128 } |
| 129 | 129 |
| 130 void DestroyGpuMemoryBuffer(const gpu::SyncToken& sync_token) { | |
| 131 // No additional state needs to be cleaned up. | |
| 132 } | |
| 133 | |
| 134 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; | 130 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; |
| 135 | 131 |
| 136 } // namespace | 132 } // namespace |
| 137 | 133 |
| 138 struct BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferRequest { | 134 struct BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferRequest { |
| 139 CreateGpuMemoryBufferRequest(const gfx::Size& size, | 135 CreateGpuMemoryBufferRequest(const gfx::Size& size, |
| 140 gfx::BufferFormat format, | 136 gfx::BufferFormat format, |
| 141 gfx::BufferUsage usage, | 137 gfx::BufferUsage usage, |
| 142 int client_id, | 138 int client_id, |
| 143 gpu::SurfaceHandle surface_handle) | 139 gpu::SurfaceHandle surface_handle) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 168 : CreateGpuMemoryBufferRequest(size, | 164 : CreateGpuMemoryBufferRequest(size, |
| 169 format, | 165 format, |
| 170 gfx::BufferUsage::GPU_READ, | 166 gfx::BufferUsage::GPU_READ, |
| 171 client_id, | 167 client_id, |
| 172 gpu::kNullSurfaceHandle), | 168 gpu::kNullSurfaceHandle), |
| 173 handle(handle) {} | 169 handle(handle) {} |
| 174 ~CreateGpuMemoryBufferFromHandleRequest() {} | 170 ~CreateGpuMemoryBufferFromHandleRequest() {} |
| 175 gfx::GpuMemoryBufferHandle handle; | 171 gfx::GpuMemoryBufferHandle handle; |
| 176 }; | 172 }; |
| 177 | 173 |
| 178 struct BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferFromClientIdRequest | |
| 179 : public CreateGpuMemoryBufferRequest { | |
| 180 CreateGpuMemoryBufferFromClientIdRequest( | |
| 181 int client_id, | |
| 182 const gfx::GpuMemoryBufferId& gpu_memory_buffer_id) | |
| 183 : CreateGpuMemoryBufferRequest(gfx::Size(), | |
| 184 gfx::BufferFormat::RGBA_8888, | |
| 185 gfx::BufferUsage::GPU_READ, | |
| 186 client_id, | |
| 187 gpu::kNullSurfaceHandle), | |
| 188 gpu_memory_buffer_id(gpu_memory_buffer_id) {} | |
| 189 ~CreateGpuMemoryBufferFromClientIdRequest() {} | |
| 190 gfx::GpuMemoryBufferId gpu_memory_buffer_id; | |
| 191 }; | |
| 192 | |
| 193 BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager( | 174 BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager( |
| 194 int gpu_client_id, | 175 int gpu_client_id, |
| 195 uint64_t gpu_client_tracing_id) | 176 uint64_t gpu_client_tracing_id) |
| 196 : native_configurations_(GetNativeGpuMemoryBufferConfigurations()), | 177 : native_configurations_(GetNativeGpuMemoryBufferConfigurations()), |
| 197 gpu_client_id_(gpu_client_id), | 178 gpu_client_id_(gpu_client_id), |
| 198 gpu_client_tracing_id_(gpu_client_tracing_id), | 179 gpu_client_tracing_id_(gpu_client_tracing_id), |
| 199 gpu_host_id_(0) { | 180 gpu_host_id_(0) { |
| 200 DCHECK(!g_gpu_memory_buffer_manager); | 181 DCHECK(!g_gpu_memory_buffer_manager); |
| 201 g_gpu_memory_buffer_manager = this; | 182 g_gpu_memory_buffer_manager = this; |
| 202 } | 183 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with " | 308 DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with " |
| 328 "an existing ID."; | 309 "an existing ID."; |
| 329 callback.Run(gfx::GpuMemoryBufferHandle()); | 310 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 330 return; | 311 return; |
| 331 } | 312 } |
| 332 | 313 |
| 333 callback.Run(gpu::GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( | 314 callback.Run(gpu::GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( |
| 334 id, size, format, child_process_handle)); | 315 id, size, format, child_process_handle)); |
| 335 } | 316 } |
| 336 | 317 |
| 337 std::unique_ptr<gfx::GpuMemoryBuffer> | |
| 338 BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferFromClientId( | |
| 339 int client_id, | |
| 340 const gfx::GpuMemoryBufferId& gpu_memory_buffer_id) { | |
| 341 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 342 | |
| 343 CreateGpuMemoryBufferFromClientIdRequest request(client_id, | |
| 344 gpu_memory_buffer_id); | |
| 345 BrowserThread::PostTask( | |
| 346 BrowserThread::IO, FROM_HERE, | |
| 347 base::Bind(&BrowserGpuMemoryBufferManager:: | |
| 348 HandleCreateGpuMemoryBufferFromClientIdOnIO, | |
| 349 base::Unretained(this), // Safe as we wait for result below. | |
| 350 base::Unretained(&request))); | |
| 351 | |
| 352 // We're blocking the UI thread, which is generally undesirable. | |
| 353 TRACE_EVENT0( | |
| 354 "browser", | |
| 355 "BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferFromClientId"); | |
| 356 base::ThreadRestrictions::ScopedAllowWait allow_wait; | |
| 357 request.event.Wait(); | |
| 358 return std::move(request.result); | |
| 359 } | |
| 360 | |
| 361 gfx::GpuMemoryBuffer* | 318 gfx::GpuMemoryBuffer* |
| 362 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( | 319 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( |
| 363 ClientBuffer buffer) { | 320 ClientBuffer buffer) { |
| 364 return gpu::GpuMemoryBufferImpl::FromClientBuffer(buffer); | 321 return gpu::GpuMemoryBufferImpl::FromClientBuffer(buffer); |
| 365 } | 322 } |
| 366 | 323 |
| 367 void BrowserGpuMemoryBufferManager::SetDestructionSyncToken( | 324 void BrowserGpuMemoryBufferManager::SetDestructionSyncToken( |
| 368 gfx::GpuMemoryBuffer* buffer, | 325 gfx::GpuMemoryBuffer* buffer, |
| 369 const gpu::SyncToken& sync_token) { | 326 const gpu::SyncToken& sync_token) { |
| 370 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( | 327 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 request->result = gpu::GpuMemoryBufferImplSharedMemory::CreateFromHandle( | 530 request->result = gpu::GpuMemoryBufferImplSharedMemory::CreateFromHandle( |
| 574 handle, request->size, request->format, request->usage, | 531 handle, request->size, request->format, request->usage, |
| 575 base::Bind( | 532 base::Bind( |
| 576 &GpuMemoryBufferDeleted, | 533 &GpuMemoryBufferDeleted, |
| 577 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), | 534 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), |
| 578 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, | 535 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, |
| 579 base::Unretained(this), new_id, request->client_id))); | 536 base::Unretained(this), new_id, request->client_id))); |
| 580 request->event.Signal(); | 537 request->event.Signal(); |
| 581 } | 538 } |
| 582 | 539 |
| 583 void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferFromClientIdOnIO( | |
| 584 CreateGpuMemoryBufferFromClientIdRequest* request) { | |
| 585 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 586 | |
| 587 // This must be robust to renderer processes specifying invalid ids or the | |
| 588 // client being removed. | |
| 589 ClientMap::iterator client_it = clients_.find(request->client_id); | |
| 590 if (client_it == clients_.end()) { | |
| 591 LOG(ERROR) << "CreateGpuMemoryBufferFromClientId: invalid client."; | |
| 592 request->event.Signal(); | |
| 593 return; | |
| 594 } | |
| 595 BufferMap& buffers = client_it->second; | |
| 596 BufferMap::iterator buffer_it = buffers.find(request->gpu_memory_buffer_id); | |
| 597 if (buffer_it == buffers.end()) { | |
| 598 LOG(ERROR) << "CreateGpuMemoryBufferFromClientId: invalid id."; | |
| 599 request->event.Signal(); | |
| 600 return; | |
| 601 } | |
| 602 | |
| 603 // Create a copy of the buffer to provide to the caller. | |
| 604 if (buffer_it->second.buffer) { | |
| 605 request->result = gpu::GpuMemoryBufferImpl::CreateFromHandle( | |
| 606 buffer_it->second.buffer->GetHandle(), | |
| 607 buffer_it->second.size, buffer_it->second.format, | |
| 608 buffer_it->second.usage, base::Bind(DestroyGpuMemoryBuffer)); | |
| 609 } | |
| 610 | |
| 611 request->event.Signal(); | |
| 612 } | |
| 613 | |
| 614 void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO( | 540 void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO( |
| 615 CreateGpuMemoryBufferRequest* request, | 541 CreateGpuMemoryBufferRequest* request, |
| 616 const gfx::GpuMemoryBufferHandle& handle) { | 542 const gfx::GpuMemoryBufferHandle& handle) { |
| 617 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 543 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 618 | 544 |
| 619 // Early out if factory failed to create the buffer. | 545 // Early out if factory failed to create the buffer. |
| 620 if (handle.is_null()) { | 546 if (handle.is_null()) { |
| 621 request->event.Signal(); | 547 request->event.Signal(); |
| 622 return; | 548 return; |
| 623 } | 549 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 637 void BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferOnIO( | 563 void BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferOnIO( |
| 638 const CreateDelegate& create_delegate, | 564 const CreateDelegate& create_delegate, |
| 639 gfx::GpuMemoryBufferId id, | 565 gfx::GpuMemoryBufferId id, |
| 640 const gfx::Size& size, | 566 const gfx::Size& size, |
| 641 gfx::BufferFormat format, | 567 gfx::BufferFormat format, |
| 642 gfx::BufferUsage usage, | 568 gfx::BufferUsage usage, |
| 643 int client_id, | 569 int client_id, |
| 644 bool reused_gpu_process, | 570 bool reused_gpu_process, |
| 645 const CreateCallback& callback) { | 571 const CreateCallback& callback) { |
| 646 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 572 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 647 TRACE_EVENT0("browser", | |
| 648 "BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferOnIO"); | |
| 649 | 573 |
| 650 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); | 574 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); |
| 651 if (!host) { | 575 if (!host) { |
| 652 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 576 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
| 653 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); | 577 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); |
| 654 if (!host) { | 578 if (!host) { |
| 655 LOG(ERROR) << "Failed to launch GPU process."; | 579 LOG(ERROR) << "Failed to launch GPU process."; |
| 656 callback.Run(gfx::GpuMemoryBufferHandle()); | 580 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 657 return; | 581 return; |
| 658 } | 582 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 | 620 |
| 697 void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO( | 621 void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO( |
| 698 const CreateDelegate& create_delegate, | 622 const CreateDelegate& create_delegate, |
| 699 gfx::GpuMemoryBufferId id, | 623 gfx::GpuMemoryBufferId id, |
| 700 int client_id, | 624 int client_id, |
| 701 int gpu_host_id, | 625 int gpu_host_id, |
| 702 bool reused_gpu_process, | 626 bool reused_gpu_process, |
| 703 const CreateCallback& callback, | 627 const CreateCallback& callback, |
| 704 const gfx::GpuMemoryBufferHandle& handle) { | 628 const gfx::GpuMemoryBufferHandle& handle) { |
| 705 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 629 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 706 TRACE_EVENT0("browser", | |
| 707 "BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO"); | |
| 708 | 630 |
| 709 ClientMap::iterator client_it = clients_.find(client_id); | 631 ClientMap::iterator client_it = clients_.find(client_id); |
| 710 | 632 |
| 711 // This can happen if client is removed while the buffer is being allocated. | 633 // This can happen if client is removed while the buffer is being allocated. |
| 712 if (client_it == clients_.end()) { | 634 if (client_it == clients_.end()) { |
| 713 if (!handle.is_null()) { | 635 if (!handle.is_null()) { |
| 714 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id); | 636 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id); |
| 715 if (host) | 637 if (host) |
| 716 host->DestroyGpuMemoryBuffer(handle.id, client_id, gpu::SyncToken()); | 638 host->DestroyGpuMemoryBuffer(handle.id, client_id, gpu::SyncToken()); |
| 717 } | 639 } |
| 718 callback.Run(gfx::GpuMemoryBufferHandle()); | 640 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 719 return; | 641 return; |
| 720 } | 642 } |
| 721 | 643 |
| 722 BufferMap& buffers = client_it->second; | 644 BufferMap& buffers = client_it->second; |
| 723 | 645 |
| 724 BufferMap::iterator buffer_it = buffers.find(id); | 646 BufferMap::iterator buffer_it = buffers.find(id); |
| 725 DCHECK(buffer_it != buffers.end()); | 647 DCHECK(buffer_it != buffers.end()); |
| 726 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER); | 648 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER); |
| 727 | 649 |
| 728 // If the handle isn't valid, that means that the GPU process crashed or is | 650 // If the handle isn't valid, that means that the GPU process crashed or is |
| 729 // misbehaving. | 651 // misbehaving. |
| 730 bool valid_handle = !handle.is_null() && handle.id == id; | 652 bool valid_handle = !handle.is_null() && handle.id == id; |
| 731 | |
| 732 // Open a copy of the buffer in the browser process for future use. | |
| 733 std::unique_ptr<gpu::GpuMemoryBufferImpl> buffer; | |
| 734 if (valid_handle) { | |
| 735 // TODO(ccameron): Enable this for all buffer types. | |
| 736 // https://crbug.com/614791 | |
| 737 if (handle.type == gfx::IO_SURFACE_BUFFER) { | |
| 738 buffer = gpu::GpuMemoryBufferImpl::CreateFromHandle( | |
| 739 handle, buffer_it->second.size, buffer_it->second.format, | |
| 740 buffer_it->second.usage, base::Bind(DestroyGpuMemoryBuffer)); | |
| 741 if (!buffer) | |
| 742 valid_handle = false; | |
| 743 } | |
| 744 } | |
| 745 | |
| 746 if (!valid_handle) { | 653 if (!valid_handle) { |
| 747 // If we failed after re-using the GPU process, it may have died in the | 654 // If we failed after re-using the GPU process, it may have died in the |
| 748 // mean time. Retry to have a chance to create a fresh GPU process. | 655 // mean time. Retry to have a chance to create a fresh GPU process. |
| 749 if (handle.is_null() && reused_gpu_process) { | 656 if (handle.is_null() && reused_gpu_process) { |
| 750 DVLOG(1) << "Failed to create buffer through existing GPU process. " | 657 DVLOG(1) << "Failed to create buffer through existing GPU process. " |
| 751 "Trying to restart GPU process."; | 658 "Trying to restart GPU process."; |
| 752 // If the GPU process has already been restarted, retry without failure | 659 // If the GPU process has already been restarted, retry without failure |
| 753 // when GPU process host ID already exists. | 660 // when GPU process host ID already exists. |
| 754 if (gpu_host_id != gpu_host_id_) | 661 if (gpu_host_id != gpu_host_id_) |
| 755 reused_gpu_process = false; | 662 reused_gpu_process = false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 766 buffers.erase(buffer_it); | 673 buffers.erase(buffer_it); |
| 767 callback.Run(gfx::GpuMemoryBufferHandle()); | 674 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 768 } | 675 } |
| 769 return; | 676 return; |
| 770 } | 677 } |
| 771 | 678 |
| 772 // Store the type and host id of this buffer so it can be cleaned up if the | 679 // Store the type and host id of this buffer so it can be cleaned up if the |
| 773 // client is removed. | 680 // client is removed. |
| 774 buffer_it->second.type = handle.type; | 681 buffer_it->second.type = handle.type; |
| 775 buffer_it->second.gpu_host_id = gpu_host_id; | 682 buffer_it->second.gpu_host_id = gpu_host_id; |
| 776 buffer_it->second.buffer = std::move(buffer); | |
| 777 | 683 |
| 778 callback.Run(handle); | 684 callback.Run(handle); |
| 779 } | 685 } |
| 780 | 686 |
| 781 void BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO( | 687 void BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO( |
| 782 gfx::GpuMemoryBufferId id, | 688 gfx::GpuMemoryBufferId id, |
| 783 int client_id, | 689 int client_id, |
| 784 const gpu::SyncToken& sync_token) { | 690 const gpu::SyncToken& sync_token) { |
| 785 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 691 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 786 DCHECK(clients_.find(client_id) != clients_.end()); | 692 DCHECK(clients_.find(client_id) != clients_.end()); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 gfx::GpuMemoryBufferType type, | 733 gfx::GpuMemoryBufferType type, |
| 828 gfx::BufferFormat format, | 734 gfx::BufferFormat format, |
| 829 gfx::BufferUsage usage, | 735 gfx::BufferUsage usage, |
| 830 int gpu_host_id) | 736 int gpu_host_id) |
| 831 : size(size), | 737 : size(size), |
| 832 type(type), | 738 type(type), |
| 833 format(format), | 739 format(format), |
| 834 usage(usage), | 740 usage(usage), |
| 835 gpu_host_id(gpu_host_id) {} | 741 gpu_host_id(gpu_host_id) {} |
| 836 | 742 |
| 837 BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(BufferInfo&& other) | 743 BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(const BufferInfo& other) = |
| 838 : size(other.size), | 744 default; |
| 839 type(other.type), | |
| 840 format(other.format), | |
| 841 usage(other.usage), | |
| 842 gpu_host_id(other.gpu_host_id), | |
| 843 buffer(std::move(other.buffer)) {} | |
| 844 | 745 |
| 845 BrowserGpuMemoryBufferManager::BufferInfo::~BufferInfo() {} | 746 BrowserGpuMemoryBufferManager::BufferInfo::~BufferInfo() {} |
| 846 | 747 |
| 847 } // namespace content | 748 } // namespace content |
| OLD | NEW |