// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/resources/pixel_buffer_raster_worker_pool.h"

#include <algorithm>

#include "base/containers/stack_container.h"
#include "base/debug/trace_event.h"
#include "base/debug/trace_event_argument.h"
#include "base/strings/stringprintf.h"
#include "cc/debug/traced_value.h"
#include "cc/resources/raster_buffer.h"
#include "cc/resources/resource.h"
#include "gpu/command_buffer/client/gles2_interface.h"

namespace cc {
namespace {

class RasterBufferImpl : public RasterBuffer {
 public:
  RasterBufferImpl(ResourceProvider* resource_provider,
                   const Resource* resource)
      : resource_provider_(resource_provider),
        resource_(resource),
        memory_(NULL),
        stride_(0) {
    resource_provider_->AcquirePixelBuffer(resource_->id());
    memory_ = resource_provider_->MapPixelBuffer(resource_->id(), &stride_);
  }

  ~RasterBufferImpl() override {
    resource_provider_->ReleasePixelBuffer(resource_->id());
  }

  // Overridden from RasterBuffer:
  void Playback(const RasterSource* raster_source,
                const gfx::Rect& rect,
                float scale) override {
    if (!memory_)
      return;

    RasterWorkerPool::PlaybackToMemory(memory_, resource_->format(),
                                       resource_->size(), stride_,
                                       raster_source, rect, scale);
  }

 private:
  ResourceProvider* resource_provider_;
  const Resource* resource_;
  uint8_t* memory_;
  int stride_;

  DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
};

const int kCheckForCompletedRasterTasksDelayMs = 6;

const size_t kMaxScheduledRasterTasks = 48;

typedef base::StackVector<RasterTask*, kMaxScheduledRasterTasks>
    RasterTaskVector;

TaskSetCollection NonEmptyTaskSetsFromTaskCounts(const size_t* task_counts) {
  TaskSetCollection task_sets;
  for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    if (task_counts[task_set])
      task_sets[task_set] = true;
  }
  return task_sets;
}

void AddTaskSetsToTaskCounts(size_t* task_counts,
                             const TaskSetCollection& task_sets) {
  for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    if (task_sets[task_set])
      task_counts[task_set]++;
  }
}

void RemoveTaskSetsFromTaskCounts(size_t* task_counts,
                                  const TaskSetCollection& task_sets) {
  for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    if (task_sets[task_set])
      task_counts[task_set]--;
  }
}

}  // namespace

PixelBufferRasterWorkerPool::RasterTaskState::RasterTaskState(
    RasterTask* task,
    const TaskSetCollection& task_sets)
    : type(UNSCHEDULED), task(task), task_sets(task_sets) {
}

// static
scoped_ptr<RasterWorkerPool> PixelBufferRasterWorkerPool::Create(
    base::SequencedTaskRunner* task_runner,
    TaskGraphRunner* task_graph_runner,
    ContextProvider* context_provider,
    ResourceProvider* resource_provider,
    size_t max_transfer_buffer_usage_bytes) {
  return make_scoped_ptr<RasterWorkerPool>(
      new PixelBufferRasterWorkerPool(task_runner,
                                      task_graph_runner,
                                      context_provider,
                                      resource_provider,
                                      max_transfer_buffer_usage_bytes));
}

PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
    base::SequencedTaskRunner* task_runner,
    TaskGraphRunner* task_graph_runner,
    ContextProvider* context_provider,
    ResourceProvider* resource_provider,
    size_t max_transfer_buffer_usage_bytes)
    : task_runner_(task_runner),
      task_graph_runner_(task_graph_runner),
      namespace_token_(task_graph_runner->GetNamespaceToken()),
      context_provider_(context_provider),
      resource_provider_(resource_provider),
      shutdown_(false),
      scheduled_raster_task_count_(0u),
      bytes_pending_upload_(0u),
      max_bytes_pending_upload_(max_transfer_buffer_usage_bytes),
      has_performed_uploads_since_last_flush_(false),
      check_for_completed_raster_task_notifier_(
          task_runner,
          base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks,
                     base::Unretained(this)),
          base::TimeDelta::FromMilliseconds(
              kCheckForCompletedRasterTasksDelayMs)),
      raster_finished_weak_ptr_factory_(this) {
  DCHECK(context_provider_);
  std::fill(task_counts_, task_counts_ + kNumberOfTaskSets, 0);
}

PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
  DCHECK_EQ(0u, raster_task_states_.size());
  DCHECK_EQ(0u, raster_tasks_with_pending_upload_.size());
  DCHECK_EQ(0u, completed_raster_tasks_.size());
  DCHECK_EQ(0u, completed_image_decode_tasks_.size());
  DCHECK(NonEmptyTaskSetsFromTaskCounts(task_counts_).none());
}

Rasterizer* PixelBufferRasterWorkerPool::AsRasterizer() { return this; }

void PixelBufferRasterWorkerPool::SetClient(RasterizerClient* client) {
  client_ = client;
}

void PixelBufferRasterWorkerPool::Shutdown() {
  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::Shutdown");

  shutdown_ = true;

  TaskGraph empty;
  task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
  task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);

  CheckForCompletedRasterizerTasks();
  CheckForCompletedUploads();

  check_for_completed_raster_task_notifier_.Shutdown();

  for (RasterTaskState::Vector::iterator it = raster_task_states_.begin();
       it != raster_task_states_.end();
       ++it) {
    RasterTaskState& state = *it;

    // All unscheduled tasks need to be canceled.
    if (state.type == RasterTaskState::UNSCHEDULED) {
      completed_raster_tasks_.push_back(state.task);
      state.type = RasterTaskState::COMPLETED;
    }
  }
  DCHECK_EQ(completed_raster_tasks_.size(), raster_task_states_.size());
}

void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");

  if (should_notify_client_if_no_tasks_are_pending_.none())
    TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);

  should_notify_client_if_no_tasks_are_pending_.set();
  std::fill(task_counts_, task_counts_ + kNumberOfTaskSets, 0);

  // Update raster task state and remove items from old queue.
  for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
       it != queue->items.end();
       ++it) {
    const RasterTaskQueue::Item& item = *it;
    RasterTask* task = item.task;

    // Remove any old items that are associated with this task. The result is
    // that the old queue is left with all items not present in this queue,
    // which we use below to determine what tasks need to be canceled.
    RasterTaskQueue::Item::Vector::iterator old_it =
        std::find_if(raster_tasks_.items.begin(),
                     raster_tasks_.items.end(),
                     RasterTaskQueue::Item::TaskComparator(task));
    if (old_it != raster_tasks_.items.end()) {
      std::swap(*old_it, raster_tasks_.items.back());
      raster_tasks_.items.pop_back();
    }

    RasterTaskState::Vector::iterator state_it =
        std::find_if(raster_task_states_.begin(),
                     raster_task_states_.end(),
                     RasterTaskState::TaskComparator(task));
    if (state_it != raster_task_states_.end()) {
      RasterTaskState& state = *state_it;

      state.task_sets = item.task_sets;
      // |raster_tasks_required_for_activation_count| accounts for all tasks
      // that need to complete before we can send a "ready to activate" signal.
      // Tasks that have already completed should not be part of this count.
      if (state.type != RasterTaskState::COMPLETED)
        AddTaskSetsToTaskCounts(task_counts_, item.task_sets);

      continue;
    }

    DCHECK(!task->HasBeenScheduled());
    raster_task_states_.push_back(RasterTaskState(task, item.task_sets));
    AddTaskSetsToTaskCounts(task_counts_, item.task_sets);
  }

  // Determine what tasks in old queue need to be canceled.
  for (RasterTaskQueue::Item::Vector::const_iterator it =
           raster_tasks_.items.begin();
       it != raster_tasks_.items.end();
       ++it) {
    const RasterTaskQueue::Item& item = *it;
    RasterTask* task = item.task;

    RasterTaskState::Vector::iterator state_it =
        std::find_if(raster_task_states_.begin(),
                     raster_task_states_.end(),
                     RasterTaskState::TaskComparator(task));
    // We've already processed completion if we can't find a RasterTaskState for
    // this task.
    if (state_it == raster_task_states_.end())
      continue;

    RasterTaskState& state = *state_it;

    // Unscheduled task can be canceled.
    if (state.type == RasterTaskState::UNSCHEDULED) {
      DCHECK(!task->HasBeenScheduled());
      DCHECK(std::find(completed_raster_tasks_.begin(),
                       completed_raster_tasks_.end(),
                       task) == completed_raster_tasks_.end());
      completed_raster_tasks_.push_back(task);
      state.type = RasterTaskState::COMPLETED;
    }

    // No longer in any task set.
    state.task_sets.reset();
  }

  raster_tasks_.Swap(queue);

  // Check for completed tasks when ScheduleTasks() is called as
  // priorities might have changed and this maximizes the number
  // of top priority tasks that are scheduled.
  CheckForCompletedRasterizerTasks();
  CheckForCompletedUploads();
  FlushUploads();

  // Schedule new tasks.
  ScheduleMoreTasks();

  // Reschedule check for completed raster tasks.
  check_for_completed_raster_task_notifier_.Schedule();

  TRACE_EVENT_ASYNC_STEP_INTO1(
      "cc", "ScheduledTasks", this, StateName(), "state", StateAsValue());
}

void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");

  CheckForCompletedRasterizerTasks();
  CheckForCompletedUploads();
  FlushUploads();

  for (RasterizerTask::Vector::const_iterator it =
           completed_image_decode_tasks_.begin();
       it != completed_image_decode_tasks_.end();
       ++it) {
    RasterizerTask* task = it->get();
    task->RunReplyOnOriginThread();
  }
  completed_image_decode_tasks_.clear();

  for (RasterTask::Vector::const_iterator it = completed_raster_tasks_.begin();
       it != completed_raster_tasks_.end();
       ++it) {
    RasterTask* task = it->get();
    RasterTaskState::Vector::iterator state_it =
        std::find_if(raster_task_states_.begin(),
                     raster_task_states_.end(),
                     RasterTaskState::TaskComparator(task));
    DCHECK(state_it != raster_task_states_.end());
    DCHECK_EQ(RasterTaskState::COMPLETED, state_it->type);

    std::swap(*state_it, raster_task_states_.back());
    raster_task_states_.pop_back();

    task->RunReplyOnOriginThread();
  }
  completed_raster_tasks_.clear();
}

scoped_ptr<RasterBuffer> PixelBufferRasterWorkerPool::AcquireBufferForRaster(
    const Resource* resource) {
  return make_scoped_ptr<RasterBuffer>(
      new RasterBufferImpl(resource_provider_, resource));
}

void PixelBufferRasterWorkerPool::ReleaseBufferForRaster(
    scoped_ptr<RasterBuffer> buffer) {
  // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
}

void PixelBufferRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
  TRACE_EVENT2("cc",
               "PixelBufferRasterWorkerPool::OnRasterFinished",
               "task_set",
               task_set,
               "should_notify_client_if_no_tasks_are_pending",
               should_notify_client_if_no_tasks_are_pending_[task_set]);

  // There's no need to call CheckForCompletedRasterTasks() if the client has
  // already been notified.
  if (!should_notify_client_if_no_tasks_are_pending_[task_set])
    return;
  raster_finished_tasks_pending_[task_set] = false;

  // This reduces latency between the time when all tasks required for
  // activation have finished running and the time when the client is
  // notified.
  CheckForCompletedRasterTasks();
}

void PixelBufferRasterWorkerPool::FlushUploads() {
  if (!has_performed_uploads_since_last_flush_)
    return;

  context_provider_->ContextGL()->ShallowFlushCHROMIUM();
  has_performed_uploads_since_last_flush_ = false;
}

void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
  RasterTask::Vector tasks_with_completed_uploads;

  // First check if any have completed.
  while (!raster_tasks_with_pending_upload_.empty()) {
    RasterTask* task = raster_tasks_with_pending_upload_.front().get();
    DCHECK(std::find_if(raster_task_states_.begin(),
                        raster_task_states_.end(),
                        RasterTaskState::TaskComparator(task)) !=
           raster_task_states_.end());
    DCHECK_EQ(RasterTaskState::UPLOADING,
              std::find_if(raster_task_states_.begin(),
                           raster_task_states_.end(),
                           RasterTaskState::TaskComparator(task))->type);

    // Uploads complete in the order they are issued.
    if (!resource_provider_->DidSetPixelsComplete(task->resource()->id()))
      break;

    tasks_with_completed_uploads.push_back(task);
    raster_tasks_with_pending_upload_.pop_front();
  }

  DCHECK(client_);
  TaskSetCollection tasks_that_should_be_forced_to_complete =
      client_->TasksThatShouldBeForcedToComplete();
  bool should_force_some_uploads_to_complete =
      shutdown_ || tasks_that_should_be_forced_to_complete.any();

  if (should_force_some_uploads_to_complete) {
    RasterTask::Vector tasks_with_uploads_to_force;
    RasterTaskDeque::iterator it = raster_tasks_with_pending_upload_.begin();
    while (it != raster_tasks_with_pending_upload_.end()) {
      RasterTask* task = it->get();
      RasterTaskState::Vector::const_iterator state_it =
          std::find_if(raster_task_states_.begin(),
                       raster_task_states_.end(),
                       RasterTaskState::TaskComparator(task));
      DCHECK(state_it != raster_task_states_.end());
      const RasterTaskState& state = *state_it;

      // Force all uploads to complete for which the client requests to do so.
      // During shutdown, force all pending uploads to complete.
      if (shutdown_ ||
          (state.task_sets & tasks_that_should_be_forced_to_complete).any()) {
        tasks_with_uploads_to_force.push_back(task);
        tasks_with_completed_uploads.push_back(task);
        it = raster_tasks_with_pending_upload_.erase(it);
        continue;
      }

      ++it;
    }

    // Force uploads in reverse order. Since forcing can cause a wait on
    // all previous uploads, we would rather wait only once downstream.
    for (RasterTask::Vector::reverse_iterator it =
             tasks_with_uploads_to_force.rbegin();
         it != tasks_with_uploads_to_force.rend();
         ++it) {
      RasterTask* task = it->get();

      resource_provider_->ForceSetPixelsToComplete(task->resource()->id());
      has_performed_uploads_since_last_flush_ = true;
    }
  }

  // Release shared memory and move tasks with completed uploads
  // to |completed_raster_tasks_|.
  for (RasterTask::Vector::const_iterator it =
           tasks_with_completed_uploads.begin();
       it != tasks_with_completed_uploads.end();
       ++it) {
    RasterTask* task = it->get();
    RasterTaskState::Vector::iterator state_it =
        std::find_if(raster_task_states_.begin(),
                     raster_task_states_.end(),
                     RasterTaskState::TaskComparator(task));
    DCHECK(state_it != raster_task_states_.end());
    RasterTaskState& state = *state_it;

    bytes_pending_upload_ -= task->resource()->bytes();

    task->WillComplete();
    task->CompleteOnOriginThread(this);
    task->DidComplete();

    DCHECK(std::find(completed_raster_tasks_.begin(),
                     completed_raster_tasks_.end(),
                     task) == completed_raster_tasks_.end());
    completed_raster_tasks_.push_back(task);
    state.type = RasterTaskState::COMPLETED;
    // Triggers if the current task belongs to a set that should be empty.
    DCHECK((state.task_sets & ~NonEmptyTaskSetsFromTaskCounts(task_counts_))
               .none());
    RemoveTaskSetsFromTaskCounts(task_counts_, state.task_sets);
  }
}

void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
  TRACE_EVENT0("cc",
               "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");

  // Since this function can be called directly, cancel any pending checks.
  check_for_completed_raster_task_notifier_.Cancel();

  DCHECK(should_notify_client_if_no_tasks_are_pending_.any());

  CheckForCompletedRasterizerTasks();
  CheckForCompletedUploads();
  FlushUploads();

  // Determine what client notifications to generate.
  TaskSetCollection will_notify_client_that_no_tasks_are_pending =
      should_notify_client_if_no_tasks_are_pending_ &
      ~raster_finished_tasks_pending_ & ~PendingTasks();

  // Adjust the need to generate notifications before scheduling more tasks.
  should_notify_client_if_no_tasks_are_pending_ &=
      ~will_notify_client_that_no_tasks_are_pending;

  scheduled_raster_task_count_ = 0;
  if (PendingRasterTaskCount())
    ScheduleMoreTasks();

  TRACE_EVENT_ASYNC_STEP_INTO1(
      "cc", "ScheduledTasks", this, StateName(), "state", StateAsValue());

  // Schedule another check for completed raster tasks while there are
  // pending raster tasks or pending uploads.
  if (PendingTasks().any())
    check_for_completed_raster_task_notifier_.Schedule();

  if (should_notify_client_if_no_tasks_are_pending_.none())
    TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);

  // Generate client notifications.
  for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    if (will_notify_client_that_no_tasks_are_pending[task_set]) {
      DCHECK(!PendingTasks()[task_set]);
      client_->DidFinishRunningTasks(task_set);
    }
  }
}

void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");

  RasterTaskVector tasks[kNumberOfTaskSets];

  unsigned priority = kRasterTaskPriorityBase;

  graph_.Reset();

  size_t bytes_pending_upload = bytes_pending_upload_;
  TaskSetCollection did_throttle_raster_tasks;
  size_t scheduled_raster_task_count = 0;

  for (RasterTaskQueue::Item::Vector::const_iterator it =
           raster_tasks_.items.begin();
       it != raster_tasks_.items.end();
       ++it) {
    const RasterTaskQueue::Item& item = *it;
    RasterTask* task = item.task;
    DCHECK(item.task_sets.any());

    // |raster_task_states_| contains the state of all tasks that we have not
    // yet run reply callbacks for.
    RasterTaskState::Vector::iterator state_it =
        std::find_if(raster_task_states_.begin(),
                     raster_task_states_.end(),
                     RasterTaskState::TaskComparator(task));
    if (state_it == raster_task_states_.end())
      continue;

    RasterTaskState& state = *state_it;

    // Skip task if completed.
    if (state.type == RasterTaskState::COMPLETED) {
      DCHECK(std::find(completed_raster_tasks_.begin(),
                       completed_raster_tasks_.end(),
                       task) != completed_raster_tasks_.end());
      continue;
    }

    // All raster tasks need to be throttled by bytes of pending uploads,
    // but if it's the only task allow it to complete no matter what its size,
    // to prevent starvation of the task queue.
    size_t new_bytes_pending_upload = bytes_pending_upload;
    new_bytes_pending_upload += task->resource()->bytes();
    if (new_bytes_pending_upload > max_bytes_pending_upload_ &&
        bytes_pending_upload) {
      did_throttle_raster_tasks |= item.task_sets;
      continue;
    }

    // If raster has finished, just update |bytes_pending_upload|.
    if (state.type == RasterTaskState::UPLOADING) {
      DCHECK(!task->HasCompleted());
      bytes_pending_upload = new_bytes_pending_upload;
      continue;
    }

    // Throttle raster tasks based on kMaxScheduledRasterTasks.
    if (scheduled_raster_task_count >= kMaxScheduledRasterTasks) {
      did_throttle_raster_tasks |= item.task_sets;
      continue;
    }

    // Update |bytes_pending_upload| now that task has cleared all
    // throttling limits.
    bytes_pending_upload = new_bytes_pending_upload;

    DCHECK(state.type == RasterTaskState::UNSCHEDULED ||
           state.type == RasterTaskState::SCHEDULED);
    state.type = RasterTaskState::SCHEDULED;

    InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);

    ++scheduled_raster_task_count;
    for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
      if (item.task_sets[task_set])
        tasks[task_set].container().push_back(task);
    }
  }

  // Cancel existing OnRasterFinished callbacks.
  raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();

  scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
  size_t scheduled_task_counts[kNumberOfTaskSets] = {0};

  for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    scheduled_task_counts[task_set] = tasks[task_set].container().size();
    DCHECK_LE(scheduled_task_counts[task_set], task_counts_[task_set]);
    // Schedule OnRasterFinished call for task set only when notification is
    // pending and throttling is not preventing all pending tasks in the set
    // from being scheduled.
    if (!did_throttle_raster_tasks[task_set] &&
        should_notify_client_if_no_tasks_are_pending_[task_set]) {
      new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
          task_runner_.get(),
          base::Bind(&PixelBufferRasterWorkerPool::OnRasterFinished,
                     raster_finished_weak_ptr_factory_.GetWeakPtr(),
                     task_set));
      raster_finished_tasks_pending_[task_set] = true;
      InsertNodeForTask(&graph_,
                        new_raster_finished_tasks[task_set].get(),
                        kRasterFinishedTaskPriority,
                        scheduled_task_counts[task_set]);
      for (RasterTaskVector::ContainerType::const_iterator it =
               tasks[task_set].container().begin();
           it != tasks[task_set].container().end();
           ++it) {
        graph_.edges.push_back(
            TaskGraph::Edge(*it, new_raster_finished_tasks[task_set].get()));
      }
    }
  }

  DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());

  ScheduleTasksOnOriginThread(this, &graph_);
  task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);

  scheduled_raster_task_count_ = scheduled_raster_task_count;

  std::copy(new_raster_finished_tasks,
            new_raster_finished_tasks + kNumberOfTaskSets,
            raster_finished_tasks_);
}

unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
  unsigned num_completed_raster_tasks =
      raster_tasks_with_pending_upload_.size() + completed_raster_tasks_.size();
  DCHECK_GE(raster_task_states_.size(), num_completed_raster_tasks);
  return raster_task_states_.size() - num_completed_raster_tasks;
}

TaskSetCollection PixelBufferRasterWorkerPool::PendingTasks() const {
  return NonEmptyTaskSetsFromTaskCounts(task_counts_);
}

const char* PixelBufferRasterWorkerPool::StateName() const {
  if (scheduled_raster_task_count_)
    return "rasterizing";
  if (PendingRasterTaskCount())
    return "throttled";
  if (!raster_tasks_with_pending_upload_.empty())
    return "waiting_for_uploads";

  return "finishing";
}

void PixelBufferRasterWorkerPool::CheckForCompletedRasterizerTasks() {
  TRACE_EVENT0("cc",
               "PixelBufferRasterWorkerPool::CheckForCompletedRasterizerTasks");

  task_graph_runner_->CollectCompletedTasks(namespace_token_,
                                            &completed_tasks_);
  for (Task::Vector::const_iterator it = completed_tasks_.begin();
       it != completed_tasks_.end();
       ++it) {
    RasterizerTask* task = static_cast<RasterizerTask*>(it->get());

    RasterTask* raster_task = task->AsRasterTask();
    if (!raster_task) {
      task->WillComplete();
      task->CompleteOnOriginThread(this);
      task->DidComplete();

      completed_image_decode_tasks_.push_back(task);
      continue;
    }

    RasterTaskState::Vector::iterator state_it =
        std::find_if(raster_task_states_.begin(),
                     raster_task_states_.end(),
                     RasterTaskState::TaskComparator(raster_task));
    DCHECK(state_it != raster_task_states_.end());

    RasterTaskState& state = *state_it;
    DCHECK_EQ(RasterTaskState::SCHEDULED, state.type);

    resource_provider_->UnmapPixelBuffer(raster_task->resource()->id());

    if (!raster_task->HasFinishedRunning()) {
      // When priorites change, a raster task can be canceled as a result of
      // no longer being of high enough priority to fit in our throttled
      // raster task budget. The task has not yet completed in this case.
      raster_task->WillComplete();
      raster_task->CompleteOnOriginThread(this);
      raster_task->DidComplete();

      RasterTaskQueue::Item::Vector::const_iterator item_it =
          std::find_if(raster_tasks_.items.begin(),
                       raster_tasks_.items.end(),
                       RasterTaskQueue::Item::TaskComparator(raster_task));
      if (item_it != raster_tasks_.items.end()) {
        state.type = RasterTaskState::UNSCHEDULED;
        continue;
      }

      DCHECK(std::find(completed_raster_tasks_.begin(),
                       completed_raster_tasks_.end(),
                       raster_task) == completed_raster_tasks_.end());
      completed_raster_tasks_.push_back(raster_task);
      state.type = RasterTaskState::COMPLETED;
      // Triggers if the current task belongs to a set that should be empty.
      DCHECK((state.task_sets & ~NonEmptyTaskSetsFromTaskCounts(task_counts_))
                 .none());
      RemoveTaskSetsFromTaskCounts(task_counts_, state.task_sets);
      continue;
    }

    resource_provider_->BeginSetPixels(raster_task->resource()->id());
    has_performed_uploads_since_last_flush_ = true;

    bytes_pending_upload_ += raster_task->resource()->bytes();
    raster_tasks_with_pending_upload_.push_back(raster_task);
    state.type = RasterTaskState::UPLOADING;
  }
  completed_tasks_.clear();
}

scoped_refptr<base::debug::ConvertableToTraceFormat>
PixelBufferRasterWorkerPool::StateAsValue() const {
  scoped_refptr<base::debug::TracedValue> state =
      new base::debug::TracedValue();
  state->SetInteger("completed_count", completed_raster_tasks_.size());
  state->BeginArray("pending_count");
  for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
    state->AppendInteger(task_counts_[task_set]);
  state->EndArray();
  state->SetInteger("pending_upload_count",
                    raster_tasks_with_pending_upload_.size());
  state->BeginDictionary("throttle_state");
  ThrottleStateAsValueInto(state.get());
  state->EndDictionary();
  return state;
}

void PixelBufferRasterWorkerPool::ThrottleStateAsValueInto(
    base::debug::TracedValue* throttle_state) const {
  throttle_state->SetInteger("bytes_available_for_upload",
                             max_bytes_pending_upload_ - bytes_pending_upload_);
  throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
  throttle_state->SetInteger("scheduled_raster_task_count",
                             scheduled_raster_task_count_);
}

}  // namespace cc
