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.
5 #include "cc/resources/gpu_raster_worker_pool.h"
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 "cc/resources/scoped_gpu_raster.h"
12 #include "gpu/command_buffer/client/gles2_interface.h"
13 #include "third_party/skia/include/gpu/GrContext.h"
18 scoped_ptr
<RasterWorkerPool
> GpuRasterWorkerPool::Create(
19 base::SequencedTaskRunner
* task_runner
,
20 ContextProvider
* context_provider
,
21 ResourceProvider
* resource_provider
) {
22 return make_scoped_ptr
<RasterWorkerPool
>(new GpuRasterWorkerPool(
23 task_runner
, context_provider
, resource_provider
));
26 GpuRasterWorkerPool::GpuRasterWorkerPool(base::SequencedTaskRunner
* task_runner
,
27 ContextProvider
* context_provider
,
28 ResourceProvider
* resource_provider
)
29 : task_runner_(task_runner
),
30 task_graph_runner_(new TaskGraphRunner
),
31 namespace_token_(task_graph_runner_
->GetNamespaceToken()),
32 context_provider_(context_provider
),
33 resource_provider_(resource_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 DCHECK(context_provider_
);
42 GpuRasterWorkerPool::~GpuRasterWorkerPool() {
43 DCHECK_EQ(0u, completed_tasks_
.size());
46 Rasterizer
* GpuRasterWorkerPool::AsRasterizer() {
50 void GpuRasterWorkerPool::SetClient(RasterizerClient
* client
) {
54 void GpuRasterWorkerPool::Shutdown() {
55 TRACE_EVENT0("cc", "GpuRasterWorkerPool::Shutdown");
58 task_graph_runner_
->ScheduleTasks(namespace_token_
, &empty
);
59 task_graph_runner_
->WaitForTasksToFinishRunning(namespace_token_
);
62 void GpuRasterWorkerPool::ScheduleTasks(RasterTaskQueue
* queue
) {
63 TRACE_EVENT0("cc", "GpuRasterWorkerPool::ScheduleTasks");
65 DCHECK_EQ(queue
->required_for_activation_count
,
67 std::count_if(queue
->items
.begin(),
69 RasterTaskQueue::Item::IsRequiredForActivation
)));
71 raster_tasks_pending_
= true;
72 raster_tasks_required_for_activation_pending_
= true;
74 unsigned priority
= kRasterTaskPriorityBase
;
78 // Cancel existing OnRasterFinished callbacks.
79 raster_finished_weak_ptr_factory_
.InvalidateWeakPtrs();
81 scoped_refptr
<RasterizerTask
>
82 new_raster_required_for_activation_finished_task(
83 CreateRasterRequiredForActivationFinishedTask(
84 queue
->required_for_activation_count
,
87 &GpuRasterWorkerPool::OnRasterRequiredForActivationFinished
,
88 raster_finished_weak_ptr_factory_
.GetWeakPtr())));
89 scoped_refptr
<RasterizerTask
> new_raster_finished_task(
90 CreateRasterFinishedTask(
92 base::Bind(&GpuRasterWorkerPool::OnRasterFinished
,
93 raster_finished_weak_ptr_factory_
.GetWeakPtr())));
95 for (RasterTaskQueue::Item::Vector::const_iterator it
= queue
->items
.begin();
96 it
!= queue
->items
.end();
98 const RasterTaskQueue::Item
& item
= *it
;
99 RasterTask
* task
= item
.task
;
100 DCHECK(!task
->HasCompleted());
102 if (item
.required_for_activation
) {
103 graph_
.edges
.push_back(TaskGraph::Edge(
104 task
, new_raster_required_for_activation_finished_task
.get()));
107 InsertNodesForRasterTask(&graph_
, task
, task
->dependencies(), priority
++);
109 graph_
.edges
.push_back(
110 TaskGraph::Edge(task
, new_raster_finished_task
.get()));
113 InsertNodeForTask(&graph_
,
114 new_raster_required_for_activation_finished_task
.get(),
115 kRasterRequiredForActivationFinishedTaskPriority
,
116 queue
->required_for_activation_count
);
117 InsertNodeForTask(&graph_
,
118 new_raster_finished_task
.get(),
119 kRasterFinishedTaskPriority
,
120 queue
->items
.size());
122 ScheduleTasksOnOriginThread(this, &graph_
);
123 task_graph_runner_
->ScheduleTasks(namespace_token_
, &graph_
);
125 ScheduleRunTasksOnOriginThread();
127 raster_finished_task_
= new_raster_finished_task
;
128 raster_required_for_activation_finished_task_
=
129 new_raster_required_for_activation_finished_task
;
132 void GpuRasterWorkerPool::CheckForCompletedTasks() {
133 TRACE_EVENT0("cc", "GpuRasterWorkerPool::CheckForCompletedTasks");
135 task_graph_runner_
->CollectCompletedTasks(namespace_token_
,
137 for (Task::Vector::const_iterator it
= completed_tasks_
.begin();
138 it
!= completed_tasks_
.end();
140 RasterizerTask
* task
= static_cast<RasterizerTask
*>(it
->get());
142 task
->WillComplete();
143 task
->CompleteOnOriginThread(this);
146 task
->RunReplyOnOriginThread();
148 completed_tasks_
.clear();
151 SkCanvas
* GpuRasterWorkerPool::AcquireCanvasForRaster(RasterTask
* task
) {
152 return resource_provider_
->MapGpuRasterBuffer(task
->resource()->id());
155 void GpuRasterWorkerPool::ReleaseCanvasForRaster(RasterTask
* task
) {
156 resource_provider_
->UnmapGpuRasterBuffer(task
->resource()->id());
159 void GpuRasterWorkerPool::OnRasterFinished() {
160 TRACE_EVENT0("cc", "GpuRasterWorkerPool::OnRasterFinished");
162 DCHECK(raster_tasks_pending_
);
163 raster_tasks_pending_
= false;
164 client_
->DidFinishRunningTasks();
167 void GpuRasterWorkerPool::OnRasterRequiredForActivationFinished() {
169 "GpuRasterWorkerPool::OnRasterRequiredForActivationFinished");
171 DCHECK(raster_tasks_required_for_activation_pending_
);
172 raster_tasks_required_for_activation_pending_
= false;
173 client_
->DidFinishRunningTasksRequiredForActivation();
176 void GpuRasterWorkerPool::ScheduleRunTasksOnOriginThread() {
177 if (run_tasks_on_origin_thread_pending_
)
180 task_runner_
->PostTask(
182 base::Bind(&GpuRasterWorkerPool::RunTasksOnOriginThread
,
183 weak_ptr_factory_
.GetWeakPtr()));
184 run_tasks_on_origin_thread_pending_
= true;
187 void GpuRasterWorkerPool::RunTasksOnOriginThread() {
188 TRACE_EVENT0("cc", "GpuRasterWorkerPool::RunTasksOnOriginThread");
190 DCHECK(run_tasks_on_origin_thread_pending_
);
191 run_tasks_on_origin_thread_pending_
= false;
193 ScopedGpuRaster
gpu_raster(context_provider_
);
194 task_graph_runner_
->RunUntilIdle();