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

Side by Side Diff: gpu/command_buffer/service/gpu_scheduler.cc

Issue 7458010: Revert 93066 - Execute all GL commands up to the put offset reported by a each flush.This means g... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/command_buffer/service/gpu_scheduler.h" 5 #include "gpu/command_buffer/service/gpu_scheduler.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/time.h" 12 #include "base/time.h"
13 #include "ui/gfx/gl/gl_context.h" 13 #include "ui/gfx/gl/gl_context.h"
14 #include "ui/gfx/gl/gl_bindings.h" 14 #include "ui/gfx/gl/gl_bindings.h"
15 #include "ui/gfx/gl/gl_surface.h" 15 #include "ui/gfx/gl/gl_surface.h"
16 #include "ui/gfx/gl/gl_switches.h" 16 #include "ui/gfx/gl/gl_switches.h"
17 17
18 using ::base::SharedMemory; 18 using ::base::SharedMemory;
19 19
20 namespace gpu { 20 namespace gpu {
21 21
22 GpuScheduler* GpuScheduler::Create(CommandBuffer* command_buffer, 22 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
23 SurfaceManager* surface_manager, 23 SurfaceManager* surface_manager,
24 gles2::ContextGroup* group) { 24 gles2::ContextGroup* group)
25 : command_buffer_(command_buffer),
26 commands_per_update_(100),
27 unscheduled_count_(0),
28 #if defined(OS_MACOSX) || defined(TOUCH_UI)
29 swap_buffers_count_(0),
30 acknowledged_swap_buffers_count_(0),
31 #endif
32 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
25 DCHECK(command_buffer); 33 DCHECK(command_buffer);
26 34 decoder_.reset(gles2::GLES2Decoder::Create(surface_manager, group));
27 gles2::GLES2Decoder* decoder = 35 decoder_->set_engine(this);
28 gles2::GLES2Decoder::Create(surface_manager, group);
29
30 GpuScheduler* scheduler = new GpuScheduler(command_buffer,
31 decoder,
32 NULL);
33
34 decoder->set_engine(scheduler);
35
36 if (CommandLine::ForCurrentProcess()->HasSwitch( 36 if (CommandLine::ForCurrentProcess()->HasSwitch(
37 switches::kEnableGPUServiceLogging)) { 37 switches::kEnableGPUServiceLogging)) {
38 decoder->set_debug(true); 38 decoder_->set_debug(true);
39 } 39 }
40
41 return scheduler;
42 } 40 }
43 41
44 GpuScheduler* GpuScheduler::CreateForTests(CommandBuffer* command_buffer, 42 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
45 gles2::GLES2Decoder* decoder, 43 gles2::GLES2Decoder* decoder,
46 CommandParser* parser) { 44 CommandParser* parser,
45 int commands_per_update)
46 : command_buffer_(command_buffer),
47 commands_per_update_(commands_per_update),
48 unscheduled_count_(0),
49 #if defined(OS_MACOSX) || defined(TOUCH_UI)
50 swap_buffers_count_(0),
51 acknowledged_swap_buffers_count_(0),
52 #endif
53 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
47 DCHECK(command_buffer); 54 DCHECK(command_buffer);
48 GpuScheduler* scheduler = new GpuScheduler(command_buffer, 55 decoder_.reset(decoder);
49 decoder, 56 parser_.reset(parser);
50 parser);
51
52 return scheduler;
53 } 57 }
54 58
55 GpuScheduler::~GpuScheduler() { 59 GpuScheduler::~GpuScheduler() {
56 Destroy(); 60 Destroy();
57 } 61 }
58 62
59 bool GpuScheduler::InitializeCommon( 63 bool GpuScheduler::InitializeCommon(
60 const scoped_refptr<gfx::GLSurface>& surface, 64 const scoped_refptr<gfx::GLSurface>& surface,
61 const scoped_refptr<gfx::GLContext>& context, 65 const scoped_refptr<gfx::GLContext>& context,
62 const gfx::Size& size, 66 const gfx::Size& size,
63 const gles2::DisallowedExtensions& disallowed_extensions, 67 const gles2::DisallowedExtensions& disallowed_extensions,
64 const char* allowed_extensions, 68 const char* allowed_extensions,
65 const std::vector<int32>& attribs) { 69 const std::vector<int32>& attribs) {
66 DCHECK(context); 70 DCHECK(context);
67 71
68 if (!context->MakeCurrent(surface)) 72 if (!context->MakeCurrent(surface))
69 return false; 73 return false;
70 74
71 #if !defined(OS_MACOSX) 75 #if !defined(OS_MACOSX)
72 // Set up swap interval for onscreen contexts. 76 // Set up swap interval for onscreen contexts.
73 if (!surface->IsOffscreen()) { 77 if (!surface->IsOffscreen()) {
74 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) 78 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
75 context->SetSwapInterval(0); 79 context->SetSwapInterval(0);
76 else 80 else
77 context->SetSwapInterval(1); 81 context->SetSwapInterval(1);
78 } 82 }
79 #endif 83 #endif
80 84
85 // Do not limit to a certain number of commands before scheduling another
86 // update when rendering onscreen.
87 if (!surface->IsOffscreen())
88 commands_per_update_ = INT_MAX;
89
81 // Map the ring buffer and create the parser. 90 // Map the ring buffer and create the parser.
82 Buffer ring_buffer = command_buffer_->GetRingBuffer(); 91 Buffer ring_buffer = command_buffer_->GetRingBuffer();
83 if (ring_buffer.ptr) { 92 if (ring_buffer.ptr) {
84 parser_.reset(new CommandParser(ring_buffer.ptr, 93 parser_.reset(new CommandParser(ring_buffer.ptr,
85 ring_buffer.size, 94 ring_buffer.size,
86 0, 95 0,
87 ring_buffer.size, 96 ring_buffer.size,
88 0, 97 0,
89 decoder_.get())); 98 decoder_.get()));
90 } else { 99 } else {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 else 137 else
129 return decoder_->SetParent(NULL, 0); 138 return decoder_->SetParent(NULL, 0);
130 } 139 }
131 140
132 #if defined(OS_MACOSX) || defined(TOUCH_UI) 141 #if defined(OS_MACOSX) || defined(TOUCH_UI)
133 namespace { 142 namespace {
134 const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1; 143 const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1;
135 } 144 }
136 #endif 145 #endif
137 146
138 void GpuScheduler::PutChanged() { 147 void GpuScheduler::PutChanged(bool sync) {
139 TRACE_EVENT1("gpu", "GpuScheduler:PutChanged", "this", this); 148 TRACE_EVENT1("gpu", "GpuScheduler:PutChanged", "this", this);
140
141 DCHECK(IsScheduled());
142
143 CommandBuffer::State state = command_buffer_->GetState(); 149 CommandBuffer::State state = command_buffer_->GetState();
144 parser_->set_put(state.put_offset); 150 parser_->set_put(state.put_offset);
151
152 if (sync)
153 ProcessCommands();
154 else
155 ScheduleProcessCommands();
156 }
157
158 void GpuScheduler::ProcessCommands() {
159 TRACE_EVENT1("gpu", "GpuScheduler:ProcessCommands", "this", this);
160 CommandBuffer::State state = command_buffer_->GetState();
145 if (state.error != error::kNoError) 161 if (state.error != error::kNoError)
146 return; 162 return;
147 163
164 if (unscheduled_count_ > 0) {
165 TRACE_EVENT1("gpu", "EarlyOut_Unscheduled",
166 "unscheduled_count_", unscheduled_count_);
167 return;
168 }
169
148 if (decoder_.get()) { 170 if (decoder_.get()) {
149 if (!decoder_->MakeCurrent()) { 171 if (!decoder_->MakeCurrent()) {
150 LOG(ERROR) << "Context lost because MakeCurrent failed."; 172 LOG(ERROR) << "Context lost because MakeCurrent failed.";
151 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); 173 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
152 command_buffer_->SetParseError(error::kLostContext); 174 command_buffer_->SetParseError(error::kLostContext);
153 return; 175 return;
154 } 176 }
155 } 177 }
156 178
157 #if defined(OS_MACOSX) 179 #if defined(OS_MACOSX)
158 bool do_rate_limiting = surface_.get() != NULL; 180 bool do_rate_limiting = surface_.get() != NULL;
159 #elif defined(TOUCH_UI) 181 #elif defined(TOUCH_UI)
160 bool do_rate_limiting = back_surface_.get() != NULL; 182 bool do_rate_limiting = back_surface_.get() != NULL;
161 #endif 183 #endif
162 184
163 #if defined(OS_MACOSX) || defined(TOUCH_UI) 185 #if defined(OS_MACOSX) || defined(TOUCH_UI)
164 // Don't swamp the browser process with SwapBuffers calls it can't handle. 186 // Don't swamp the browser process with SwapBuffers calls it can't handle.
165 DCHECK(!do_rate_limiting || 187 if (do_rate_limiting &&
166 swap_buffers_count_ - acknowledged_swap_buffers_count_ == 0); 188 swap_buffers_count_ - acknowledged_swap_buffers_count_ >=
189 kMaxOutstandingSwapBuffersCallsPerOnscreenContext) {
190 TRACE_EVENT0("gpu", "EarlyOut_OSX_Throttle");
191 // Stop doing work on this command buffer. In the GPU process,
192 // receipt of the GpuMsg_AcceleratedSurfaceBuffersSwappedACK
193 // message causes ProcessCommands to be scheduled again.
194 return;
195 }
167 #endif 196 #endif
168 197
198 base::TimeTicks start_time = base::TimeTicks::Now();
199 base::TimeDelta elapsed;
200 bool is_break = false;
169 error::Error error = error::kNoError; 201 error::Error error = error::kNoError;
170 while (!parser_->IsEmpty()) { 202 do {
171 error = parser_->ProcessCommand(); 203 int commands_processed = 0;
204 while (commands_processed < commands_per_update_ &&
205 !parser_->IsEmpty()) {
206 error = parser_->ProcessCommand();
172 207
173 // TODO(piman): various classes duplicate various pieces of state, leading 208 // TODO(piman): various classes duplicate various pieces of state, leading
174 // to needlessly complex update logic. It should be possible to simply 209 // to needlessly complex update logic. It should be possible to simply
175 // share the state across all of them. 210 // share the state across all of them.
176 command_buffer_->SetGetOffset(static_cast<int32>(parser_->get())); 211 command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
177 212
178 if (error::IsError(error)) { 213 if (error == error::kWaiting || error == error::kYield) {
179 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); 214 is_break = true;
180 command_buffer_->SetParseError(error); 215 break;
181 return; 216 } else if (error::IsError(error)) {
217 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
218 command_buffer_->SetParseError(error);
219 return;
220 }
221
222 if (unscheduled_count_ > 0) {
223 is_break = true;
224 break;
225 }
226
227 ++commands_processed;
228 if (command_processed_callback_.get()) {
229 command_processed_callback_->Run();
230 }
182 } 231 }
232 elapsed = base::TimeTicks::Now() - start_time;
233 } while(!is_break &&
234 !parser_->IsEmpty() &&
235 elapsed.InMicroseconds() < kMinimumSchedulerQuantumMicros);
183 236
184 if (command_processed_callback_.get()) 237 if (unscheduled_count_ == 0 &&
185 command_processed_callback_->Run(); 238 error != error::kWaiting &&
186 239 !parser_->IsEmpty()) {
187 if (unscheduled_count_ > 0) 240 ScheduleProcessCommands();
188 return;
189 } 241 }
190 } 242 }
191 243
192 void GpuScheduler::SetScheduled(bool scheduled) { 244 void GpuScheduler::SetScheduled(bool scheduled) {
193 TRACE_EVENT2("gpu", "GpuScheduler:SetScheduled", "this", this, 245 TRACE_EVENT2("gpu", "GpuScheduler:SetScheduled", "this", this,
194 "new unscheduled_count_", 246 "new unscheduled_count_",
195 unscheduled_count_ + (scheduled? -1 : 1)); 247 unscheduled_count_ + (scheduled? -1 : 1));
196 if (scheduled) { 248 if (scheduled) {
197 --unscheduled_count_; 249 --unscheduled_count_;
198 DCHECK_GE(unscheduled_count_, 0); 250 DCHECK_GE(unscheduled_count_, 0);
199 251
200 if (unscheduled_count_ == 0 && scheduled_callback_.get()) 252 if (unscheduled_count_ == 0) {
201 scheduled_callback_->Run(); 253 if (scheduled_callback_.get())
254 scheduled_callback_->Run();
255
256 ScheduleProcessCommands();
257 }
202 } else { 258 } else {
203 ++unscheduled_count_; 259 ++unscheduled_count_;
204 } 260 }
205 } 261 }
206 262
207 bool GpuScheduler::IsScheduled() { 263 bool GpuScheduler::IsScheduled() {
208 return unscheduled_count_ == 0; 264 return unscheduled_count_ == 0;
209 } 265 }
210 266
211 void GpuScheduler::SetScheduledCallback(Callback0::Type* scheduled_callback) { 267 void GpuScheduler::SetScheduledCallback(Callback0::Type* scheduled_callback) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 Callback0::Type* callback) { 313 Callback0::Type* callback) {
258 command_processed_callback_.reset(callback); 314 command_processed_callback_.reset(callback);
259 } 315 }
260 316
261 void GpuScheduler::SetTokenCallback( 317 void GpuScheduler::SetTokenCallback(
262 const base::Callback<void(int32)>& callback) { 318 const base::Callback<void(int32)>& callback) {
263 DCHECK(set_token_callback_.is_null()); 319 DCHECK(set_token_callback_.is_null());
264 set_token_callback_ = callback; 320 set_token_callback_ = callback;
265 } 321 }
266 322
267 GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, 323 void GpuScheduler::ScheduleProcessCommands() {
268 gles2::GLES2Decoder* decoder, 324 MessageLoop::current()->PostTask(
269 CommandParser* parser) 325 FROM_HERE,
270 : command_buffer_(command_buffer), 326 method_factory_.NewRunnableMethod(&GpuScheduler::ProcessCommands));
271 decoder_(decoder),
272 parser_(parser),
273 unscheduled_count_(0),
274 #if defined(OS_MACOSX) || defined(TOUCH_UI)
275 swap_buffers_count_(0),
276 acknowledged_swap_buffers_count_(0),
277 #endif
278 method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
279 } 327 }
280 328
281 void GpuScheduler::WillResize(gfx::Size size) { 329 void GpuScheduler::WillResize(gfx::Size size) {
282 if (wrapped_resize_callback_.get()) { 330 if (wrapped_resize_callback_.get()) {
283 wrapped_resize_callback_->Run(size); 331 wrapped_resize_callback_->Run(size);
284 } 332 }
285 } 333 }
286 334
287 } // namespace gpu 335 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/gpu_scheduler.h ('k') | gpu/command_buffer/service/gpu_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698