Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / service / gpu_scheduler.cc
blobaa311b6b8231507a51d9672a4c17fe9a6641123e
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
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gpu_scheduler.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/compiler_specific.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/time/time.h"
12 #include "base/trace_event/trace_event.h"
13 #include "gpu/command_buffer/service/logger.h"
14 #include "ui/gl/gl_bindings.h"
15 #include "ui/gl/gl_fence.h"
16 #include "ui/gl/gl_switches.h"
18 using ::base::SharedMemory;
20 namespace gpu {
22 GpuScheduler::GpuScheduler(CommandBufferServiceBase* command_buffer,
23 AsyncAPIInterface* handler,
24 gles2::GLES2Decoder* decoder)
25 : command_buffer_(command_buffer),
26 handler_(handler),
27 decoder_(decoder),
28 scheduled_(true),
29 was_preempted_(false) {}
31 GpuScheduler::~GpuScheduler() {}
33 void GpuScheduler::PutChanged() {
34 TRACE_EVENT1(
35 "gpu", "GpuScheduler:PutChanged",
36 "decoder", decoder_ ? decoder_->GetLogger()->GetLogPrefix() : "None");
38 CommandBuffer::State state = command_buffer_->GetLastState();
40 // If there is no parser, exit.
41 if (!parser_.get()) {
42 DCHECK_EQ(state.get_offset, command_buffer_->GetPutOffset());
43 return;
46 parser_->set_put(command_buffer_->GetPutOffset());
47 if (state.error != error::kNoError)
48 return;
50 base::TimeTicks begin_time(base::TimeTicks::Now());
51 error::Error error = error::kNoError;
52 if (decoder_)
53 decoder_->BeginDecoding();
54 while (!parser_->IsEmpty()) {
55 if (IsPreempted())
56 break;
58 DCHECK(scheduled());
60 error = parser_->ProcessCommands(CommandParser::kParseCommandsSlice);
62 if (error == error::kDeferCommandUntilLater) {
63 DCHECK(!scheduled());
64 break;
67 // TODO(piman): various classes duplicate various pieces of state, leading
68 // to needlessly complex update logic. It should be possible to simply
69 // share the state across all of them.
70 command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
72 if (error::IsError(error)) {
73 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
74 command_buffer_->SetParseError(error);
75 break;
78 if (!command_processed_callback_.is_null())
79 command_processed_callback_.Run();
81 if (!scheduled())
82 break;
85 if (decoder_) {
86 if (!error::IsError(error) && decoder_->WasContextLost()) {
87 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
88 command_buffer_->SetParseError(error::kLostContext);
90 decoder_->EndDecoding();
91 decoder_->AddProcessingCommandsTime(base::TimeTicks::Now() - begin_time);
95 void GpuScheduler::SetScheduled(bool scheduled) {
96 TRACE_EVENT2("gpu", "GpuScheduler:SetScheduled", "this", this, "scheduled",
97 scheduled);
98 if (scheduled_ == scheduled)
99 return;
100 scheduled_ = scheduled;
101 if (!scheduling_changed_callback_.is_null())
102 scheduling_changed_callback_.Run(scheduled);
105 bool GpuScheduler::HasPendingQueries() const {
106 return (decoder_ && decoder_->HasPendingQueries());
109 void GpuScheduler::ProcessPendingQueries() {
110 if (!decoder_)
111 return;
112 decoder_->ProcessPendingQueries(false);
115 void GpuScheduler::SetSchedulingChangedCallback(
116 const SchedulingChangedCallback& callback) {
117 scheduling_changed_callback_ = callback;
120 scoped_refptr<Buffer> GpuScheduler::GetSharedMemoryBuffer(int32 shm_id) {
121 return command_buffer_->GetTransferBuffer(shm_id);
124 void GpuScheduler::set_token(int32 token) {
125 command_buffer_->SetToken(token);
128 bool GpuScheduler::SetGetBuffer(int32 transfer_buffer_id) {
129 scoped_refptr<Buffer> ring_buffer =
130 command_buffer_->GetTransferBuffer(transfer_buffer_id);
131 if (!ring_buffer.get()) {
132 return false;
135 if (!parser_.get()) {
136 parser_.reset(new CommandParser(handler_));
139 parser_->SetBuffer(
140 ring_buffer->memory(), ring_buffer->size(), 0, ring_buffer->size());
142 SetGetOffset(0);
143 return true;
146 bool GpuScheduler::SetGetOffset(int32 offset) {
147 if (parser_->set_get(offset)) {
148 command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
149 return true;
151 return false;
154 int32 GpuScheduler::GetGetOffset() {
155 return parser_->get();
158 void GpuScheduler::SetCommandProcessedCallback(
159 const base::Closure& callback) {
160 command_processed_callback_ = callback;
163 bool GpuScheduler::IsPreempted() {
164 if (!preemption_flag_.get())
165 return false;
167 if (!was_preempted_ && preemption_flag_->IsSet()) {
168 TRACE_COUNTER_ID1("gpu", "GpuScheduler::Preempted", this, 1);
169 was_preempted_ = true;
170 } else if (was_preempted_ && !preemption_flag_->IsSet()) {
171 TRACE_COUNTER_ID1("gpu", "GpuScheduler::Preempted", this, 0);
172 was_preempted_ = false;
175 return preemption_flag_->IsSet();
178 bool GpuScheduler::HasMoreIdleWork() const {
179 return (decoder_ && decoder_->HasMoreIdleWork());
182 void GpuScheduler::PerformIdleWork() {
183 if (!decoder_)
184 return;
185 decoder_->PerformIdleWork();
188 } // namespace gpu