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 "base/debug/trace_event_argument.h"
11 #include "cc/debug/traced_value.h"
12 #include "cc/resources/resource_pool.h"
13 #include "cc/resources/scoped_resource.h"
14 #include "gpu/command_buffer/client/gles2_interface.h"
19 scoped_ptr<RasterWorkerPool> ImageCopyRasterWorkerPool::Create(
20 base::SequencedTaskRunner* task_runner,
21 TaskGraphRunner* task_graph_runner,
22 ContextProvider* context_provider,
23 ResourceProvider* resource_provider,
24 ResourcePool* resource_pool) {
25 return make_scoped_ptr<RasterWorkerPool>(
26 new ImageCopyRasterWorkerPool(task_runner,
33 ImageCopyRasterWorkerPool::ImageCopyRasterWorkerPool(
34 base::SequencedTaskRunner* task_runner,
35 TaskGraphRunner* task_graph_runner,
36 ContextProvider* context_provider,
37 ResourceProvider* resource_provider,
38 ResourcePool* resource_pool)
39 : task_runner_(task_runner),
40 task_graph_runner_(task_graph_runner),
41 namespace_token_(task_graph_runner->GetNamespaceToken()),
42 context_provider_(context_provider),
43 resource_provider_(resource_provider),
44 resource_pool_(resource_pool),
45 has_performed_copy_since_last_flush_(false),
46 raster_tasks_pending_(false),
47 raster_tasks_required_for_activation_pending_(false),
48 raster_finished_weak_ptr_factory_(this) {
49 DCHECK(context_provider_);
52 ImageCopyRasterWorkerPool::~ImageCopyRasterWorkerPool() {
53 DCHECK_EQ(0u, raster_task_states_.size());
56 Rasterizer* ImageCopyRasterWorkerPool::AsRasterizer() { return this; }
58 void ImageCopyRasterWorkerPool::SetClient(RasterizerClient* client) {
62 void ImageCopyRasterWorkerPool::Shutdown() {
63 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::Shutdown");
66 task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
67 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
70 void ImageCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
71 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::ScheduleTasks");
73 DCHECK_EQ(queue->required_for_activation_count,
75 std::count_if(queue->items.begin(),
77 RasterTaskQueue::Item::IsRequiredForActivation)));
79 if (!raster_tasks_pending_)
80 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
82 raster_tasks_pending_ = true;
83 raster_tasks_required_for_activation_pending_ = true;
85 unsigned priority = kRasterTaskPriorityBase;
89 // Cancel existing OnRasterFinished callbacks.
90 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
92 scoped_refptr<RasterizerTask>
93 new_raster_required_for_activation_finished_task(
94 CreateRasterRequiredForActivationFinishedTask(
95 queue->required_for_activation_count,
97 base::Bind(&ImageCopyRasterWorkerPool::
98 OnRasterRequiredForActivationFinished,
99 raster_finished_weak_ptr_factory_.GetWeakPtr())));
100 scoped_refptr<RasterizerTask> new_raster_finished_task(
101 CreateRasterFinishedTask(
103 base::Bind(&ImageCopyRasterWorkerPool::OnRasterFinished,
104 raster_finished_weak_ptr_factory_.GetWeakPtr())));
106 resource_pool_->CheckBusyResources();
108 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
109 it != queue->items.end();
111 const RasterTaskQueue::Item& item = *it;
112 RasterTask* task = item.task;
113 DCHECK(!task->HasCompleted());
115 if (item.required_for_activation) {
116 graph_.edges.push_back(TaskGraph::Edge(
117 task, new_raster_required_for_activation_finished_task.get()));
120 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
122 graph_.edges.push_back(
123 TaskGraph::Edge(task, new_raster_finished_task.get()));
126 InsertNodeForTask(&graph_,
127 new_raster_required_for_activation_finished_task.get(),
128 kRasterRequiredForActivationFinishedTaskPriority,
129 queue->required_for_activation_count);
130 InsertNodeForTask(&graph_,
131 new_raster_finished_task.get(),
132 kRasterFinishedTaskPriority,
133 queue->items.size());
135 ScheduleTasksOnOriginThread(this, &graph_);
136 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
138 raster_finished_task_ = new_raster_finished_task;
139 raster_required_for_activation_finished_task_ =
140 new_raster_required_for_activation_finished_task;
142 resource_pool_->ReduceResourceUsage();
144 TRACE_EVENT_ASYNC_STEP_INTO1(
145 "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
148 void ImageCopyRasterWorkerPool::CheckForCompletedTasks() {
149 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::CheckForCompletedTasks");
151 task_graph_runner_->CollectCompletedTasks(namespace_token_,
153 for (Task::Vector::const_iterator it = completed_tasks_.begin();
154 it != completed_tasks_.end();
156 RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
158 task->WillComplete();
159 task->CompleteOnOriginThread(this);
162 task->RunReplyOnOriginThread();
164 completed_tasks_.clear();
169 SkCanvas* ImageCopyRasterWorkerPool::AcquireCanvasForRaster(RasterTask* task) {
170 DCHECK_EQ(task->resource()->format(), resource_pool_->resource_format());
171 scoped_ptr<ScopedResource> resource(
172 resource_pool_->AcquireResource(task->resource()->size()));
173 SkCanvas* canvas = resource_provider_->MapImageRasterBuffer(resource->id());
174 DCHECK(std::find_if(raster_task_states_.begin(),
175 raster_task_states_.end(),
176 RasterTaskState::TaskComparator(task)) ==
177 raster_task_states_.end());
178 raster_task_states_.push_back(RasterTaskState(task, resource.release()));
182 void ImageCopyRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) {
183 RasterTaskState::Vector::iterator it =
184 std::find_if(raster_task_states_.begin(),
185 raster_task_states_.end(),
186 RasterTaskState::TaskComparator(task));
187 DCHECK(it != raster_task_states_.end());
188 scoped_ptr<ScopedResource> resource(it->resource);
189 std::swap(*it, raster_task_states_.back());
190 raster_task_states_.pop_back();
192 bool content_has_changed =
193 resource_provider_->UnmapImageRasterBuffer(resource->id());
195 // |content_has_changed| can be false as result of task being canceled or
196 // task implementation deciding not to modify bitmap (ie. analysis of raster
197 // commands detected content as a solid color).
198 if (content_has_changed) {
199 resource_provider_->CopyResource(resource->id(), task->resource()->id());
200 has_performed_copy_since_last_flush_ = true;
203 resource_pool_->ReleaseResource(resource.Pass());
206 void ImageCopyRasterWorkerPool::OnRasterFinished() {
207 TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::OnRasterFinished");
209 DCHECK(raster_tasks_pending_);
210 raster_tasks_pending_ = false;
211 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
212 client_->DidFinishRunningTasks();
215 void ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished() {
217 "cc", "ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished");
219 DCHECK(raster_tasks_required_for_activation_pending_);
220 raster_tasks_required_for_activation_pending_ = false;
221 TRACE_EVENT_ASYNC_STEP_INTO1(
222 "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
223 client_->DidFinishRunningTasksRequiredForActivation();
226 void ImageCopyRasterWorkerPool::FlushCopies() {
227 if (!has_performed_copy_since_last_flush_)
230 context_provider_->ContextGL()->ShallowFlushCHROMIUM();
231 has_performed_copy_since_last_flush_ = false;
234 scoped_refptr<base::debug::ConvertableToTraceFormat>
235 ImageCopyRasterWorkerPool::StateAsValue() const {
236 scoped_refptr<base::debug::TracedValue> state =
237 new base::debug::TracedValue();
239 state->SetInteger("pending_count", raster_task_states_.size());
240 state->SetBoolean("tasks_required_for_activation_pending",
241 raster_tasks_required_for_activation_pending_);
242 state->BeginDictionary("staging_state");
243 StagingStateAsValueInto(state.get());
244 state->EndDictionary();
248 void ImageCopyRasterWorkerPool::StagingStateAsValueInto(
249 base::debug::TracedValue* staging_state) const {
250 staging_state->SetInteger("staging_resource_count",
251 resource_pool_->total_resource_count());
252 staging_state->SetInteger("bytes_used_for_staging_resources",
253 resource_pool_->total_memory_usage_bytes());
254 staging_state->SetInteger("pending_copy_count",
255 resource_pool_->total_resource_count() -
256 resource_pool_->acquired_resource_count());
257 staging_state->SetInteger("bytes_pending_copy",
258 resource_pool_->total_memory_usage_bytes() -
259 resource_pool_->acquired_memory_usage_bytes());