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.
5 #include "cc/resources/raster_worker_pool.h"
9 #include "base/debug/trace_event_synthetic_delay.h"
10 #include "base/lazy_instance.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/threading/simple_thread.h"
13 #include "cc/base/scoped_ptr_deque.h"
18 class RasterTaskGraphRunner
: public TaskGraphRunner
,
19 public base::DelegateSimpleThread::Delegate
{
21 RasterTaskGraphRunner()
22 : synthetic_delay_(base::debug::TraceEventSyntheticDelay::Lookup(
23 "cc.RasterRequiredForActivation")) {
24 size_t num_threads
= RasterWorkerPool::GetNumRasterThreads();
25 while (workers_
.size() < num_threads
) {
26 scoped_ptr
<base::DelegateSimpleThread
> worker
=
27 make_scoped_ptr(new base::DelegateSimpleThread(
29 base::StringPrintf("CompositorRasterWorker%u",
30 static_cast<unsigned>(workers_
.size() + 1))
33 #if defined(OS_ANDROID) || defined(OS_LINUX)
34 worker
->SetThreadPriority(base::kThreadPriority_Background
);
36 workers_
.push_back(worker
.Pass());
40 virtual ~RasterTaskGraphRunner() { NOTREACHED(); }
42 base::debug::TraceEventSyntheticDelay
* synthetic_delay() {
43 return synthetic_delay_
;
47 // Overridden from base::DelegateSimpleThread::Delegate:
48 virtual void Run() OVERRIDE
{
49 TaskGraphRunner::Run();
52 ScopedPtrDeque
<base::DelegateSimpleThread
> workers_
;
53 base::debug::TraceEventSyntheticDelay
* synthetic_delay_
;
56 base::LazyInstance
<RasterTaskGraphRunner
>::Leaky g_task_graph_runner
=
57 LAZY_INSTANCE_INITIALIZER
;
59 const int kDefaultNumRasterThreads
= 1;
61 int g_num_raster_threads
= 0;
63 class RasterFinishedTaskImpl
: public RasterizerTask
{
65 explicit RasterFinishedTaskImpl(
66 base::SequencedTaskRunner
* task_runner
,
67 const base::Closure
& on_raster_finished_callback
)
68 : task_runner_(task_runner
),
69 on_raster_finished_callback_(on_raster_finished_callback
) {}
71 // Overridden from Task:
72 virtual void RunOnWorkerThread() OVERRIDE
{
73 TRACE_EVENT0("cc", "RasterFinishedTaskImpl::RunOnWorkerThread");
77 // Overridden from RasterizerTask:
78 virtual void ScheduleOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{}
79 virtual void CompleteOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{}
80 virtual void RunReplyOnOriginThread() OVERRIDE
{}
83 virtual ~RasterFinishedTaskImpl() {}
85 void RasterFinished() {
86 task_runner_
->PostTask(FROM_HERE
, on_raster_finished_callback_
);
90 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
91 const base::Closure on_raster_finished_callback_
;
93 DISALLOW_COPY_AND_ASSIGN(RasterFinishedTaskImpl
);
96 class RasterRequiredForActivationFinishedTaskImpl
97 : public RasterFinishedTaskImpl
{
99 RasterRequiredForActivationFinishedTaskImpl(
100 base::SequencedTaskRunner
* task_runner
,
101 const base::Closure
& on_raster_finished_callback
,
102 size_t tasks_required_for_activation_count
)
103 : RasterFinishedTaskImpl(task_runner
, on_raster_finished_callback
),
104 tasks_required_for_activation_count_(
105 tasks_required_for_activation_count
) {
106 if (tasks_required_for_activation_count_
) {
107 g_task_graph_runner
.Get().synthetic_delay()->BeginParallel(
108 &activation_delay_end_time_
);
112 // Overridden from Task:
113 virtual void RunOnWorkerThread() OVERRIDE
{
115 "cc", "RasterRequiredForActivationFinishedTaskImpl::RunOnWorkerThread");
117 if (tasks_required_for_activation_count_
) {
118 g_task_graph_runner
.Get().synthetic_delay()->EndParallel(
119 activation_delay_end_time_
);
125 virtual ~RasterRequiredForActivationFinishedTaskImpl() {}
127 base::TimeTicks activation_delay_end_time_
;
128 const size_t tasks_required_for_activation_count_
;
130 DISALLOW_COPY_AND_ASSIGN(RasterRequiredForActivationFinishedTaskImpl
);
135 // This allows an external rasterize on-demand system to run raster tasks
136 // with highest priority using the same task graph runner instance.
137 unsigned RasterWorkerPool::kOnDemandRasterTaskPriority
= 0u;
138 // This allows a micro benchmark system to run tasks with highest priority,
139 // since it should finish as quickly as possible.
140 unsigned RasterWorkerPool::kBenchmarkRasterTaskPriority
= 0u;
141 // Task priorities that make sure raster finished tasks run before any
142 // remaining raster tasks.
143 unsigned RasterWorkerPool::kRasterFinishedTaskPriority
= 2u;
144 unsigned RasterWorkerPool::kRasterRequiredForActivationFinishedTaskPriority
=
146 unsigned RasterWorkerPool::kRasterTaskPriorityBase
= 3u;
148 RasterWorkerPool::RasterWorkerPool() {}
150 RasterWorkerPool::~RasterWorkerPool() {}
153 void RasterWorkerPool::SetNumRasterThreads(int num_threads
) {
154 DCHECK_LT(0, num_threads
);
155 DCHECK_EQ(0, g_num_raster_threads
);
157 g_num_raster_threads
= num_threads
;
161 int RasterWorkerPool::GetNumRasterThreads() {
162 if (!g_num_raster_threads
)
163 g_num_raster_threads
= kDefaultNumRasterThreads
;
165 return g_num_raster_threads
;
169 TaskGraphRunner
* RasterWorkerPool::GetTaskGraphRunner() {
170 return g_task_graph_runner
.Pointer();
174 scoped_refptr
<RasterizerTask
> RasterWorkerPool::CreateRasterFinishedTask(
175 base::SequencedTaskRunner
* task_runner
,
176 const base::Closure
& on_raster_finished_callback
) {
177 return make_scoped_refptr(
178 new RasterFinishedTaskImpl(task_runner
, on_raster_finished_callback
));
182 scoped_refptr
<RasterizerTask
>
183 RasterWorkerPool::CreateRasterRequiredForActivationFinishedTask(
184 size_t tasks_required_for_activation_count
,
185 base::SequencedTaskRunner
* task_runner
,
186 const base::Closure
& on_raster_finished_callback
) {
187 return make_scoped_refptr(new RasterRequiredForActivationFinishedTaskImpl(
189 on_raster_finished_callback
,
190 tasks_required_for_activation_count
));
194 void RasterWorkerPool::ScheduleTasksOnOriginThread(RasterizerTaskClient
* client
,
196 TRACE_EVENT0("cc", "Rasterizer::ScheduleTasksOnOriginThread");
198 for (TaskGraph::Node::Vector::iterator it
= graph
->nodes
.begin();
199 it
!= graph
->nodes
.end();
201 TaskGraph::Node
& node
= *it
;
202 RasterizerTask
* task
= static_cast<RasterizerTask
*>(node
.task
);
204 if (!task
->HasBeenScheduled()) {
205 task
->WillSchedule();
206 task
->ScheduleOnOriginThread(client
);
213 void RasterWorkerPool::InsertNodeForTask(TaskGraph
* graph
,
214 RasterizerTask
* task
,
216 size_t dependencies
) {
217 DCHECK(std::find_if(graph
->nodes
.begin(),
219 TaskGraph::Node::TaskComparator(task
)) ==
221 graph
->nodes
.push_back(TaskGraph::Node(task
, priority
, dependencies
));
225 void RasterWorkerPool::InsertNodesForRasterTask(
227 RasterTask
* raster_task
,
228 const ImageDecodeTask::Vector
& decode_tasks
,
230 size_t dependencies
= 0u;
232 // Insert image decode tasks.
233 for (ImageDecodeTask::Vector::const_iterator it
= decode_tasks
.begin();
234 it
!= decode_tasks
.end();
236 ImageDecodeTask
* decode_task
= it
->get();
238 // Skip if already decoded.
239 if (decode_task
->HasCompleted())
244 // Add decode task if it doesn't already exists in graph.
245 TaskGraph::Node::Vector::iterator decode_it
=
246 std::find_if(graph
->nodes
.begin(),
248 TaskGraph::Node::TaskComparator(decode_task
));
249 if (decode_it
== graph
->nodes
.end())
250 InsertNodeForTask(graph
, decode_task
, priority
, 0u);
252 graph
->edges
.push_back(TaskGraph::Edge(decode_task
, raster_task
));
255 InsertNodeForTask(graph
, raster_task
, priority
, dependencies
);