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/direct_raster_worker_pool.h"
7 #include "cc/output/context_provider.h"
8 #include "cc/resources/resource.h"
9 #include "cc/resources/resource_provider.h"
10 #include "gpu/command_buffer/client/gles2_interface.h"
11 #include "third_party/skia/include/gpu/GrContext.h"
16 scoped_ptr
<RasterWorkerPool
> DirectRasterWorkerPool::Create(
17 ResourceProvider
* resource_provider
,
18 ContextProvider
* context_provider
) {
19 return make_scoped_ptr
<RasterWorkerPool
>(
20 new DirectRasterWorkerPool(resource_provider
, context_provider
));
23 DirectRasterWorkerPool::DirectRasterWorkerPool(
24 ResourceProvider
* resource_provider
,
25 ContextProvider
* context_provider
)
26 : RasterWorkerPool(NULL
, resource_provider
),
27 context_provider_(context_provider
),
28 run_tasks_on_origin_thread_pending_(false),
29 raster_tasks_pending_(false),
30 raster_tasks_required_for_activation_pending_(false),
31 weak_factory_(this) {}
33 DirectRasterWorkerPool::~DirectRasterWorkerPool() {
34 DCHECK_EQ(0u, completed_tasks_
.size());
37 void DirectRasterWorkerPool::ScheduleTasks(RasterTaskQueue
* queue
) {
38 TRACE_EVENT0("cc", "DirectRasterWorkerPool::ScheduleTasks");
40 DCHECK_EQ(queue
->required_for_activation_count
,
42 std::count_if(queue
->items
.begin(),
44 RasterTaskQueue::Item::IsRequiredForActivation
)));
46 raster_tasks_pending_
= true;
47 raster_tasks_required_for_activation_pending_
= true;
49 scoped_refptr
<internal::WorkerPoolTask
>
50 new_raster_required_for_activation_finished_task(
51 CreateRasterRequiredForActivationFinishedTask(
52 queue
->required_for_activation_count
));
53 scoped_refptr
<internal::WorkerPoolTask
> new_raster_finished_task(
54 CreateRasterFinishedTask());
56 // Need to cancel tasks not present in new queue if we haven't had a
57 // chance to run the previous set of tasks yet.
58 // TODO(reveman): Remove this once only tasks for which
59 // ::ScheduleOnOriginThread has been called need to be canceled.
60 if (run_tasks_on_origin_thread_pending_
) {
61 for (RasterTaskQueue::Item::Vector::const_iterator it
=
62 raster_tasks_
.items
.begin();
63 it
!= raster_tasks_
.items
.end();
65 internal::RasterWorkerPoolTask
* task
= it
->task
;
67 if (std::find_if(queue
->items
.begin(),
69 RasterTaskQueue::Item::TaskComparator(task
)) ==
71 completed_tasks_
.push_back(task
);
75 ScheduleRunTasksOnOriginThread();
77 raster_tasks_
.Swap(queue
);
79 set_raster_finished_task(new_raster_finished_task
);
80 set_raster_required_for_activation_finished_task(
81 new_raster_required_for_activation_finished_task
);
84 unsigned DirectRasterWorkerPool::GetResourceTarget() const {
88 ResourceFormat
DirectRasterWorkerPool::GetResourceFormat() const {
89 return resource_provider()->best_texture_format();
92 void DirectRasterWorkerPool::CheckForCompletedTasks() {
93 TRACE_EVENT0("cc", "DirectRasterWorkerPool::CheckForCompletedTasks");
95 for (internal::WorkerPoolTask::Vector::const_iterator it
=
96 completed_tasks_
.begin();
97 it
!= completed_tasks_
.end();
99 internal::WorkerPoolTask
* task
= it
->get();
101 task
->RunReplyOnOriginThread();
103 completed_tasks_
.clear();
106 SkCanvas
* DirectRasterWorkerPool::AcquireCanvasForRaster(
107 internal::WorkerPoolTask
* task
,
108 const Resource
* resource
) {
109 return resource_provider()->MapDirectRasterBuffer(resource
->id());
112 void DirectRasterWorkerPool::ReleaseCanvasForRaster(
113 internal::WorkerPoolTask
* task
,
114 const Resource
* resource
) {
115 resource_provider()->UnmapDirectRasterBuffer(resource
->id());
118 void DirectRasterWorkerPool::OnRasterTasksFinished() {
119 DCHECK(raster_tasks_pending_
);
120 raster_tasks_pending_
= false;
121 client()->DidFinishRunningTasks();
124 void DirectRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
125 DCHECK(raster_tasks_required_for_activation_pending_
);
126 raster_tasks_required_for_activation_pending_
= false;
127 client()->DidFinishRunningTasksRequiredForActivation();
130 void DirectRasterWorkerPool::ScheduleRunTasksOnOriginThread() {
131 if (run_tasks_on_origin_thread_pending_
)
134 base::MessageLoopProxy::current()->PostTask(
136 base::Bind(&DirectRasterWorkerPool::RunTasksOnOriginThread
,
137 weak_factory_
.GetWeakPtr()));
138 run_tasks_on_origin_thread_pending_
= true;
141 void DirectRasterWorkerPool::RunTasksOnOriginThread() {
142 TRACE_EVENT0("cc", "DirectRasterWorkerPool::RunTasksOnOriginThread");
144 DCHECK(run_tasks_on_origin_thread_pending_
);
145 run_tasks_on_origin_thread_pending_
= false;
147 if (!raster_tasks_
.items
.empty()) {
148 DCHECK(context_provider_
);
149 DCHECK(context_provider_
->ContextGL());
150 // TODO(alokp): Use a trace macro to push/pop markers.
151 // Using push/pop functions directly incurs cost to evaluate function
152 // arguments even when tracing is disabled.
153 context_provider_
->ContextGL()->PushGroupMarkerEXT(
154 0, "DirectRasterWorkerPool::RunTasksOnOriginThread");
156 GrContext
* gr_context
= context_provider_
->GrContext();
157 // TODO(alokp): Implement TestContextProvider::GrContext().
159 gr_context
->resetContext();
161 for (RasterTaskQueue::Item::Vector::const_iterator it
=
162 raster_tasks_
.items
.begin();
163 it
!= raster_tasks_
.items
.end();
165 internal::RasterWorkerPoolTask
* task
= it
->task
;
166 DCHECK(!task
->HasCompleted());
168 // First need to run all dependencies.
169 for (internal::WorkerPoolTask::Vector::const_iterator it
=
170 task
->dependencies().begin();
171 it
!= task
->dependencies().end();
173 internal::WorkerPoolTask
* dependency
= it
->get();
174 if (dependency
->HasCompleted())
177 RunTaskOnOriginThread(dependency
);
178 completed_tasks_
.push_back(dependency
);
181 RunTaskOnOriginThread(task
);
182 completed_tasks_
.push_back(task
);
185 // TODO(alokp): Implement TestContextProvider::GrContext().
189 context_provider_
->ContextGL()->PopGroupMarkerEXT();
192 RunTaskOnOriginThread(raster_required_for_activation_finished_task());
193 RunTaskOnOriginThread(raster_finished_task());