OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "cc/resources/gpu_raster_worker_pool.h" | |
6 | |
7 #include <algorithm> | |
8 | |
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" | |
21 | |
22 namespace cc { | |
23 namespace { | |
24 | |
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) {} | |
35 | |
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()); | |
46 | |
47 if (!sk_surface) | |
48 return; | |
49 | |
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)); | |
56 | |
57 | |
58 canvas->save(); | |
59 raster_source->PlaybackToCanvas(canvas.get(), rect, scale); | |
60 canvas->restore(); | |
61 | |
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()); | |
65 } | |
66 | |
67 private: | |
68 ResourceProvider::ScopedWriteLockGr lock_; | |
69 const Resource* resource_; | |
70 SkMultiPictureDraw* multi_picture_draw_; | |
71 bool use_distance_field_text_; | |
72 | |
73 DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); | |
74 }; | |
75 | |
76 } // namespace | |
77 | |
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)); | |
89 } | |
90 | |
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_); | |
105 } | |
106 | |
107 GpuRasterWorkerPool::~GpuRasterWorkerPool() { | |
108 DCHECK_EQ(0u, completed_tasks_.size()); | |
109 } | |
110 | |
111 Rasterizer* GpuRasterWorkerPool::AsRasterizer() { | |
112 return this; | |
113 } | |
114 | |
115 void GpuRasterWorkerPool::SetClient(RasterizerClient* client) { | |
116 client_ = client; | |
117 } | |
118 | |
119 void GpuRasterWorkerPool::Shutdown() { | |
120 TRACE_EVENT0("cc", "GpuRasterWorkerPool::Shutdown"); | |
121 | |
122 TaskGraph empty; | |
123 task_graph_runner_->ScheduleTasks(namespace_token_, &empty); | |
124 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); | |
125 } | |
126 | |
127 void GpuRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) { | |
128 TRACE_EVENT0("cc", "GpuRasterWorkerPool::ScheduleTasks"); | |
129 | |
130 // Mark all task sets as pending. | |
131 raster_pending_.set(); | |
132 | |
133 unsigned priority = kRasterTaskPriorityBase; | |
134 | |
135 graph_.Reset(); | |
136 | |
137 // Cancel existing OnRasterFinished callbacks. | |
138 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs(); | |
139 | |
140 scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets]; | |
141 | |
142 size_t task_count[kNumberOfTaskSets] = {0}; | |
143 | |
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)); | |
150 } | |
151 | |
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()); | |
158 | |
159 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) { | |
160 if (!item.task_sets[task_set]) | |
161 continue; | |
162 | |
163 ++task_count[task_set]; | |
164 | |
165 graph_.edges.push_back( | |
166 TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get())); | |
167 } | |
168 | |
169 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++); | |
170 } | |
171 | |
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]); | |
177 } | |
178 | |
179 ScheduleTasksOnOriginThread(this, &graph_); | |
180 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); | |
181 | |
182 ScheduleRunTasksOnOriginThread(); | |
183 | |
184 std::copy(new_raster_finished_tasks, | |
185 new_raster_finished_tasks + kNumberOfTaskSets, | |
186 raster_finished_tasks_); | |
187 } | |
188 | |
189 void GpuRasterWorkerPool::CheckForCompletedTasks() { | |
190 TRACE_EVENT0("cc", "GpuRasterWorkerPool::CheckForCompletedTasks"); | |
191 | |
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()); | |
198 | |
199 task->WillComplete(); | |
200 task->CompleteOnOriginThread(this); | |
201 task->DidComplete(); | |
202 | |
203 task->RunReplyOnOriginThread(); | |
204 } | |
205 completed_tasks_.clear(); | |
206 } | |
207 | |
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_)); | |
215 } | |
216 | |
217 void GpuRasterWorkerPool::ReleaseBufferForRaster( | |
218 scoped_ptr<RasterBuffer> buffer) { | |
219 // Nothing to do here. RasterBufferImpl destructor cleans up after itself. | |
220 } | |
221 | |
222 void GpuRasterWorkerPool::OnRasterFinished(TaskSet task_set) { | |
223 TRACE_EVENT1( | |
224 "cc", "GpuRasterWorkerPool::OnRasterFinished", "task_set", task_set); | |
225 | |
226 DCHECK(raster_pending_[task_set]); | |
227 raster_pending_[task_set] = false; | |
228 client_->DidFinishRunningTasks(task_set); | |
229 } | |
230 | |
231 void GpuRasterWorkerPool::ScheduleRunTasksOnOriginThread() { | |
232 if (run_tasks_on_origin_thread_pending_) | |
233 return; | |
234 | |
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; | |
240 } | |
241 | |
242 void GpuRasterWorkerPool::RunTasksOnOriginThread() { | |
243 TRACE_EVENT0("cc", "GpuRasterWorkerPool::RunTasksOnOriginThread"); | |
244 | |
245 DCHECK(run_tasks_on_origin_thread_pending_); | |
246 run_tasks_on_origin_thread_pending_ = false; | |
247 | |
248 ScopedGpuRaster gpu_raster(context_provider_); | |
249 task_graph_runner_->RunUntilIdle(); | |
250 | |
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(); | |
254 } | |
255 | |
256 } // namespace cc | |
OLD | NEW |