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.
5 #include "cc/resources/image_copy_raster_worker_pool.h"
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"
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
));
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) {}
41 ImageCopyRasterWorkerPool::~ImageCopyRasterWorkerPool() {
42 DCHECK_EQ(0u, raster_task_states_
.size());
45 Rasterizer
* ImageCopyRasterWorkerPool::AsRasterizer() { return this; }
47 void ImageCopyRasterWorkerPool::SetClient(RasterizerClient
* client
) {
51 void ImageCopyRasterWorkerPool::Shutdown() {
52 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::Shutdown");
55 task_graph_runner_
->ScheduleTasks(namespace_token_
, &empty
);
56 task_graph_runner_
->WaitForTasksToFinishRunning(namespace_token_
);
59 void ImageCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue
* queue
) {
60 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::ScheduleTasks");
62 DCHECK_EQ(queue
->required_for_activation_count
,
64 std::count_if(queue
->items
.begin(),
66 RasterTaskQueue::Item::IsRequiredForActivation
)));
68 if (!raster_tasks_pending_
)
69 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
71 raster_tasks_pending_
= true;
72 raster_tasks_required_for_activation_pending_
= true;
74 unsigned priority
= kRasterTaskPriorityBase
;
78 // Cancel existing OnRasterFinished callbacks.
79 raster_finished_weak_ptr_factory_
.InvalidateWeakPtrs();
81 scoped_refptr
<RasterizerTask
>
82 new_raster_required_for_activation_finished_task(
83 CreateRasterRequiredForActivationFinishedTask(
84 queue
->required_for_activation_count
,
86 base::Bind(&ImageCopyRasterWorkerPool::
87 OnRasterRequiredForActivationFinished
,
88 raster_finished_weak_ptr_factory_
.GetWeakPtr())));
89 scoped_refptr
<RasterizerTask
> new_raster_finished_task(
90 CreateRasterFinishedTask(
92 base::Bind(&ImageCopyRasterWorkerPool::OnRasterFinished
,
93 raster_finished_weak_ptr_factory_
.GetWeakPtr())));
95 resource_pool_
->CheckBusyResources();
97 for (RasterTaskQueue::Item::Vector::const_iterator it
= queue
->items
.begin();
98 it
!= queue
->items
.end();
100 const RasterTaskQueue::Item
& item
= *it
;
101 RasterTask
* task
= item
.task
;
102 DCHECK(!task
->HasCompleted());
104 if (item
.required_for_activation
) {
105 graph_
.edges
.push_back(TaskGraph::Edge(
106 task
, new_raster_required_for_activation_finished_task
.get()));
109 InsertNodesForRasterTask(&graph_
, task
, task
->dependencies(), priority
++);
111 graph_
.edges
.push_back(
112 TaskGraph::Edge(task
, new_raster_finished_task
.get()));
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());
124 ScheduleTasksOnOriginThread(this, &graph_
);
125 task_graph_runner_
->ScheduleTasks(namespace_token_
, &graph_
);
127 raster_finished_task_
= new_raster_finished_task
;
128 raster_required_for_activation_finished_task_
=
129 new_raster_required_for_activation_finished_task
;
131 resource_pool_
->ReduceResourceUsage();
133 TRACE_EVENT_ASYNC_STEP_INTO1(
139 TracedValue::FromValue(StateAsValue().release()));
142 void ImageCopyRasterWorkerPool::CheckForCompletedTasks() {
143 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::CheckForCompletedTasks");
145 task_graph_runner_
->CollectCompletedTasks(namespace_token_
,
147 for (Task::Vector::const_iterator it
= completed_tasks_
.begin();
148 it
!= completed_tasks_
.end();
150 RasterizerTask
* task
= static_cast<RasterizerTask
*>(it
->get());
152 task
->WillComplete();
153 task
->CompleteOnOriginThread(this);
156 task
->RunReplyOnOriginThread();
158 completed_tasks_
.clear();
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()));
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();
186 bool content_has_changed
=
187 resource_provider_
->UnmapImageRasterBuffer(resource
->id());
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;
197 resource_pool_
->ReleaseResource(resource
.Pass());
200 void ImageCopyRasterWorkerPool::OnRasterFinished() {
201 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::OnRasterFinished");
203 DCHECK(raster_tasks_pending_
);
204 raster_tasks_pending_
= false;
205 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
206 client_
->DidFinishRunningTasks();
209 void ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished() {
211 "cc", "ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished");
213 DCHECK(raster_tasks_required_for_activation_pending_
);
214 raster_tasks_required_for_activation_pending_
= false;
215 TRACE_EVENT_ASYNC_STEP_INTO1(
221 TracedValue::FromValue(StateAsValue().release()));
222 client_
->DidFinishRunningTasksRequiredForActivation();
225 void ImageCopyRasterWorkerPool::FlushCopies() {
226 if (!has_performed_copy_since_last_flush_
)
229 resource_provider_
->ShallowFlushIfSupported();
230 has_performed_copy_since_last_flush_
= false;
233 scoped_ptr
<base::Value
> ImageCopyRasterWorkerPool::StateAsValue() const {
234 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue
);
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());
241 return state
.PassAs
<base::Value
>();
243 scoped_ptr
<base::Value
> ImageCopyRasterWorkerPool::StagingStateAsValue() const {
244 scoped_ptr
<base::DictionaryValue
> staging_state(new base::DictionaryValue
);
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());
257 return staging_state
.PassAs
<base::Value
>();