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"
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
;
22 GpuScheduler::GpuScheduler(CommandBufferServiceBase
* command_buffer
,
23 AsyncAPIInterface
* handler
,
24 gles2::GLES2Decoder
* decoder
)
25 : command_buffer_(command_buffer
),
29 was_preempted_(false) {}
31 GpuScheduler::~GpuScheduler() {}
33 void GpuScheduler::PutChanged() {
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.
42 DCHECK_EQ(state
.get_offset
, command_buffer_
->GetPutOffset());
46 parser_
->set_put(command_buffer_
->GetPutOffset());
47 if (state
.error
!= error::kNoError
)
50 base::TimeTicks
begin_time(base::TimeTicks::Now());
51 error::Error error
= error::kNoError
;
53 decoder_
->BeginDecoding();
54 while (!parser_
->IsEmpty()) {
60 error
= parser_
->ProcessCommands(CommandParser::kParseCommandsSlice
);
62 if (error
== error::kDeferCommandUntilLater
) {
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
);
78 if (!command_processed_callback_
.is_null())
79 command_processed_callback_
.Run();
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",
98 if (scheduled_
== scheduled
)
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() {
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()) {
135 if (!parser_
.get()) {
136 parser_
.reset(new CommandParser(handler_
));
140 ring_buffer
->memory(), ring_buffer
->size(), 0, ring_buffer
->size());
146 bool GpuScheduler::SetGetOffset(int32 offset
) {
147 if (parser_
->set_get(offset
)) {
148 command_buffer_
->SetGetOffset(static_cast<int32
>(parser_
->get()));
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())
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() {
185 decoder_
->PerformIdleWork();