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

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

Issue 2811513002: gpu: Simplify the error handling during gpu memory buffer allocation. (Closed)
Patch Set: tot merge Created 3 years, 8 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 <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 12 matching lines...) Expand all
23 #include "gpu/ipc/client/gpu_memory_buffer_impl.h" 23 #include "gpu/ipc/client/gpu_memory_buffer_impl.h"
24 #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h" 24 #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h"
25 #include "gpu/ipc/common/gpu_memory_buffer_support.h" 25 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
26 #include "ui/gfx/buffer_format_util.h" 26 #include "ui/gfx/buffer_format_util.h"
27 #include "ui/gfx/gpu_memory_buffer_tracing.h" 27 #include "ui/gfx/gpu_memory_buffer_tracing.h"
28 #include "ui/gl/gl_switches.h" 28 #include "ui/gl/gl_switches.h"
29 29
30 namespace content { 30 namespace content {
31 namespace { 31 namespace {
32 32
33 void HostCreateGpuMemoryBuffer(
34 gpu::SurfaceHandle surface_handle,
35 GpuProcessHost* host,
36 gfx::GpuMemoryBufferId id,
37 const gfx::Size& size,
38 gfx::BufferFormat format,
39 gfx::BufferUsage usage,
40 int client_id,
41 const BrowserGpuMemoryBufferManager::CreateCallback& callback) {
42 host->CreateGpuMemoryBuffer(id, size, format, usage, client_id,
43 surface_handle, callback);
44 }
45
46 void GpuMemoryBufferDeleted( 33 void GpuMemoryBufferDeleted(
47 scoped_refptr<base::SingleThreadTaskRunner> destruction_task_runner, 34 scoped_refptr<base::SingleThreadTaskRunner> destruction_task_runner,
48 const gpu::GpuMemoryBufferImpl::DestructionCallback& destruction_callback, 35 const gpu::GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
49 const gpu::SyncToken& sync_token) { 36 const gpu::SyncToken& sync_token) {
50 destruction_task_runner->PostTask( 37 destruction_task_runner->PostTask(
51 FROM_HERE, base::Bind(destruction_callback, sync_token)); 38 FROM_HERE, base::Bind(destruction_callback, sync_token));
52 } 39 }
53 40
54 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr; 41 BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr;
55 42
(...skipping 20 matching lines...) Expand all
76 int client_id; 63 int client_id;
77 gpu::SurfaceHandle surface_handle; 64 gpu::SurfaceHandle surface_handle;
78 std::unique_ptr<gfx::GpuMemoryBuffer> result; 65 std::unique_ptr<gfx::GpuMemoryBuffer> result;
79 }; 66 };
80 67
81 BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager( 68 BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager(
82 int gpu_client_id, 69 int gpu_client_id,
83 uint64_t gpu_client_tracing_id) 70 uint64_t gpu_client_tracing_id)
84 : native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()), 71 : native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()),
85 gpu_client_id_(gpu_client_id), 72 gpu_client_id_(gpu_client_id),
86 gpu_client_tracing_id_(gpu_client_tracing_id), 73 gpu_client_tracing_id_(gpu_client_tracing_id) {
87 gpu_host_id_(0) {
88 DCHECK(!g_gpu_memory_buffer_manager); 74 DCHECK(!g_gpu_memory_buffer_manager);
89 g_gpu_memory_buffer_manager = this; 75 g_gpu_memory_buffer_manager = this;
90 } 76 }
91 77
92 BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() { 78 BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() {
93 g_gpu_memory_buffer_manager = nullptr; 79 g_gpu_memory_buffer_manager = nullptr;
94 } 80 }
95 81
96 // static 82 // static
97 BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() { 83 BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() {
(...skipping 13 matching lines...) Expand all
111 gfx::GpuMemoryBufferId id, 97 gfx::GpuMemoryBufferId id,
112 const gfx::Size& size, 98 const gfx::Size& size,
113 gfx::BufferFormat format, 99 gfx::BufferFormat format,
114 gfx::BufferUsage usage, 100 gfx::BufferUsage usage,
115 int child_client_id, 101 int child_client_id,
116 const AllocationCallback& callback) { 102 const AllocationCallback& callback) {
117 DCHECK_CURRENTLY_ON(BrowserThread::IO); 103 DCHECK_CURRENTLY_ON(BrowserThread::IO);
118 104
119 // Use service side allocation for native configurations. 105 // Use service side allocation for native configurations.
120 if (IsNativeGpuMemoryBufferConfiguration(format, usage)) { 106 if (IsNativeGpuMemoryBufferConfiguration(format, usage)) {
121 CreateGpuMemoryBufferOnIO( 107 CreateGpuMemoryBufferOnIO(id, size, format, usage, gpu::kNullSurfaceHandle,
122 base::Bind(&HostCreateGpuMemoryBuffer, gpu::kNullSurfaceHandle), id, 108 child_client_id, callback);
123 size, format, usage, child_client_id, false, callback);
124 return; 109 return;
125 } 110 }
126 111
127 // Early out if we cannot fallback to shared memory buffer. 112 // Early out if we cannot fallback to shared memory buffer.
128 if (!gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) || 113 if (!gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
129 !gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, 114 !gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size,
130 format)) { 115 format)) {
131 callback.Run(gfx::GpuMemoryBufferHandle()); 116 callback.Run(gfx::GpuMemoryBufferHandle());
132 return; 117 return;
133 } 118 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 CreateGpuMemoryBufferRequest* request) { 252 CreateGpuMemoryBufferRequest* request) {
268 DCHECK_CURRENTLY_ON(BrowserThread::IO); 253 DCHECK_CURRENTLY_ON(BrowserThread::IO);
269 254
270 gfx::GpuMemoryBufferId new_id = content::GetNextGenericSharedMemoryId(); 255 gfx::GpuMemoryBufferId new_id = content::GetNextGenericSharedMemoryId();
271 256
272 // Use service side allocation for native configurations. 257 // Use service side allocation for native configurations.
273 if (IsNativeGpuMemoryBufferConfiguration(request->format, request->usage)) { 258 if (IsNativeGpuMemoryBufferConfiguration(request->format, request->usage)) {
274 // Note: Unretained is safe as this is only used for synchronous allocation 259 // Note: Unretained is safe as this is only used for synchronous allocation
275 // from a non-IO thread. 260 // from a non-IO thread.
276 CreateGpuMemoryBufferOnIO( 261 CreateGpuMemoryBufferOnIO(
277 base::Bind(&HostCreateGpuMemoryBuffer, request->surface_handle), new_id, 262 new_id, request->size, request->format, request->usage,
278 request->size, request->format, request->usage, request->client_id, 263 request->surface_handle, request->client_id,
279 false,
280 base::Bind( 264 base::Bind(
281 &BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO, 265 &BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO,
282 base::Unretained(this), base::Unretained(request))); 266 base::Unretained(this), base::Unretained(request)));
283 return; 267 return;
284 } 268 }
285 269
286 DCHECK(gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage)) 270 DCHECK(gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
287 << static_cast<int>(request->usage); 271 << static_cast<int>(request->usage);
288 272
289 BufferMap& buffers = clients_[request->client_id]; 273 BufferMap& buffers = clients_[request->client_id];
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 handle, request->size, request->format, request->usage, 307 handle, request->size, request->format, request->usage,
324 base::Bind( 308 base::Bind(
325 &GpuMemoryBufferDeleted, 309 &GpuMemoryBufferDeleted,
326 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), 310 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
327 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, 311 base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO,
328 base::Unretained(this), handle.id, request->client_id))); 312 base::Unretained(this), handle.id, request->client_id)));
329 request->event.Signal(); 313 request->event.Signal();
330 } 314 }
331 315
332 void BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferOnIO( 316 void BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferOnIO(
333 const CreateDelegate& create_delegate,
334 gfx::GpuMemoryBufferId id, 317 gfx::GpuMemoryBufferId id,
335 const gfx::Size& size, 318 const gfx::Size& size,
336 gfx::BufferFormat format, 319 gfx::BufferFormat format,
337 gfx::BufferUsage usage, 320 gfx::BufferUsage usage,
321 gpu::SurfaceHandle surface_handle,
338 int client_id, 322 int client_id,
339 bool reused_gpu_process,
340 const CreateCallback& callback) { 323 const CreateCallback& callback) {
341 DCHECK_CURRENTLY_ON(BrowserThread::IO); 324 DCHECK_CURRENTLY_ON(BrowserThread::IO);
342
343 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
344 if (!host) {
345 host = GpuProcessHost::Get();
346 if (!host) {
347 LOG(ERROR) << "Failed to launch GPU process.";
348 callback.Run(gfx::GpuMemoryBufferHandle());
349 return;
350 }
351 gpu_host_id_ = host->host_id();
352 reused_gpu_process = false;
353 } else {
354 if (reused_gpu_process) {
355 // We come here if we retried to create the buffer because of a failure
356 // in GpuMemoryBufferCreatedOnIO, but we ended up with the same process
357 // ID, meaning the failure was not because of a channel error, but
358 // another reason. So fail now.
359 LOG(ERROR) << "Failed to create GpuMemoryBuffer.";
360 callback.Run(gfx::GpuMemoryBufferHandle());
361 return;
362 }
363 reused_gpu_process = true;
364 }
365
366 BufferMap& buffers = clients_[client_id]; 325 BufferMap& buffers = clients_[client_id];
367 326
368 // Note: Handling of cases where the client is removed before the allocation 327 // Note: Handling of cases where the client is removed before the allocation
369 // completes is less subtle if we set the buffer type to EMPTY_BUFFER here 328 // completes is less subtle if we set the buffer type to EMPTY_BUFFER here
370 // and verify that this has not changed when creation completes. 329 // and verify that this has not changed when creation completes.
371 auto insert_result = buffers.insert(std::make_pair( 330 auto insert_result = buffers.insert(std::make_pair(
372 id, BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0))); 331 id, BufferInfo(size, gfx::EMPTY_BUFFER, format, usage, 0)));
373 if (!insert_result.second) { 332 if (!insert_result.second) {
374 DLOG(ERROR) << "Child process attempted to create a GpuMemoryBuffer with " 333 DLOG(ERROR) << "Child process attempted to create a GpuMemoryBuffer with "
375 "an existing ID."; 334 "an existing ID.";
376 callback.Run(gfx::GpuMemoryBufferHandle()); 335 callback.Run(gfx::GpuMemoryBufferHandle());
377 return; 336 return;
378 } 337 }
379 338
339 GpuProcessHost* host = GpuProcessHost::Get();
380 // Note: Unretained is safe as IO thread is stopped before manager is 340 // Note: Unretained is safe as IO thread is stopped before manager is
381 // destroyed. 341 // destroyed.
382 create_delegate.Run( 342 host->CreateGpuMemoryBuffer(
383 host, id, size, format, usage, client_id, 343 id, size, format, usage, client_id, surface_handle,
384 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO, 344 base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO,
385 base::Unretained(this), create_delegate, id, client_id, 345 base::Unretained(this), id, surface_handle, client_id,
386 gpu_host_id_, reused_gpu_process, callback)); 346 host->host_id(), callback));
387 } 347 }
388 348
389 void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO( 349 void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO(
390 const CreateDelegate& create_delegate,
391 gfx::GpuMemoryBufferId id, 350 gfx::GpuMemoryBufferId id,
351 gpu::SurfaceHandle surface_handle,
392 int client_id, 352 int client_id,
393 int gpu_host_id, 353 int gpu_host_id,
394 bool reused_gpu_process,
395 const CreateCallback& callback, 354 const CreateCallback& callback,
396 const gfx::GpuMemoryBufferHandle& handle) { 355 const gfx::GpuMemoryBufferHandle& handle,
356 GpuProcessHost::BufferCreationStatus status) {
397 DCHECK_CURRENTLY_ON(BrowserThread::IO); 357 DCHECK_CURRENTLY_ON(BrowserThread::IO);
398 358
399 ClientMap::iterator client_it = clients_.find(client_id); 359 ClientMap::iterator client_it = clients_.find(client_id);
400 360
401 // This can happen if client is removed while the buffer is being allocated. 361 // This can happen if client is removed while the buffer is being allocated.
402 if (client_it == clients_.end()) { 362 if (client_it == clients_.end()) {
403 if (!handle.is_null()) { 363 if (!handle.is_null()) {
404 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id); 364 GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id);
405 if (host) 365 if (host)
406 host->DestroyGpuMemoryBuffer(handle.id, client_id, gpu::SyncToken()); 366 host->DestroyGpuMemoryBuffer(handle.id, client_id, gpu::SyncToken());
407 } 367 }
408 callback.Run(gfx::GpuMemoryBufferHandle()); 368 callback.Run(gfx::GpuMemoryBufferHandle());
409 return; 369 return;
410 } 370 }
411 371
412 BufferMap& buffers = client_it->second; 372 BufferMap& buffers = client_it->second;
413 373
414 BufferMap::iterator buffer_it = buffers.find(id); 374 BufferMap::iterator buffer_it = buffers.find(id);
415 DCHECK(buffer_it != buffers.end()); 375 DCHECK(buffer_it != buffers.end());
416 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER); 376 DCHECK_EQ(buffer_it->second.type, gfx::EMPTY_BUFFER);
417 377
418 // If the handle isn't valid, that means that the GPU process crashed or is 378 // If the handle isn't valid, that means that the GPU process crashed or is
419 // misbehaving. 379 // misbehaving.
420 bool valid_handle = !handle.is_null() && handle.id == id; 380 bool valid_handle = !handle.is_null() && handle.id == id;
421 if (!valid_handle) { 381 if (!valid_handle) {
422 // If we failed after re-using the GPU process, it may have died in the 382 // If we failed after re-using the GPU process, it may have died in the
423 // mean time. Retry to have a chance to create a fresh GPU process. 383 // mean time. Retry to have a chance to create a fresh GPU process.
424 if (handle.is_null() && reused_gpu_process) { 384 if (handle.is_null() &&
385 status == GpuProcessHost::BufferCreationStatus::GPU_HOST_INVALID) {
425 DVLOG(1) << "Failed to create buffer through existing GPU process. " 386 DVLOG(1) << "Failed to create buffer through existing GPU process. "
426 "Trying to restart GPU process."; 387 "Trying to restart GPU process.";
427 // If the GPU process has already been restarted, retry without failure
428 // when GPU process host ID already exists.
429 if (gpu_host_id != gpu_host_id_)
430 reused_gpu_process = false;
431 gfx::Size size = buffer_it->second.size; 388 gfx::Size size = buffer_it->second.size;
432 gfx::BufferFormat format = buffer_it->second.format; 389 gfx::BufferFormat format = buffer_it->second.format;
433 gfx::BufferUsage usage = buffer_it->second.usage; 390 gfx::BufferUsage usage = buffer_it->second.usage;
434 // Remove the buffer entry and call CreateGpuMemoryBufferOnIO again. 391 // Remove the buffer entry and call CreateGpuMemoryBufferOnIO again.
435 buffers.erase(buffer_it); 392 buffers.erase(buffer_it);
436 CreateGpuMemoryBufferOnIO(create_delegate, id, size, format, usage, 393 CreateGpuMemoryBufferOnIO(id, size, format, usage, surface_handle,
437 client_id, reused_gpu_process, callback); 394 client_id, callback);
438 } else { 395 } else {
439 // Remove the buffer entry and run the allocation callback with an empty 396 // Remove the buffer entry and run the allocation callback with an empty
440 // handle to indicate failure. 397 // handle to indicate failure.
441 buffers.erase(buffer_it); 398 buffers.erase(buffer_it);
442 callback.Run(gfx::GpuMemoryBufferHandle()); 399 callback.Run(gfx::GpuMemoryBufferHandle());
443 } 400 }
444 return; 401 return;
445 } 402 }
446 403
447 // Store the type and host id of this buffer so it can be cleaned up if the 404 // Store the type and host id of this buffer so it can be cleaned up if the
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 format(format), 464 format(format),
508 usage(usage), 465 usage(usage),
509 gpu_host_id(gpu_host_id) {} 466 gpu_host_id(gpu_host_id) {}
510 467
511 BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(const BufferInfo& other) = 468 BrowserGpuMemoryBufferManager::BufferInfo::BufferInfo(const BufferInfo& other) =
512 default; 469 default;
513 470
514 BrowserGpuMemoryBufferManager::BufferInfo::~BufferInfo() {} 471 BrowserGpuMemoryBufferManager::BufferInfo::~BufferInfo() {}
515 472
516 } // namespace content 473 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/gpu/browser_gpu_memory_buffer_manager.h ('k') | content/browser/gpu/gpu_process_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698