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/direct_raster_worker_pool.h" 6 7 #include "base/debug/trace_event.h" 8 #include "cc/output/context_provider.h" 9 #include "cc/resources/resource.h" 10 #include "cc/resources/resource_provider.h" 11 #include "gpu/command_buffer/client/gles2_interface.h" 12 #include "third_party/skia/include/gpu/GrContext.h" 13 14 namespace cc { 15 16 // static 17 scoped_ptr<RasterWorkerPool> DirectRasterWorkerPool::Create( 18 base::SequencedTaskRunner* task_runner, 19 ResourceProvider* resource_provider, 20 ContextProvider* context_provider) { 21 return make_scoped_ptr<RasterWorkerPool>(new DirectRasterWorkerPool( 22 task_runner, resource_provider, context_provider)); 23 } 24 25 DirectRasterWorkerPool::DirectRasterWorkerPool( 26 base::SequencedTaskRunner* task_runner, 27 ResourceProvider* resource_provider, 28 ContextProvider* context_provider) 29 : task_runner_(task_runner), 30 task_graph_runner_(new TaskGraphRunner), 31 namespace_token_(task_graph_runner_->GetNamespaceToken()), 32 resource_provider_(resource_provider), 33 context_provider_(context_provider), 34 run_tasks_on_origin_thread_pending_(false), 35 raster_tasks_pending_(false), 36 raster_tasks_required_for_activation_pending_(false), 37 raster_finished_weak_ptr_factory_(this), 38 weak_ptr_factory_(this) {} 39 40 DirectRasterWorkerPool::~DirectRasterWorkerPool() { 41 DCHECK_EQ(0u, completed_tasks_.size()); 42 } 43 44 Rasterizer* DirectRasterWorkerPool::AsRasterizer() { return this; } 45 46 void DirectRasterWorkerPool::SetClient(RasterizerClient* client) { 47 client_ = client; 48 } 49 50 void DirectRasterWorkerPool::Shutdown() { 51 TRACE_EVENT0("cc", "DirectRasterWorkerPool::Shutdown"); 52 53 TaskGraph empty; 54 task_graph_runner_->ScheduleTasks(namespace_token_, &empty); 55 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); 56 } 57 58 void DirectRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) { 59 TRACE_EVENT0("cc", "DirectRasterWorkerPool::ScheduleTasks"); 60 61 DCHECK_EQ(queue->required_for_activation_count, 62 static_cast<size_t>( 63 std::count_if(queue->items.begin(), 64 queue->items.end(), 65 RasterTaskQueue::Item::IsRequiredForActivation))); 66 67 raster_tasks_pending_ = true; 68 raster_tasks_required_for_activation_pending_ = true; 69 70 unsigned priority = kRasterTaskPriorityBase; 71 72 graph_.Reset(); 73 74 // Cancel existing OnRasterFinished callbacks. 75 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs(); 76 77 scoped_refptr<RasterizerTask> 78 new_raster_required_for_activation_finished_task( 79 CreateRasterRequiredForActivationFinishedTask( 80 queue->required_for_activation_count, 81 task_runner_.get(), 82 base::Bind(&DirectRasterWorkerPool:: 83 OnRasterRequiredForActivationFinished, 84 raster_finished_weak_ptr_factory_.GetWeakPtr()))); 85 scoped_refptr<RasterizerTask> new_raster_finished_task( 86 CreateRasterFinishedTask( 87 task_runner_.get(), 88 base::Bind(&DirectRasterWorkerPool::OnRasterFinished, 89 raster_finished_weak_ptr_factory_.GetWeakPtr()))); 90 91 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin(); 92 it != queue->items.end(); 93 ++it) { 94 const RasterTaskQueue::Item& item = *it; 95 RasterTask* task = item.task; 96 DCHECK(!task->HasCompleted()); 97 98 if (item.required_for_activation) { 99 graph_.edges.push_back(TaskGraph::Edge( 100 task, new_raster_required_for_activation_finished_task.get())); 101 } 102 103 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++); 104 105 graph_.edges.push_back( 106 TaskGraph::Edge(task, new_raster_finished_task.get())); 107 } 108 109 InsertNodeForTask(&graph_, 110 new_raster_required_for_activation_finished_task.get(), 111 kRasterRequiredForActivationFinishedTaskPriority, 112 queue->required_for_activation_count); 113 InsertNodeForTask(&graph_, 114 new_raster_finished_task.get(), 115 kRasterFinishedTaskPriority, 116 queue->items.size()); 117 118 ScheduleTasksOnOriginThread(this, &graph_); 119 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); 120 121 ScheduleRunTasksOnOriginThread(); 122 123 raster_finished_task_ = new_raster_finished_task; 124 raster_required_for_activation_finished_task_ = 125 new_raster_required_for_activation_finished_task; 126 } 127 128 void DirectRasterWorkerPool::CheckForCompletedTasks() { 129 TRACE_EVENT0("cc", "DirectRasterWorkerPool::CheckForCompletedTasks"); 130 131 task_graph_runner_->CollectCompletedTasks(namespace_token_, 132 &completed_tasks_); 133 for (Task::Vector::const_iterator it = completed_tasks_.begin(); 134 it != completed_tasks_.end(); 135 ++it) { 136 RasterizerTask* task = static_cast<RasterizerTask*>(it->get()); 137 138 task->WillComplete(); 139 task->CompleteOnOriginThread(this); 140 task->DidComplete(); 141 142 task->RunReplyOnOriginThread(); 143 } 144 completed_tasks_.clear(); 145 } 146 147 SkCanvas* DirectRasterWorkerPool::AcquireCanvasForRaster(RasterTask* task) { 148 return resource_provider_->MapDirectRasterBuffer(task->resource()->id()); 149 } 150 151 void DirectRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) { 152 resource_provider_->UnmapDirectRasterBuffer(task->resource()->id()); 153 } 154 155 void DirectRasterWorkerPool::OnRasterFinished() { 156 TRACE_EVENT0("cc", "DirectRasterWorkerPool::OnRasterFinished"); 157 158 DCHECK(raster_tasks_pending_); 159 raster_tasks_pending_ = false; 160 client_->DidFinishRunningTasks(); 161 } 162 163 void DirectRasterWorkerPool::OnRasterRequiredForActivationFinished() { 164 TRACE_EVENT0("cc", 165 "DirectRasterWorkerPool::OnRasterRequiredForActivationFinished"); 166 167 DCHECK(raster_tasks_required_for_activation_pending_); 168 raster_tasks_required_for_activation_pending_ = false; 169 client_->DidFinishRunningTasksRequiredForActivation(); 170 } 171 172 void DirectRasterWorkerPool::ScheduleRunTasksOnOriginThread() { 173 if (run_tasks_on_origin_thread_pending_) 174 return; 175 176 task_runner_->PostTask( 177 FROM_HERE, 178 base::Bind(&DirectRasterWorkerPool::RunTasksOnOriginThread, 179 weak_ptr_factory_.GetWeakPtr())); 180 run_tasks_on_origin_thread_pending_ = true; 181 } 182 183 void DirectRasterWorkerPool::RunTasksOnOriginThread() { 184 TRACE_EVENT0("cc", "DirectRasterWorkerPool::RunTasksOnOriginThread"); 185 186 DCHECK(run_tasks_on_origin_thread_pending_); 187 run_tasks_on_origin_thread_pending_ = false; 188 189 if (context_provider_) { 190 DCHECK(context_provider_->ContextGL()); 191 // TODO(alokp): Use a trace macro to push/pop markers. 192 // Using push/pop functions directly incurs cost to evaluate function 193 // arguments even when tracing is disabled. 194 context_provider_->ContextGL()->PushGroupMarkerEXT( 195 0, "DirectRasterWorkerPool::RunTasksOnOriginThread"); 196 197 GrContext* gr_context = context_provider_->GrContext(); 198 // TODO(alokp): Implement TestContextProvider::GrContext(). 199 if (gr_context) 200 gr_context->resetContext(); 201 } 202 203 task_graph_runner_->RunUntilIdle(); 204 205 if (context_provider_) { 206 GrContext* gr_context = context_provider_->GrContext(); 207 // TODO(alokp): Implement TestContextProvider::GrContext(). 208 if (gr_context) 209 gr_context->flush(); 210 211 context_provider_->ContextGL()->PopGroupMarkerEXT(); 212 } 213 } 214 215 } // namespace cc 216