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

Side by Side Diff: content/browser/gpu/browser_gpu_memory_buffer_manager.cc

Issue 1280513002: Add GenericSharedMemoryId and use w/ GpuMemoryBuffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@trackpools
Patch Set: Avoid double map lookup Created 5 years, 4 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
OLDNEW
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_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
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
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()); 255
256 if (!TryAddNewBufferToMap(
257 buffers, id,
258 BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0))) {
259 LOG(ERROR) << "Client process attempted to allocate a GpuMemoryBuffer with "
reveman 2015/08/10 22:16:14 nit: "Child process..." to be consistent with func
ericrk 2015/08/11 01:40:07 Done.
260 "an existing ID. Failing allocation.";
reveman 2015/08/10 22:16:14 nit: I think "Failing allocation." is implicit fro
ericrk 2015/08/11 01:40:07 Done.
261 callback.Run(gfx::GpuMemoryBufferHandle());
262 return;
263 }
259 264
260 // Allocate shared memory buffer as fallback. 265 // Allocate shared memory buffer as fallback.
261 buffers[new_id] =
262 BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0);
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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 base::trace_event::MemoryAllocatorDump::kUnitsBytes, 311 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
309 buffer_size_in_bytes); 312 buffer_size_in_bytes);
310 313
311 // Create the cross-process ownership edge. If the client creates a 314 // Create the cross-process ownership edge. If the client creates a
312 // corresponding dump for the same buffer, this will avoid to 315 // corresponding dump for the same buffer, this will avoid to
313 // double-count them in tracing. If, instead, no other process will emit a 316 // double-count them in tracing. If, instead, no other process will emit a
314 // dump with the same guid, the segment will be accounted to the browser. 317 // dump with the same guid, the segment will be accounted to the browser.
315 uint64 client_tracing_process_id = ClientIdToTracingProcessId(client_id); 318 uint64 client_tracing_process_id = ClientIdToTracingProcessId(client_id);
316 319
317 base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid = 320 base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid =
318 gfx::GetGpuMemoryBufferGUIDForTracing(client_tracing_process_id, 321 base::GetGenericSharedMemoryGUIDForTracing(client_tracing_process_id,
319 buffer_id); 322 buffer_id);
320 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); 323 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
321 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); 324 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid);
322 } 325 }
323 } 326 }
324 327
325 return true; 328 return true;
326 } 329 }
327 330
328 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer( 331 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer(
329 gfx::GpuMemoryBufferId id, 332 gfx::GpuMemoryBufferId id,
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 = content::GetNextGenericSharedMemoryId();
403 406
404 // Use service side allocation if this is a supported configuration. 407 // Use service side allocation if this is a supported configuration.
405 if (IsGpuMemoryBufferConfigurationSupported(request->format, 408 if (IsGpuMemoryBufferConfigurationSupported(request->format,
406 request->usage)) { 409 request->usage)) {
407 // Note: Unretained is safe as this is only used for synchronous allocation 410 // Note: Unretained is safe as this is only used for synchronous allocation
408 // from a non-IO thread. 411 // from a non-IO thread.
409 AllocateGpuMemoryBufferOnIO( 412 AllocateGpuMemoryBufferOnIO(
410 new_id, request->size, request->format, request->usage, 413 new_id, request->size, request->format, request->usage,
411 request->client_id, request->surface_id, false, 414 request->client_id, request->surface_id, false,
412 base::Bind(&BrowserGpuMemoryBufferManager:: 415 base::Bind(&BrowserGpuMemoryBufferManager::
413 GpuMemoryBufferAllocatedForSurfaceOnIO, 416 GpuMemoryBufferAllocatedForSurfaceOnIO,
414 base::Unretained(this), base::Unretained(request))); 417 base::Unretained(this), base::Unretained(request)));
415 return; 418 return;
416 } 419 }
417 420
418 DCHECK(GpuMemoryBufferImplSharedMemory::IsFormatSupported(request->format)) 421 DCHECK(GpuMemoryBufferImplSharedMemory::IsFormatSupported(request->format))
419 << static_cast<int>(request->format); 422 << static_cast<int>(request->format);
420 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage)) 423 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
421 << static_cast<int>(request->usage); 424 << static_cast<int>(request->usage);
422 425
423 BufferMap& buffers = clients_[request->client_id]; 426 BufferMap& buffers = clients_[request->client_id];
424 DCHECK(buffers.find(new_id) == buffers.end());
425 427
426 // Allocate shared memory buffer as fallback. 428 // Allocate shared memory buffer as fallback.
427 buffers[new_id] = BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER, 429 DCHECK(TryAddNewBufferToMap(
428 request->format, request->usage, 0); 430 buffers, new_id, BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER,
431 request->format, request->usage, 0)));
reveman 2015/08/10 22:16:14 Is this DCHECK safe? Is it not possible for a chil
ericrk 2015/08/11 01:40:07 The ID here is safe, as it's allocated and control
429 // Note: Unretained is safe as IO thread is stopped before manager is 432 // Note: Unretained is safe as IO thread is stopped before manager is
430 // destroyed. 433 // destroyed.
431 request->result = GpuMemoryBufferImplSharedMemory::Create( 434 request->result = GpuMemoryBufferImplSharedMemory::Create(
432 new_id, request->size, request->format, 435 new_id, request->size, request->format,
433 base::Bind( 436 base::Bind(
434 &GpuMemoryBufferDeleted, 437 &GpuMemoryBufferDeleted,
435 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), 438 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
436 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, 439 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
437 base::Unretained(this), new_id, request->client_id))); 440 base::Unretained(this), new_id, request->client_id)));
438 request->event.Signal(); 441 request->event.Signal();
(...skipping 26 matching lines...) Expand all
465 gfx::GpuMemoryBufferId id, 468 gfx::GpuMemoryBufferId id,
466 const gfx::Size& size, 469 const gfx::Size& size,
467 gfx::BufferFormat format, 470 gfx::BufferFormat format,
468 gfx::BufferUsage usage, 471 gfx::BufferUsage usage,
469 int client_id, 472 int client_id,
470 int surface_id, 473 int surface_id,
471 bool reused_gpu_process, 474 bool reused_gpu_process,
472 const AllocationCallback& callback) { 475 const AllocationCallback& callback) {
473 DCHECK_CURRENTLY_ON(BrowserThread::IO); 476 DCHECK_CURRENTLY_ON(BrowserThread::IO);
474 477
475 BufferMap& buffers = clients_[client_id];
476 DCHECK(buffers.find(id) == buffers.end());
477
478 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); 478 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
479 if (!host) { 479 if (!host) {
480 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, 480 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
481 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); 481 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE);
482 if (!host) { 482 if (!host) {
483 LOG(ERROR) << "Failed to launch GPU process."; 483 LOG(ERROR) << "Failed to launch GPU process.";
484 callback.Run(gfx::GpuMemoryBufferHandle()); 484 callback.Run(gfx::GpuMemoryBufferHandle());
485 return; 485 return;
486 } 486 }
487 gpu_host_id_ = host->host_id(); 487 gpu_host_id_ = host->host_id();
488 reused_gpu_process = false; 488 reused_gpu_process = false;
489 } else { 489 } else {
490 if (reused_gpu_process) { 490 if (reused_gpu_process) {
491 // We come here if we retried to allocate the buffer because of a 491 // We come here if we retried to allocate the buffer because of a
492 // failure in GpuMemoryBufferAllocatedOnIO, but we ended up with the 492 // failure in GpuMemoryBufferAllocatedOnIO, but we ended up with the
493 // same process ID, meaning the failure was not because of a channel 493 // same process ID, meaning the failure was not because of a channel
494 // error, but another reason. So fail now. 494 // error, but another reason. So fail now.
495 LOG(ERROR) << "Failed to allocate GpuMemoryBuffer."; 495 LOG(ERROR) << "Failed to allocate GpuMemoryBuffer.";
496 callback.Run(gfx::GpuMemoryBufferHandle()); 496 callback.Run(gfx::GpuMemoryBufferHandle());
497 return; 497 return;
498 } 498 }
499 reused_gpu_process = true; 499 reused_gpu_process = true;
500 } 500 }
501 501
502 BufferMap& buffers = clients_[client_id];
503
502 // Note: Handling of cases where the client is removed before the allocation 504 // 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 505 // 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. 506 // and verify that this has not changed when allocation completes.
505 buffers[id] = BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0); 507 if (!TryAddNewBufferToMap(
508 buffers, id, BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0))) {
509 LOG(ERROR) << "Client process attempted to allocate a GpuMemoryBuffer with "
510 "an existing ID. Failing allocation.";
511 callback.Run(gfx::GpuMemoryBufferHandle());
512 return;
513 }
506 514
507 // Note: Unretained is safe as IO thread is stopped before manager is 515 // Note: Unretained is safe as IO thread is stopped before manager is
508 // destroyed. 516 // destroyed.
509 host->CreateGpuMemoryBuffer( 517 host->CreateGpuMemoryBuffer(
510 id, size, format, usage, client_id, surface_id, 518 id, size, format, usage, client_id, surface_id,
511 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO, 519 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO,
512 base::Unretained(this), id, client_id, surface_id, 520 base::Unretained(this), id, client_id, surface_id,
513 gpu_host_id_, reused_gpu_process, callback)); 521 gpu_host_id_, reused_gpu_process, callback));
514 } 522 }
515 523
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 // The gpu_client uses a fixed tracing ID. 622 // The gpu_client uses a fixed tracing ID.
615 return gpu_client_tracing_id_; 623 return gpu_client_tracing_id_;
616 } 624 }
617 625
618 // In normal cases, |client_id| is a child process id, so we can perform 626 // In normal cases, |client_id| is a child process id, so we can perform
619 // the standard conversion. 627 // the standard conversion.
620 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( 628 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
621 client_id); 629 client_id);
622 } 630 }
623 631
632 bool BrowserGpuMemoryBufferManager::TryAddNewBufferToMap(
633 BufferMap& buffers,
634 int id,
635 const BufferInfo& buffer_info) {
636 auto insert_result = buffers.insert(std::make_pair(
637 id, buffer_info));
638
639 // Pair is returned. Second value is true if a new element was inserted.
640 return insert_result.second;
641 }
reveman 2015/08/10 22:16:14 I think "if (!buffers_.insert(make_pair(key, value
ericrk 2015/08/11 01:40:07 removed this... probably not worth the function...
642
624 } // namespace content 643 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/gpu/browser_gpu_memory_buffer_manager.h ('k') | content/browser/renderer_host/render_message_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698