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/zero_copy_raster_worker_pool.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/debug/trace_event.h"
     10 #include "base/debug/trace_event_argument.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "cc/debug/traced_value.h"
     13 #include "cc/resources/raster_buffer.h"
     14 #include "cc/resources/resource.h"
     15 #include "third_party/skia/include/utils/SkNullCanvas.h"
     16 
     17 namespace cc {
     18 namespace {
     19 
     20 class RasterBufferImpl : public RasterBuffer {
     21  public:
     22   RasterBufferImpl(ResourceProvider* resource_provider,
     23                    const Resource* resource)
     24       : resource_provider_(resource_provider),
     25         resource_(resource),
     26         stride_(0),
     27         buffer_(resource_provider->MapImage(resource->id(), &stride_)) {}
     28 
     29   virtual ~RasterBufferImpl() {
     30     resource_provider_->UnmapImage(resource_->id());
     31 
     32     // This RasterBuffer implementation provides direct access to the memory
     33     // used by the GPU. Read lock fences are required to ensure that we're not
     34     // trying to map a resource that is currently in-use by the GPU.
     35     resource_provider_->EnableReadLockFences(resource_->id());
     36   }
     37 
     38   // Overridden from RasterBuffer:
     39   virtual skia::RefPtr<SkCanvas> AcquireSkCanvas() OVERRIDE {
     40     if (!buffer_)
     41       return skia::AdoptRef(SkCreateNullCanvas());
     42 
     43     RasterWorkerPool::AcquireBitmapForBuffer(
     44         &bitmap_, buffer_, resource_->format(), resource_->size(), stride_);
     45     return skia::AdoptRef(new SkCanvas(bitmap_));
     46   }
     47   virtual void ReleaseSkCanvas(const skia::RefPtr<SkCanvas>& canvas) OVERRIDE {
     48     if (!buffer_)
     49       return;
     50 
     51     RasterWorkerPool::ReleaseBitmapForBuffer(
     52         &bitmap_, buffer_, resource_->format());
     53   }
     54 
     55  private:
     56   ResourceProvider* resource_provider_;
     57   const Resource* resource_;
     58   int stride_;
     59   uint8_t* buffer_;
     60   SkBitmap bitmap_;
     61 
     62   DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
     63 };
     64 
     65 }  // namespace
     66 
     67 // static
     68 scoped_ptr<RasterWorkerPool> ZeroCopyRasterWorkerPool::Create(
     69     base::SequencedTaskRunner* task_runner,
     70     TaskGraphRunner* task_graph_runner,
     71     ResourceProvider* resource_provider) {
     72   return make_scoped_ptr<RasterWorkerPool>(new ZeroCopyRasterWorkerPool(
     73       task_runner, task_graph_runner, resource_provider));
     74 }
     75 
     76 ZeroCopyRasterWorkerPool::ZeroCopyRasterWorkerPool(
     77     base::SequencedTaskRunner* task_runner,
     78     TaskGraphRunner* task_graph_runner,
     79     ResourceProvider* resource_provider)
     80     : task_runner_(task_runner),
     81       task_graph_runner_(task_graph_runner),
     82       namespace_token_(task_graph_runner->GetNamespaceToken()),
     83       resource_provider_(resource_provider),
     84       raster_finished_weak_ptr_factory_(this) {
     85 }
     86 
     87 ZeroCopyRasterWorkerPool::~ZeroCopyRasterWorkerPool() {
     88 }
     89 
     90 Rasterizer* ZeroCopyRasterWorkerPool::AsRasterizer() {
     91   return this;
     92 }
     93 
     94 void ZeroCopyRasterWorkerPool::SetClient(RasterizerClient* client) {
     95   client_ = client;
     96 }
     97 
     98 void ZeroCopyRasterWorkerPool::Shutdown() {
     99   TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::Shutdown");
    100 
    101   TaskGraph empty;
    102   task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
    103   task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
    104 }
    105 
    106 void ZeroCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
    107   TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::ScheduleTasks");
    108 
    109   if (raster_pending_.none())
    110     TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
    111 
    112   // Mark all task sets as pending.
    113   raster_pending_.set();
    114 
    115   unsigned priority = kRasterTaskPriorityBase;
    116 
    117   graph_.Reset();
    118 
    119   // Cancel existing OnRasterFinished callbacks.
    120   raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
    121 
    122   scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
    123 
    124   size_t task_count[kNumberOfTaskSets] = {0};
    125 
    126   for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    127     new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
    128         task_runner_.get(),
    129         base::Bind(&ZeroCopyRasterWorkerPool::OnRasterFinished,
    130                    raster_finished_weak_ptr_factory_.GetWeakPtr(),
    131                    task_set));
    132   }
    133 
    134   for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
    135        it != queue->items.end();
    136        ++it) {
    137     const RasterTaskQueue::Item& item = *it;
    138     RasterTask* task = item.task;
    139     DCHECK(!task->HasCompleted());
    140 
    141     for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    142       if (!item.task_sets[task_set])
    143         continue;
    144 
    145       ++task_count[task_set];
    146 
    147       graph_.edges.push_back(
    148           TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get()));
    149     }
    150 
    151     InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
    152   }
    153 
    154   for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
    155     InsertNodeForTask(&graph_,
    156                       new_raster_finished_tasks[task_set].get(),
    157                       kRasterFinishedTaskPriority,
    158                       task_count[task_set]);
    159   }
    160 
    161   ScheduleTasksOnOriginThread(this, &graph_);
    162   task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
    163 
    164   std::copy(new_raster_finished_tasks,
    165             new_raster_finished_tasks + kNumberOfTaskSets,
    166             raster_finished_tasks_);
    167 
    168   TRACE_EVENT_ASYNC_STEP_INTO1(
    169       "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
    170 }
    171 
    172 void ZeroCopyRasterWorkerPool::CheckForCompletedTasks() {
    173   TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::CheckForCompletedTasks");
    174 
    175   task_graph_runner_->CollectCompletedTasks(namespace_token_,
    176                                             &completed_tasks_);
    177   for (Task::Vector::const_iterator it = completed_tasks_.begin();
    178        it != completed_tasks_.end();
    179        ++it) {
    180     RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
    181 
    182     task->WillComplete();
    183     task->CompleteOnOriginThread(this);
    184     task->DidComplete();
    185 
    186     task->RunReplyOnOriginThread();
    187   }
    188   completed_tasks_.clear();
    189 }
    190 
    191 scoped_ptr<RasterBuffer> ZeroCopyRasterWorkerPool::AcquireBufferForRaster(
    192     const Resource* resource) {
    193   // RasterBuffer implementation depends on an image having been acquired for
    194   // the resource.
    195   resource_provider_->AcquireImage(resource->id());
    196 
    197   return make_scoped_ptr<RasterBuffer>(
    198       new RasterBufferImpl(resource_provider_, resource));
    199 }
    200 
    201 void ZeroCopyRasterWorkerPool::ReleaseBufferForRaster(
    202     scoped_ptr<RasterBuffer> buffer) {
    203   // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
    204 }
    205 
    206 void ZeroCopyRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
    207   TRACE_EVENT1(
    208       "cc", "ZeroCopyRasterWorkerPool::OnRasterFinished", "task_set", task_set);
    209 
    210   DCHECK(raster_pending_[task_set]);
    211   raster_pending_[task_set] = false;
    212   if (raster_pending_.any()) {
    213     TRACE_EVENT_ASYNC_STEP_INTO1(
    214         "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
    215   } else {
    216     TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
    217   }
    218   client_->DidFinishRunningTasks(task_set);
    219 }
    220 
    221 scoped_refptr<base::debug::ConvertableToTraceFormat>
    222 ZeroCopyRasterWorkerPool::StateAsValue() const {
    223   scoped_refptr<base::debug::TracedValue> state =
    224       new base::debug::TracedValue();
    225 
    226   state->BeginArray("tasks_pending");
    227   for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
    228     state->AppendBoolean(raster_pending_[task_set]);
    229   state->EndArray();
    230   return state;
    231 }
    232 
    233 }  // namespace cc
    234