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/containers/stack_container.h"
8 #include "base/debug/trace_event.h"
9 #include "base/values.h"
10 #include "cc/debug/traced_value.h"
11 #include "cc/resources/resource.h"
12 #include "third_party/skia/include/core/SkBitmapDevice.h"
13
14 #if defined(OS_ANDROID)
15 #include "base/android/sys_utils.h"
16 #endif
17
18 namespace cc {
19
20 namespace {
21
22 class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask {
23 public:
24 typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply;
25
PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask * task,uint8_t * buffer,const Reply & reply)26 PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task,
27 uint8_t* buffer,
28 const Reply& reply)
29 : task_(task),
30 buffer_(buffer),
31 reply_(reply),
32 needs_upload_(false) {
33 }
34
35 // Overridden from internal::WorkerPoolTask:
RunOnWorkerThread(unsigned thread_index)36 virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
37 // |buffer_| can be NULL in lost context situations.
38 if (!buffer_) {
39 // |needs_upload_| still needs to be true as task has not
40 // been canceled.
41 needs_upload_ = true;
42 return;
43 }
44 needs_upload_ = task_->RunOnWorkerThread(thread_index,
45 buffer_,
46 task_->resource()->size(),
47 0);
48 }
CompleteOnOriginThread()49 virtual void CompleteOnOriginThread() OVERRIDE {
50 // |needs_upload_| must be be false if task didn't run.
51 DCHECK(HasFinishedRunning() || !needs_upload_);
52 reply_.Run(!HasFinishedRunning(), needs_upload_);
53 }
54
55 private:
~PixelBufferWorkerPoolTaskImpl()56 virtual ~PixelBufferWorkerPoolTaskImpl() {}
57
58 scoped_refptr<internal::RasterWorkerPoolTask> task_;
59 uint8_t* buffer_;
60 const Reply reply_;
61 bool needs_upload_;
62
63 DISALLOW_COPY_AND_ASSIGN(PixelBufferWorkerPoolTaskImpl);
64 };
65
66 const int kCheckForCompletedRasterTasksDelayMs = 6;
67
68 const size_t kMaxScheduledRasterTasks = 48;
69
70 typedef base::StackVector<internal::GraphNode*,
71 kMaxScheduledRasterTasks> NodeVector;
72
AddDependenciesToGraphNode(internal::GraphNode * node,const NodeVector::ContainerType & dependencies)73 void AddDependenciesToGraphNode(
74 internal::GraphNode* node,
75 const NodeVector::ContainerType& dependencies) {
76 for (NodeVector::ContainerType::const_iterator it = dependencies.begin();
77 it != dependencies.end(); ++it) {
78 internal::GraphNode* dependency = *it;
79
80 node->add_dependency();
81 dependency->add_dependent(node);
82 }
83 }
84
85 // Only used as std::find_if predicate for DCHECKs.
WasCanceled(const internal::RasterWorkerPoolTask * task)86 bool WasCanceled(const internal::RasterWorkerPoolTask* task) {
87 return task->WasCanceled();
88 }
89
90 } // namespace
91
PixelBufferRasterWorkerPool(ResourceProvider * resource_provider,size_t num_threads,size_t max_transfer_buffer_usage_bytes)92 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
93 ResourceProvider* resource_provider,
94 size_t num_threads,
95 size_t max_transfer_buffer_usage_bytes)
96 : RasterWorkerPool(resource_provider, num_threads),
97 shutdown_(false),
98 scheduled_raster_task_count_(0),
99 bytes_pending_upload_(0),
100 max_bytes_pending_upload_(max_transfer_buffer_usage_bytes),
101 has_performed_uploads_since_last_flush_(false),
102 check_for_completed_raster_tasks_pending_(false),
103 should_notify_client_if_no_tasks_are_pending_(false),
104 should_notify_client_if_no_tasks_required_for_activation_are_pending_(
105 false) {
106 }
107
~PixelBufferRasterWorkerPool()108 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
109 DCHECK(shutdown_);
110 DCHECK(!check_for_completed_raster_tasks_pending_);
111 DCHECK_EQ(0u, pixel_buffer_tasks_.size());
112 DCHECK_EQ(0u, tasks_with_pending_upload_.size());
113 DCHECK_EQ(0u, completed_tasks_.size());
114 }
115
Shutdown()116 void PixelBufferRasterWorkerPool::Shutdown() {
117 shutdown_ = true;
118 RasterWorkerPool::Shutdown();
119 RasterWorkerPool::CheckForCompletedTasks();
120 CheckForCompletedUploads();
121 check_for_completed_raster_tasks_callback_.Cancel();
122 check_for_completed_raster_tasks_pending_ = false;
123 for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
124 it != pixel_buffer_tasks_.end(); ++it) {
125 internal::RasterWorkerPoolTask* task = it->first;
126 internal::WorkerPoolTask* pixel_buffer_task = it->second.get();
127
128 // All inactive tasks needs to be canceled.
129 if (!pixel_buffer_task && !task->HasFinishedRunning()) {
130 task->DidRun(true);
131 completed_tasks_.push_back(task);
132 }
133 }
134 DCHECK_EQ(completed_tasks_.size(), pixel_buffer_tasks_.size());
135 }
136
ScheduleTasks(RasterTask::Queue * queue)137 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
138 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
139
140 RasterWorkerPool::SetRasterTasks(queue);
141
142 if (!should_notify_client_if_no_tasks_are_pending_)
143 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
144
145 should_notify_client_if_no_tasks_are_pending_ = true;
146 should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true;
147
148 tasks_required_for_activation_.clear();
149
150 // Build new pixel buffer task set.
151 TaskMap new_pixel_buffer_tasks;
152 for (RasterTaskVector::const_iterator it = raster_tasks().begin();
153 it != raster_tasks().end(); ++it) {
154 internal::RasterWorkerPoolTask* task = it->get();
155 DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end());
156 DCHECK(!task->HasCompleted());
157 DCHECK(!task->WasCanceled());
158
159 new_pixel_buffer_tasks[task] = pixel_buffer_tasks_[task];
160 pixel_buffer_tasks_.erase(task);
161
162 if (IsRasterTaskRequiredForActivation(task))
163 tasks_required_for_activation_.insert(task);
164 }
165
166 // Transfer remaining pixel buffer tasks to |new_pixel_buffer_tasks|
167 // and cancel all remaining inactive tasks.
168 for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
169 it != pixel_buffer_tasks_.end(); ++it) {
170 internal::RasterWorkerPoolTask* task = it->first;
171 internal::WorkerPoolTask* pixel_buffer_task = it->second.get();
172
173 // Move task to |new_pixel_buffer_tasks|
174 new_pixel_buffer_tasks[task] = pixel_buffer_task;
175
176 // Inactive task can be canceled.
177 if (!pixel_buffer_task && !task->HasFinishedRunning()) {
178 task->DidRun(true);
179 DCHECK(std::find(completed_tasks_.begin(),
180 completed_tasks_.end(),
181 task) == completed_tasks_.end());
182 completed_tasks_.push_back(task);
183 } else if (IsRasterTaskRequiredForActivation(task)) {
184 tasks_required_for_activation_.insert(task);
185 }
186 }
187
188 // |tasks_required_for_activation_| contains all tasks that need to
189 // complete before we can send a "ready to activate" signal. Tasks
190 // that have already completed should not be part of this set.
191 for (TaskDeque::const_iterator it = completed_tasks_.begin();
192 it != completed_tasks_.end() && !tasks_required_for_activation_.empty();
193 ++it) {
194 tasks_required_for_activation_.erase(*it);
195 }
196
197 pixel_buffer_tasks_.swap(new_pixel_buffer_tasks);
198
199 // Check for completed tasks when ScheduleTasks() is called as
200 // priorities might have changed and this maximizes the number
201 // of top priority tasks that are scheduled.
202 RasterWorkerPool::CheckForCompletedTasks();
203 CheckForCompletedUploads();
204 FlushUploads();
205
206 // Schedule new tasks.
207 ScheduleMoreTasks();
208
209 // Cancel any pending check for completed raster tasks and schedule
210 // another check.
211 check_for_completed_raster_tasks_callback_.Cancel();
212 check_for_completed_raster_tasks_pending_ = false;
213 ScheduleCheckForCompletedRasterTasks();
214
215 TRACE_EVENT_ASYNC_STEP_INTO1(
216 "cc", "ScheduledTasks", this, StateName(),
217 "state", TracedValue::FromValue(StateAsValue().release()));
218 }
219
GetResourceTarget() const220 GLenum PixelBufferRasterWorkerPool::GetResourceTarget() const {
221 return GL_TEXTURE_2D;
222 }
223
GetResourceFormat() const224 ResourceFormat PixelBufferRasterWorkerPool::GetResourceFormat() const {
225 return resource_provider()->memory_efficient_texture_format();
226 }
227
CheckForCompletedTasks()228 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
229 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
230
231 RasterWorkerPool::CheckForCompletedTasks();
232 CheckForCompletedUploads();
233 FlushUploads();
234
235 TaskDeque completed_tasks;
236 completed_tasks_.swap(completed_tasks);
237
238 while (!completed_tasks.empty()) {
239 internal::RasterWorkerPoolTask* task = completed_tasks.front().get();
240 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
241
242 pixel_buffer_tasks_.erase(task);
243
244 task->WillComplete();
245 task->CompleteOnOriginThread();
246 task->DidComplete();
247
248 completed_tasks.pop_front();
249 }
250 }
251
OnRasterTasksFinished()252 void PixelBufferRasterWorkerPool::OnRasterTasksFinished() {
253 // |should_notify_client_if_no_tasks_are_pending_| can be set to false as
254 // a result of a scheduled CheckForCompletedRasterTasks() call. No need to
255 // perform another check in that case as we've already notified the client.
256 if (!should_notify_client_if_no_tasks_are_pending_)
257 return;
258
259 // Call CheckForCompletedRasterTasks() when we've finished running all
260 // raster tasks needed since last time ScheduleTasks() was called.
261 // This reduces latency between the time when all tasks have finished
262 // running and the time when the client is notified.
263 CheckForCompletedRasterTasks();
264 }
265
OnRasterTasksRequiredForActivationFinished()266 void PixelBufferRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
267 // Analogous to OnRasterTasksFinished(), there's no need to call
268 // CheckForCompletedRasterTasks() if the client has already been notified.
269 if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_)
270 return;
271
272 // This reduces latency between the time when all tasks required for
273 // activation have finished running and the time when the client is
274 // notified.
275 CheckForCompletedRasterTasks();
276 }
277
FlushUploads()278 void PixelBufferRasterWorkerPool::FlushUploads() {
279 if (!has_performed_uploads_since_last_flush_)
280 return;
281
282 resource_provider()->ShallowFlushIfSupported();
283 has_performed_uploads_since_last_flush_ = false;
284 }
285
CheckForCompletedUploads()286 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
287 TaskDeque tasks_with_completed_uploads;
288
289 // First check if any have completed.
290 while (!tasks_with_pending_upload_.empty()) {
291 internal::RasterWorkerPoolTask* task =
292 tasks_with_pending_upload_.front().get();
293
294 // Uploads complete in the order they are issued.
295 if (!resource_provider()->DidSetPixelsComplete(task->resource()->id()))
296 break;
297
298 tasks_with_completed_uploads.push_back(task);
299 tasks_with_pending_upload_.pop_front();
300 }
301
302 DCHECK(client());
303 bool should_force_some_uploads_to_complete =
304 shutdown_ || client()->ShouldForceTasksRequiredForActivationToComplete();
305
306 if (should_force_some_uploads_to_complete) {
307 TaskDeque tasks_with_uploads_to_force;
308 TaskDeque::iterator it = tasks_with_pending_upload_.begin();
309 while (it != tasks_with_pending_upload_.end()) {
310 internal::RasterWorkerPoolTask* task = it->get();
311 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
312
313 // Force all uploads required for activation to complete.
314 // During shutdown, force all pending uploads to complete.
315 if (shutdown_ || IsRasterTaskRequiredForActivation(task)) {
316 tasks_with_uploads_to_force.push_back(task);
317 tasks_with_completed_uploads.push_back(task);
318 it = tasks_with_pending_upload_.erase(it);
319 continue;
320 }
321
322 ++it;
323 }
324
325 // Force uploads in reverse order. Since forcing can cause a wait on
326 // all previous uploads, we would rather wait only once downstream.
327 for (TaskDeque::reverse_iterator it = tasks_with_uploads_to_force.rbegin();
328 it != tasks_with_uploads_to_force.rend();
329 ++it) {
330 resource_provider()->ForceSetPixelsToComplete((*it)->resource()->id());
331 has_performed_uploads_since_last_flush_ = true;
332 }
333 }
334
335 // Release shared memory and move tasks with completed uploads
336 // to |completed_tasks_|.
337 while (!tasks_with_completed_uploads.empty()) {
338 internal::RasterWorkerPoolTask* task =
339 tasks_with_completed_uploads.front().get();
340
341 // It's now safe to release the pixel buffer and the shared memory.
342 resource_provider()->ReleasePixelBuffer(task->resource()->id());
343
344 bytes_pending_upload_ -= task->resource()->bytes();
345
346 task->DidRun(false);
347
348 DCHECK(std::find(completed_tasks_.begin(),
349 completed_tasks_.end(),
350 task) == completed_tasks_.end());
351 completed_tasks_.push_back(task);
352
353 tasks_required_for_activation_.erase(task);
354
355 tasks_with_completed_uploads.pop_front();
356 }
357 }
358
ScheduleCheckForCompletedRasterTasks()359 void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() {
360 if (check_for_completed_raster_tasks_pending_)
361 return;
362
363 check_for_completed_raster_tasks_callback_.Reset(
364 base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks,
365 base::Unretained(this)));
366 base::MessageLoopProxy::current()->PostDelayedTask(
367 FROM_HERE,
368 check_for_completed_raster_tasks_callback_.callback(),
369 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs));
370 check_for_completed_raster_tasks_pending_ = true;
371 }
372
CheckForCompletedRasterTasks()373 void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
374 TRACE_EVENT0(
375 "cc", "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");
376
377 DCHECK(should_notify_client_if_no_tasks_are_pending_);
378
379 check_for_completed_raster_tasks_callback_.Cancel();
380 check_for_completed_raster_tasks_pending_ = false;
381
382 RasterWorkerPool::CheckForCompletedTasks();
383 CheckForCompletedUploads();
384 FlushUploads();
385
386 // Determine what client notifications to generate.
387 bool will_notify_client_that_no_tasks_required_for_activation_are_pending =
388 (should_notify_client_if_no_tasks_required_for_activation_are_pending_ &&
389 !HasPendingTasksRequiredForActivation());
390 bool will_notify_client_that_no_tasks_are_pending =
391 (should_notify_client_if_no_tasks_are_pending_ &&
392 !HasPendingTasks());
393
394 // Adjust the need to generate notifications before scheduling more tasks.
395 should_notify_client_if_no_tasks_required_for_activation_are_pending_ &=
396 !will_notify_client_that_no_tasks_required_for_activation_are_pending;
397 should_notify_client_if_no_tasks_are_pending_ &=
398 !will_notify_client_that_no_tasks_are_pending;
399
400 scheduled_raster_task_count_ = 0;
401 if (PendingRasterTaskCount())
402 ScheduleMoreTasks();
403
404 TRACE_EVENT_ASYNC_STEP_INTO1(
405 "cc", "ScheduledTasks", this, StateName(),
406 "state", TracedValue::FromValue(StateAsValue().release()));
407
408 // Schedule another check for completed raster tasks while there are
409 // pending raster tasks or pending uploads.
410 if (HasPendingTasks())
411 ScheduleCheckForCompletedRasterTasks();
412
413 // Generate client notifications.
414 if (will_notify_client_that_no_tasks_required_for_activation_are_pending) {
415 DCHECK(std::find_if(raster_tasks_required_for_activation().begin(),
416 raster_tasks_required_for_activation().end(),
417 WasCanceled) ==
418 raster_tasks_required_for_activation().end());
419 client()->DidFinishRunningTasksRequiredForActivation();
420 }
421 if (will_notify_client_that_no_tasks_are_pending) {
422 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
423 DCHECK(!HasPendingTasksRequiredForActivation());
424 client()->DidFinishRunningTasks();
425 }
426 }
427
ScheduleMoreTasks()428 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
429 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
430
431 enum RasterTaskType {
432 PREPAINT_TYPE = 0,
433 REQUIRED_FOR_ACTIVATION_TYPE = 1,
434 NUM_TYPES = 2
435 };
436 NodeVector tasks[NUM_TYPES];
437 unsigned priority = 2u; // 0-1 reserved for RasterFinished tasks.
438 TaskGraph graph;
439
440 size_t bytes_pending_upload = bytes_pending_upload_;
441
442 for (RasterTaskVector::const_iterator it = raster_tasks().begin();
443 it != raster_tasks().end(); ++it) {
444 internal::RasterWorkerPoolTask* task = it->get();
445
446 // |pixel_buffer_tasks_| contains all tasks that have not yet completed.
447 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task);
448 if (pixel_buffer_it == pixel_buffer_tasks_.end())
449 continue;
450
451 // HasFinishedRunning() will return true when set pixels has completed.
452 if (task->HasFinishedRunning()) {
453 DCHECK(std::find(completed_tasks_.begin(),
454 completed_tasks_.end(),
455 task) != completed_tasks_.end());
456 continue;
457 }
458
459 // All raster tasks need to be throttled by bytes of pending uploads.
460 size_t new_bytes_pending_upload = bytes_pending_upload;
461 new_bytes_pending_upload += task->resource()->bytes();
462 if (new_bytes_pending_upload > max_bytes_pending_upload_)
463 break;
464
465 internal::WorkerPoolTask* pixel_buffer_task = pixel_buffer_it->second.get();
466
467 // If raster has finished, just update |bytes_pending_upload|.
468 if (pixel_buffer_task && pixel_buffer_task->HasCompleted()) {
469 bytes_pending_upload = new_bytes_pending_upload;
470 continue;
471 }
472
473 // Throttle raster tasks based on kMaxScheduledRasterTasks.
474 size_t scheduled_raster_task_count =
475 tasks[PREPAINT_TYPE].container().size() +
476 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
477 if (scheduled_raster_task_count >= kMaxScheduledRasterTasks)
478 break;
479
480 // Update |bytes_pending_upload| now that task has cleared all
481 // throttling limits.
482 bytes_pending_upload = new_bytes_pending_upload;
483
484 RasterTaskType type = IsRasterTaskRequiredForActivation(task) ?
485 REQUIRED_FOR_ACTIVATION_TYPE :
486 PREPAINT_TYPE;
487
488 // Use existing pixel buffer task if available.
489 if (pixel_buffer_task) {
490 tasks[type].container().push_back(
491 CreateGraphNodeForRasterTask(pixel_buffer_task,
492 task->dependencies(),
493 priority++,
494 &graph));
495 continue;
496 }
497
498 // Request a pixel buffer. This will reserve shared memory.
499 resource_provider()->AcquirePixelBuffer(task->resource()->id());
500
501 // MapPixelBuffer() returns NULL if context was lost at the time
502 // AcquirePixelBuffer() was called. For simplicity we still post
503 // a raster task that is essentially a noop in these situations.
504 uint8* buffer = resource_provider()->MapPixelBuffer(
505 task->resource()->id());
506
507 scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task(
508 new PixelBufferWorkerPoolTaskImpl(
509 task,
510 buffer,
511 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted,
512 base::Unretained(this),
513 make_scoped_refptr(task))));
514 pixel_buffer_tasks_[task] = new_pixel_buffer_task;
515 tasks[type].container().push_back(
516 CreateGraphNodeForRasterTask(new_pixel_buffer_task.get(),
517 task->dependencies(),
518 priority++,
519 &graph));
520 }
521
522 scoped_refptr<internal::WorkerPoolTask>
523 new_raster_required_for_activation_finished_task;
524
525 size_t scheduled_raster_task_required_for_activation_count =
526 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
527 DCHECK_LE(scheduled_raster_task_required_for_activation_count,
528 tasks_required_for_activation_.size());
529 // Schedule OnRasterTasksRequiredForActivationFinished call only when
530 // notification is pending and throttling is not preventing all pending
531 // tasks required for activation from being scheduled.
532 if (scheduled_raster_task_required_for_activation_count ==
533 tasks_required_for_activation_.size() &&
534 should_notify_client_if_no_tasks_required_for_activation_are_pending_) {
535 new_raster_required_for_activation_finished_task =
536 CreateRasterRequiredForActivationFinishedTask();
537 internal::GraphNode* raster_required_for_activation_finished_node =
538 CreateGraphNodeForTask(
539 new_raster_required_for_activation_finished_task.get(),
540 0u, // Priority 0
541 &graph);
542 AddDependenciesToGraphNode(
543 raster_required_for_activation_finished_node,
544 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container());
545 }
546
547 scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task;
548
549 size_t scheduled_raster_task_count =
550 tasks[PREPAINT_TYPE].container().size() +
551 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
552 DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());
553 // Schedule OnRasterTasksFinished call only when notification is pending
554 // and throttling is not preventing all pending tasks from being scheduled.
555 if (scheduled_raster_task_count == PendingRasterTaskCount() &&
556 should_notify_client_if_no_tasks_are_pending_) {
557 new_raster_finished_task = CreateRasterFinishedTask();
558 internal::GraphNode* raster_finished_node =
559 CreateGraphNodeForTask(new_raster_finished_task.get(),
560 1u, // Priority 1
561 &graph);
562 for (unsigned type = 0; type < NUM_TYPES; ++type) {
563 AddDependenciesToGraphNode(
564 raster_finished_node,
565 tasks[type].container());
566 }
567 }
568
569 SetTaskGraph(&graph);
570
571 scheduled_raster_task_count_ = scheduled_raster_task_count;
572
573 set_raster_finished_task(new_raster_finished_task);
574 set_raster_required_for_activation_finished_task(
575 new_raster_required_for_activation_finished_task);
576 }
577
OnRasterTaskCompleted(scoped_refptr<internal::RasterWorkerPoolTask> task,bool was_canceled,bool needs_upload)578 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted(
579 scoped_refptr<internal::RasterWorkerPoolTask> task,
580 bool was_canceled,
581 bool needs_upload) {
582 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc"),
583 "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
584 "was_canceled", was_canceled,
585 "needs_upload", needs_upload);
586
587 DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end());
588
589 // Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
590 resource_provider()->UnmapPixelBuffer(task->resource()->id());
591
592 if (!needs_upload) {
593 resource_provider()->ReleasePixelBuffer(task->resource()->id());
594
595 if (was_canceled) {
596 // When priorites change, a raster task can be canceled as a result of
597 // no longer being of high enough priority to fit in our throttled
598 // raster task budget. The task has not yet completed in this case.
599 RasterTaskVector::const_iterator it = std::find(raster_tasks().begin(),
600 raster_tasks().end(),
601 task);
602 if (it != raster_tasks().end()) {
603 pixel_buffer_tasks_[task.get()] = NULL;
604 return;
605 }
606 }
607
608 task->DidRun(was_canceled);
609 DCHECK(std::find(completed_tasks_.begin(),
610 completed_tasks_.end(),
611 task) == completed_tasks_.end());
612 completed_tasks_.push_back(task);
613 tasks_required_for_activation_.erase(task);
614 return;
615 }
616
617 DCHECK(!was_canceled);
618
619 resource_provider()->BeginSetPixels(task->resource()->id());
620 has_performed_uploads_since_last_flush_ = true;
621
622 bytes_pending_upload_ += task->resource()->bytes();
623 tasks_with_pending_upload_.push_back(task);
624 }
625
PendingRasterTaskCount() const626 unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
627 unsigned num_completed_raster_tasks =
628 tasks_with_pending_upload_.size() + completed_tasks_.size();
629 DCHECK_GE(pixel_buffer_tasks_.size(), num_completed_raster_tasks);
630 return pixel_buffer_tasks_.size() - num_completed_raster_tasks;
631 }
632
HasPendingTasks() const633 bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
634 return PendingRasterTaskCount() || !tasks_with_pending_upload_.empty();
635 }
636
HasPendingTasksRequiredForActivation() const637 bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
638 return !tasks_required_for_activation_.empty();
639 }
640
StateName() const641 const char* PixelBufferRasterWorkerPool::StateName() const {
642 if (scheduled_raster_task_count_)
643 return "rasterizing";
644 if (PendingRasterTaskCount())
645 return "throttled";
646 if (!tasks_with_pending_upload_.empty())
647 return "waiting_for_uploads";
648
649 return "finishing";
650 }
651
StateAsValue() const652 scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const {
653 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
654
655 state->SetInteger("completed_count", completed_tasks_.size());
656 state->SetInteger("pending_count", pixel_buffer_tasks_.size());
657 state->SetInteger("pending_upload_count", tasks_with_pending_upload_.size());
658 state->SetInteger("required_for_activation_count",
659 tasks_required_for_activation_.size());
660 state->Set("scheduled_state", ScheduledStateAsValue().release());
661 state->Set("throttle_state", ThrottleStateAsValue().release());
662 return state.PassAs<base::Value>();
663 }
664
ThrottleStateAsValue() const665 scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
666 const {
667 scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue);
668
669 throttle_state->SetInteger("bytes_available_for_upload",
670 max_bytes_pending_upload_ - bytes_pending_upload_);
671 throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
672 throttle_state->SetInteger("scheduled_raster_task_count",
673 scheduled_raster_task_count_);
674 return throttle_state.PassAs<base::Value>();
675 }
676
677 } // namespace cc
678