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

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

Powered by Google App Engine
This is Rietveld 408576698