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"
9 #include "base/debug/trace_event.h"
10 #include "cc/output/context_provider.h"
11 #include "cc/resources/raster_buffer.h"
12 #include "cc/resources/raster_source.h"
13 #include "cc/resources/resource.h"
14 #include "cc/resources/resource_provider.h"
15 #include "cc/resources/scoped_gpu_raster.h"
16 #include "gpu/command_buffer/client/gles2_interface.h"
17 #include "third_party/skia/include/core/SkMultiPictureDraw.h"
18 #include "third_party/skia/include/core/SkPictureRecorder.h"
19 #include "third_party/skia/include/core/SkSurface.h"
20 #include "third_party/skia/include/gpu/GrContext.h"
25 class RasterBufferImpl
: public RasterBuffer
{
27 RasterBufferImpl(ResourceProvider
* resource_provider
,
28 const Resource
* resource
,
29 SkMultiPictureDraw
* multi_picture_draw
,
30 bool use_distance_field_text
)
31 : lock_(resource_provider
, resource
->id()),
33 multi_picture_draw_(multi_picture_draw
),
34 use_distance_field_text_(use_distance_field_text
) {}
36 // Overridden from RasterBuffer:
37 void Playback(const RasterSource
* raster_source
,
38 const gfx::Rect
& rect
,
39 float scale
) override
{
40 // Turn on distance fields for layers that have ever animated.
41 bool use_distance_field_text
=
42 use_distance_field_text_
||
43 raster_source
->ShouldAttemptToUseDistanceFieldText();
44 SkSurface
* sk_surface
= lock_
.GetSkSurface(use_distance_field_text
,
45 raster_source
->CanUseLCDText());
50 SkPictureRecorder recorder
;
51 gfx::Size size
= resource_
->size();
52 const int flags
= SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag
;
53 skia::RefPtr
<SkCanvas
> canvas
=
54 skia::SharePtr(recorder
.beginRecording(size
.width(), size
.height(),
59 raster_source
->PlaybackToCanvas(canvas
.get(), rect
, scale
);
62 // Add the canvas and recorded picture to |multi_picture_draw_|.
63 skia::RefPtr
<SkPicture
> picture
= skia::AdoptRef(recorder
.endRecording());
64 multi_picture_draw_
->add(sk_surface
->getCanvas(), picture
.get());
68 ResourceProvider::ScopedWriteLockGr lock_
;
69 const Resource
* resource_
;
70 SkMultiPictureDraw
* multi_picture_draw_
;
71 bool use_distance_field_text_
;
73 DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl
);
79 scoped_ptr
<RasterWorkerPool
> GpuRasterWorkerPool::Create(
80 base::SequencedTaskRunner
* task_runner
,
81 ContextProvider
* context_provider
,
82 ResourceProvider
* resource_provider
,
83 bool use_distance_field_text
) {
84 return make_scoped_ptr
<RasterWorkerPool
>(
85 new GpuRasterWorkerPool(task_runner
,
88 use_distance_field_text
));
91 GpuRasterWorkerPool::GpuRasterWorkerPool(base::SequencedTaskRunner
* task_runner
,
92 ContextProvider
* context_provider
,
93 ResourceProvider
* resource_provider
,
94 bool use_distance_field_text
)
95 : task_runner_(task_runner
),
96 task_graph_runner_(new TaskGraphRunner
),
97 namespace_token_(task_graph_runner_
->GetNamespaceToken()),
98 context_provider_(context_provider
),
99 resource_provider_(resource_provider
),
100 run_tasks_on_origin_thread_pending_(false),
101 use_distance_field_text_(use_distance_field_text
),
102 raster_finished_weak_ptr_factory_(this),
103 weak_ptr_factory_(this) {
104 DCHECK(context_provider_
);
107 GpuRasterWorkerPool::~GpuRasterWorkerPool() {
108 DCHECK_EQ(0u, completed_tasks_
.size());
111 Rasterizer
* GpuRasterWorkerPool::AsRasterizer() {
115 void GpuRasterWorkerPool::SetClient(RasterizerClient
* client
) {
119 void GpuRasterWorkerPool::Shutdown() {
120 TRACE_EVENT0("cc", "GpuRasterWorkerPool::Shutdown");
123 task_graph_runner_
->ScheduleTasks(namespace_token_
, &empty
);
124 task_graph_runner_
->WaitForTasksToFinishRunning(namespace_token_
);
127 void GpuRasterWorkerPool::ScheduleTasks(RasterTaskQueue
* queue
) {
128 TRACE_EVENT0("cc", "GpuRasterWorkerPool::ScheduleTasks");
130 // Mark all task sets as pending.
131 raster_pending_
.set();
133 unsigned priority
= kRasterTaskPriorityBase
;
137 // Cancel existing OnRasterFinished callbacks.
138 raster_finished_weak_ptr_factory_
.InvalidateWeakPtrs();
140 scoped_refptr
<RasterizerTask
> new_raster_finished_tasks
[kNumberOfTaskSets
];
142 size_t task_count
[kNumberOfTaskSets
] = {0};
144 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
145 new_raster_finished_tasks
[task_set
] = CreateRasterFinishedTask(
147 base::Bind(&GpuRasterWorkerPool::OnRasterFinished
,
148 raster_finished_weak_ptr_factory_
.GetWeakPtr(),
152 for (RasterTaskQueue::Item::Vector::const_iterator it
= queue
->items
.begin();
153 it
!= queue
->items
.end();
155 const RasterTaskQueue::Item
& item
= *it
;
156 RasterTask
* task
= item
.task
;
157 DCHECK(!task
->HasCompleted());
159 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
160 if (!item
.task_sets
[task_set
])
163 ++task_count
[task_set
];
165 graph_
.edges
.push_back(
166 TaskGraph::Edge(task
, new_raster_finished_tasks
[task_set
].get()));
169 InsertNodesForRasterTask(&graph_
, task
, task
->dependencies(), priority
++);
172 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
173 InsertNodeForTask(&graph_
,
174 new_raster_finished_tasks
[task_set
].get(),
175 kRasterFinishedTaskPriority
,
176 task_count
[task_set
]);
179 ScheduleTasksOnOriginThread(this, &graph_
);
180 task_graph_runner_
->ScheduleTasks(namespace_token_
, &graph_
);
182 ScheduleRunTasksOnOriginThread();
184 std::copy(new_raster_finished_tasks
,
185 new_raster_finished_tasks
+ kNumberOfTaskSets
,
186 raster_finished_tasks_
);
189 void GpuRasterWorkerPool::CheckForCompletedTasks() {
190 TRACE_EVENT0("cc", "GpuRasterWorkerPool::CheckForCompletedTasks");
192 task_graph_runner_
->CollectCompletedTasks(namespace_token_
,
194 for (Task::Vector::const_iterator it
= completed_tasks_
.begin();
195 it
!= completed_tasks_
.end();
197 RasterizerTask
* task
= static_cast<RasterizerTask
*>(it
->get());
199 task
->WillComplete();
200 task
->CompleteOnOriginThread(this);
203 task
->RunReplyOnOriginThread();
205 completed_tasks_
.clear();
208 scoped_ptr
<RasterBuffer
> GpuRasterWorkerPool::AcquireBufferForRaster(
209 const Resource
* resource
) {
210 return make_scoped_ptr
<RasterBuffer
>(
211 new RasterBufferImpl(resource_provider_
,
213 &multi_picture_draw_
,
214 use_distance_field_text_
));
217 void GpuRasterWorkerPool::ReleaseBufferForRaster(
218 scoped_ptr
<RasterBuffer
> buffer
) {
219 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
222 void GpuRasterWorkerPool::OnRasterFinished(TaskSet task_set
) {
224 "cc", "GpuRasterWorkerPool::OnRasterFinished", "task_set", task_set
);
226 DCHECK(raster_pending_
[task_set
]);
227 raster_pending_
[task_set
] = false;
228 client_
->DidFinishRunningTasks(task_set
);
231 void GpuRasterWorkerPool::ScheduleRunTasksOnOriginThread() {
232 if (run_tasks_on_origin_thread_pending_
)
235 task_runner_
->PostTask(
237 base::Bind(&GpuRasterWorkerPool::RunTasksOnOriginThread
,
238 weak_ptr_factory_
.GetWeakPtr()));
239 run_tasks_on_origin_thread_pending_
= true;
242 void GpuRasterWorkerPool::RunTasksOnOriginThread() {
243 TRACE_EVENT0("cc", "GpuRasterWorkerPool::RunTasksOnOriginThread");
245 DCHECK(run_tasks_on_origin_thread_pending_
);
246 run_tasks_on_origin_thread_pending_
= false;
248 ScopedGpuRaster
gpu_raster(context_provider_
);
249 task_graph_runner_
->RunUntilIdle();
251 // Draw each all of the pictures that were collected. This will also clear
252 // the pictures and canvases added to |multi_picture_draw_|
253 multi_picture_draw_
.draw();