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 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 task_->RunOnWorkerThread(thread_index, 38 buffer_, 39 task_->resource()->size(), 40 stride_); 41 } 42 virtual void CompleteOnOriginThread() OVERRIDE { 43 reply_.Run(!HasFinishedRunning()); 44 } 45 46 private: 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 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 69 ImageRasterWorkerPool::~ImageRasterWorkerPool() { 70 DCHECK_EQ(0u, image_tasks_.size()); 71 } 72 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 160 GLenum ImageRasterWorkerPool::GetResourceTarget() const { 161 return texture_target_; 162 } 163 164 ResourceFormat ImageRasterWorkerPool::GetResourceFormat() const { 165 return resource_provider()->best_texture_format(); 166 } 167 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 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 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 203 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 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