Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / resources / zero_copy_raster_worker_pool.cc
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