Home | History | Annotate | Download | only in resources
      1 // Copyright 2013 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.
      4 
      5 #include "cc/resources/image_raster_worker_pool.h"
      6 
      7 #include "base/debug/trace_event.h"
      8 #include "base/values.h"
      9 #include "cc/debug/traced_value.h"
     10 #include "cc/resources/resource.h"
     11 #include "third_party/skia/include/core/SkDevice.h"
     12 
     13 namespace cc {
     14 
     15 namespace {
     16 
     17 class ImageWorkerPoolTaskImpl : public internal::WorkerPoolTask {
     18  public:
     19   typedef base::Callback<void(bool was_canceled)> Reply;
     20 
     21   ImageWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task,
     22                           uint8_t* buffer,
     23                           int stride,
     24                           const Reply& reply)
     25       : task_(task),
     26         buffer_(buffer),
     27         stride_(stride),
     28         reply_(reply) {
     29   }
     30 
     31   // Overridden from internal::WorkerPoolTask:
     32   virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
     33     TRACE_EVENT0("cc", "ImageWorkerPoolTaskImpl::RunOnWorkerThread");
     34     if (!buffer_)
     35       return;
     36 
     37     SkBitmap bitmap;
     38     bitmap.setConfig(SkBitmap::kARGB_8888_Config,
     39                      task_->resource()->size().width(),
     40                      task_->resource()->size().height(),
     41                      stride_);
     42     bitmap.setPixels(buffer_);
     43     SkDevice device(bitmap);
     44     task_->RunOnWorkerThread(&device, thread_index);
     45   }
     46   virtual void CompleteOnOriginThread() OVERRIDE {
     47     reply_.Run(!HasFinishedRunning());
     48   }
     49 
     50  private:
     51   virtual ~ImageWorkerPoolTaskImpl() {}
     52 
     53   scoped_refptr<internal::RasterWorkerPoolTask> task_;
     54   uint8_t* buffer_;
     55   int stride_;
     56   const Reply reply_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(ImageWorkerPoolTaskImpl);
     59 };
     60 
     61 }  // namespace
     62 
     63 ImageRasterWorkerPool::ImageRasterWorkerPool(
     64     ResourceProvider* resource_provider, size_t num_threads)
     65     : RasterWorkerPool(resource_provider, num_threads),
     66       raster_tasks_pending_(false),
     67       raster_tasks_required_for_activation_pending_(false) {
     68 }
     69 
     70 ImageRasterWorkerPool::~ImageRasterWorkerPool() {
     71   DCHECK_EQ(0u, image_tasks_.size());
     72 }
     73 
     74 void ImageRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
     75   TRACE_EVENT0("cc", "ImageRasterWorkerPool::ScheduleTasks");
     76 
     77   RasterWorkerPool::SetRasterTasks(queue);
     78 
     79   if (!raster_tasks_pending_)
     80     TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
     81 
     82   raster_tasks_pending_ = true;
     83   raster_tasks_required_for_activation_pending_ = true;
     84 
     85   unsigned priority = 0u;
     86   TaskGraph graph;
     87 
     88   scoped_refptr<internal::WorkerPoolTask>
     89       new_raster_required_for_activation_finished_task(
     90           CreateRasterRequiredForActivationFinishedTask());
     91   internal::GraphNode* raster_required_for_activation_finished_node =
     92       CreateGraphNodeForTask(
     93           new_raster_required_for_activation_finished_task.get(),
     94           priority++,
     95           &graph);
     96 
     97   scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task(
     98       CreateRasterFinishedTask());
     99   internal::GraphNode* raster_finished_node =
    100       CreateGraphNodeForTask(new_raster_finished_task.get(),
    101                              priority++,
    102                              &graph);
    103 
    104   for (RasterTaskVector::const_iterator it = raster_tasks().begin();
    105        it != raster_tasks().end(); ++it) {
    106     internal::RasterWorkerPoolTask* task = it->get();
    107 
    108     TaskMap::iterator image_it = image_tasks_.find(task);
    109     if (image_it != image_tasks_.end()) {
    110       internal::WorkerPoolTask* image_task = image_it->second.get();
    111       CreateGraphNodeForImageTask(
    112           image_task,
    113           task->dependencies(),
    114           priority++,
    115           IsRasterTaskRequiredForActivation(task),
    116           raster_required_for_activation_finished_node,
    117           raster_finished_node,
    118           &graph);
    119       continue;
    120     }
    121 
    122     // Acquire image for resource.
    123     resource_provider()->AcquireImage(task->resource()->id());
    124 
    125     // Map image for raster.
    126     uint8* buffer = resource_provider()->MapImage(task->resource()->id());
    127     int stride = resource_provider()->GetImageStride(task->resource()->id());
    128 
    129     scoped_refptr<internal::WorkerPoolTask> new_image_task(
    130         new ImageWorkerPoolTaskImpl(
    131             task,
    132             buffer,
    133             stride,
    134             base::Bind(&ImageRasterWorkerPool::OnRasterTaskCompleted,
    135                        base::Unretained(this),
    136                        make_scoped_refptr(task))));
    137     image_tasks_[task] = new_image_task;
    138     CreateGraphNodeForImageTask(
    139         new_image_task.get(),
    140         task->dependencies(),
    141         priority++,
    142         IsRasterTaskRequiredForActivation(task),
    143         raster_required_for_activation_finished_node,
    144         raster_finished_node,
    145         &graph);
    146   }
    147 
    148   SetTaskGraph(&graph);
    149 
    150   set_raster_finished_task(new_raster_finished_task);
    151   set_raster_required_for_activation_finished_task(
    152       new_raster_required_for_activation_finished_task);
    153 
    154   TRACE_EVENT_ASYNC_STEP1(
    155       "cc", "ScheduledTasks", this, "rasterizing",
    156       "state", TracedValue::FromValue(StateAsValue().release()));
    157 }
    158 
    159 void ImageRasterWorkerPool::OnRasterTasksFinished() {
    160   DCHECK(raster_tasks_pending_);
    161   raster_tasks_pending_ = false;
    162   TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
    163   client()->DidFinishRunningTasks();
    164 }
    165 
    166 void ImageRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
    167   DCHECK(raster_tasks_required_for_activation_pending_);
    168   raster_tasks_required_for_activation_pending_ = false;
    169   TRACE_EVENT_ASYNC_STEP1(
    170       "cc", "ScheduledTasks", this, "rasterizing",
    171       "state", TracedValue::FromValue(StateAsValue().release()));
    172   client()->DidFinishRunningTasksRequiredForActivation();
    173 }
    174 
    175 void ImageRasterWorkerPool::OnRasterTaskCompleted(
    176     scoped_refptr<internal::RasterWorkerPoolTask> task,
    177     bool was_canceled) {
    178   TRACE_EVENT1("cc", "ImageRasterWorkerPool::OnRasterTaskCompleted",
    179                "was_canceled", was_canceled);
    180 
    181   DCHECK(image_tasks_.find(task.get()) != image_tasks_.end());
    182 
    183   // Balanced with MapImage() call in ScheduleTasks().
    184   resource_provider()->UnmapImage(task->resource()->id());
    185 
    186   task->DidRun(was_canceled);
    187   task->WillComplete();
    188   task->CompleteOnOriginThread();
    189   task->DidComplete();
    190 
    191   image_tasks_.erase(task.get());
    192 }
    193 
    194 scoped_ptr<base::Value> ImageRasterWorkerPool::StateAsValue() const {
    195   scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
    196 
    197   state->SetBoolean("tasks_required_for_activation_pending",
    198                     raster_tasks_required_for_activation_pending_);
    199   state->Set("scheduled_state", ScheduledStateAsValue().release());
    200   return state.PassAs<base::Value>();
    201 }
    202 
    203 // static
    204 void ImageRasterWorkerPool::CreateGraphNodeForImageTask(
    205     internal::WorkerPoolTask* image_task,
    206     const TaskVector& decode_tasks,
    207     unsigned priority,
    208     bool is_required_for_activation,
    209     internal::GraphNode* raster_required_for_activation_finished_node,
    210     internal::GraphNode* raster_finished_node,
    211     TaskGraph* graph) {
    212   internal::GraphNode* image_node = CreateGraphNodeForRasterTask(image_task,
    213                                                                  decode_tasks,
    214                                                                  priority,
    215                                                                  graph);
    216 
    217   if (is_required_for_activation) {
    218     raster_required_for_activation_finished_node->add_dependency();
    219     image_node->add_dependent(raster_required_for_activation_finished_node);
    220   }
    221 
    222   raster_finished_node->add_dependency();
    223   image_node->add_dependent(raster_finished_node);
    224 }
    225 
    226 }  // namespace cc
    227