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 |