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