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.
5 #include "cc/resources/zero_copy_raster_worker_pool.h"
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"
20 class RasterBufferImpl : public RasterBuffer {
22 RasterBufferImpl(ResourceProvider* resource_provider,
23 const Resource* resource)
24 : resource_provider_(resource_provider),
27 buffer_(resource_provider->MapImage(resource->id(), &stride_)) {}
29 virtual ~RasterBufferImpl() {
30 resource_provider_->UnmapImage(resource_->id());
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());
38 // Overridden from RasterBuffer:
39 virtual skia::RefPtr<SkCanvas> AcquireSkCanvas() OVERRIDE {
41 return skia::AdoptRef(SkCreateNullCanvas());
43 RasterWorkerPool::AcquireBitmapForBuffer(
44 &bitmap_, buffer_, resource_->format(), resource_->size(), stride_);
45 return skia::AdoptRef(new SkCanvas(bitmap_));
47 virtual void ReleaseSkCanvas(const skia::RefPtr<SkCanvas>& canvas) OVERRIDE {
51 RasterWorkerPool::ReleaseBitmapForBuffer(
52 &bitmap_, buffer_, resource_->format());
56 ResourceProvider* resource_provider_;
57 const Resource* resource_;
62 DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
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));
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) {
87 ZeroCopyRasterWorkerPool::~ZeroCopyRasterWorkerPool() {
90 Rasterizer* ZeroCopyRasterWorkerPool::AsRasterizer() {
94 void ZeroCopyRasterWorkerPool::SetClient(RasterizerClient* client) {
98 void ZeroCopyRasterWorkerPool::Shutdown() {
99 TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::Shutdown");
102 task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
103 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
106 void ZeroCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
107 TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::ScheduleTasks");
109 if (raster_pending_.none())
110 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
112 // Mark all task sets as pending.
113 raster_pending_.set();
115 unsigned priority = kRasterTaskPriorityBase;
119 // Cancel existing OnRasterFinished callbacks.
120 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
122 scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets];
124 size_t task_count[kNumberOfTaskSets] = {0};
126 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
127 new_raster_finished_tasks[task_set] = CreateRasterFinishedTask(
129 base::Bind(&ZeroCopyRasterWorkerPool::OnRasterFinished,
130 raster_finished_weak_ptr_factory_.GetWeakPtr(),
134 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
135 it != queue->items.end();
137 const RasterTaskQueue::Item& item = *it;
138 RasterTask* task = item.task;
139 DCHECK(!task->HasCompleted());
141 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) {
142 if (!item.task_sets[task_set])
145 ++task_count[task_set];
147 graph_.edges.push_back(
148 TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get()));
151 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
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]);
161 ScheduleTasksOnOriginThread(this, &graph_);
162 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
164 std::copy(new_raster_finished_tasks,
165 new_raster_finished_tasks + kNumberOfTaskSets,
166 raster_finished_tasks_);
168 TRACE_EVENT_ASYNC_STEP_INTO1(
169 "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
172 void ZeroCopyRasterWorkerPool::CheckForCompletedTasks() {
173 TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::CheckForCompletedTasks");
175 task_graph_runner_->CollectCompletedTasks(namespace_token_,
177 for (Task::Vector::const_iterator it = completed_tasks_.begin();
178 it != completed_tasks_.end();
180 RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
182 task->WillComplete();
183 task->CompleteOnOriginThread(this);
186 task->RunReplyOnOriginThread();
188 completed_tasks_.clear();
191 scoped_ptr<RasterBuffer> ZeroCopyRasterWorkerPool::AcquireBufferForRaster(
192 const Resource* resource) {
193 // RasterBuffer implementation depends on an image having been acquired for
195 resource_provider_->AcquireImage(resource->id());
197 return make_scoped_ptr<RasterBuffer>(
198 new RasterBufferImpl(resource_provider_, resource));
201 void ZeroCopyRasterWorkerPool::ReleaseBufferForRaster(
202 scoped_ptr<RasterBuffer> buffer) {
203 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
206 void ZeroCopyRasterWorkerPool::OnRasterFinished(TaskSet task_set) {
208 "cc", "ZeroCopyRasterWorkerPool::OnRasterFinished", "task_set", task_set);
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());
216 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
218 client_->DidFinishRunningTasks(task_set);
221 scoped_refptr<base::debug::ConvertableToTraceFormat>
222 ZeroCopyRasterWorkerPool::StateAsValue() const {
223 scoped_refptr<base::debug::TracedValue> state =
224 new base::debug::TracedValue();
226 state->BeginArray("tasks_pending");
227 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
228 state->AppendBoolean(raster_pending_[task_set]);