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