• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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