• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "cc/resources/image_raster_worker_pool.h"
6 
7 #include "base/debug/trace_event.h"
8 #include "base/values.h"
9 #include "cc/debug/traced_value.h"
10 #include "cc/resources/resource.h"
11 #include "third_party/skia/include/core/SkBitmapDevice.h"
12 
13 namespace cc {
14 
15 namespace {
16 
17 class ImageWorkerPoolTaskImpl : public internal::WorkerPoolTask {
18  public:
19   typedef base::Callback<void(bool was_canceled)> Reply;
20 
ImageWorkerPoolTaskImpl(internal::RasterWorkerPoolTask * task,uint8_t * buffer,int stride,const Reply & reply)21   ImageWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task,
22                           uint8_t* buffer,
23                           int stride,
24                           const Reply& reply)
25       : task_(task),
26         buffer_(buffer),
27         stride_(stride),
28         reply_(reply) {
29   }
30 
31   // Overridden from internal::WorkerPoolTask:
RunOnWorkerThread(unsigned thread_index)32   virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
33     TRACE_EVENT0("cc", "ImageWorkerPoolTaskImpl::RunOnWorkerThread");
34     if (!buffer_)
35       return;
36 
37     task_->RunOnWorkerThread(thread_index,
38                              buffer_,
39                              task_->resource()->size(),
40                              stride_);
41   }
CompleteOnOriginThread()42   virtual void CompleteOnOriginThread() OVERRIDE {
43     reply_.Run(!HasFinishedRunning());
44   }
45 
46  private:
~ImageWorkerPoolTaskImpl()47   virtual ~ImageWorkerPoolTaskImpl() {}
48 
49   scoped_refptr<internal::RasterWorkerPoolTask> task_;
50   uint8_t* buffer_;
51   int stride_;
52   const Reply reply_;
53 
54   DISALLOW_COPY_AND_ASSIGN(ImageWorkerPoolTaskImpl);
55 };
56 
57 }  // namespace
58 
ImageRasterWorkerPool(ResourceProvider * resource_provider,size_t num_threads,GLenum texture_target)59 ImageRasterWorkerPool::ImageRasterWorkerPool(
60     ResourceProvider* resource_provider,
61     size_t num_threads,
62     GLenum texture_target)
63     : RasterWorkerPool(resource_provider, num_threads),
64       texture_target_(texture_target),
65       raster_tasks_pending_(false),
66       raster_tasks_required_for_activation_pending_(false) {
67 }
68 
~ImageRasterWorkerPool()69 ImageRasterWorkerPool::~ImageRasterWorkerPool() {
70   DCHECK_EQ(0u, image_tasks_.size());
71 }
72 
ScheduleTasks(RasterTask::Queue * queue)73 void ImageRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
74   TRACE_EVENT0("cc", "ImageRasterWorkerPool::ScheduleTasks");
75 
76   RasterWorkerPool::SetRasterTasks(queue);
77 
78   if (!raster_tasks_pending_)
79     TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
80 
81   raster_tasks_pending_ = true;
82   raster_tasks_required_for_activation_pending_ = true;
83 
84   unsigned priority = 0u;
85   TaskGraph graph;
86 
87   scoped_refptr<internal::WorkerPoolTask>
88       new_raster_required_for_activation_finished_task(
89           CreateRasterRequiredForActivationFinishedTask());
90   internal::GraphNode* raster_required_for_activation_finished_node =
91       CreateGraphNodeForTask(
92           new_raster_required_for_activation_finished_task.get(),
93           priority++,
94           &graph);
95 
96   scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task(
97       CreateRasterFinishedTask());
98   internal::GraphNode* raster_finished_node =
99       CreateGraphNodeForTask(new_raster_finished_task.get(),
100                              priority++,
101                              &graph);
102 
103   for (RasterTaskVector::const_iterator it = raster_tasks().begin();
104        it != raster_tasks().end(); ++it) {
105     internal::RasterWorkerPoolTask* task = it->get();
106     DCHECK(!task->HasCompleted());
107     DCHECK(!task->WasCanceled());
108 
109     TaskMap::iterator image_it = image_tasks_.find(task);
110     if (image_it != image_tasks_.end()) {
111       internal::WorkerPoolTask* image_task = image_it->second.get();
112       CreateGraphNodeForImageTask(
113           image_task,
114           task->dependencies(),
115           priority++,
116           IsRasterTaskRequiredForActivation(task),
117           raster_required_for_activation_finished_node,
118           raster_finished_node,
119           &graph);
120       continue;
121     }
122 
123     // Acquire image for resource.
124     resource_provider()->AcquireImage(task->resource()->id());
125 
126     // Map image for raster.
127     uint8* buffer = resource_provider()->MapImage(task->resource()->id());
128     int stride = resource_provider()->GetImageStride(task->resource()->id());
129 
130     scoped_refptr<internal::WorkerPoolTask> new_image_task(
131         new ImageWorkerPoolTaskImpl(
132             task,
133             buffer,
134             stride,
135             base::Bind(&ImageRasterWorkerPool::OnRasterTaskCompleted,
136                        base::Unretained(this),
137                        make_scoped_refptr(task))));
138     image_tasks_[task] = new_image_task;
139     CreateGraphNodeForImageTask(
140         new_image_task.get(),
141         task->dependencies(),
142         priority++,
143         IsRasterTaskRequiredForActivation(task),
144         raster_required_for_activation_finished_node,
145         raster_finished_node,
146         &graph);
147   }
148 
149   SetTaskGraph(&graph);
150 
151   set_raster_finished_task(new_raster_finished_task);
152   set_raster_required_for_activation_finished_task(
153       new_raster_required_for_activation_finished_task);
154 
155   TRACE_EVENT_ASYNC_STEP_INTO1(
156       "cc", "ScheduledTasks", this, "rasterizing",
157       "state", TracedValue::FromValue(StateAsValue().release()));
158 }
159 
GetResourceTarget() const160 GLenum ImageRasterWorkerPool::GetResourceTarget() const {
161   return texture_target_;
162 }
163 
GetResourceFormat() const164 ResourceFormat ImageRasterWorkerPool::GetResourceFormat() const {
165   return resource_provider()->best_texture_format();
166 }
167 
OnRasterTasksFinished()168 void ImageRasterWorkerPool::OnRasterTasksFinished() {
169   DCHECK(raster_tasks_pending_);
170   raster_tasks_pending_ = false;
171   TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
172   client()->DidFinishRunningTasks();
173 }
174 
OnRasterTasksRequiredForActivationFinished()175 void ImageRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
176   DCHECK(raster_tasks_required_for_activation_pending_);
177   raster_tasks_required_for_activation_pending_ = false;
178   TRACE_EVENT_ASYNC_STEP_INTO1(
179       "cc", "ScheduledTasks", this, "rasterizing",
180       "state", TracedValue::FromValue(StateAsValue().release()));
181   client()->DidFinishRunningTasksRequiredForActivation();
182 }
183 
OnRasterTaskCompleted(scoped_refptr<internal::RasterWorkerPoolTask> task,bool was_canceled)184 void ImageRasterWorkerPool::OnRasterTaskCompleted(
185     scoped_refptr<internal::RasterWorkerPoolTask> task,
186     bool was_canceled) {
187   TRACE_EVENT1("cc", "ImageRasterWorkerPool::OnRasterTaskCompleted",
188                "was_canceled", was_canceled);
189 
190   DCHECK(image_tasks_.find(task.get()) != image_tasks_.end());
191 
192   // Balanced with MapImage() call in ScheduleTasks().
193   resource_provider()->UnmapImage(task->resource()->id());
194 
195   task->DidRun(was_canceled);
196   task->WillComplete();
197   task->CompleteOnOriginThread();
198   task->DidComplete();
199 
200   image_tasks_.erase(task.get());
201 }
202 
StateAsValue() const203 scoped_ptr<base::Value> ImageRasterWorkerPool::StateAsValue() const {
204   scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
205 
206   state->SetBoolean("tasks_required_for_activation_pending",
207                     raster_tasks_required_for_activation_pending_);
208   state->Set("scheduled_state", ScheduledStateAsValue().release());
209   return state.PassAs<base::Value>();
210 }
211 
212 // static
CreateGraphNodeForImageTask(internal::WorkerPoolTask * image_task,const TaskVector & decode_tasks,unsigned priority,bool is_required_for_activation,internal::GraphNode * raster_required_for_activation_finished_node,internal::GraphNode * raster_finished_node,TaskGraph * graph)213 void ImageRasterWorkerPool::CreateGraphNodeForImageTask(
214     internal::WorkerPoolTask* image_task,
215     const TaskVector& decode_tasks,
216     unsigned priority,
217     bool is_required_for_activation,
218     internal::GraphNode* raster_required_for_activation_finished_node,
219     internal::GraphNode* raster_finished_node,
220     TaskGraph* graph) {
221   internal::GraphNode* image_node = CreateGraphNodeForRasterTask(image_task,
222                                                                  decode_tasks,
223                                                                  priority,
224                                                                  graph);
225 
226   if (is_required_for_activation) {
227     raster_required_for_activation_finished_node->add_dependency();
228     image_node->add_dependent(raster_required_for_activation_finished_node);
229   }
230 
231   raster_finished_node->add_dependency();
232   image_node->add_dependent(raster_finished_node);
233 }
234 
235 }  // namespace cc
236