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 |