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

Side by Side Diff: gpu/ipc/client/command_buffer_proxy_impl.cc

Issue 1916303003: Report lost context from GLES2Implementation based on share group state. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: lost-share-group: disconnect-channel Created 4 years, 7 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
« no previous file with comments | « gpu/ipc/client/command_buffer_proxy_impl.h ('k') | mojo/gles2/command_buffer_client_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « gpu/ipc/client/command_buffer_proxy_impl.h ('k') | mojo/gles2/command_buffer_client_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698