| 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 | 24 |
| 24 #if defined(OS_MACOSX) | 25 #if defined(OS_MACOSX) |
| 25 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h" | 26 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h" |
| 26 #endif | 27 #endif |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration)) | 114 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration)) |
| 114 configurations.push_back(configuration); | 115 configurations.push_back(configuration); |
| 115 } | 116 } |
| 116 #endif | 117 #endif |
| 117 | 118 |
| 118 return configurations; | 119 return configurations; |
| 119 } | 120 } |
| 120 | 121 |
| 121 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; | 122 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; |
| 122 | 123 |
| 123 // Global atomic to generate gpu memory buffer unique IDs. | |
| 124 base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id; | |
| 125 | |
| 126 } // namespace | 124 } // namespace |
| 127 | 125 |
| 128 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest { | 126 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest { |
| 129 AllocateGpuMemoryBufferRequest(const gfx::Size& size, | 127 AllocateGpuMemoryBufferRequest(const gfx::Size& size, |
| 130 gfx::BufferFormat format, | 128 gfx::BufferFormat format, |
| 131 gfx::BufferUsage usage, | 129 gfx::BufferUsage usage, |
| 132 int client_id, | 130 int client_id, |
| 133 int surface_id) | 131 int surface_id) |
| 134 : event(true, false), | 132 : event(true, false), |
| 135 size(size), | 133 size(size), |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout( | 204 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout( |
| 207 const gfx::Size& size, | 205 const gfx::Size& size, |
| 208 gfx::BufferFormat format, | 206 gfx::BufferFormat format, |
| 209 int32 surface_id) { | 207 int32 surface_id) { |
| 210 DCHECK_GT(surface_id, 0); | 208 DCHECK_GT(surface_id, 0); |
| 211 return AllocateGpuMemoryBufferForSurface( | 209 return AllocateGpuMemoryBufferForSurface( |
| 212 size, format, gfx::BufferUsage::SCANOUT, surface_id); | 210 size, format, gfx::BufferUsage::SCANOUT, surface_id); |
| 213 } | 211 } |
| 214 | 212 |
| 215 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess( | 213 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess( |
| 214 gfx::GpuMemoryBufferId id, |
| 216 const gfx::Size& size, | 215 const gfx::Size& size, |
| 217 gfx::BufferFormat format, | 216 gfx::BufferFormat format, |
| 218 gfx::BufferUsage usage, | 217 gfx::BufferUsage usage, |
| 219 base::ProcessHandle child_process_handle, | 218 base::ProcessHandle child_process_handle, |
| 220 int child_client_id, | 219 int child_client_id, |
| 221 const AllocationCallback& callback) { | 220 const AllocationCallback& callback) { |
| 222 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 221 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 223 | 222 |
| 224 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext(); | |
| 225 | |
| 226 // Use service side allocation if this is a supported configuration. | 223 // Use service side allocation if this is a supported configuration. |
| 227 if (IsGpuMemoryBufferConfigurationSupported(format, usage)) { | 224 if (IsGpuMemoryBufferConfigurationSupported(format, usage)) { |
| 228 AllocateGpuMemoryBufferOnIO(new_id, size, format, usage, child_client_id, 0, | 225 AllocateGpuMemoryBufferOnIO(id, size, format, usage, child_client_id, 0, |
| 229 false, callback); | 226 false, callback); |
| 230 return; | 227 return; |
| 231 } | 228 } |
| 232 | 229 |
| 233 // Early out if we cannot fallback to shared memory buffer. | 230 // Early out if we cannot fallback to shared memory buffer. |
| 234 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) || | 231 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) || |
| 235 !GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) || | 232 !GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) || |
| 236 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) { | 233 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) { |
| 237 callback.Run(gfx::GpuMemoryBufferHandle()); | 234 callback.Run(gfx::GpuMemoryBufferHandle()); |
| 238 return; | 235 return; |
| 239 } | 236 } |
| 240 | 237 |
| 241 BufferMap& buffers = clients_[child_client_id]; | 238 BufferMap& buffers = clients_[child_client_id]; |
| 242 DCHECK(buffers.find(new_id) == buffers.end()); | 239 DCHECK(buffers.find(id) == buffers.end()); |
| 243 | 240 |
| 244 // Allocate shared memory buffer as fallback. | 241 // Allocate shared memory buffer as fallback. |
| 245 buffers[new_id] = | 242 buffers[id] = BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0); |
| 246 BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0); | |
| 247 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( | 243 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( |
| 248 new_id, size, format, child_process_handle)); | 244 id, size, format, child_process_handle)); |
| 249 } | 245 } |
| 250 | 246 |
| 251 gfx::GpuMemoryBuffer* | 247 gfx::GpuMemoryBuffer* |
| 252 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( | 248 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( |
| 253 ClientBuffer buffer) { | 249 ClientBuffer buffer) { |
| 254 return GpuMemoryBufferImpl::FromClientBuffer(buffer); | 250 return GpuMemoryBufferImpl::FromClientBuffer(buffer); |
| 255 } | 251 } |
| 256 | 252 |
| 257 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( | 253 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( |
| 258 gfx::GpuMemoryBuffer* buffer, | 254 gfx::GpuMemoryBuffer* buffer, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 284 // but the factory can be made to return the exact size if this | 280 // but the factory can be made to return the exact size if this |
| 285 // approximation is not good enough. | 281 // approximation is not good enough. |
| 286 bool valid_size = GpuMemoryBufferImpl::BufferSizeInBytes( | 282 bool valid_size = GpuMemoryBufferImpl::BufferSizeInBytes( |
| 287 buffer.second.size, buffer.second.format, &buffer_size_in_bytes); | 283 buffer.second.size, buffer.second.format, &buffer_size_in_bytes); |
| 288 DCHECK(valid_size); | 284 DCHECK(valid_size); |
| 289 | 285 |
| 290 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | 286 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
| 291 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | 287 base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 292 buffer_size_in_bytes); | 288 buffer_size_in_bytes); |
| 293 | 289 |
| 290 uint64 client_tracing_process_id = ClientIdToTracingProcessId(client_id); |
| 291 |
| 294 // Create the cross-process ownership edge. If the client creates a | 292 // Create the cross-process ownership edge. If the client creates a |
| 295 // corresponding dump for the same buffer, this will avoid to | 293 // corresponding dump for the same buffer, this will avoid to |
| 296 // double-count them in tracing. If, instead, no other process will emit a | 294 // double-count them in tracing. If, instead, no other process will emit a |
| 297 // dump with the same guid, the segment will be accounted to the browser. | 295 // dump with the same guid, the segment will be accounted to the browser. |
| 298 uint64 client_tracing_process_id = ClientIdToTracingProcessId(client_id); | |
| 299 | |
| 300 base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid = | 296 base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid = |
| 301 gfx::GetGpuMemoryBufferGUIDForTracing(client_tracing_process_id, | 297 gfx::GetGpuMemoryBufferGUIDForTracing(client_tracing_process_id, |
| 302 buffer_id); | 298 buffer_id); |
| 303 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); | 299 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); |
| 304 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); | 300 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); |
| 301 |
| 302 // Create an additional shared ownership edge with the generic shared |
| 303 // memory id for the shared memory which backs this GpuMemoryBuffer. |
| 304 base::trace_event::MemoryAllocatorDumpGuid shared_memory_guid = |
| 305 base::trace_event::GetGenericSharedMemoryGUIDForTracing( |
| 306 client_tracing_process_id, buffer_id); |
| 307 pmd->CreateSharedGlobalAllocatorDump(shared_memory_guid); |
| 308 |
| 309 // The link from the shared memory guid to the gpu memory buffer guid is |
| 310 // set higher than the link from the shared memory guid to its various |
| 311 // dumps. This ensures that memory is tracked with the gpu memory buffer. |
| 312 const int kImportance = 2; |
| 313 pmd->AddOwnershipEdge(shared_buffer_guid, shared_memory_guid, |
| 314 kImportance); |
| 305 } | 315 } |
| 306 } | 316 } |
| 307 | 317 |
| 308 return true; | 318 return true; |
| 309 } | 319 } |
| 310 | 320 |
| 311 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer( | 321 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer( |
| 312 gfx::GpuMemoryBufferId id, | 322 gfx::GpuMemoryBufferId id, |
| 313 base::ProcessHandle child_process_handle, | 323 base::ProcessHandle child_process_handle, |
| 314 int child_client_id, | 324 int child_client_id, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 if (configuration.format == format && configuration.usage == usage) | 385 if (configuration.format == format && configuration.usage == usage) |
| 376 return true; | 386 return true; |
| 377 } | 387 } |
| 378 return false; | 388 return false; |
| 379 } | 389 } |
| 380 | 390 |
| 381 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO( | 391 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO( |
| 382 AllocateGpuMemoryBufferRequest* request) { | 392 AllocateGpuMemoryBufferRequest* request) { |
| 383 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 393 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 384 | 394 |
| 385 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext(); | 395 gfx::GpuMemoryBufferId new_id = content::GetNextGenericSharedMemoryId(); |
| 386 | 396 |
| 387 // Use service side allocation if this is a supported configuration. | 397 // Use service side allocation if this is a supported configuration. |
| 388 if (IsGpuMemoryBufferConfigurationSupported(request->format, | 398 if (IsGpuMemoryBufferConfigurationSupported(request->format, |
| 389 request->usage)) { | 399 request->usage)) { |
| 390 // Note: Unretained is safe as this is only used for synchronous allocation | 400 // Note: Unretained is safe as this is only used for synchronous allocation |
| 391 // from a non-IO thread. | 401 // from a non-IO thread. |
| 392 AllocateGpuMemoryBufferOnIO( | 402 AllocateGpuMemoryBufferOnIO( |
| 393 new_id, request->size, request->format, request->usage, | 403 new_id, request->size, request->format, request->usage, |
| 394 request->client_id, request->surface_id, false, | 404 request->client_id, request->surface_id, false, |
| 395 base::Bind(&BrowserGpuMemoryBufferManager:: | 405 base::Bind(&BrowserGpuMemoryBufferManager:: |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 return gpu_client_tracing_id_; | 608 return gpu_client_tracing_id_; |
| 599 } | 609 } |
| 600 | 610 |
| 601 // In normal cases, |client_id| is a child process id, so we can perform | 611 // In normal cases, |client_id| is a child process id, so we can perform |
| 602 // the standard conversion. | 612 // the standard conversion. |
| 603 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( | 613 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( |
| 604 client_id); | 614 client_id); |
| 605 } | 615 } |
| 606 | 616 |
| 607 } // namespace content | 617 } // namespace content |
| OLD | NEW |