1 // Copyright 2014 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_copy_raster_worker_pool.h"
6
7 #include <algorithm>
8
9 #include "base/debug/trace_event.h"
10 #include "cc/debug/traced_value.h"
11 #include "cc/resources/resource_pool.h"
12 #include "cc/resources/scoped_resource.h"
13
14 namespace cc {
15
16 // static
Create(base::SequencedTaskRunner * task_runner,TaskGraphRunner * task_graph_runner,ResourceProvider * resource_provider,ResourcePool * resource_pool)17 scoped_ptr<RasterWorkerPool> ImageCopyRasterWorkerPool::Create(
18 base::SequencedTaskRunner* task_runner,
19 TaskGraphRunner* task_graph_runner,
20 ResourceProvider* resource_provider,
21 ResourcePool* resource_pool) {
22 return make_scoped_ptr<RasterWorkerPool>(new ImageCopyRasterWorkerPool(
23 task_runner, task_graph_runner, resource_provider, resource_pool));
24 }
25
ImageCopyRasterWorkerPool(base::SequencedTaskRunner * task_runner,TaskGraphRunner * task_graph_runner,ResourceProvider * resource_provider,ResourcePool * resource_pool)26 ImageCopyRasterWorkerPool::ImageCopyRasterWorkerPool(
27 base::SequencedTaskRunner* task_runner,
28 TaskGraphRunner* task_graph_runner,
29 ResourceProvider* resource_provider,
30 ResourcePool* resource_pool)
31 : task_runner_(task_runner),
32 task_graph_runner_(task_graph_runner),
33 namespace_token_(task_graph_runner->GetNamespaceToken()),
34 resource_provider_(resource_provider),
35 resource_pool_(resource_pool),
36 has_performed_copy_since_last_flush_(false),
37 raster_tasks_pending_(false),
38 raster_tasks_required_for_activation_pending_(false),
39 raster_finished_weak_ptr_factory_(this) {}
40
~ImageCopyRasterWorkerPool()41 ImageCopyRasterWorkerPool::~ImageCopyRasterWorkerPool() {
42 DCHECK_EQ(0u, raster_task_states_.size());
43 }
44
AsRasterizer()45 Rasterizer* ImageCopyRasterWorkerPool::AsRasterizer() { return this; }
46
SetClient(RasterizerClient * client)47 void ImageCopyRasterWorkerPool::SetClient(RasterizerClient* client) {
48 client_ = client;
49 }
50
Shutdown()51 void ImageCopyRasterWorkerPool::Shutdown() {
52 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::Shutdown");
53
54 TaskGraph empty;
55 task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
56 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
57 }
58
ScheduleTasks(RasterTaskQueue * queue)59 void ImageCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
60 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::ScheduleTasks");
61
62 DCHECK_EQ(queue->required_for_activation_count,
63 static_cast<size_t>(
64 std::count_if(queue->items.begin(),
65 queue->items.end(),
66 RasterTaskQueue::Item::IsRequiredForActivation)));
67
68 if (!raster_tasks_pending_)
69 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
70
71 raster_tasks_pending_ = true;
72 raster_tasks_required_for_activation_pending_ = true;
73
74 unsigned priority = kRasterTaskPriorityBase;
75
76 graph_.Reset();
77
78 // Cancel existing OnRasterFinished callbacks.
79 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
80
81 scoped_refptr<RasterizerTask>
82 new_raster_required_for_activation_finished_task(
83 CreateRasterRequiredForActivationFinishedTask(
84 queue->required_for_activation_count,
85 task_runner_.get(),
86 base::Bind(&ImageCopyRasterWorkerPool::
87 OnRasterRequiredForActivationFinished,
88 raster_finished_weak_ptr_factory_.GetWeakPtr())));
89 scoped_refptr<RasterizerTask> new_raster_finished_task(
90 CreateRasterFinishedTask(
91 task_runner_.get(),
92 base::Bind(&ImageCopyRasterWorkerPool::OnRasterFinished,
93 raster_finished_weak_ptr_factory_.GetWeakPtr())));
94
95 resource_pool_->CheckBusyResources();
96
97 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
98 it != queue->items.end();
99 ++it) {
100 const RasterTaskQueue::Item& item = *it;
101 RasterTask* task = item.task;
102 DCHECK(!task->HasCompleted());
103
104 if (item.required_for_activation) {
105 graph_.edges.push_back(TaskGraph::Edge(
106 task, new_raster_required_for_activation_finished_task.get()));
107 }
108
109 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
110
111 graph_.edges.push_back(
112 TaskGraph::Edge(task, new_raster_finished_task.get()));
113 }
114
115 InsertNodeForTask(&graph_,
116 new_raster_required_for_activation_finished_task.get(),
117 kRasterRequiredForActivationFinishedTaskPriority,
118 queue->required_for_activation_count);
119 InsertNodeForTask(&graph_,
120 new_raster_finished_task.get(),
121 kRasterFinishedTaskPriority,
122 queue->items.size());
123
124 ScheduleTasksOnOriginThread(this, &graph_);
125 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
126
127 raster_finished_task_ = new_raster_finished_task;
128 raster_required_for_activation_finished_task_ =
129 new_raster_required_for_activation_finished_task;
130
131 resource_pool_->ReduceResourceUsage();
132
133 TRACE_EVENT_ASYNC_STEP_INTO1(
134 "cc",
135 "ScheduledTasks",
136 this,
137 "rasterizing",
138 "state",
139 TracedValue::FromValue(StateAsValue().release()));
140 }
141
CheckForCompletedTasks()142 void ImageCopyRasterWorkerPool::CheckForCompletedTasks() {
143 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::CheckForCompletedTasks");
144
145 task_graph_runner_->CollectCompletedTasks(namespace_token_,
146 &completed_tasks_);
147 for (Task::Vector::const_iterator it = completed_tasks_.begin();
148 it != completed_tasks_.end();
149 ++it) {
150 RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
151
152 task->WillComplete();
153 task->CompleteOnOriginThread(this);
154 task->DidComplete();
155
156 task->RunReplyOnOriginThread();
157 }
158 completed_tasks_.clear();
159
160 FlushCopies();
161 }
162
AcquireCanvasForRaster(RasterTask * task)163 SkCanvas* ImageCopyRasterWorkerPool::AcquireCanvasForRaster(RasterTask* task) {
164 DCHECK_EQ(task->resource()->format(), resource_pool_->resource_format());
165 scoped_ptr<ScopedResource> resource(
166 resource_pool_->AcquireResource(task->resource()->size()));
167 SkCanvas* canvas = resource_provider_->MapImageRasterBuffer(resource->id());
168 DCHECK(std::find_if(raster_task_states_.begin(),
169 raster_task_states_.end(),
170 RasterTaskState::TaskComparator(task)) ==
171 raster_task_states_.end());
172 raster_task_states_.push_back(RasterTaskState(task, resource.release()));
173 return canvas;
174 }
175
ReleaseCanvasForRaster(RasterTask * task)176 void ImageCopyRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) {
177 RasterTaskState::Vector::iterator it =
178 std::find_if(raster_task_states_.begin(),
179 raster_task_states_.end(),
180 RasterTaskState::TaskComparator(task));
181 DCHECK(it != raster_task_states_.end());
182 scoped_ptr<ScopedResource> resource(it->resource);
183 std::swap(*it, raster_task_states_.back());
184 raster_task_states_.pop_back();
185
186 bool content_has_changed =
187 resource_provider_->UnmapImageRasterBuffer(resource->id());
188
189 // |content_has_changed| can be false as result of task being canceled or
190 // task implementation deciding not to modify bitmap (ie. analysis of raster
191 // commands detected content as a solid color).
192 if (content_has_changed) {
193 resource_provider_->CopyResource(resource->id(), task->resource()->id());
194 has_performed_copy_since_last_flush_ = true;
195 }
196
197 resource_pool_->ReleaseResource(resource.Pass());
198 }
199
OnRasterFinished()200 void ImageCopyRasterWorkerPool::OnRasterFinished() {
201 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::OnRasterFinished");
202
203 DCHECK(raster_tasks_pending_);
204 raster_tasks_pending_ = false;
205 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
206 client_->DidFinishRunningTasks();
207 }
208
OnRasterRequiredForActivationFinished()209 void ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished() {
210 TRACE_EVENT0(
211 "cc", "ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished");
212
213 DCHECK(raster_tasks_required_for_activation_pending_);
214 raster_tasks_required_for_activation_pending_ = false;
215 TRACE_EVENT_ASYNC_STEP_INTO1(
216 "cc",
217 "ScheduledTasks",
218 this,
219 "rasterizing",
220 "state",
221 TracedValue::FromValue(StateAsValue().release()));
222 client_->DidFinishRunningTasksRequiredForActivation();
223 }
224
FlushCopies()225 void ImageCopyRasterWorkerPool::FlushCopies() {
226 if (!has_performed_copy_since_last_flush_)
227 return;
228
229 resource_provider_->ShallowFlushIfSupported();
230 has_performed_copy_since_last_flush_ = false;
231 }
232
StateAsValue() const233 scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StateAsValue() const {
234 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
235
236 state->SetInteger("pending_count", raster_task_states_.size());
237 state->SetBoolean("tasks_required_for_activation_pending",
238 raster_tasks_required_for_activation_pending_);
239 state->Set("staging_state", StagingStateAsValue().release());
240
241 return state.PassAs<base::Value>();
242 }
StagingStateAsValue() const243 scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StagingStateAsValue() const {
244 scoped_ptr<base::DictionaryValue> staging_state(new base::DictionaryValue);
245
246 staging_state->SetInteger("staging_resource_count",
247 resource_pool_->total_resource_count());
248 staging_state->SetInteger("bytes_used_for_staging_resources",
249 resource_pool_->total_memory_usage_bytes());
250 staging_state->SetInteger("pending_copy_count",
251 resource_pool_->total_resource_count() -
252 resource_pool_->acquired_resource_count());
253 staging_state->SetInteger("bytes_pending_copy",
254 resource_pool_->total_memory_usage_bytes() -
255 resource_pool_->acquired_memory_usage_bytes());
256
257 return staging_state.PassAs<base::Value>();
258 }
259
260 } // namespace cc
261