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

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

Powered by Google App Engine
This is Rietveld 408576698