| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "gpu/ipc/client/command_buffer_proxy_impl.h" | 5 #include "gpu/ipc/client/command_buffer_proxy_impl.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/shared_memory.h" | 12 #include "base/memory/shared_memory.h" |
| 13 #include "base/optional.h" |
| 13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 14 #include "base/thread_task_runner_handle.h" | 15 #include "base/thread_task_runner_handle.h" |
| 15 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
| 16 #include "gpu/command_buffer/client/gpu_control_client.h" | 17 #include "gpu/command_buffer/client/gpu_control_client.h" |
| 17 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" | 18 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" |
| 18 #include "gpu/command_buffer/common/cmd_buffer_common.h" | 19 #include "gpu/command_buffer/common/cmd_buffer_common.h" |
| 19 #include "gpu/command_buffer/common/command_buffer_id.h" | 20 #include "gpu/command_buffer/common/command_buffer_id.h" |
| 20 #include "gpu/command_buffer/common/command_buffer_shared.h" | 21 #include "gpu/command_buffer/common/command_buffer_shared.h" |
| 21 #include "gpu/command_buffer/common/gpu_memory_allocation.h" | 22 #include "gpu/command_buffer/common/gpu_memory_allocation.h" |
| 22 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" | 23 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ConsoleMsg, OnConsoleMessage); | 79 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ConsoleMsg, OnConsoleMessage); |
| 79 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalAck, OnSignalAck); | 80 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalAck, OnSignalAck); |
| 80 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SwapBuffersCompleted, | 81 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SwapBuffersCompleted, |
| 81 OnSwapBuffersCompleted); | 82 OnSwapBuffersCompleted); |
| 82 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_UpdateVSyncParameters, | 83 IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_UpdateVSyncParameters, |
| 83 OnUpdateVSyncParameters); | 84 OnUpdateVSyncParameters); |
| 84 IPC_MESSAGE_UNHANDLED(handled = false) | 85 IPC_MESSAGE_UNHANDLED(handled = false) |
| 85 IPC_END_MESSAGE_MAP() | 86 IPC_END_MESSAGE_MAP() |
| 86 | 87 |
| 87 if (!handled) { | 88 if (!handled) { |
| 88 DLOG(ERROR) << "Gpu process sent invalid message."; | 89 LOG(ERROR) << "Gpu process sent invalid message."; |
| 89 InvalidGpuMessage(); | 90 OnGpuAsyncMessageError(gpu::error::kInvalidGpuMessage, |
| 91 gpu::error::kLostContext); |
| 90 } | 92 } |
| 91 return handled; | 93 return handled; |
| 92 } | 94 } |
| 93 | 95 |
| 94 void CommandBufferProxyImpl::OnChannelError() { | 96 void CommandBufferProxyImpl::OnChannelError() { |
| 95 std::unique_ptr<base::AutoLock> lock; | 97 std::unique_ptr<base::AutoLock> lock; |
| 96 if (lock_) | 98 if (lock_) |
| 97 lock.reset(new base::AutoLock(*lock_)); | 99 lock.reset(new base::AutoLock(*lock_)); |
| 98 | 100 |
| 99 gpu::error::ContextLostReason context_lost_reason = | 101 gpu::error::ContextLostReason context_lost_reason = |
| 100 gpu::error::kGpuChannelLost; | 102 gpu::error::kGpuChannelLost; |
| 101 if (shared_state_shm_ && shared_state_shm_->memory()) { | 103 if (shared_state_shm_ && shared_state_shm_->memory()) { |
| 102 TryUpdateState(); | |
| 103 // The GPU process might have intentionally been crashed | 104 // The GPU process might have intentionally been crashed |
| 104 // (exit_on_context_lost), so try to find out the original reason. | 105 // (exit_on_context_lost), so try to find out the original reason. |
| 106 TryUpdateStateDontReportError(); |
| 105 if (last_state_.error == gpu::error::kLostContext) | 107 if (last_state_.error == gpu::error::kLostContext) |
| 106 context_lost_reason = last_state_.context_lost_reason; | 108 context_lost_reason = last_state_.context_lost_reason; |
| 107 } | 109 } |
| 108 OnDestroyed(context_lost_reason, gpu::error::kLostContext); | 110 OnGpuAsyncMessageError(context_lost_reason, gpu::error::kLostContext); |
| 109 } | 111 } |
| 110 | 112 |
| 111 void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason, | 113 void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason, |
| 112 gpu::error::Error error) { | 114 gpu::error::Error error) { |
| 113 CheckLock(); | 115 OnGpuAsyncMessageError(reason, error); |
| 114 | |
| 115 // When the client sees that the context is lost, they should delete this | |
| 116 // CommandBufferProxyImpl and create a new one. | |
| 117 last_state_.error = error; | |
| 118 last_state_.context_lost_reason = reason; | |
| 119 | |
| 120 // Prevent any further messages from being sent, and ensure we only call | |
| 121 // the client for lost context a single time. | |
| 122 if (channel_) { | |
| 123 channel_->DestroyCommandBuffer(this); | |
| 124 channel_ = nullptr; | |
| 125 if (gpu_control_client_) | |
| 126 gpu_control_client_->OnGpuControlLostContext(); | |
| 127 } | |
| 128 } | 116 } |
| 129 | 117 |
| 130 void CommandBufferProxyImpl::OnConsoleMessage( | 118 void CommandBufferProxyImpl::OnConsoleMessage( |
| 131 const GPUCommandBufferConsoleMessage& message) { | 119 const GPUCommandBufferConsoleMessage& message) { |
| 132 if (gpu_control_client_) | 120 if (gpu_control_client_) |
| 133 gpu_control_client_->OnGpuControlErrorMessage(message.message.c_str(), | 121 gpu_control_client_->OnGpuControlErrorMessage(message.message.c_str(), |
| 134 message.id); | 122 message.id); |
| 135 } | 123 } |
| 136 | 124 |
| 137 void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) { | 125 void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) { |
| 138 std::unique_ptr<base::AutoLock> lock; | 126 std::unique_ptr<base::AutoLock> lock; |
| 139 if (lock_) | 127 if (lock_) |
| 140 lock.reset(new base::AutoLock(*lock_)); | 128 lock.reset(new base::AutoLock(*lock_)); |
| 141 deletion_observers_.AddObserver(observer); | 129 deletion_observers_.AddObserver(observer); |
| 142 } | 130 } |
| 143 | 131 |
| 144 void CommandBufferProxyImpl::RemoveDeletionObserver( | 132 void CommandBufferProxyImpl::RemoveDeletionObserver( |
| 145 DeletionObserver* observer) { | 133 DeletionObserver* observer) { |
| 146 std::unique_ptr<base::AutoLock> lock; | 134 std::unique_ptr<base::AutoLock> lock; |
| 147 if (lock_) | 135 if (lock_) |
| 148 lock.reset(new base::AutoLock(*lock_)); | 136 lock.reset(new base::AutoLock(*lock_)); |
| 149 deletion_observers_.RemoveObserver(observer); | 137 deletion_observers_.RemoveObserver(observer); |
| 150 } | 138 } |
| 151 | 139 |
| 152 void CommandBufferProxyImpl::OnSignalAck(uint32_t id) { | 140 void CommandBufferProxyImpl::OnSignalAck(uint32_t id) { |
| 153 SignalTaskMap::iterator it = signal_tasks_.find(id); | 141 SignalTaskMap::iterator it = signal_tasks_.find(id); |
| 154 if (it == signal_tasks_.end()) { | 142 if (it == signal_tasks_.end()) { |
| 155 DLOG(ERROR) << "Gpu process sent invalid SignalAck."; | 143 LOG(ERROR) << "Gpu process sent invalid SignalAck."; |
| 156 InvalidGpuMessage(); | 144 OnGpuAsyncMessageError(gpu::error::kInvalidGpuMessage, |
| 145 gpu::error::kLostContext); |
| 157 return; | 146 return; |
| 158 } | 147 } |
| 159 base::Closure callback = it->second; | 148 base::Closure callback = it->second; |
| 160 signal_tasks_.erase(it); | 149 signal_tasks_.erase(it); |
| 161 callback.Run(); | 150 callback.Run(); |
| 162 } | 151 } |
| 163 | 152 |
| 164 bool CommandBufferProxyImpl::Initialize() { | 153 bool CommandBufferProxyImpl::Initialize() { |
| 165 TRACE_EVENT0("gpu", "CommandBufferProxyImpl::Initialize"); | 154 TRACE_EVENT0("gpu", "CommandBufferProxyImpl::Initialize"); |
| 166 shared_state_shm_.reset(channel_->factory() | 155 shared_state_shm_.reset(channel_->factory() |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 void CommandBufferProxyImpl::WaitForTokenInRange(int32_t start, int32_t end) { | 279 void CommandBufferProxyImpl::WaitForTokenInRange(int32_t start, int32_t end) { |
| 291 CheckLock(); | 280 CheckLock(); |
| 292 TRACE_EVENT2("gpu", "CommandBufferProxyImpl::WaitForToken", "start", start, | 281 TRACE_EVENT2("gpu", "CommandBufferProxyImpl::WaitForToken", "start", start, |
| 293 "end", end); | 282 "end", end); |
| 294 TryUpdateState(); | 283 TryUpdateState(); |
| 295 if (!InRange(start, end, last_state_.token) && | 284 if (!InRange(start, end, last_state_.token) && |
| 296 last_state_.error == gpu::error::kNoError) { | 285 last_state_.error == gpu::error::kNoError) { |
| 297 gpu::CommandBuffer::State state; | 286 gpu::CommandBuffer::State state; |
| 298 if (Send(new GpuCommandBufferMsg_WaitForTokenInRange(route_id_, start, end, | 287 if (Send(new GpuCommandBufferMsg_WaitForTokenInRange(route_id_, start, end, |
| 299 &state))) | 288 &state))) |
| 300 OnUpdateState(state); | 289 SetStateFromSyncReply(state); |
| 301 } | 290 } |
| 302 if (!InRange(start, end, last_state_.token) && | 291 if (!InRange(start, end, last_state_.token) && |
| 303 last_state_.error == gpu::error::kNoError) { | 292 last_state_.error == gpu::error::kNoError) { |
| 304 DLOG(ERROR) << "GPU state invalid after WaitForTokenInRange."; | 293 LOG(ERROR) << "GPU state invalid after WaitForTokenInRange."; |
| 305 InvalidGpuReply(); | 294 OnGpuSyncReplyError(); |
| 306 } | 295 } |
| 307 } | 296 } |
| 308 | 297 |
| 309 void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32_t start, | 298 void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32_t start, |
| 310 int32_t end) { | 299 int32_t end) { |
| 311 CheckLock(); | 300 CheckLock(); |
| 312 TRACE_EVENT2("gpu", "CommandBufferProxyImpl::WaitForGetOffset", "start", | 301 TRACE_EVENT2("gpu", "CommandBufferProxyImpl::WaitForGetOffset", "start", |
| 313 start, "end", end); | 302 start, "end", end); |
| 314 TryUpdateState(); | 303 TryUpdateState(); |
| 315 if (!InRange(start, end, last_state_.get_offset) && | 304 if (!InRange(start, end, last_state_.get_offset) && |
| 316 last_state_.error == gpu::error::kNoError) { | 305 last_state_.error == gpu::error::kNoError) { |
| 317 gpu::CommandBuffer::State state; | 306 gpu::CommandBuffer::State state; |
| 318 if (Send(new GpuCommandBufferMsg_WaitForGetOffsetInRange(route_id_, start, | 307 if (Send(new GpuCommandBufferMsg_WaitForGetOffsetInRange(route_id_, start, |
| 319 end, &state))) | 308 end, &state))) |
| 320 OnUpdateState(state); | 309 SetStateFromSyncReply(state); |
| 321 } | 310 } |
| 322 if (!InRange(start, end, last_state_.get_offset) && | 311 if (!InRange(start, end, last_state_.get_offset) && |
| 323 last_state_.error == gpu::error::kNoError) { | 312 last_state_.error == gpu::error::kNoError) { |
| 324 DLOG(ERROR) << "GPU state invalid after WaitForGetOffsetInRange."; | 313 LOG(ERROR) << "GPU state invalid after WaitForGetOffsetInRange."; |
| 325 InvalidGpuReply(); | 314 OnGpuSyncReplyError(); |
| 326 } | 315 } |
| 327 } | 316 } |
| 328 | 317 |
| 329 void CommandBufferProxyImpl::SetGetBuffer(int32_t shm_id) { | 318 void CommandBufferProxyImpl::SetGetBuffer(int32_t shm_id) { |
| 330 CheckLock(); | 319 CheckLock(); |
| 331 if (last_state_.error != gpu::error::kNoError) | 320 if (last_state_.error != gpu::error::kNoError) |
| 332 return; | 321 return; |
| 333 | 322 |
| 334 Send(new GpuCommandBufferMsg_SetGetBuffer(route_id_, shm_id)); | 323 Send(new GpuCommandBufferMsg_SetGetBuffer(route_id_, shm_id)); |
| 335 last_put_offset_ = -1; | 324 last_put_offset_ = -1; |
| 336 } | 325 } |
| 337 | 326 |
| 338 scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer( | 327 scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer( |
| 339 size_t size, | 328 size_t size, |
| 340 int32_t* id) { | 329 int32_t* id) { |
| 341 CheckLock(); | 330 CheckLock(); |
| 342 *id = -1; | 331 *id = -1; |
| 343 | 332 |
| 344 if (last_state_.error != gpu::error::kNoError) | 333 if (last_state_.error != gpu::error::kNoError) |
| 345 return NULL; | 334 return NULL; |
| 346 | 335 |
| 347 int32_t new_id = channel_->ReserveTransferBufferId(); | 336 int32_t new_id = channel_->ReserveTransferBufferId(); |
| 348 | 337 |
| 349 std::unique_ptr<base::SharedMemory> shared_memory( | 338 std::unique_ptr<base::SharedMemory> shared_memory( |
| 350 channel_->factory()->AllocateSharedMemory(size)); | 339 channel_->factory()->AllocateSharedMemory(size)); |
| 351 if (!shared_memory) { | 340 if (!shared_memory) { |
| 352 if (last_state_.error == gpu::error::kNoError) | 341 if (last_state_.error == gpu::error::kNoError) |
| 353 last_state_.error = gpu::error::kOutOfBounds; | 342 OnClientError(gpu::error::kOutOfBounds); |
| 354 return NULL; | 343 return NULL; |
| 355 } | 344 } |
| 356 | 345 |
| 357 DCHECK(!shared_memory->memory()); | 346 DCHECK(!shared_memory->memory()); |
| 358 if (!shared_memory->Map(size)) { | 347 if (!shared_memory->Map(size)) { |
| 359 if (last_state_.error == gpu::error::kNoError) | 348 if (last_state_.error == gpu::error::kNoError) |
| 360 last_state_.error = gpu::error::kOutOfBounds; | 349 OnClientError(gpu::error::kOutOfBounds); |
| 361 return NULL; | 350 return NULL; |
| 362 } | 351 } |
| 363 | 352 |
| 364 // This handle is owned by the GPU process and must be passed to it or it | 353 // This handle is owned by the GPU process and must be passed to it or it |
| 365 // will leak. In otherwords, do not early out on error between here and the | 354 // will leak. In otherwords, do not early out on error between here and the |
| 366 // sending of the RegisterTransferBuffer IPC below. | 355 // sending of the RegisterTransferBuffer IPC below. |
| 367 base::SharedMemoryHandle handle = | 356 base::SharedMemoryHandle handle = |
| 368 channel_->ShareToGpuProcess(shared_memory->handle()); | 357 channel_->ShareToGpuProcess(shared_memory->handle()); |
| 369 if (!base::SharedMemory::IsHandleValid(handle)) { | 358 if (!base::SharedMemory::IsHandleValid(handle)) { |
| 370 if (last_state_.error == gpu::error::kNoError) | 359 if (last_state_.error == gpu::error::kNoError) |
| 371 last_state_.error = gpu::error::kLostContext; | 360 OnClientError(gpu::error::kLostContext); |
| 372 return NULL; | 361 return NULL; |
| 373 } | 362 } |
| 374 | 363 |
| 375 Send(new GpuCommandBufferMsg_RegisterTransferBuffer(route_id_, new_id, handle, | 364 Send(new GpuCommandBufferMsg_RegisterTransferBuffer(route_id_, new_id, handle, |
| 376 size)); | 365 size)); |
| 377 *id = new_id; | 366 *id = new_id; |
| 378 scoped_refptr<gpu::Buffer> buffer( | 367 scoped_refptr<gpu::Buffer> buffer( |
| 379 gpu::MakeBufferFromSharedMemory(std::move(shared_memory), size)); | 368 gpu::MakeBufferFromSharedMemory(std::move(shared_memory), size)); |
| 380 return buffer; | 369 return buffer; |
| 381 } | 370 } |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 DLOG(ERROR) << "GpuCommandBufferMsg_CreateStreamTexture returned failure"; | 488 DLOG(ERROR) << "GpuCommandBufferMsg_CreateStreamTexture returned failure"; |
| 500 return 0; | 489 return 0; |
| 501 } | 490 } |
| 502 return stream_id; | 491 return stream_id; |
| 503 } | 492 } |
| 504 | 493 |
| 505 void CommandBufferProxyImpl::SetLock(base::Lock* lock) { | 494 void CommandBufferProxyImpl::SetLock(base::Lock* lock) { |
| 506 lock_ = lock; | 495 lock_ = lock; |
| 507 } | 496 } |
| 508 | 497 |
| 509 bool CommandBufferProxyImpl::IsGpuChannelLost() { | |
| 510 return !channel_ || channel_->IsLost(); | |
| 511 } | |
| 512 | |
| 513 void CommandBufferProxyImpl::EnsureWorkVisible() { | 498 void CommandBufferProxyImpl::EnsureWorkVisible() { |
| 514 if (channel_) | 499 if (channel_) |
| 515 channel_->ValidateFlushIDReachedServer(stream_id_, true); | 500 channel_->ValidateFlushIDReachedServer(stream_id_, true); |
| 516 } | 501 } |
| 517 | 502 |
| 518 gpu::CommandBufferNamespace CommandBufferProxyImpl::GetNamespaceID() const { | 503 gpu::CommandBufferNamespace CommandBufferProxyImpl::GetNamespaceID() const { |
| 519 return gpu::CommandBufferNamespace::GPU_IO; | 504 return gpu::CommandBufferNamespace::GPU_IO; |
| 520 } | 505 } |
| 521 | 506 |
| 522 gpu::CommandBufferId CommandBufferProxyImpl::GetCommandBufferID() const { | 507 gpu::CommandBufferId CommandBufferProxyImpl::GetCommandBufferID() const { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 return true; | 627 return true; |
| 643 } | 628 } |
| 644 | 629 |
| 645 if (channel_->Send(msg)) | 630 if (channel_->Send(msg)) |
| 646 return true; | 631 return true; |
| 647 | 632 |
| 648 // Flag the command buffer as lost. Defer deleting the channel until | 633 // Flag the command buffer as lost. Defer deleting the channel until |
| 649 // OnChannelError is called after returning to the message loop in case | 634 // OnChannelError is called after returning to the message loop in case |
| 650 // it is referenced elsewhere. | 635 // it is referenced elsewhere. |
| 651 DVLOG(1) << "CommandBufferProxyImpl::Send failed. Losing context."; | 636 DVLOG(1) << "CommandBufferProxyImpl::Send failed. Losing context."; |
| 652 last_state_.error = gpu::error::kLostContext; | 637 OnClientError(gpu::error::kLostContext); |
| 653 return false; | 638 return false; |
| 654 } | 639 } |
| 655 | 640 |
| 656 void CommandBufferProxyImpl::OnUpdateState( | 641 void CommandBufferProxyImpl::SetStateFromSyncReply( |
| 657 const gpu::CommandBuffer::State& state) { | 642 const gpu::CommandBuffer::State& state) { |
| 643 DCHECK(last_state_.error == gpu::error::kNoError); |
| 658 // Handle wraparound. It works as long as we don't have more than 2B state | 644 // Handle wraparound. It works as long as we don't have more than 2B state |
| 659 // updates in flight across which reordering occurs. | 645 // updates in flight across which reordering occurs. |
| 660 if (state.generation - last_state_.generation < 0x80000000U) | 646 if (state.generation - last_state_.generation < 0x80000000U) |
| 661 last_state_ = state; | 647 last_state_ = state; |
| 648 if (last_state_.error != gpu::error::kNoError) |
| 649 OnGpuStateError(); |
| 662 } | 650 } |
| 663 | 651 |
| 664 void CommandBufferProxyImpl::TryUpdateState() { | 652 void CommandBufferProxyImpl::TryUpdateState() { |
| 653 if (last_state_.error == gpu::error::kNoError) { |
| 654 shared_state()->Read(&last_state_); |
| 655 if (last_state_.error != gpu::error::kNoError) |
| 656 OnGpuStateError(); |
| 657 } |
| 658 } |
| 659 |
| 660 void CommandBufferProxyImpl::TryUpdateStateDontReportError() { |
| 665 if (last_state_.error == gpu::error::kNoError) | 661 if (last_state_.error == gpu::error::kNoError) |
| 666 shared_state()->Read(&last_state_); | 662 shared_state()->Read(&last_state_); |
| 667 } | 663 } |
| 668 | 664 |
| 669 void CommandBufferProxyImpl::UpdateVerifiedReleases(uint32_t verified_flush) { | 665 void CommandBufferProxyImpl::UpdateVerifiedReleases(uint32_t verified_flush) { |
| 670 while (!flushed_release_flush_id_.empty()) { | 666 while (!flushed_release_flush_id_.empty()) { |
| 671 const std::pair<uint64_t, uint32_t>& front_item = | 667 const std::pair<uint64_t, uint32_t>& front_item = |
| 672 flushed_release_flush_id_.front(); | 668 flushed_release_flush_id_.front(); |
| 673 if (front_item.second > verified_flush) | 669 if (front_item.second > verified_flush) |
| 674 break; | 670 break; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 695 swap_buffers_completion_callback_.Run(latency_info, result); | 691 swap_buffers_completion_callback_.Run(latency_info, result); |
| 696 } | 692 } |
| 697 } | 693 } |
| 698 | 694 |
| 699 void CommandBufferProxyImpl::OnUpdateVSyncParameters(base::TimeTicks timebase, | 695 void CommandBufferProxyImpl::OnUpdateVSyncParameters(base::TimeTicks timebase, |
| 700 base::TimeDelta interval) { | 696 base::TimeDelta interval) { |
| 701 if (!update_vsync_parameters_completion_callback_.is_null()) | 697 if (!update_vsync_parameters_completion_callback_.is_null()) |
| 702 update_vsync_parameters_completion_callback_.Run(timebase, interval); | 698 update_vsync_parameters_completion_callback_.Run(timebase, interval); |
| 703 } | 699 } |
| 704 | 700 |
| 705 void CommandBufferProxyImpl::InvalidGpuMessage() { | 701 void CommandBufferProxyImpl::OnGpuSyncReplyError() { |
| 706 LOG(ERROR) << "Received invalid message from the GPU process."; | 702 last_state_.error = gpu::error::kLostContext; |
| 707 OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext); | 703 last_state_.context_lost_reason = gpu::error::kInvalidGpuMessage; |
| 704 // This method may be inside a callstack from the GpuControlClient (we got a |
| 705 // bad reply to something we are sending to the GPU process). So avoid |
| 706 // re-entering the GpuControlClient here. |
| 707 DisconnectChannelInFreshCallStack(); |
| 708 } | 708 } |
| 709 | 709 |
| 710 void CommandBufferProxyImpl::InvalidGpuReply() { | 710 void CommandBufferProxyImpl::OnGpuAsyncMessageError( |
| 711 gpu::error::ContextLostReason reason, |
| 712 gpu::error::Error error) { |
| 711 CheckLock(); | 713 CheckLock(); |
| 712 LOG(ERROR) << "Received invalid reply from the GPU process."; | 714 last_state_.error = error; |
| 713 last_state_.error = gpu::error::kLostContext; | 715 last_state_.context_lost_reason = reason; |
| 714 last_state_.context_lost_reason = gpu::error::kInvalidGpuMessage; | 716 // This method only occurs when receiving IPC messages, so we know it's not in |
| 715 callback_thread_->PostTask( | 717 // a callstack from the GpuControlClient. |
| 716 FROM_HERE, | 718 DisconnectChannel(); |
| 717 base::Bind(&CommandBufferProxyImpl::InvalidGpuReplyOnClientThread, | |
| 718 weak_this_)); | |
| 719 } | 719 } |
| 720 | 720 |
| 721 void CommandBufferProxyImpl::InvalidGpuReplyOnClientThread() { | 721 void CommandBufferProxyImpl::OnGpuStateError() { |
| 722 std::unique_ptr<base::AutoLock> lock; | 722 DCHECK(last_state_.error != gpu::error::kNoError); |
| 723 // This method may be inside a callstack from the GpuControlClient (we |
| 724 // encountered an error while trying to perform some action). So avoid |
| 725 // re-entering the GpuControlClient here. |
| 726 DisconnectChannelInFreshCallStack(); |
| 727 } |
| 728 |
| 729 void CommandBufferProxyImpl::OnClientError(gpu::error::Error error) { |
| 730 CheckLock(); |
| 731 last_state_.error = error; |
| 732 last_state_.context_lost_reason = gpu::error::kUnknown; |
| 733 // This method may be inside a callstack from the GpuControlClient (we |
| 734 // encountered an error while trying to perform some action). So avoid |
| 735 // re-entering the GpuControlClient here. |
| 736 DisconnectChannelInFreshCallStack(); |
| 737 } |
| 738 |
| 739 void CommandBufferProxyImpl::DisconnectChannelInFreshCallStack() { |
| 740 CheckLock(); |
| 741 // Inform the GpuControlClient of the lost state immediately, though this may |
| 742 // be a re-entrant call to the client so we use the MaybeReentrant variant. |
| 743 if (gpu_control_client_) |
| 744 gpu_control_client_->OnGpuControlLostContextMaybeReentrant(); |
| 745 // Create a fresh call stack to keep the |channel_| alive while we unwind the |
| 746 // stack in case things will use it, and give the GpuChannelClient a chance to |
| 747 // act fully on the lost context. |
| 748 callback_thread_->PostTask( |
| 749 FROM_HERE, base::Bind(&CommandBufferProxyImpl::LockAndDisconnectChannel, |
| 750 weak_this_)); |
| 751 } |
| 752 |
| 753 void CommandBufferProxyImpl::LockAndDisconnectChannel() { |
| 754 base::Optional<base::AutoLock> hold; |
| 723 if (lock_) | 755 if (lock_) |
| 724 lock.reset(new base::AutoLock(*lock_)); | 756 hold.emplace(*lock_); |
| 725 OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext); | 757 DisconnectChannel(); |
| 758 } |
| 759 |
| 760 void CommandBufferProxyImpl::DisconnectChannel() { |
| 761 CheckLock(); |
| 762 // Prevent any further messages from being sent, and ensure we only call |
| 763 // the client for lost context a single time. |
| 764 if (!channel_) |
| 765 return; |
| 766 channel_->DestroyCommandBuffer(this); |
| 767 channel_ = nullptr; |
| 768 if (gpu_control_client_) |
| 769 gpu_control_client_->OnGpuControlLostContext(); |
| 726 } | 770 } |
| 727 | 771 |
| 728 } // namespace gpu | 772 } // namespace gpu |
| OLD | NEW |