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_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()); | 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 Loading... | |
| 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 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 = 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |