Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / cc / resources / gpu_raster_worker_pool.cc
blobd29855ad5c150c92cf64791e607c50fb14cb7043
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 <algorithm>
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"
22 namespace cc {
23 namespace {
25 class RasterBufferImpl : public RasterBuffer {
26 public:
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()),
32 resource_(resource),
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());
47 if (!sk_surface)
48 return;
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(),
55 NULL, flags));
58 canvas->save();
59 raster_source->PlaybackToCanvas(canvas.get(), rect, scale);
60 canvas->restore();
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());
67 private:
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);
76 } // namespace
78 // static
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,
86 context_provider,
87 resource_provider,
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() {
112 return this;
115 void GpuRasterWorkerPool::SetClient(RasterizerClient* client) {
116 client_ = client;
119 void GpuRasterWorkerPool::Shutdown() {
120 TRACE_EVENT0("cc", "GpuRasterWorkerPool::Shutdown");
122 TaskGraph empty;
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;
135 graph_.Reset();
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(
146 task_runner_.get(),
147 base::Bind(&GpuRasterWorkerPool::OnRasterFinished,
148 raster_finished_weak_ptr_factory_.GetWeakPtr(),
149 task_set));
152 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
153 it != queue->items.end();
154 ++it) {
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])
161 continue;
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_,
193 &completed_tasks_);
194 for (Task::Vector::const_iterator it = completed_tasks_.begin();
195 it != completed_tasks_.end();
196 ++it) {
197 RasterizerTask* task = static_cast<RasterizerTask*>(it->get());
199 task->WillComplete();
200 task->CompleteOnOriginThread(this);
201 task->DidComplete();
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_,
212 resource,
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) {
223 TRACE_EVENT1(
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_)
233 return;
235 task_runner_->PostTask(
236 FROM_HERE,
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();
256 } // namespace cc