Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / content / browser / gpu / browser_gpu_memory_buffer_manager.cc
blob777f508ad091e3f423433149698e84eaeeb1bc31
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
3 // found in the LICENSE file.
5 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
7 #include "base/atomic_sequence_num.h"
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "base/trace_event/process_memory_dump.h"
14 #include "base/trace_event/trace_event.h"
15 #include "content/browser/gpu/gpu_process_host.h"
16 #include "content/common/child_process_host_impl.h"
17 #include "content/common/generic_shared_memory_id_generator.h"
18 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
19 #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
20 #include "content/common/gpu/gpu_memory_buffer_factory_shared_memory.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/common/content_switches.h"
23 #include "gpu/GLES2/gl2extchromium.h"
24 #include "ui/gfx/buffer_format_util.h"
25 #include "ui/gl/gl_switches.h"
27 #if defined(OS_MACOSX)
28 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
29 #endif
31 #if defined(OS_ANDROID)
32 #include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
33 #endif
35 #if defined(USE_OZONE)
36 #include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h"
37 #endif
39 namespace content {
40 namespace {
42 void GpuMemoryBufferDeleted(
43 scoped_refptr<base::SingleThreadTaskRunner> destruction_task_runner,
44 const GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
45 uint32 sync_point) {
46 destruction_task_runner->PostTask(
47 FROM_HERE, base::Bind(destruction_callback, sync_point));
50 bool IsGpuMemoryBufferFactoryConfigurationSupported(
51 gfx::GpuMemoryBufferType type,
52 const GpuMemoryBufferFactory::Configuration& configuration) {
53 switch (type) {
54 case gfx::SHARED_MEMORY_BUFFER:
55 return GpuMemoryBufferFactorySharedMemory::
56 IsGpuMemoryBufferConfigurationSupported(configuration.format,
57 configuration.usage);
58 #if defined(OS_MACOSX)
59 case gfx::IO_SURFACE_BUFFER:
60 return GpuMemoryBufferFactoryIOSurface::
61 IsGpuMemoryBufferConfigurationSupported(configuration.format,
62 configuration.usage);
63 #endif
64 #if defined(OS_ANDROID)
65 case gfx::SURFACE_TEXTURE_BUFFER:
66 return GpuMemoryBufferFactorySurfaceTexture::
67 IsGpuMemoryBufferConfigurationSupported(configuration.format,
68 configuration.usage);
69 #endif
70 #if defined(USE_OZONE)
71 case gfx::OZONE_NATIVE_PIXMAP:
72 return GpuMemoryBufferFactoryOzoneNativePixmap::
73 IsGpuMemoryBufferConfigurationSupported(configuration.format,
74 configuration.usage);
75 #endif
76 default:
77 NOTREACHED();
78 return false;
82 gfx::GpuMemoryBufferType GetGpuMemoryBufferFactoryType() {
83 std::vector<gfx::GpuMemoryBufferType> supported_types;
84 GpuMemoryBufferFactory::GetSupportedTypes(&supported_types);
85 DCHECK(!supported_types.empty());
87 // The GPU service will always use the preferred type.
88 return supported_types[0];
91 std::vector<GpuMemoryBufferFactory::Configuration>
92 GetSupportedGpuMemoryBufferConfigurations(gfx::GpuMemoryBufferType type) {
93 std::vector<GpuMemoryBufferFactory::Configuration> configurations;
94 #if defined(OS_MACOSX)
95 bool enable_native_gpu_memory_buffers =
96 !base::CommandLine::ForCurrentProcess()->HasSwitch(
97 switches::kDisableNativeGpuMemoryBuffers);
98 #else
99 bool enable_native_gpu_memory_buffers =
100 base::CommandLine::ForCurrentProcess()->HasSwitch(
101 switches::kEnableNativeGpuMemoryBuffers);
102 #endif
104 // Disable native buffers when using Mesa.
105 if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
106 switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
107 enable_native_gpu_memory_buffers = false;
110 if (enable_native_gpu_memory_buffers) {
111 const GpuMemoryBufferFactory::Configuration kNativeConfigurations[] = {
112 {gfx::BufferFormat::R_8, gfx::BufferUsage::MAP},
113 {gfx::BufferFormat::R_8, gfx::BufferUsage::PERSISTENT_MAP},
114 {gfx::BufferFormat::RGBA_4444, gfx::BufferUsage::MAP},
115 {gfx::BufferFormat::RGBA_4444, gfx::BufferUsage::PERSISTENT_MAP},
116 {gfx::BufferFormat::RGBA_8888, gfx::BufferUsage::MAP},
117 {gfx::BufferFormat::RGBA_8888, gfx::BufferUsage::PERSISTENT_MAP},
118 {gfx::BufferFormat::BGRA_8888, gfx::BufferUsage::MAP},
119 {gfx::BufferFormat::BGRA_8888, gfx::BufferUsage::PERSISTENT_MAP},
120 {gfx::BufferFormat::UYVY_422, gfx::BufferUsage::MAP},
121 {gfx::BufferFormat::UYVY_422, gfx::BufferUsage::PERSISTENT_MAP},
122 {gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::MAP},
123 {gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::PERSISTENT_MAP},
125 for (auto& configuration : kNativeConfigurations) {
126 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration))
127 configurations.push_back(configuration);
131 #if defined(USE_OZONE) || defined(OS_MACOSX)
132 const GpuMemoryBufferFactory::Configuration kScanoutConfigurations[] = {
133 {gfx::BufferFormat::BGRA_8888, gfx::BufferUsage::SCANOUT},
134 {gfx::BufferFormat::BGRX_8888, gfx::BufferUsage::SCANOUT},
135 {gfx::BufferFormat::UYVY_422, gfx::BufferUsage::SCANOUT},
136 {gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::SCANOUT},
138 for (auto& configuration : kScanoutConfigurations) {
139 if (IsGpuMemoryBufferFactoryConfigurationSupported(type, configuration))
140 configurations.push_back(configuration);
142 #endif
144 return configurations;
147 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr;
149 } // namespace
151 struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest {
152 AllocateGpuMemoryBufferRequest(const gfx::Size& size,
153 gfx::BufferFormat format,
154 gfx::BufferUsage usage,
155 int client_id,
156 int surface_id)
157 : event(true, false),
158 size(size),
159 format(format),
160 usage(usage),
161 client_id(client_id),
162 surface_id(surface_id) {}
163 ~AllocateGpuMemoryBufferRequest() {}
164 base::WaitableEvent event;
165 gfx::Size size;
166 gfx::BufferFormat format;
167 gfx::BufferUsage usage;
168 int client_id;
169 int surface_id;
170 scoped_ptr<gfx::GpuMemoryBuffer> result;
173 BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager(
174 int gpu_client_id,
175 uint64_t gpu_client_tracing_id)
176 : factory_type_(GetGpuMemoryBufferFactoryType()),
177 supported_configurations_(
178 GetSupportedGpuMemoryBufferConfigurations(factory_type_)),
179 gpu_client_id_(gpu_client_id),
180 gpu_client_tracing_id_(gpu_client_tracing_id),
181 gpu_host_id_(0) {
182 DCHECK(!g_gpu_memory_buffer_manager);
183 g_gpu_memory_buffer_manager = this;
186 BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() {
187 g_gpu_memory_buffer_manager = nullptr;
190 // static
191 BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() {
192 return g_gpu_memory_buffer_manager;
195 // static
196 uint32 BrowserGpuMemoryBufferManager::GetImageTextureTarget(
197 gfx::BufferFormat format,
198 gfx::BufferUsage usage) {
199 gfx::GpuMemoryBufferType type = GetGpuMemoryBufferFactoryType();
200 for (auto& configuration : GetSupportedGpuMemoryBufferConfigurations(type)) {
201 if (configuration.format != format || configuration.usage != usage)
202 continue;
204 switch (type) {
205 case gfx::SURFACE_TEXTURE_BUFFER:
206 case gfx::OZONE_NATIVE_PIXMAP:
207 // GPU memory buffers that are shared with the GL using EGLImages
208 // require TEXTURE_EXTERNAL_OES.
209 return GL_TEXTURE_EXTERNAL_OES;
210 case gfx::IO_SURFACE_BUFFER:
211 // IOSurface backed images require GL_TEXTURE_RECTANGLE_ARB.
212 return GL_TEXTURE_RECTANGLE_ARB;
213 default:
214 return GL_TEXTURE_2D;
218 return GL_TEXTURE_2D;
221 scoped_ptr<gfx::GpuMemoryBuffer>
222 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer(const gfx::Size& size,
223 gfx::BufferFormat format,
224 gfx::BufferUsage usage) {
225 return AllocateGpuMemoryBufferForSurface(size, format, usage, 0);
228 scoped_ptr<gfx::GpuMemoryBuffer>
229 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout(
230 const gfx::Size& size,
231 gfx::BufferFormat format,
232 int32 surface_id) {
233 DCHECK_GT(surface_id, 0);
234 return AllocateGpuMemoryBufferForSurface(
235 size, format, gfx::BufferUsage::SCANOUT, surface_id);
238 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
239 gfx::GpuMemoryBufferId id,
240 const gfx::Size& size,
241 gfx::BufferFormat format,
242 gfx::BufferUsage usage,
243 base::ProcessHandle child_process_handle,
244 int child_client_id,
245 const AllocationCallback& callback) {
246 DCHECK_CURRENTLY_ON(BrowserThread::IO);
248 // Use service side allocation if this is a supported configuration.
249 if (IsGpuMemoryBufferConfigurationSupported(format, usage)) {
250 AllocateGpuMemoryBufferOnIO(id, size, format, usage, child_client_id, 0,
251 false, callback);
252 return;
255 // Early out if we cannot fallback to shared memory buffer.
256 if (!GpuMemoryBufferImplSharedMemory::IsFormatSupported(format) ||
257 !GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
258 !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) {
259 callback.Run(gfx::GpuMemoryBufferHandle());
260 return;
263 BufferMap& buffers = clients_[child_client_id];
265 // Allocate shared memory buffer as fallback.
266 auto insert_result = buffers.insert(std::make_pair(
267 id, BufferInfo(size, gfx::SHARED_MEMORY_BUFFER, format, usage, 0)));
268 if (!insert_result.second) {
269 DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with "
270 "an existing ID.";
271 callback.Run(gfx::GpuMemoryBufferHandle());
272 return;
275 callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
276 id, size, format, child_process_handle));
279 gfx::GpuMemoryBuffer*
280 BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
281 ClientBuffer buffer) {
282 return GpuMemoryBufferImpl::FromClientBuffer(buffer);
285 void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint(
286 gfx::GpuMemoryBuffer* buffer,
287 uint32 sync_point) {
288 static_cast<GpuMemoryBufferImpl*>(buffer)
289 ->set_destruction_sync_point(sync_point);
292 bool BrowserGpuMemoryBufferManager::OnMemoryDump(
293 const base::trace_event::MemoryDumpArgs& args,
294 base::trace_event::ProcessMemoryDump* pmd) {
295 DCHECK_CURRENTLY_ON(BrowserThread::IO);
297 for (const auto& client : clients_) {
298 int client_id = client.first;
300 for (const auto& buffer : client.second) {
301 if (buffer.second.type == gfx::EMPTY_BUFFER)
302 continue;
304 gfx::GpuMemoryBufferId buffer_id = buffer.first;
305 base::trace_event::MemoryAllocatorDump* dump =
306 pmd->CreateAllocatorDump(base::StringPrintf(
307 "gpumemorybuffer/client_%d/buffer_%d", client_id, buffer_id.id));
308 if (!dump)
309 return false;
311 size_t buffer_size_in_bytes = gfx::BufferSizeForBufferFormat(
312 buffer.second.size, buffer.second.format);
313 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
314 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
315 buffer_size_in_bytes);
317 // Create the cross-process ownership edge. If the client creates a
318 // corresponding dump for the same buffer, this will avoid to
319 // double-count them in tracing. If, instead, no other process will emit a
320 // dump with the same guid, the segment will be accounted to the browser.
321 uint64 client_tracing_process_id = ClientIdToTracingProcessId(client_id);
323 base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid =
324 gfx::GetGpuMemoryBufferGUIDForTracing(client_tracing_process_id,
325 buffer_id);
326 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
327 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid);
331 return true;
334 void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer(
335 gfx::GpuMemoryBufferId id,
336 base::ProcessHandle child_process_handle,
337 int child_client_id,
338 uint32 sync_point) {
339 DCHECK_CURRENTLY_ON(BrowserThread::IO);
341 DestroyGpuMemoryBufferOnIO(id, child_client_id, sync_point);
344 void BrowserGpuMemoryBufferManager::ProcessRemoved(
345 base::ProcessHandle process_handle,
346 int client_id) {
347 DCHECK_CURRENTLY_ON(BrowserThread::IO);
349 ClientMap::iterator client_it = clients_.find(client_id);
350 if (client_it == clients_.end())
351 return;
353 for (const auto& buffer : client_it->second) {
354 // This might happen if buffer is currenlty in the process of being
355 // allocated. The buffer will in that case be cleaned up when allocation
356 // completes.
357 if (buffer.second.type == gfx::EMPTY_BUFFER)
358 continue;
360 GpuProcessHost* host = GpuProcessHost::FromID(buffer.second.gpu_host_id);
361 if (host)
362 host->DestroyGpuMemoryBuffer(buffer.first, client_id, 0);
365 clients_.erase(client_it);
368 scoped_ptr<gfx::GpuMemoryBuffer>
369 BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface(
370 const gfx::Size& size,
371 gfx::BufferFormat format,
372 gfx::BufferUsage usage,
373 int32 surface_id) {
374 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
376 AllocateGpuMemoryBufferRequest request(size, format, usage, gpu_client_id_,
377 surface_id);
378 BrowserThread::PostTask(
379 BrowserThread::IO, FROM_HERE,
380 base::Bind(
381 &BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO,
382 base::Unretained(this), // Safe as we wait for result below.
383 base::Unretained(&request)));
385 // We're blocking the UI thread, which is generally undesirable.
386 TRACE_EVENT0(
387 "browser",
388 "BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurface");
389 base::ThreadRestrictions::ScopedAllowWait allow_wait;
390 request.event.Wait();
391 return request.result.Pass();
394 bool BrowserGpuMemoryBufferManager::IsGpuMemoryBufferConfigurationSupported(
395 gfx::BufferFormat format,
396 gfx::BufferUsage usage) const {
397 for (auto& configuration : supported_configurations_) {
398 if (configuration.format == format && configuration.usage == usage)
399 return true;
401 return false;
404 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForSurfaceOnIO(
405 AllocateGpuMemoryBufferRequest* request) {
406 DCHECK_CURRENTLY_ON(BrowserThread::IO);
408 gfx::GpuMemoryBufferId new_id = content::GetNextGenericSharedMemoryId();
410 // Use service side allocation if this is a supported configuration.
411 if (IsGpuMemoryBufferConfigurationSupported(request->format,
412 request->usage)) {
413 // Note: Unretained is safe as this is only used for synchronous allocation
414 // from a non-IO thread.
415 AllocateGpuMemoryBufferOnIO(
416 new_id, request->size, request->format, request->usage,
417 request->client_id, request->surface_id, false,
418 base::Bind(&BrowserGpuMemoryBufferManager::
419 GpuMemoryBufferAllocatedForSurfaceOnIO,
420 base::Unretained(this), base::Unretained(request)));
421 return;
424 DCHECK(GpuMemoryBufferImplSharedMemory::IsFormatSupported(request->format))
425 << static_cast<int>(request->format);
426 DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
427 << static_cast<int>(request->usage);
429 BufferMap& buffers = clients_[request->client_id];
431 // Allocate shared memory buffer as fallback.
432 auto insert_result = buffers.insert(std::make_pair(
433 new_id, BufferInfo(request->size, gfx::SHARED_MEMORY_BUFFER,
434 request->format, request->usage, 0)));
435 DCHECK(insert_result.second);
437 // Note: Unretained is safe as IO thread is stopped before manager is
438 // destroyed.
439 request->result = GpuMemoryBufferImplSharedMemory::Create(
440 new_id, request->size, request->format,
441 base::Bind(
442 &GpuMemoryBufferDeleted,
443 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
444 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
445 base::Unretained(this), new_id, request->client_id)));
446 request->event.Signal();
449 void BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedForSurfaceOnIO(
450 AllocateGpuMemoryBufferRequest* request,
451 const gfx::GpuMemoryBufferHandle& handle) {
452 DCHECK_CURRENTLY_ON(BrowserThread::IO);
454 // Early out if factory failed to allocate the buffer.
455 if (handle.is_null()) {
456 request->event.Signal();
457 return;
460 // Note: Unretained is safe as IO thread is stopped before manager is
461 // destroyed.
462 request->result = GpuMemoryBufferImpl::CreateFromHandle(
463 handle, request->size, request->format, request->usage,
464 base::Bind(
465 &GpuMemoryBufferDeleted,
466 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
467 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
468 base::Unretained(this), handle.id, request->client_id)));
469 request->event.Signal();
472 void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO(
473 gfx::GpuMemoryBufferId id,
474 const gfx::Size& size,
475 gfx::BufferFormat format,
476 gfx::BufferUsage usage,
477 int client_id,
478 int surface_id,
479 bool reused_gpu_process,
480 const AllocationCallback& callback) {
481 DCHECK_CURRENTLY_ON(BrowserThread::IO);
483 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
484 if (!host) {
485 host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
486 CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE);
487 if (!host) {
488 LOG(ERROR) << "Failed to launch GPU process.";
489 callback.Run(gfx::GpuMemoryBufferHandle());
490 return;
492 gpu_host_id_ = host->host_id();
493 reused_gpu_process = false;
494 } else {
495 if (reused_gpu_process) {
496 // We come here if we retried to allocate the buffer because of a
497 // failure in GpuMemoryBufferAllocatedOnIO, but we ended up with the
498 // same process ID, meaning the failure was not because of a channel
499 // error, but another reason. So fail now.
500 LOG(ERROR) << "Failed to allocate GpuMemoryBuffer.";
501 callback.Run(gfx::GpuMemoryBufferHandle());
502 return;
504 reused_gpu_process = true;
507 BufferMap& buffers = clients_[client_id];
509 // Note: Handling of cases where the client is removed before the allocation
510 // completes is less subtle if we set the buffer type to EMPTY_BUFFER here
511 // and verify that this has not changed when allocation completes.
512 auto insert_result = buffers.insert(std::make_pair(
513 id, BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0)));
514 if (!insert_result.second) {
515 DLOG(ERROR) << "Child process attempted to allocate a GpuMemoryBuffer with "
516 "an existing ID.";
517 callback.Run(gfx::GpuMemoryBufferHandle());
518 return;
521 // Note: Unretained is safe as IO thread is stopped before manager is
522 // destroyed.
523 host->CreateGpuMemoryBuffer(
524 id, size, format, usage, client_id, surface_id,
525 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO,
526 base::Unretained(this), id, client_id, surface_id,
527 gpu_host_id_, reused_gpu_process, callback));
530 void BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedOnIO(
531 gfx::GpuMemoryBufferId id,
532 int client_id,
533 int surface_id,
534 int gpu_host_id,
535 bool reused_gpu_process,
536 const AllocationCallback& callback,
537 const gfx::GpuMemoryBufferHandle& handle) {
538 DCHECK_CURRENTLY_ON(BrowserThread::IO);
540 ClientMap::iterator client_it = clients_.find(client_id);
542 // This can happen if client is removed while the buffer is being allocated.
543 if (client_it == clients_.end()) {
544 if (!handle.is_null()) {
545 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id);
546 if (host)
547 host->DestroyGpuMemoryBuffer(handle.id, client_id, 0);
549 callback.Run(gfx::GpuMemoryBufferHandle());
550 return;
553 BufferMap& buffers = client_it->second;
555 BufferMap::iterator buffer_it = buffers.find(id);
556 DCHECK(buffer_it != buffers.end());
557 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER);
559 // If the handle isn't valid, that means that the GPU process crashed or is
560 // misbehaving.
561 bool valid_handle = !handle.is_null() && handle.id == id;
562 if (!valid_handle) {
563 // If we failed after re-using the GPU process, it may have died in the
564 // mean time. Retry to have a chance to create a fresh GPU process.
565 if (handle.is_null() && reused_gpu_process) {
566 DVLOG(1) << "Failed to create buffer through existing GPU process. "
567 "Trying to restart GPU process.";
568 // If the GPU process has already been restarted, retry without failure
569 // when GPU process host ID already exists.
570 if (gpu_host_id != gpu_host_id_)
571 reused_gpu_process = false;
572 gfx::Size size = buffer_it->second.size;
573 gfx::BufferFormat format = buffer_it->second.format;
574 gfx::BufferUsage usage = buffer_it->second.usage;
575 // Remove the buffer entry and call AllocateGpuMemoryBufferOnIO again.
576 buffers.erase(buffer_it);
577 AllocateGpuMemoryBufferOnIO(id, size, format, usage, client_id,
578 surface_id, reused_gpu_process, callback);
579 } else {
580 // Remove the buffer entry and run the allocation callback with an empty
581 // handle to indicate failure.
582 buffers.erase(buffer_it);
583 callback.Run(gfx::GpuMemoryBufferHandle());
585 return;
588 // Store the type and host id of this buffer so it can be cleaned up if the
589 // client is removed.
590 buffer_it->second.type = handle.type;
591 buffer_it->second.gpu_host_id = gpu_host_id;
593 callback.Run(handle);
596 void BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO(
597 gfx::GpuMemoryBufferId id,
598 int client_id,
599 uint32 sync_point) {
600 DCHECK_CURRENTLY_ON(BrowserThread::IO);
601 DCHECK(clients_.find(client_id) != clients_.end());
603 BufferMap& buffers = clients_[client_id];
605 BufferMap::iterator buffer_it = buffers.find(id);
606 if (buffer_it == buffers.end()) {
607 LOG(ERROR) << "Invalid GpuMemoryBuffer ID for client.";
608 return;
611 // This can happen if a client managed to call this while a buffer is in the
612 // process of being allocated.
613 if (buffer_it->second.type == gfx::EMPTY_BUFFER) {
614 LOG(ERROR) << "Invalid GpuMemoryBuffer type.";
615 return;
618 GpuProcessHost* host = GpuProcessHost::FromID(buffer_it->second.gpu_host_id);
619 if (host)
620 host->DestroyGpuMemoryBuffer(id, client_id, sync_point);
622 buffers.erase(buffer_it);
625 uint64_t BrowserGpuMemoryBufferManager::ClientIdToTracingProcessId(
626 int client_id) const {
627 if (client_id == gpu_client_id_) {
628 // The gpu_client uses a fixed tracing ID.
629 return gpu_client_tracing_id_;
632 // In normal cases, |client_id| is a child process id, so we can perform
633 // the standard conversion.
634 return ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
635 client_id);
638 } // namespace content