Chromium Code Reviews| 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 "base/atomic_sequence_num.h" | 7 #include "base/atomic_sequence_num.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
| 12 #include "base/threading/thread_restrictions.h" | 12 #include "base/threading/thread_restrictions.h" |
| 13 #include "base/trace_event/process_memory_dump.h" | 13 #include "base/trace_event/process_memory_dump.h" |
| 14 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
| 15 #include "content/browser/gpu/gpu_process_host.h" | 15 #include "content/browser/gpu/gpu_process_host.h" |
| 16 #include "content/common/child_process_host_impl.h" | 16 #include "content/common/child_process_host_impl.h" |
| 17 #include "content/common/generic_shared_memory_tracing_id_generator.h" | |
| 17 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" | 18 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" |
| 18 #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h" | 19 #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h" |
| 19 #include "content/common/gpu/gpu_memory_buffer_factory_shared_memory.h" | 20 #include "content/common/gpu/gpu_memory_buffer_factory_shared_memory.h" |
| 20 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
| 21 #include "content/public/common/content_switches.h" | 22 #include "content/public/common/content_switches.h" |
| 22 #include "gpu/GLES2/gl2extchromium.h" | 23 #include "gpu/GLES2/gl2extchromium.h" |
| 23 #include "ui/gl/gl_switches.h" | 24 #include "ui/gl/gl_switches.h" |
| 24 | 25 |
| 25 #if defined(OS_MACOSX) | 26 #if defined(OS_MACOSX) |
| 26 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h" | 27 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration)) | 130 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration)) |
| 130 configurations.push_back(configuration); | 131 configurations.push_back(configuration); |
| 131 } | 132 } |
| 132 #endif | 133 #endif |
| 133 | 134 |
| 134 return configurations; | 135 return configurations; |
| 135 } | 136 } |
| 136 | 137 |
| 137 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; | 138 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; |
| 138 | 139 |
| 139 // Global atomic to generate gpu memory buffer unique IDs. | |
| 140 base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id; | |
| 141 | |
| 142 } // namespace | 140 } // namespace |
| 143 | 141 |
| 144 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest { | 142 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest { |
| 145 AllocateGpuMemoryBufferRequest(const gfx::Size& size, | 143 AllocateGpuMemoryBufferRequest(const gfx::Size& size, |
| 146 gfx::BufferFormat format, | 144 gfx::BufferFormat format, |
| 147 gfx::BufferUsage usage, | 145 gfx::BufferUsage usage, |
| 148 int client_id, | 146 int client_id, |
| 149 int surface_id) | 147 int surface_id) |
| 150 : event(true, false), | 148 : event(true, false), |
| 151 size(size), | 149 size(size), |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout( | 220 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout( |
| 223 const gfx::Size& size, | 221 const gfx::Size& size, |
| 224 gfx::BufferFormat format, | 222 gfx::BufferFormat format, |
| 225 int32 surface_id) { | 223 int32 surface_id) { |
| 226 DCHECK_GT(surface_id, 0); | 224 DCHECK_GT(surface_id, 0); |
| 227 return AllocateGpuMemoryBufferForSurface( | 225 return AllocateGpuMemoryBufferForSurface( |
| 228 size, format, gfx::BufferUsage::SCANOUT, surface_id); | 226 size, format, gfx::BufferUsage::SCANOUT, surface_id); |
| 229 } | 227 } |
| 230 | 228 |
| 231 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess( | 229 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess( |
| 230 gfx::GpuMemoryBufferId id, | |
| 232 const gfx::Size& size, | 231 const gfx::Size& size, |
| 233 gfx::BufferFormat format, | 232 gfx::BufferFormat format, |
| 234 gfx::BufferUsage usage, | 233 gfx::BufferUsage usage, |
| 235 base::ProcessHandle child_process_handle, | 234 base::ProcessHandle child_process_handle, |
| 236 int child_client_id, | 235 int child_client_id, |
| 237 const AllocationCallback& callback) { | 236 const AllocationCallback& callback) { |
| 238 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 237 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 239 | 238 |
| 240 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext(); | |
| 241 | |
| 242 // Use service side allocation if this is a supported configuration. | 239 // Use service side allocation if this is a supported configuration. |
| 243 if (IsGpuMemoryBufferConfigurationSupported(format, usage)) { | 240 if (IsGpuMemoryBufferConfigurationSupported(format, usage)) { |
| 244 AllocateGpuMemoryBufferOnIO(new_id, size, format, usage, child_client_id, 0, | 241 AllocateGpuMemoryBufferOnIO(id, size, format, usage, child_client_id, 0, |
| 245 false, callback); | 242 false, callback); |
| 246 return; | 243 return; |
| 247 } | 244 } |
| 248 | 245 |
| 249 // Early out if we cannot fallback to shared memory buffer. | 246 // Early out if we cannot fallback to shared memory buffer. |
| 250 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) || | 247 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) || |
| 251 !GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) || | 248 !GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) || |
| 252 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) { | 249 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) { |
| 253 callback.Run(gfx::GpuMemoryBufferHandle()); | 250 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 254 return; | 251 return; |
| 255 } | 252 } |
| 256 | 253 |
| 257 BufferMap& buffers = clients_[child_client_id]; | 254 BufferMap& buffers = clients_[child_client_id]; |
| 258 DCHECK(buffers.find(new_id) == buffers.end()); | |
| 259 | 255 |
| 260 // Allocate shared memory buffer as fallback. | 256 // Allocate shared memory buffer as fallback. |
| 261 buffers[new_id] = | 257 auto insert_result = buffers.insert(std::make_pair( |
|
danakj
2015/08/13 00:25:06
Looks good.
| |
| 262 BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0); | 258 id, BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0))); |
| 259 if (!insert_result.second) { | |
| 260 DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with " | |
| 261 "an existing ID."; | |
| 262 callback.Run(gfx::GpuMemoryBufferHandle()); | |
| 263 return; | |
| 264 } | |
| 265 | |
| 263 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( | 266 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( |
| 264 new_id, size, format, child_process_handle)); | 267 id, size, format, child_process_handle)); |
| 265 } | 268 } |
| 266 | 269 |
| 267 gfx::GpuMemoryBuffer* | 270 gfx::GpuMemoryBuffer* |
| 268 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( | 271 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( |
| 269 ClientBuffer buffer) { | 272 ClientBuffer buffer) { |
| 270 return GpuMemoryBufferImpl::FromClientBuffer(buffer); | 273 return GpuMemoryBufferImpl::FromClientBuffer(buffer); |
| 271 } | 274 } |
| 272 | 275 |
| 273 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( | 276 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( |
| 274 gfx::GpuMemoryBuffer* buffer, | 277 gfx::GpuMemoryBuffer* buffer, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 285 for (const auto& client : clients_) { | 288 for (const auto& client : clients_) { |
| 286 int client_id = client.first; | 289 int client_id = client.first; |
| 287 | 290 |
| 288 for (const auto& buffer : client.second) { | 291 for (const auto& buffer : client.second) { |
| 289 if (buffer.second.type == gfx::EMPTY_BUFFER) | 292 if (buffer.second.type == gfx::EMPTY_BUFFER) |
| 290 continue; | 293 continue; |
| 291 | 294 |
| 292 gfx::GpuMemoryBufferId buffer_id = buffer.first; | 295 gfx::GpuMemoryBufferId buffer_id = buffer.first; |
| 293 base::trace_event::MemoryAllocatorDump* dump = | 296 base::trace_event::MemoryAllocatorDump* dump = |
| 294 pmd->CreateAllocatorDump(base::StringPrintf( | 297 pmd->CreateAllocatorDump(base::StringPrintf( |
| 295 "gpumemorybuffer/client_%d/buffer_%d", client_id, buffer_id)); | 298 "gpumemorybuffer/client_%d/buffer_%d", client_id, buffer_id.id)); |
| 296 if (!dump) | 299 if (!dump) |
| 297 return false; | 300 return false; |
| 298 | 301 |
| 299 size_t buffer_size_in_bytes = 0; | 302 size_t buffer_size_in_bytes = 0; |
| 300 // Note: BufferSizeInBytes returns an approximated size for the buffer | 303 // Note: BufferSizeInBytes returns an approximated size for the buffer |
| 301 // but the factory can be made to return the exact size if this | 304 // but the factory can be made to return the exact size if this |
| 302 // approximation is not good enough. | 305 // approximation is not good enough. |
| 303 bool valid_size = GpuMemoryBufferImpl::BufferSizeInBytes( | 306 bool valid_size = GpuMemoryBufferImpl::BufferSizeInBytes( |
| 304 buffer.second.size, buffer.second.format, &buffer_size_in_bytes); | 307 buffer.second.size, buffer.second.format, &buffer_size_in_bytes); |
| 305 DCHECK(valid_size); | 308 DCHECK(valid_size); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 if (configuration.format == format && configuration.usage == usage) | 395 if (configuration.format == format && configuration.usage == usage) |
| 393 return true; | 396 return true; |
| 394 } | 397 } |
| 395 return false; | 398 return false; |
| 396 } | 399 } |
| 397 | 400 |
| 398 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO( | 401 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO( |
| 399 AllocateGpuMemoryBufferRequest* request) { | 402 AllocateGpuMemoryBufferRequest* request) { |
| 400 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 403 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 401 | 404 |
| 402 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext(); | 405 gfx::GpuMemoryBufferId new_id = |
| 406 content::GetNextGenericSharedMemoryTracingId(); | |
| 403 | 407 |
| 404 // Use service side allocation if this is a supported configuration. | 408 // Use service side allocation if this is a supported configuration. |
| 405 if (IsGpuMemoryBufferConfigurationSupported(request->format, | 409 if (IsGpuMemoryBufferConfigurationSupported(request->format, |
| 406 request->usage)) { | 410 request->usage)) { |
| 407 // Note: Unretained is safe as this is only used for synchronous allocation | 411 // Note: Unretained is safe as this is only used for synchronous allocation |
| 408 // from a non-IO thread. | 412 // from a non-IO thread. |
| 409 AllocateGpuMemoryBufferOnIO( | 413 AllocateGpuMemoryBufferOnIO( |
| 410 new_id, request->size, request->format, request->usage, | 414 new_id, request->size, request->format, request->usage, |
| 411 request->client_id, request->surface_id, false, | 415 request->client_id, request->surface_id, false, |
| 412 base::Bind(&BrowserGpuMemoryBufferManager:: | 416 base::Bind(&BrowserGpuMemoryBufferManager:: |
| 413 GpuMemoryBufferAllocatedForSurfaceOnIO, | 417 GpuMemoryBufferAllocatedForSurfaceOnIO, |
| 414 base::Unretained(this), base::Unretained(request))); | 418 base::Unretained(this), base::Unretained(request))); |
| 415 return; | 419 return; |
| 416 } | 420 } |
| 417 | 421 |
| 418 DCHECK(GpuMemoryBufferImplSharedMemory::IsFormatSupported(request->format)) | 422 DCHECK(GpuMemoryBufferImplSharedMemory::IsFormatSupported(request->format)) |
| 419 << static_cast<int>(request->format); | 423 << static_cast<int>(request->format); |
| 420 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage)) | 424 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage)) |
| 421 << static_cast<int>(request->usage); | 425 << static_cast<int>(request->usage); |
| 422 | 426 |
| 423 BufferMap& buffers = clients_[request->client_id]; | 427 BufferMap& buffers = clients_[request->client_id]; |
| 424 DCHECK(buffers.find(new_id) == buffers.end()); | |
| 425 | 428 |
| 426 // Allocate shared memory buffer as fallback. | 429 // Allocate shared memory buffer as fallback. |
| 427 buffers[new_id] = BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER, | 430 auto insert_result = buffers.insert(std::make_pair( |
| 428 request->format, request->usage, 0); | 431 new_id, BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER, |
| 432 request->format, request->usage, 0))); | |
| 433 DCHECK(insert_result.second); | |
| 434 | |
| 429 // Note: Unretained is safe as IO thread is stopped before manager is | 435 // Note: Unretained is safe as IO thread is stopped before manager is |
| 430 // destroyed. | 436 // destroyed. |
| 431 request->result = GpuMemoryBufferImplSharedMemory::Create( | 437 request->result = GpuMemoryBufferImplSharedMemory::Create( |
| 432 new_id, request->size, request->format, | 438 new_id, request->size, request->format, |
| 433 base::Bind( | 439 base::Bind( |
| 434 &GpuMemoryBufferDeleted, | 440 &GpuMemoryBufferDeleted, |
| 435 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), | 441 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), |
| 436 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, | 442 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, |
| 437 base::Unretained(this), new_id, request->client_id))); | 443 base::Unretained(this), new_id, request->client_id))); |
| 438 request->event.Signal(); | 444 request->event.Signal(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 465 gfx::GpuMemoryBufferId id, | 471 gfx::GpuMemoryBufferId id, |
| 466 const gfx::Size& size, | 472 const gfx::Size& size, |
| 467 gfx::BufferFormat format, | 473 gfx::BufferFormat format, |
| 468 gfx::BufferUsage usage, | 474 gfx::BufferUsage usage, |
| 469 int client_id, | 475 int client_id, |
| 470 int surface_id, | 476 int surface_id, |
| 471 bool reused_gpu_process, | 477 bool reused_gpu_process, |
| 472 const AllocationCallback& callback) { | 478 const AllocationCallback& callback) { |
| 473 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 479 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 474 | 480 |
| 475 BufferMap& buffers = clients_[client_id]; | |
| 476 DCHECK(buffers.find(id) == buffers.end()); | |
| 477 | |
| 478 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); | 481 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); |
| 479 if (!host) { | 482 if (!host) { |
| 480 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 483 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
| 481 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); | 484 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); |
| 482 if (!host) { | 485 if (!host) { |
| 483 LOG(ERROR) << "Failed to launch GPU process."; | 486 LOG(ERROR) << "Failed to launch GPU process."; |
| 484 callback.Run(gfx::GpuMemoryBufferHandle()); | 487 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 485 return; | 488 return; |
| 486 } | 489 } |
| 487 gpu_host_id_ = host->host_id(); | 490 gpu_host_id_ = host->host_id(); |
| 488 reused_gpu_process = false; | 491 reused_gpu_process = false; |
| 489 } else { | 492 } else { |
| 490 if (reused_gpu_process) { | 493 if (reused_gpu_process) { |
| 491 // We come here if we retried to allocate the buffer because of a | 494 // We come here if we retried to allocate the buffer because of a |
| 492 // failure in GpuMemoryBufferAllocatedOnIO, but we ended up with the | 495 // failure in GpuMemoryBufferAllocatedOnIO, but we ended up with the |
| 493 // same process ID, meaning the failure was not because of a channel | 496 // same process ID, meaning the failure was not because of a channel |
| 494 // error, but another reason. So fail now. | 497 // error, but another reason. So fail now. |
| 495 LOG(ERROR) << "Failed to allocate GpuMemoryBuffer."; | 498 LOG(ERROR) << "Failed to allocate GpuMemoryBuffer."; |
| 496 callback.Run(gfx::GpuMemoryBufferHandle()); | 499 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 497 return; | 500 return; |
| 498 } | 501 } |
| 499 reused_gpu_process = true; | 502 reused_gpu_process = true; |
| 500 } | 503 } |
| 501 | 504 |
| 505 BufferMap& buffers = clients_[client_id]; | |
| 506 | |
| 502 // Note: Handling of cases where the client is removed before the allocation | 507 // Note: Handling of cases where the client is removed before the allocation |
| 503 // completes is less subtle if we set the buffer type to EMPTY_BUFFER here | 508 // completes is less subtle if we set the buffer type to EMPTY_BUFFER here |
| 504 // and verify that this has not changed when allocation completes. | 509 // and verify that this has not changed when allocation completes. |
| 505 buffers[id] = BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0); | 510 auto insert_result = buffers.insert(std::make_pair( |
| 511 id, BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0))); | |
| 512 if (!insert_result.second) { | |
| 513 DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with " | |
|
reveman
2015/08/13 08:24:44
If using DLOG here then please switch to DLOG for
| |
| 514 "an existing ID."; | |
| 515 callback.Run(gfx::GpuMemoryBufferHandle()); | |
| 516 return; | |
| 517 } | |
| 506 | 518 |
| 507 // Note: Unretained is safe as IO thread is stopped before manager is | 519 // Note: Unretained is safe as IO thread is stopped before manager is |
| 508 // destroyed. | 520 // destroyed. |
| 509 host->CreateGpuMemoryBuffer( | 521 host->CreateGpuMemoryBuffer( |
| 510 id, size, format, usage, client_id, surface_id, | 522 id, size, format, usage, client_id, surface_id, |
| 511 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO, | 523 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO, |
| 512 base::Unretained(this), id, client_id, surface_id, | 524 base::Unretained(this), id, client_id, surface_id, |
| 513 gpu_host_id_, reused_gpu_process, callback)); | 525 gpu_host_id_, reused_gpu_process, callback)); |
| 514 } | 526 } |
| 515 | 527 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 615 return gpu_client_tracing_id_; | 627 return gpu_client_tracing_id_; |
| 616 } | 628 } |
| 617 | 629 |
| 618 // In normal cases, |client_id| is a child process id, so we can perform | 630 // In normal cases, |client_id| is a child process id, so we can perform |
| 619 // the standard conversion. | 631 // the standard conversion. |
| 620 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( | 632 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( |
| 621 client_id); | 633 client_id); |
| 622 } | 634 } |
| 623 | 635 |
| 624 } // namespace content | 636 } // namespace content |
| OLD | NEW |