| 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 <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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |