Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/in_process_command_buffer.h" | 5 #include "gpu/ipc/in_process_command_buffer.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <queue> | 10 #include <queue> |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 490 #if DCHECK_IS_ON() | 490 #if DCHECK_IS_ON() |
| 491 // This method shouldn't be called more than once. | 491 // This method shouldn't be called more than once. |
| 492 DCHECK(!context_lost_); | 492 DCHECK(!context_lost_); |
| 493 context_lost_ = true; | 493 context_lost_ = true; |
| 494 #endif | 494 #endif |
| 495 | 495 |
| 496 if (gpu_control_client_) | 496 if (gpu_control_client_) |
| 497 gpu_control_client_->OnGpuControlLostContext(); | 497 gpu_control_client_->OnGpuControlLostContext(); |
| 498 } | 498 } |
| 499 | 499 |
| 500 CommandBuffer::State InProcessCommandBuffer::GetStateFast() { | |
| 501 CheckSequencedThread(); | |
| 502 base::AutoLock lock(state_after_last_flush_lock_); | |
| 503 if (state_after_last_flush_.generation - last_state_.generation < 0x80000000U) | |
| 504 last_state_ = state_after_last_flush_; | |
| 505 return last_state_; | |
| 506 } | |
| 507 | |
| 508 void InProcessCommandBuffer::QueueTask(bool out_of_order, | 500 void InProcessCommandBuffer::QueueTask(bool out_of_order, |
| 509 const base::Closure& task) { | 501 const base::Closure& task) { |
| 510 if (out_of_order) { | 502 if (out_of_order) { |
| 511 service_->ScheduleTask(task); | 503 service_->ScheduleTask(task); |
| 512 return; | 504 return; |
| 513 } | 505 } |
| 514 // Release the |task_queue_lock_| before calling ScheduleTask because | 506 // Release the |task_queue_lock_| before calling ScheduleTask because |
| 515 // the callback may get called immediately and attempt to acquire the lock. | 507 // the callback may get called immediately and attempt to acquire the lock. |
| 516 SyncPointManager* sync_manager = service_->sync_point_manager(); | 508 SyncPointManager* sync_manager = service_->sync_point_manager(); |
| 517 uint32_t order_num = | 509 uint32_t order_num = |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 536 sync_point_order_data_->PauseProcessingOrderNumber(task->order_number); | 528 sync_point_order_data_->PauseProcessingOrderNumber(task->order_number); |
| 537 return; | 529 return; |
| 538 } | 530 } |
| 539 sync_point_order_data_->FinishProcessingOrderNumber(task->order_number); | 531 sync_point_order_data_->FinishProcessingOrderNumber(task->order_number); |
| 540 task_queue_.pop(); | 532 task_queue_.pop(); |
| 541 } | 533 } |
| 542 } | 534 } |
| 543 | 535 |
| 544 CommandBuffer::State InProcessCommandBuffer::GetLastState() { | 536 CommandBuffer::State InProcessCommandBuffer::GetLastState() { |
| 545 CheckSequencedThread(); | 537 CheckSequencedThread(); |
| 538 base::AutoLock lock(last_state_lock_); | |
| 546 return last_state_; | 539 return last_state_; |
| 547 } | 540 } |
| 548 | 541 |
| 549 int32_t InProcessCommandBuffer::GetLastToken() { | 542 void InProcessCommandBuffer::UpdateLastStateOnGpuThread() { |
| 550 CheckSequencedThread(); | 543 CheckSequencedThread(); |
| 551 GetStateFast(); | 544 command_buffer_lock_.AssertAcquired(); |
| 552 return last_state_.token; | 545 base::AutoLock lock(last_state_lock_); |
| 546 State state = command_buffer_->GetLastState(); | |
| 547 if (state.generation - last_state_.generation < 0x80000000U) | |
| 548 last_state_ = state; | |
| 553 } | 549 } |
| 554 | 550 |
| 555 void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset) { | 551 void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset) { |
| 556 CheckSequencedThread(); | 552 CheckSequencedThread(); |
| 557 ScopedEvent handle_flush(&flush_event_); | 553 ScopedEvent handle_flush(&flush_event_); |
| 558 base::AutoLock lock(command_buffer_lock_); | 554 base::AutoLock lock(command_buffer_lock_); |
| 559 | 555 |
| 560 { | 556 command_buffer_->Flush(put_offset); |
| 561 command_buffer_->Flush(put_offset); | 557 // Update state before signaling the flush event. |
| 562 { | 558 UpdateLastStateOnGpuThread(); |
| 563 // Update state before signaling the flush event. | |
| 564 base::AutoLock lock(state_after_last_flush_lock_); | |
| 565 state_after_last_flush_ = command_buffer_->GetLastState(); | |
| 566 } | |
| 567 } | |
| 568 | 559 |
| 569 // If we've processed all pending commands but still have pending queries, | 560 // If we've processed all pending commands but still have pending queries, |
| 570 // pump idle work until the query is passed. | 561 // pump idle work until the query is passed. |
| 571 if (put_offset == state_after_last_flush_.get_offset && | 562 if (put_offset == command_buffer_->GetLastState().get_offset && |
| 572 (executor_->HasMoreIdleWork() || executor_->HasPendingQueries())) { | 563 (executor_->HasMoreIdleWork() || executor_->HasPendingQueries())) { |
| 573 ScheduleDelayedWorkOnGpuThread(); | 564 ScheduleDelayedWorkOnGpuThread(); |
| 574 } | 565 } |
| 575 } | 566 } |
| 576 | 567 |
| 577 void InProcessCommandBuffer::PerformDelayedWorkOnGpuThread() { | 568 void InProcessCommandBuffer::PerformDelayedWorkOnGpuThread() { |
| 578 CheckSequencedThread(); | 569 CheckSequencedThread(); |
| 579 delayed_work_pending_ = false; | 570 delayed_work_pending_ = false; |
| 580 base::AutoLock lock(command_buffer_lock_); | 571 base::AutoLock lock(command_buffer_lock_); |
| 581 if (MakeCurrent()) { | 572 if (MakeCurrent()) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 592 if (delayed_work_pending_) | 583 if (delayed_work_pending_) |
| 593 return; | 584 return; |
| 594 delayed_work_pending_ = true; | 585 delayed_work_pending_ = true; |
| 595 service_->ScheduleDelayedWork( | 586 service_->ScheduleDelayedWork( |
| 596 base::Bind(&InProcessCommandBuffer::PerformDelayedWorkOnGpuThread, | 587 base::Bind(&InProcessCommandBuffer::PerformDelayedWorkOnGpuThread, |
| 597 gpu_thread_weak_ptr_)); | 588 gpu_thread_weak_ptr_)); |
| 598 } | 589 } |
| 599 | 590 |
| 600 void InProcessCommandBuffer::Flush(int32_t put_offset) { | 591 void InProcessCommandBuffer::Flush(int32_t put_offset) { |
| 601 CheckSequencedThread(); | 592 CheckSequencedThread(); |
| 602 if (last_state_.error != gpu::error::kNoError) | 593 if (GetLastState().error != gpu::error::kNoError) |
| 603 return; | 594 return; |
| 604 | 595 |
| 605 if (last_put_offset_ == put_offset) | 596 if (last_put_offset_ == put_offset) |
| 606 return; | 597 return; |
| 607 | 598 |
| 608 last_put_offset_ = put_offset; | 599 last_put_offset_ = put_offset; |
| 609 base::Closure task = base::Bind(&InProcessCommandBuffer::FlushOnGpuThread, | 600 base::Closure task = base::Bind(&InProcessCommandBuffer::FlushOnGpuThread, |
| 610 gpu_thread_weak_ptr_, put_offset); | 601 gpu_thread_weak_ptr_, put_offset); |
| 611 QueueTask(false, task); | 602 QueueTask(false, task); |
| 612 | 603 |
| 613 flushed_fence_sync_release_ = next_fence_sync_release_ - 1; | 604 flushed_fence_sync_release_ = next_fence_sync_release_ - 1; |
| 614 } | 605 } |
| 615 | 606 |
| 616 void InProcessCommandBuffer::OrderingBarrier(int32_t put_offset) { | 607 void InProcessCommandBuffer::OrderingBarrier(int32_t put_offset) { |
| 617 Flush(put_offset); | 608 Flush(put_offset); |
| 618 } | 609 } |
| 619 | 610 |
| 620 void InProcessCommandBuffer::WaitForTokenInRange(int32_t start, int32_t end) { | 611 CommandBuffer::State InProcessCommandBuffer::WaitForTokenInRange(int32_t start, |
| 612 int32_t end) { | |
| 621 CheckSequencedThread(); | 613 CheckSequencedThread(); |
| 622 while (!InRange(start, end, GetLastToken()) && | 614 State last_state = GetLastState(); |
| 623 last_state_.error == gpu::error::kNoError) { | 615 while (!InRange(start, end, last_state.token) && |
| 616 last_state.error == gpu::error::kNoError) { | |
| 624 flush_event_.Wait(); | 617 flush_event_.Wait(); |
| 618 last_state = GetLastState(); | |
| 625 } | 619 } |
| 620 return last_state; | |
| 626 } | 621 } |
| 627 | 622 |
| 628 void InProcessCommandBuffer::WaitForGetOffsetInRange(int32_t start, | 623 CommandBuffer::State InProcessCommandBuffer::WaitForGetOffsetInRange( |
| 629 int32_t end) { | 624 int32_t start, |
| 625 int32_t end) { | |
| 630 CheckSequencedThread(); | 626 CheckSequencedThread(); |
| 631 | 627 State last_state = GetLastState(); |
| 632 GetStateFast(); | 628 while (!InRange(start, end, last_state.get_offset) && |
| 633 while (!InRange(start, end, last_state_.get_offset) && | 629 last_state.error == gpu::error::kNoError) { |
| 634 last_state_.error == gpu::error::kNoError) { | |
| 635 flush_event_.Wait(); | 630 flush_event_.Wait(); |
| 636 GetStateFast(); | 631 last_state = GetLastState(); |
| 637 } | 632 } |
| 633 return last_state; | |
| 638 } | 634 } |
| 639 | 635 |
| 640 void InProcessCommandBuffer::SetGetBuffer(int32_t shm_id) { | 636 void InProcessCommandBuffer::SetGetBuffer(int32_t shm_id) { |
| 641 CheckSequencedThread(); | 637 CheckSequencedThread(); |
| 642 if (last_state_.error != gpu::error::kNoError) | 638 if (GetLastState().error != gpu::error::kNoError) |
| 643 return; | 639 return; |
| 644 | 640 |
| 645 base::WaitableEvent completion( | 641 base::WaitableEvent completion( |
| 646 base::WaitableEvent::ResetPolicy::MANUAL, | 642 base::WaitableEvent::ResetPolicy::MANUAL, |
| 647 base::WaitableEvent::InitialState::NOT_SIGNALED); | 643 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 648 base::Closure task = | 644 base::Closure task = |
| 649 base::Bind(&InProcessCommandBuffer::SetGetBufferOnGpuThread, | 645 base::Bind(&InProcessCommandBuffer::SetGetBufferOnGpuThread, |
| 650 base::Unretained(this), shm_id, &completion); | 646 base::Unretained(this), shm_id, &completion); |
| 651 QueueTask(false, task); | 647 QueueTask(false, task); |
| 652 completion.Wait(); | 648 completion.Wait(); |
| 653 | 649 |
| 654 { | 650 last_put_offset_ = 0; |
|
piman
2016/12/08 01:21:47
Nice catch!
| |
| 655 base::AutoLock lock(state_after_last_flush_lock_); | |
| 656 state_after_last_flush_ = command_buffer_->GetLastState(); | |
| 657 } | |
| 658 } | 651 } |
| 659 | 652 |
| 660 void InProcessCommandBuffer::SetGetBufferOnGpuThread( | 653 void InProcessCommandBuffer::SetGetBufferOnGpuThread( |
| 661 int32_t shm_id, | 654 int32_t shm_id, |
| 662 base::WaitableEvent* completion) { | 655 base::WaitableEvent* completion) { |
| 663 base::AutoLock lock(command_buffer_lock_); | 656 base::AutoLock lock(command_buffer_lock_); |
| 664 command_buffer_->SetGetBuffer(shm_id); | 657 command_buffer_->SetGetBuffer(shm_id); |
| 665 last_put_offset_ = 0; | 658 UpdateLastStateOnGpuThread(); |
| 666 completion->Signal(); | 659 completion->Signal(); |
| 667 } | 660 } |
| 668 | 661 |
| 669 scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer( | 662 scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer( |
| 670 size_t size, | 663 size_t size, |
| 671 int32_t* id) { | 664 int32_t* id) { |
| 672 CheckSequencedThread(); | 665 CheckSequencedThread(); |
| 673 base::AutoLock lock(command_buffer_lock_); | 666 base::AutoLock lock(command_buffer_lock_); |
| 674 return command_buffer_->CreateTransferBuffer(size, id); | 667 return command_buffer_->CreateTransferBuffer(size, id); |
| 675 } | 668 } |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1023 } | 1016 } |
| 1024 | 1017 |
| 1025 bool InProcessCommandBuffer::IsFenceSyncFlushed(uint64_t release) { | 1018 bool InProcessCommandBuffer::IsFenceSyncFlushed(uint64_t release) { |
| 1026 return release <= flushed_fence_sync_release_; | 1019 return release <= flushed_fence_sync_release_; |
| 1027 } | 1020 } |
| 1028 | 1021 |
| 1029 bool InProcessCommandBuffer::IsFenceSyncFlushReceived(uint64_t release) { | 1022 bool InProcessCommandBuffer::IsFenceSyncFlushReceived(uint64_t release) { |
| 1030 return IsFenceSyncFlushed(release); | 1023 return IsFenceSyncFlushed(release); |
| 1031 } | 1024 } |
| 1032 | 1025 |
| 1026 bool InProcessCommandBuffer::IsFenceSyncReleased(uint64_t release) { | |
| 1027 return release <= GetLastState().release_count; | |
| 1028 } | |
| 1029 | |
| 1033 void InProcessCommandBuffer::SignalSyncToken(const SyncToken& sync_token, | 1030 void InProcessCommandBuffer::SignalSyncToken(const SyncToken& sync_token, |
| 1034 const base::Closure& callback) { | 1031 const base::Closure& callback) { |
| 1035 CheckSequencedThread(); | 1032 CheckSequencedThread(); |
| 1036 QueueTask( | 1033 QueueTask( |
| 1037 true, | 1034 true, |
| 1038 base::Bind(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread, | 1035 base::Bind(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread, |
| 1039 base::Unretained(this), sync_token, WrapCallback(callback))); | 1036 base::Unretained(this), sync_token, WrapCallback(callback))); |
| 1040 } | 1037 } |
| 1041 | 1038 |
| 1042 bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken( | 1039 bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken( |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1125 void InProcessCommandBuffer::SetSwapBuffersCompletionCallback( | 1122 void InProcessCommandBuffer::SetSwapBuffersCompletionCallback( |
| 1126 const SwapBuffersCompletionCallback& callback) { | 1123 const SwapBuffersCompletionCallback& callback) { |
| 1127 swap_buffers_completion_callback_ = callback; | 1124 swap_buffers_completion_callback_ = callback; |
| 1128 } | 1125 } |
| 1129 | 1126 |
| 1130 void InProcessCommandBuffer::SetUpdateVSyncParametersCallback( | 1127 void InProcessCommandBuffer::SetUpdateVSyncParametersCallback( |
| 1131 const UpdateVSyncParametersCallback& callback) { | 1128 const UpdateVSyncParametersCallback& callback) { |
| 1132 update_vsync_parameters_completion_callback_ = callback; | 1129 update_vsync_parameters_completion_callback_ = callback; |
| 1133 } | 1130 } |
| 1134 | 1131 |
| 1135 gpu::error::Error InProcessCommandBuffer::GetLastError() { | |
| 1136 CheckSequencedThread(); | |
| 1137 return last_state_.error; | |
| 1138 } | |
| 1139 | |
| 1140 namespace { | 1132 namespace { |
| 1141 | 1133 |
| 1142 void PostCallback( | 1134 void PostCallback( |
| 1143 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 1135 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 1144 const base::Closure& callback) { | 1136 const base::Closure& callback) { |
| 1145 // The task_runner.get() check is to support using InProcessCommandBuffer on | 1137 // The task_runner.get() check is to support using InProcessCommandBuffer on |
| 1146 // a thread without a message loop. | 1138 // a thread without a message loop. |
| 1147 if (task_runner.get() && !task_runner->BelongsToCurrentThread()) { | 1139 if (task_runner.get() && !task_runner->BelongsToCurrentThread()) { |
| 1148 task_runner->PostTask(FROM_HERE, callback); | 1140 task_runner->PostTask(FROM_HERE, callback); |
| 1149 } else { | 1141 } else { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1173 return wrapped_callback; | 1165 return wrapped_callback; |
| 1174 } | 1166 } |
| 1175 | 1167 |
| 1176 InProcessCommandBuffer::GpuTask::GpuTask(const base::Closure& callback, | 1168 InProcessCommandBuffer::GpuTask::GpuTask(const base::Closure& callback, |
| 1177 uint32_t order_number) | 1169 uint32_t order_number) |
| 1178 : callback(callback), order_number(order_number) {} | 1170 : callback(callback), order_number(order_number) {} |
| 1179 | 1171 |
| 1180 InProcessCommandBuffer::GpuTask::~GpuTask() {} | 1172 InProcessCommandBuffer::GpuTask::~GpuTask() {} |
| 1181 | 1173 |
| 1182 } // namespace gpu | 1174 } // namespace gpu |
| OLD | NEW |