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 if (buffers.find(id) != buffers.end()) { |
reveman
2015/08/06 19:19:36
nit: please save the iterator and use it to set Bu
ericrk
2015/08/06 22:05:19
At this point iterator shouldn't exist (we expect
| |
240 LOG(ERROR) << "Client process attempted to allocate a GpuMemoryBuffer with " | |
241 "an existing ID. Failing allocation."; | |
242 callback.Run(gfx::GpuMemoryBufferHandle()); | |
243 return; | |
244 } | |
243 | 245 |
244 // Allocate shared memory buffer as fallback. | 246 // Allocate shared memory buffer as fallback. |
245 buffers[new_id] = | 247 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( | 248 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess( |
248 new_id, size, format, child_process_handle)); | 249 id, size, format, child_process_handle)); |
249 } | 250 } |
250 | 251 |
251 gfx::GpuMemoryBuffer* | 252 gfx::GpuMemoryBuffer* |
252 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( | 253 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer( |
253 ClientBuffer buffer) { | 254 ClientBuffer buffer) { |
254 return GpuMemoryBufferImpl::FromClientBuffer(buffer); | 255 return GpuMemoryBufferImpl::FromClientBuffer(buffer); |
255 } | 256 } |
256 | 257 |
257 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( | 258 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint( |
258 gfx::GpuMemoryBuffer* buffer, | 259 gfx::GpuMemoryBuffer* buffer, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 // corresponding dump for the same buffer, this will avoid to | 296 // corresponding dump for the same buffer, this will avoid to |
296 // double-count them in tracing. If, instead, no other process will emit a | 297 // 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. | 298 // dump with the same guid, the segment will be accounted to the browser. |
298 uint64 client_tracing_process_id = ClientIdToTracingProcessId(client_id); | 299 uint64 client_tracing_process_id = ClientIdToTracingProcessId(client_id); |
299 | 300 |
300 base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid = | 301 base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid = |
301 gfx::GetGpuMemoryBufferGUIDForTracing(client_tracing_process_id, | 302 gfx::GetGpuMemoryBufferGUIDForTracing(client_tracing_process_id, |
302 buffer_id); | 303 buffer_id); |
303 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); | 304 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); |
304 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); | 305 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); |
306 | |
307 if (buffer.second.type == | |
308 gfx::GpuMemoryBufferType::SHARED_MEMORY_BUFFER) { | |
309 // Normally, the GpuMemoryBufferFactory handles establishing the link | |
310 // between a GpuMemoryBufferId and any GenericSharedMemoryId. However, | |
311 // there is no manager for SHARED_MEMORY_BUFFER buffers, so handle | |
312 // this here. | |
reveman
2015/08/06 19:19:36
I was thinking that establishing the link is still
ericrk
2015/08/06 22:05:19
Using same GUID for both GpuMemoryBuffers and Gene
| |
313 GpuMemoryBufferImplSharedMemory::DumpGenericSharedMemory( | |
314 pmd, client_tracing_process_id, buffer_id); | |
reveman
2015/08/06 19:19:36
Can we move this into a static function as part Gp
ericrk
2015/08/06 22:05:19
Pulled this for now, will re-add generic memory du
| |
315 } | |
305 } | 316 } |
306 } | 317 } |
307 | 318 |
308 return true; | 319 return true; |
309 } | 320 } |
310 | 321 |
311 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer( | 322 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer( |
312 gfx::GpuMemoryBufferId id, | 323 gfx::GpuMemoryBufferId id, |
313 base::ProcessHandle child_process_handle, | 324 base::ProcessHandle child_process_handle, |
314 int child_client_id, | 325 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) | 386 if (configuration.format == format && configuration.usage == usage) |
376 return true; | 387 return true; |
377 } | 388 } |
378 return false; | 389 return false; |
379 } | 390 } |
380 | 391 |
381 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO( | 392 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO( |
382 AllocateGpuMemoryBufferRequest* request) { | 393 AllocateGpuMemoryBufferRequest* request) { |
383 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 394 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
384 | 395 |
385 gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext(); | 396 gfx::GpuMemoryBufferId new_id = content::GetNextGenericSharedMemoryId(); |
386 | 397 |
387 // Use service side allocation if this is a supported configuration. | 398 // Use service side allocation if this is a supported configuration. |
388 if (IsGpuMemoryBufferConfigurationSupported(request->format, | 399 if (IsGpuMemoryBufferConfigurationSupported(request->format, |
389 request->usage)) { | 400 request->usage)) { |
390 // Note: Unretained is safe as this is only used for synchronous allocation | 401 // Note: Unretained is safe as this is only used for synchronous allocation |
391 // from a non-IO thread. | 402 // from a non-IO thread. |
392 AllocateGpuMemoryBufferOnIO( | 403 AllocateGpuMemoryBufferOnIO( |
393 new_id, request->size, request->format, request->usage, | 404 new_id, request->size, request->format, request->usage, |
394 request->client_id, request->surface_id, false, | 405 request->client_id, request->surface_id, false, |
395 base::Bind(&BrowserGpuMemoryBufferManager:: | 406 base::Bind(&BrowserGpuMemoryBufferManager:: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
449 const gfx::Size& size, | 460 const gfx::Size& size, |
450 gfx::BufferFormat format, | 461 gfx::BufferFormat format, |
451 gfx::BufferUsage usage, | 462 gfx::BufferUsage usage, |
452 int client_id, | 463 int client_id, |
453 int surface_id, | 464 int surface_id, |
454 bool reused_gpu_process, | 465 bool reused_gpu_process, |
455 const AllocationCallback& callback) { | 466 const AllocationCallback& callback) { |
456 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 467 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
457 | 468 |
458 BufferMap& buffers = clients_[client_id]; | 469 BufferMap& buffers = clients_[client_id]; |
459 DCHECK(buffers.find(id) == buffers.end()); | 470 if (buffers.find(id) != buffers.end()) { |
reveman
2015/08/06 19:19:36
same here. can we avoid two lookups?
ericrk
2015/08/06 22:05:19
Same comment as above.
| |
471 LOG(ERROR) << "Client process attempted to allocate a GpuMemoryBuffer with " | |
472 "an existing ID. Failing allocation."; | |
473 callback.Run(gfx::GpuMemoryBufferHandle()); | |
474 return; | |
475 } | |
460 | 476 |
461 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); | 477 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); |
462 if (!host) { | 478 if (!host) { |
463 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 479 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
464 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); | 480 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE); |
465 if (!host) { | 481 if (!host) { |
466 LOG(ERROR) << "Failed to launch GPU process."; | 482 LOG(ERROR) << "Failed to launch GPU process."; |
467 callback.Run(gfx::GpuMemoryBufferHandle()); | 483 callback.Run(gfx::GpuMemoryBufferHandle()); |
468 return; | 484 return; |
469 } | 485 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
598 return gpu_client_tracing_id_; | 614 return gpu_client_tracing_id_; |
599 } | 615 } |
600 | 616 |
601 // In normal cases, |client_id| is a child process id, so we can perform | 617 // In normal cases, |client_id| is a child process id, so we can perform |
602 // the standard conversion. | 618 // the standard conversion. |
603 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( | 619 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId( |
604 client_id); | 620 client_id); |
605 } | 621 } |
606 | 622 |
607 } // namespace content | 623 } // namespace content |
OLD | NEW |