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

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: rebase 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
« no previous file with comments | « cc/resources/pixel_buffer_raster_worker_pool.h ('k') | cc/resources/raster_worker_pool.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_(true) {
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() || !buffer_ || !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 bytes_pending_upload_ -= task->resource()->bytes();
166
167 task->DidRun();
168 DidFinishRasterTask(task);
169 pixel_buffer_tasks_.erase(task);
170
171 tasks_with_pending_upload_.pop_front();
172 }
173
174 ScheduleMoreTasks();
175 }
176
177 bool PixelBufferRasterWorkerPool::ForceUploadToComplete(
178 const RasterTask& raster_task) {
179 for (TaskDeque::iterator it = tasks_with_pending_upload_.begin();
180 it != tasks_with_pending_upload_.end(); ++it) {
181 internal::RasterWorkerPoolTask* task = *it;
182 if (task == raster_task.internal_) {
183 resource_provider_->ForceSetPixelsToComplete(task->resource()->id());
184 return true;
185 }
186 }
187
188 return false;
189 }
190
191 void PixelBufferRasterWorkerPool::
192 DidFinishDispatchingWorkerPoolCompletionCallbacks() {
193 // If a flush is needed, do it now before starting to dispatch more tasks.
194 if (has_performed_uploads_since_last_flush_) {
195 resource_provider_->ShallowFlushIfSupported();
196 has_performed_uploads_since_last_flush_ = false;
197 }
198 }
199
200 bool PixelBufferRasterWorkerPool::CanScheduleRasterTask(
201 internal::RasterWorkerPoolTask* task) {
202 if (tasks_with_pending_upload_.size() >= kMaxPendingUploads)
203 return false;
204 size_t new_bytes_pending = bytes_pending_upload_;
205 new_bytes_pending += task->resource()->bytes();
206 return new_bytes_pending <= kMaxPendingUploadBytes;
207 }
208
209 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
210 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
211
212 internal::WorkerPoolTask::TaskVector raster_tasks;
213
214 for (RasterTask::Queue::TaskVector::iterator it = raster_tasks_.begin();
215 it != raster_tasks_.end(); ++it) {
216 internal::RasterWorkerPoolTask* task = *it;
217
218 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task);
219 if (pixel_buffer_it == pixel_buffer_tasks_.end())
220 continue;
221
222 scoped_refptr<internal::WorkerPoolTask> pixel_buffer_task(
223 pixel_buffer_it->second);
224 if (pixel_buffer_task) {
225 if (!pixel_buffer_task->HasCompleted())
226 raster_tasks.push_back(pixel_buffer_task);
227 continue;
228 }
229
230 if (!CanScheduleRasterTask(task))
231 break;
232
233 // Request a pixel buffer. This will reserve shared memory.
234 resource_provider_->AcquirePixelBuffer(task->resource()->id());
235
236 // MapPixelBuffer() returns NULL if context was lost at the time
237 // AcquirePixelBuffer() was called. For simplicity we still post
238 // a raster task that is essentially a noop in these situations.
239 uint8* buffer = resource_provider_->MapPixelBuffer(task->resource()->id());
240
241 // TODO(reveman): Avoid having to make a copy of dependencies.
242 internal::WorkerPoolTask::TaskVector dependencies = task->dependencies();
243 pixel_buffer_task = make_scoped_refptr(
244 new PixelBufferWorkerPoolTaskImpl(
245 task,
246 &dependencies,
247 buffer,
248 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted,
249 base::Unretained(this),
250 make_scoped_refptr(task))));
251
252 pixel_buffer_tasks_[task] = pixel_buffer_task;
253 raster_tasks.push_back(pixel_buffer_task);
254 }
255
256 ScheduleRasterTasks(&raster_tasks);
257 }
258
259 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted(
260 scoped_refptr<internal::RasterWorkerPoolTask> task,
261 bool was_canceled,
262 bool needs_upload) {
263 TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
264 "was_canceled", was_canceled,
265 "needs_upload", needs_upload);
266
267 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
268
269 // Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
270 resource_provider_->UnmapPixelBuffer(task->resource()->id());
271
272 if (!needs_upload) {
273 resource_provider_->ReleasePixelBuffer(task->resource()->id());
274 // No upload needed. Dispatch completion callback.
275 if (!was_canceled)
276 task->DidRun();
277
278 DidFinishRasterTask(task);
279 pixel_buffer_tasks_.erase(task);
280 return;
281 }
282
283 resource_provider_->BeginSetPixels(task->resource()->id());
284 has_performed_uploads_since_last_flush_ = true;
285
286 bytes_pending_upload_ += task->resource()->bytes();
287 tasks_with_pending_upload_.push_back(task);
288 }
289
290 void PixelBufferRasterWorkerPool::AbortPendingUploads() {
291 while (!tasks_with_pending_upload_.empty()) {
292 internal::RasterWorkerPoolTask* task = tasks_with_pending_upload_.front();
293
294 resource_provider_->AbortSetPixels(task->resource()->id());
295 resource_provider_->ReleasePixelBuffer(task->resource()->id());
296
297 bytes_pending_upload_ -= task->resource()->bytes();
298
299 // Need to run the reply callback even though task was aborted.
300 DidFinishRasterTask(task);
301 pixel_buffer_tasks_.erase(task);
302
303 tasks_with_pending_upload_.pop_front();
304 }
305 }
306
307 void PixelBufferRasterWorkerPool::DidFinishRasterTask(
308 internal::RasterWorkerPoolTask* task) {
309 task->DidComplete();
310 task->DispatchCompletionCallback();
311 }
312
313 } // namespace cc
OLDNEW
« no previous file with comments | « cc/resources/pixel_buffer_raster_worker_pool.h ('k') | cc/resources/raster_worker_pool.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698