| Index: gpu/command_buffer/service/gpu_scheduler.cc
 | 
| ===================================================================
 | 
| --- gpu/command_buffer/service/gpu_scheduler.cc	(revision 92876)
 | 
| +++ gpu/command_buffer/service/gpu_scheduler.cc	(working copy)
 | 
| @@ -19,41 +19,37 @@
 | 
|  
 | 
|  namespace gpu {
 | 
|  
 | 
| -GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
 | 
| -                           SurfaceManager* surface_manager,
 | 
| -                           gles2::ContextGroup* group)
 | 
| -    : command_buffer_(command_buffer),
 | 
| -      commands_per_update_(100),
 | 
| -      unscheduled_count_(0),
 | 
| -#if defined(OS_MACOSX) || defined(TOUCH_UI)
 | 
| -      swap_buffers_count_(0),
 | 
| -      acknowledged_swap_buffers_count_(0),
 | 
| -#endif
 | 
| -      method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
 | 
| +GpuScheduler* GpuScheduler::Create(CommandBuffer* command_buffer,
 | 
| +                                   SurfaceManager* surface_manager,
 | 
| +                                   gles2::ContextGroup* group) {
 | 
|    DCHECK(command_buffer);
 | 
| -  decoder_.reset(gles2::GLES2Decoder::Create(surface_manager, group));
 | 
| -  decoder_->set_engine(this);
 | 
| +
 | 
| +  gles2::GLES2Decoder* decoder =
 | 
| +      gles2::GLES2Decoder::Create(surface_manager, group);
 | 
| +
 | 
| +  GpuScheduler* scheduler = new GpuScheduler(command_buffer,
 | 
| +                                             decoder,
 | 
| +                                             NULL);
 | 
| +
 | 
| +  decoder->set_engine(scheduler);
 | 
| +
 | 
|    if (CommandLine::ForCurrentProcess()->HasSwitch(
 | 
|        switches::kEnableGPUServiceLogging)) {
 | 
| -    decoder_->set_debug(true);
 | 
| +    decoder->set_debug(true);
 | 
|    }
 | 
| +
 | 
| +  return scheduler;
 | 
|  }
 | 
|  
 | 
| -GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
 | 
| -                           gles2::GLES2Decoder* decoder,
 | 
| -                           CommandParser* parser,
 | 
| -                           int commands_per_update)
 | 
| -    : command_buffer_(command_buffer),
 | 
| -      commands_per_update_(commands_per_update),
 | 
| -      unscheduled_count_(0),
 | 
| -#if defined(OS_MACOSX) || defined(TOUCH_UI)
 | 
| -      swap_buffers_count_(0),
 | 
| -      acknowledged_swap_buffers_count_(0),
 | 
| -#endif
 | 
| -      method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
 | 
| +GpuScheduler* GpuScheduler::CreateForTests(CommandBuffer* command_buffer,
 | 
| +                                           gles2::GLES2Decoder* decoder,
 | 
| +                                           CommandParser* parser) {
 | 
|    DCHECK(command_buffer);
 | 
| -  decoder_.reset(decoder);
 | 
| -  parser_.reset(parser);
 | 
| +  GpuScheduler* scheduler = new GpuScheduler(command_buffer,
 | 
| +                                             decoder,
 | 
| +                                             parser);
 | 
| +
 | 
| +  return scheduler;
 | 
|  }
 | 
|  
 | 
|  GpuScheduler::~GpuScheduler() {
 | 
| @@ -82,11 +78,6 @@
 | 
|    }
 | 
|  #endif
 | 
|  
 | 
| -  // Do not limit to a certain number of commands before scheduling another
 | 
| -  // update when rendering onscreen.
 | 
| -  if (!surface->IsOffscreen())
 | 
| -    commands_per_update_ = INT_MAX;
 | 
| -
 | 
|    // Map the ring buffer and create the parser.
 | 
|    Buffer ring_buffer = command_buffer_->GetRingBuffer();
 | 
|    if (ring_buffer.ptr) {
 | 
| @@ -144,29 +135,16 @@
 | 
|  }
 | 
|  #endif
 | 
|  
 | 
| -void GpuScheduler::PutChanged(bool sync) {
 | 
| +void GpuScheduler::PutChanged() {
 | 
|    TRACE_EVENT1("gpu", "GpuScheduler:PutChanged", "this", this);
 | 
| -  CommandBuffer::State state = command_buffer_->GetState();
 | 
| -  parser_->set_put(state.put_offset);
 | 
|  
 | 
| -  if (sync)
 | 
| -    ProcessCommands();
 | 
| -  else
 | 
| -    ScheduleProcessCommands();
 | 
| -}
 | 
| +  DCHECK(IsScheduled());
 | 
|  
 | 
| -void GpuScheduler::ProcessCommands() {
 | 
| -  TRACE_EVENT1("gpu", "GpuScheduler:ProcessCommands", "this", this);
 | 
|    CommandBuffer::State state = command_buffer_->GetState();
 | 
| +  parser_->set_put(state.put_offset);
 | 
|    if (state.error != error::kNoError)
 | 
|      return;
 | 
|  
 | 
| -  if (unscheduled_count_ > 0) {
 | 
| -    TRACE_EVENT1("gpu", "EarlyOut_Unscheduled",
 | 
| -                 "unscheduled_count_", unscheduled_count_);
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
|    if (decoder_.get()) {
 | 
|      if (!decoder_->MakeCurrent()) {
 | 
|        LOG(ERROR) << "Context lost because MakeCurrent failed.";
 | 
| @@ -184,60 +162,30 @@
 | 
|  
 | 
|  #if defined(OS_MACOSX) || defined(TOUCH_UI)
 | 
|    // Don't swamp the browser process with SwapBuffers calls it can't handle.
 | 
| -  if (do_rate_limiting &&
 | 
| -      swap_buffers_count_ - acknowledged_swap_buffers_count_ >=
 | 
| -      kMaxOutstandingSwapBuffersCallsPerOnscreenContext) {
 | 
| -    TRACE_EVENT0("gpu", "EarlyOut_OSX_Throttle");
 | 
| -    // Stop doing work on this command buffer. In the GPU process,
 | 
| -    // receipt of the GpuMsg_AcceleratedSurfaceBuffersSwappedACK
 | 
| -    // message causes ProcessCommands to be scheduled again.
 | 
| -    return;
 | 
| -  }
 | 
| +  DCHECK(!do_rate_limiting ||
 | 
| +         swap_buffers_count_ - acknowledged_swap_buffers_count_ == 0);
 | 
|  #endif
 | 
|  
 | 
| -  base::TimeTicks start_time = base::TimeTicks::Now();
 | 
| -  base::TimeDelta elapsed;
 | 
| -  bool is_break = false;
 | 
|    error::Error error = error::kNoError;
 | 
| -  do {
 | 
| -    int commands_processed = 0;
 | 
| -    while (commands_processed < commands_per_update_ &&
 | 
| -           !parser_->IsEmpty()) {
 | 
| -      error = parser_->ProcessCommand();
 | 
| +  while (!parser_->IsEmpty()) {
 | 
| +    error = parser_->ProcessCommand();
 | 
|  
 | 
| -      // TODO(piman): various classes duplicate various pieces of state, leading
 | 
| -      // to needlessly complex update logic. It should be possible to simply
 | 
| -      // share the state across all of them.
 | 
| -      command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
 | 
| +    // TODO(piman): various classes duplicate various pieces of state, leading
 | 
| +    // to needlessly complex update logic. It should be possible to simply
 | 
| +    // share the state across all of them.
 | 
| +    command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
 | 
|  
 | 
| -      if (error == error::kWaiting || error == error::kYield) {
 | 
| -        is_break = true;
 | 
| -        break;
 | 
| -      } else if (error::IsError(error)) {
 | 
| -        command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
 | 
| -        command_buffer_->SetParseError(error);
 | 
| -        return;
 | 
| -      }
 | 
| -
 | 
| -      if (unscheduled_count_ > 0) {
 | 
| -        is_break = true;
 | 
| -        break;
 | 
| -      }
 | 
| -
 | 
| -      ++commands_processed;
 | 
| -      if (command_processed_callback_.get()) {
 | 
| -        command_processed_callback_->Run();
 | 
| -      }
 | 
| +    if (error::IsError(error)) {
 | 
| +      command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
 | 
| +      command_buffer_->SetParseError(error);
 | 
| +      return;
 | 
|      }
 | 
| -    elapsed = base::TimeTicks::Now() - start_time;
 | 
| -  } while(!is_break &&
 | 
| -          !parser_->IsEmpty() &&
 | 
| -          elapsed.InMicroseconds() < kMinimumSchedulerQuantumMicros);
 | 
|  
 | 
| -  if (unscheduled_count_ == 0 &&
 | 
| -      error != error::kWaiting &&
 | 
| -      !parser_->IsEmpty()) {
 | 
| -    ScheduleProcessCommands();
 | 
| +    if (command_processed_callback_.get())
 | 
| +      command_processed_callback_->Run();
 | 
| +
 | 
| +    if (unscheduled_count_ > 0)
 | 
| +      return;
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -249,12 +197,8 @@
 | 
|      --unscheduled_count_;
 | 
|      DCHECK_GE(unscheduled_count_, 0);
 | 
|  
 | 
| -    if (unscheduled_count_ == 0) {
 | 
| -      if (scheduled_callback_.get())
 | 
| -        scheduled_callback_->Run();
 | 
| -
 | 
| -      ScheduleProcessCommands();
 | 
| -    }
 | 
| +    if (unscheduled_count_ == 0 && scheduled_callback_.get())
 | 
| +      scheduled_callback_->Run();
 | 
|    } else {
 | 
|      ++unscheduled_count_;
 | 
|    }
 | 
| @@ -320,10 +264,18 @@
 | 
|    set_token_callback_ = callback;
 | 
|  }
 | 
|  
 | 
| -void GpuScheduler::ScheduleProcessCommands() {
 | 
| -  MessageLoop::current()->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      method_factory_.NewRunnableMethod(&GpuScheduler::ProcessCommands));
 | 
| +GpuScheduler::GpuScheduler(CommandBuffer* command_buffer,
 | 
| +                           gles2::GLES2Decoder* decoder,
 | 
| +                           CommandParser* parser)
 | 
| +    : command_buffer_(command_buffer),
 | 
| +      decoder_(decoder),
 | 
| +      parser_(parser),
 | 
| +      unscheduled_count_(0),
 | 
| +#if defined(OS_MACOSX) || defined(TOUCH_UI)
 | 
| +      swap_buffers_count_(0),
 | 
| +      acknowledged_swap_buffers_count_(0),
 | 
| +#endif
 | 
| +      method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
 | 
|  }
 | 
|  
 | 
|  void GpuScheduler::WillResize(gfx::Size size) {
 | 
| 
 |