Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: cc/resources/pixel_buffer_raster_worker_pool.cc

Issue 16190002: cc: Add new RasterWorkerPool interface. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Add missing CheckForCompletedTasks calls Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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/pixel_buffer_raster_worker_pool.h"
6
7 #include "base/debug/trace_event.h"
8 #include "cc/resources/resource.h"
9 #include "third_party/skia/include/core/SkDevice.h"
10
11 namespace cc {
12
13 namespace {
14
15 class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask {
16 public:
17 typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply;
18
19 PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task,
20 TaskVector* dependencies,
21 uint8_t* buffer,
22 const Reply& reply)
23 : internal::WorkerPoolTask(dependencies),
24 task_(task),
25 buffer_(buffer),
26 reply_(reply),
27 needs_upload_(false) {
28 }
29
30 // Overridden from internal::WorkerPoolTask:
31 virtual void RunOnThread(unsigned thread_index) OVERRIDE {
32 // |buffer_| can be NULL in lost context situations.
33 if (!buffer_)
34 return;
35 SkBitmap bitmap;
36 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
37 task_->resource()->size().width(),
38 task_->resource()->size().height());
39 bitmap.setPixels(buffer_);
40 SkDevice device(bitmap);
41 needs_upload_ = task_->RunOnThread(&device, thread_index);
42 }
43 virtual void DispatchCompletionCallback() OVERRIDE {
44 DCHECK(HasFinishedRunning() || !needs_upload_);
45 reply_.Run(!HasFinishedRunning(), needs_upload_);
46 }
47
48 private:
49 virtual ~PixelBufferWorkerPoolTaskImpl() {}
50
51 scoped_refptr<internal::RasterWorkerPoolTask> task_;
52 uint8_t* buffer_;
53 const Reply reply_;
54 bool needs_upload_;
55
56 DISALLOW_COPY_AND_ASSIGN(PixelBufferWorkerPoolTaskImpl);
57 };
58
59 // If we raster too fast we become upload bound, and pending
60 // uploads consume memory. For maximum upload throughput, we would
61 // want to allow for upload_throughput * pipeline_time of pending
62 // uploads, after which we are just wasting memory. Since we don't
63 // know our upload throughput yet, this just caps our memory usage.
64 #if defined(OS_ANDROID)
65 // For reference, the Nexus10 can upload 1MB in about 2.5ms.
66 // Assuming a three frame deep pipeline this implies ~20MB.
67 const size_t kMaxPendingUploadBytes = 20 * 1024 * 1024;
68 // TODO(epenner): We should remove this upload limit (crbug.com/176197)
69 const size_t kMaxPendingUploads = 72;
70 #else
71 const size_t kMaxPendingUploadBytes = 100 * 1024 * 1024;
72 const size_t kMaxPendingUploads = 1000;
73 #endif
74
75 } // namespace
76
77 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
78 ResourceProvider* resource_provider,
79 size_t num_threads) : RasterWorkerPool(resource_provider, num_threads),
80 bytes_pending_upload_(0),
81 has_performed_uploads_since_last_flush_(false) {
82 // TODO(reveman): Remove WorkerPool client interface.
83 WorkerPool::SetClient(this);
84 }
85
86 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
87 DCHECK_EQ(0u, pixel_buffer_tasks_.size());
88 DCHECK_EQ(0u, tasks_with_pending_upload_.size());
89 }
90
91 void PixelBufferRasterWorkerPool::Shutdown() {
92 RasterWorkerPool::Shutdown();
93 AbortPendingUploads();
94 for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
95 it != pixel_buffer_tasks_.end(); ++it) {
96 internal::RasterWorkerPoolTask* task = it->first;
97 DCHECK(!it->second);
98
99 // Everything else has been canceled.
100 DidFinishRasterTask(task);
101 }
102 pixel_buffer_tasks_.clear();
103 }
104
105 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
106 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
107
108 RasterWorkerPool::SetRasterTasks(queue);
109
110 // Build new pixel buffer task set.
111 TaskMap new_pixel_buffer_tasks;
112 for (RasterTask::Queue::TaskVector::iterator it = raster_tasks_.begin();
113 it != raster_tasks_.end(); ++it) {
114 internal::RasterWorkerPoolTask* task = *it;
115 DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end());
116 DCHECK(!task->HasCompleted());
117
118 // Use existing pixel buffer task if available.
119 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task);
120 if (pixel_buffer_it == pixel_buffer_tasks_.end()) {
121 new_pixel_buffer_tasks[task] = NULL;
122 continue;
123 }
124
125 new_pixel_buffer_tasks[task] = pixel_buffer_it->second;
126 pixel_buffer_tasks_.erase(task);
127 }
128
129 // Transfer active pixel buffer tasks to |new_pixel_buffer_tasks|
130 // and cancel any remaining tasks.
131 for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
132 it != pixel_buffer_tasks_.end(); ++it) {
133 internal::RasterWorkerPoolTask* task = it->first;
134
135 // Move task to |new_pixel_buffer_tasks|
136 if (it->second) {
137 new_pixel_buffer_tasks[task] = it->second;
138 continue;
139 }
140
141 // Everything else can be canceled.
142 DidFinishRasterTask(task);
143 }
144
145 pixel_buffer_tasks_.swap(new_pixel_buffer_tasks);
146
147 ScheduleMoreTasks();
148 }
149
150 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
151 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
152
153 WorkerPool::CheckForCompletedTasks();
154
155 while (!tasks_with_pending_upload_.empty()) {
156 internal::RasterWorkerPoolTask* task = tasks_with_pending_upload_.front();
157
158 // Uploads complete in the order they are issued.
159 if (!resource_provider_->DidSetPixelsComplete(task->resource()->id()))
160 break;
161
162 // It's now safe to release the pixel buffer and the shared memory.
163 resource_provider_->ReleasePixelBuffer(task->resource()->id());
164
165 task->DidRun();
166 DidFinishRasterTask(task);
167 pixel_buffer_tasks_.erase(task);
168
169 bytes_pending_upload_ -= task->resource()->bytes();
170 tasks_with_pending_upload_.pop_front();
171 }
172
173 ScheduleMoreTasks();
174 }
175
176 bool PixelBufferRasterWorkerPool::ForceUploadToComplete(
177 const RasterTask& raster_task) {
178 for (TaskDeque::iterator it = tasks_with_pending_upload_.begin();
179 it != tasks_with_pending_upload_.end(); ++it) {
180 internal::RasterWorkerPoolTask* task = *it;
181 if (task == raster_task.internal_) {
182 resource_provider_->ForceSetPixelsToComplete(task->resource()->id());
183 return true;
184 }
185 }
186
187 return false;
188 }
189
190 void PixelBufferRasterWorkerPool::
191 DidFinishDispatchingWorkerPoolCompletionCallbacks() {
192 // If a flush is needed, do it now before starting to dispatch more tasks.
193 if (has_performed_uploads_since_last_flush_) {
194 resource_provider_->ShallowFlushIfSupported();
195 has_performed_uploads_since_last_flush_ = false;
196 }
197 }
198
199 bool PixelBufferRasterWorkerPool::CanScheduleRasterTask(
200 internal::RasterWorkerPoolTask* task) {
201 if (tasks_with_pending_upload_.size() >= kMaxPendingUploads)
202 return false;
203 size_t new_bytes_pending = bytes_pending_upload_;
204 new_bytes_pending += task->resource()->bytes();
205 return new_bytes_pending <= kMaxPendingUploadBytes;
206 }
207
208 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
209 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
210
211 internal::WorkerPoolTask::TaskVector raster_tasks;
212
213 for (RasterTask::Queue::TaskVector::iterator it = raster_tasks_.begin();
214 it != raster_tasks_.end(); ++it) {
215 internal::RasterWorkerPoolTask* task = *it;
216
217 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task);
218 if (pixel_buffer_it == pixel_buffer_tasks_.end())
219 continue;
220
221 scoped_refptr<internal::WorkerPoolTask> pixel_buffer_task(
222 pixel_buffer_it->second);
223 if (pixel_buffer_task) {
224 if (!pixel_buffer_task->HasCompleted())
225 raster_tasks.push_back(pixel_buffer_task);
226 continue;
227 }
228
229 if (!CanScheduleRasterTask(task))
230 break;
231
232 // Request a pixel buffer. This will reserve shared memory.
233 resource_provider_->AcquirePixelBuffer(task->resource()->id());
234
235 // MapPixelBuffer() returns NULL if context was lost at the time
236 // AcquirePixelBuffer() was called. For simplicity we still post
237 // a raster task that is essentially a noop in these situations.
238 uint8* buffer = resource_provider_->MapPixelBuffer(task->resource()->id());
239
240 // TODO(reveman): Avoid having to make a copy of dependencies.
241 internal::WorkerPoolTask::TaskVector dependencies = task->dependencies();
242 pixel_buffer_task = make_scoped_refptr(
243 new PixelBufferWorkerPoolTaskImpl(
244 task,
245 &dependencies,
246 buffer,
247 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted,
248 base::Unretained(this),
249 make_scoped_refptr(task))));
250
251 pixel_buffer_tasks_[task] = pixel_buffer_task;
252 raster_tasks.push_back(pixel_buffer_task);
253 }
254
255 ScheduleRasterTasks(&raster_tasks);
256 }
257
258 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted(
259 scoped_refptr<internal::RasterWorkerPoolTask> task,
260 bool was_canceled,
261 bool needs_upload) {
262 TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
263 "was_canceled", was_canceled,
264 "needs_upload", needs_upload);
265
266 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
267
268 // Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
269 resource_provider_->UnmapPixelBuffer(task->resource()->id());
270
271 if (!needs_upload) {
272 resource_provider_->ReleasePixelBuffer(task->resource()->id());
273 // No upload needed. Dispatch completion callback.
274 if (!was_canceled)
275 task->DidRun();
276
277 DidFinishRasterTask(task);
278 pixel_buffer_tasks_.erase(task);
279 return;
280 }
281
282 resource_provider_->BeginSetPixels(task->resource()->id());
283 has_performed_uploads_since_last_flush_ = true;
284
285 bytes_pending_upload_ += task->resource()->bytes();
286 tasks_with_pending_upload_.push_back(task);
287 }
288
289 void PixelBufferRasterWorkerPool::AbortPendingUploads() {
290 while (!tasks_with_pending_upload_.empty()) {
291 internal::RasterWorkerPoolTask* task = tasks_with_pending_upload_.front();
292
293 resource_provider_->AbortSetPixels(task->resource()->id());
294 resource_provider_->ReleasePixelBuffer(task->resource()->id());
295
296 // Need to run the reply callback even though task was aborted.
297 DidFinishRasterTask(task);
298 pixel_buffer_tasks_.erase(task);
299
300 bytes_pending_upload_ -= task->resource()->bytes();
301 tasks_with_pending_upload_.pop_front();
302 }
303 }
304
305 void PixelBufferRasterWorkerPool::DidFinishRasterTask(
306 internal::RasterWorkerPoolTask* task) {
307 task->DidComplete();
308 task->DispatchCompletionCallback();
309 }
310
311 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698