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.
5 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
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"
16 const int kCheckForCompletedRasterTasksDelayMs = 6;
18 const size_t kMaxScheduledRasterTasks = 48;
20 typedef base::StackVector<internal::WorkerPoolTask*, kMaxScheduledRasterTasks>
23 // Only used as std::find_if predicate for DCHECKs.
24 bool WasCanceled(const internal::RasterWorkerPoolTask* task) {
25 return !task->HasFinishedRunning();
31 scoped_ptr<RasterWorkerPool> PixelBufferRasterWorkerPool::Create(
32 ResourceProvider* resource_provider,
33 size_t max_transfer_buffer_usage_bytes) {
34 return make_scoped_ptr<RasterWorkerPool>(
35 new PixelBufferRasterWorkerPool(GetTaskGraphRunner(),
37 max_transfer_buffer_usage_bytes));
40 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
41 internal::TaskGraphRunner* task_graph_runner,
42 ResourceProvider* resource_provider,
43 size_t max_transfer_buffer_usage_bytes)
44 : RasterWorkerPool(task_graph_runner, resource_provider),
46 scheduled_raster_task_count_(0),
47 bytes_pending_upload_(0),
48 max_bytes_pending_upload_(max_transfer_buffer_usage_bytes),
49 has_performed_uploads_since_last_flush_(false),
50 check_for_completed_raster_tasks_pending_(false),
51 should_notify_client_if_no_tasks_are_pending_(false),
52 should_notify_client_if_no_tasks_required_for_activation_are_pending_(
54 raster_finished_task_pending_(false),
55 raster_required_for_activation_finished_task_pending_(false),
56 weak_factory_(this) {}
58 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
60 DCHECK(!check_for_completed_raster_tasks_pending_);
61 DCHECK_EQ(0u, raster_task_states_.size());
62 DCHECK_EQ(0u, raster_tasks_with_pending_upload_.size());
63 DCHECK_EQ(0u, completed_raster_tasks_.size());
64 DCHECK_EQ(0u, completed_image_decode_tasks_.size());
67 void PixelBufferRasterWorkerPool::Shutdown() {
69 RasterWorkerPool::Shutdown();
71 CheckForCompletedWorkerPoolTasks();
72 CheckForCompletedUploads();
74 weak_factory_.InvalidateWeakPtrs();
75 check_for_completed_raster_tasks_pending_ = false;
77 for (RasterTaskStateMap::iterator it = raster_task_states_.begin();
78 it != raster_task_states_.end();
80 internal::RasterWorkerPoolTask* task = it->first;
82 // All unscheduled tasks need to be canceled.
83 if (it->second == UNSCHEDULED) {
84 completed_raster_tasks_.push_back(task);
85 it->second = COMPLETED;
88 DCHECK_EQ(completed_raster_tasks_.size(), raster_task_states_.size());
91 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
92 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
94 if (!should_notify_client_if_no_tasks_are_pending_)
95 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
97 should_notify_client_if_no_tasks_are_pending_ = true;
98 should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true;
100 raster_tasks_required_for_activation_.clear();
102 // Build new raster task state map.
103 RasterTaskStateMap new_raster_task_states;
104 for (RasterTaskQueueIterator it(queue); it; ++it) {
105 internal::RasterWorkerPoolTask* task = *it;
106 DCHECK(new_raster_task_states.find(task) == new_raster_task_states.end());
108 RasterTaskStateMap::iterator state_it = raster_task_states_.find(task);
109 if (state_it != raster_task_states_.end()) {
110 RasterTaskState state = state_it->second;
112 new_raster_task_states[task] = state;
113 // |raster_tasks_required_for_activation_| contains all tasks that need to
114 // complete before we can send a "ready to activate" signal. Tasks that
115 // have already completed should not be part of this set.
116 if (state != COMPLETED && it.required_for_activation())
117 raster_tasks_required_for_activation_.insert(task);
119 raster_task_states_.erase(state_it);
121 DCHECK(!task->HasBeenScheduled());
122 new_raster_task_states[task] = UNSCHEDULED;
123 if (it.required_for_activation())
124 raster_tasks_required_for_activation_.insert(task);
128 // Transfer old raster task state to |new_raster_task_states| and cancel all
129 // remaining unscheduled tasks.
130 for (RasterTaskStateMap::iterator it = raster_task_states_.begin();
131 it != raster_task_states_.end();
133 internal::RasterWorkerPoolTask* task = it->first;
134 DCHECK(new_raster_task_states.find(task) == new_raster_task_states.end());
136 // Unscheduled task can be canceled.
137 if (it->second == UNSCHEDULED) {
138 DCHECK(!task->HasBeenScheduled());
139 DCHECK(std::find(completed_raster_tasks_.begin(),
140 completed_raster_tasks_.end(),
141 task) == completed_raster_tasks_.end());
142 completed_raster_tasks_.push_back(task);
143 new_raster_task_states[task] = COMPLETED;
147 // Move state to |new_raster_task_states|.
148 new_raster_task_states[task] = it->second;
151 raster_tasks_.Swap(queue);
152 raster_task_states_.swap(new_raster_task_states);
154 // Check for completed tasks when ScheduleTasks() is called as
155 // priorities might have changed and this maximizes the number
156 // of top priority tasks that are scheduled.
157 CheckForCompletedWorkerPoolTasks();
158 CheckForCompletedUploads();
161 // Schedule new tasks.
164 // Cancel any pending check for completed raster tasks and schedule
166 check_for_completed_raster_tasks_time_ = base::TimeTicks();
167 ScheduleCheckForCompletedRasterTasks();
169 TRACE_EVENT_ASYNC_STEP_INTO1(
175 TracedValue::FromValue(StateAsValue().release()));
178 unsigned PixelBufferRasterWorkerPool::GetResourceTarget() const {
179 return GL_TEXTURE_2D;
182 ResourceFormat PixelBufferRasterWorkerPool::GetResourceFormat() const {
183 return resource_provider()->memory_efficient_texture_format();
186 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
187 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
189 CheckForCompletedWorkerPoolTasks();
190 CheckForCompletedUploads();
193 while (!completed_image_decode_tasks_.empty()) {
194 internal::WorkerPoolTask* task =
195 completed_image_decode_tasks_.front().get();
197 task->RunReplyOnOriginThread();
199 completed_image_decode_tasks_.pop_front();
202 while (!completed_raster_tasks_.empty()) {
203 internal::RasterWorkerPoolTask* task =
204 completed_raster_tasks_.front().get();
205 DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
206 DCHECK_EQ(COMPLETED, raster_task_states_[task]);
208 raster_task_states_.erase(task);
210 task->RunReplyOnOriginThread();
212 completed_raster_tasks_.pop_front();
216 SkCanvas* PixelBufferRasterWorkerPool::AcquireCanvasForRaster(
217 internal::RasterWorkerPoolTask* task) {
218 resource_provider()->AcquirePixelRasterBuffer(task->resource()->id());
219 return resource_provider()->MapPixelRasterBuffer(task->resource()->id());
222 void PixelBufferRasterWorkerPool::OnRasterCompleted(
223 internal::RasterWorkerPoolTask* task,
224 const PicturePileImpl::Analysis& analysis) {
225 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc"),
226 "PixelBufferRasterWorkerPool::OnRasterCompleted",
228 !task->HasFinishedRunning(),
230 task->HasFinishedRunning() && !analysis.is_solid_color);
232 DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
233 DCHECK_EQ(SCHEDULED, raster_task_states_[task]);
235 // Balanced with MapPixelRasterBuffer() call in AcquireCanvasForRaster().
236 resource_provider()->UnmapPixelRasterBuffer(task->resource()->id());
238 if (!task->HasFinishedRunning() || analysis.is_solid_color) {
239 resource_provider()->ReleasePixelRasterBuffer(task->resource()->id());
241 if (!task->HasFinishedRunning()) {
242 // When priorites change, a raster task can be canceled as a result of
243 // no longer being of high enough priority to fit in our throttled
244 // raster task budget. The task has not yet completed in this case.
245 for (RasterTaskQueueIterator it(&raster_tasks_); it; ++it) {
247 raster_task_states_[task] = UNSCHEDULED;
253 DCHECK(std::find(completed_raster_tasks_.begin(),
254 completed_raster_tasks_.end(),
255 task) == completed_raster_tasks_.end());
256 completed_raster_tasks_.push_back(task);
257 raster_task_states_[task] = COMPLETED;
258 raster_tasks_required_for_activation_.erase(task);
262 DCHECK(task->HasFinishedRunning());
264 resource_provider()->BeginSetPixels(task->resource()->id());
265 has_performed_uploads_since_last_flush_ = true;
267 bytes_pending_upload_ += task->resource()->bytes();
268 raster_tasks_with_pending_upload_.push_back(task);
269 raster_task_states_[task] = UPLOADING;
272 void PixelBufferRasterWorkerPool::OnImageDecodeCompleted(
273 internal::WorkerPoolTask* task) {
274 completed_image_decode_tasks_.push_back(task);
277 void PixelBufferRasterWorkerPool::OnRasterTasksFinished() {
278 // |should_notify_client_if_no_tasks_are_pending_| can be set to false as
279 // a result of a scheduled CheckForCompletedRasterTasks() call. No need to
280 // perform another check in that case as we've already notified the client.
281 if (!should_notify_client_if_no_tasks_are_pending_)
283 raster_finished_task_pending_ = false;
285 // Call CheckForCompletedRasterTasks() when we've finished running all
286 // raster tasks needed since last time ScheduleTasks() was called.
287 // This reduces latency between the time when all tasks have finished
288 // running and the time when the client is notified.
289 CheckForCompletedRasterTasks();
292 void PixelBufferRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
293 // Analogous to OnRasterTasksFinished(), there's no need to call
294 // CheckForCompletedRasterTasks() if the client has already been notified.
295 if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_)
297 raster_required_for_activation_finished_task_pending_ = false;
299 // This reduces latency between the time when all tasks required for
300 // activation have finished running and the time when the client is
302 CheckForCompletedRasterTasks();
305 void PixelBufferRasterWorkerPool::FlushUploads() {
306 if (!has_performed_uploads_since_last_flush_)
309 resource_provider()->ShallowFlushIfSupported();
310 has_performed_uploads_since_last_flush_ = false;
313 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
314 RasterTaskDeque tasks_with_completed_uploads;
316 // First check if any have completed.
317 while (!raster_tasks_with_pending_upload_.empty()) {
318 internal::RasterWorkerPoolTask* task =
319 raster_tasks_with_pending_upload_.front().get();
320 DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
321 DCHECK_EQ(UPLOADING, raster_task_states_[task]);
323 // Uploads complete in the order they are issued.
324 if (!resource_provider()->DidSetPixelsComplete(task->resource()->id()))
327 tasks_with_completed_uploads.push_back(task);
328 raster_tasks_with_pending_upload_.pop_front();
332 bool should_force_some_uploads_to_complete =
333 shutdown_ || client()->ShouldForceTasksRequiredForActivationToComplete();
335 if (should_force_some_uploads_to_complete) {
336 RasterTaskDeque tasks_with_uploads_to_force;
337 RasterTaskDeque::iterator it = raster_tasks_with_pending_upload_.begin();
338 while (it != raster_tasks_with_pending_upload_.end()) {
339 internal::RasterWorkerPoolTask* task = it->get();
340 DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
342 // Force all uploads required for activation to complete.
343 // During shutdown, force all pending uploads to complete.
344 if (shutdown_ || IsRasterTaskRequiredForActivation(task)) {
345 tasks_with_uploads_to_force.push_back(task);
346 tasks_with_completed_uploads.push_back(task);
347 it = raster_tasks_with_pending_upload_.erase(it);
354 // Force uploads in reverse order. Since forcing can cause a wait on
355 // all previous uploads, we would rather wait only once downstream.
356 for (RasterTaskDeque::reverse_iterator it =
357 tasks_with_uploads_to_force.rbegin();
358 it != tasks_with_uploads_to_force.rend();
360 resource_provider()->ForceSetPixelsToComplete((*it)->resource()->id());
361 has_performed_uploads_since_last_flush_ = true;
365 // Release shared memory and move tasks with completed uploads
366 // to |completed_raster_tasks_|.
367 while (!tasks_with_completed_uploads.empty()) {
368 internal::RasterWorkerPoolTask* task =
369 tasks_with_completed_uploads.front().get();
371 // It's now safe to release the pixel buffer and the shared memory.
372 resource_provider()->ReleasePixelRasterBuffer(task->resource()->id());
374 bytes_pending_upload_ -= task->resource()->bytes();
376 DCHECK(std::find(completed_raster_tasks_.begin(),
377 completed_raster_tasks_.end(),
378 task) == completed_raster_tasks_.end());
379 completed_raster_tasks_.push_back(task);
380 raster_task_states_[task] = COMPLETED;
382 raster_tasks_required_for_activation_.erase(task);
384 tasks_with_completed_uploads.pop_front();
388 void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() {
389 base::TimeDelta delay =
390 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs);
391 if (check_for_completed_raster_tasks_time_.is_null())
392 check_for_completed_raster_tasks_time_ = base::TimeTicks::Now() + delay;
394 if (check_for_completed_raster_tasks_pending_)
397 base::MessageLoopProxy::current()->PostDelayedTask(
399 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
400 weak_factory_.GetWeakPtr()),
402 check_for_completed_raster_tasks_pending_ = true;
405 void PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks() {
406 if (check_for_completed_raster_tasks_time_.is_null()) {
407 check_for_completed_raster_tasks_pending_ = false;
411 base::TimeDelta delay =
412 check_for_completed_raster_tasks_time_ - base::TimeTicks::Now();
414 // Post another delayed task if it is not yet time to check for completed
416 if (delay > base::TimeDelta()) {
417 base::MessageLoopProxy::current()->PostDelayedTask(
419 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
420 weak_factory_.GetWeakPtr()),
425 check_for_completed_raster_tasks_pending_ = false;
426 CheckForCompletedRasterTasks();
429 void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
431 "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");
433 DCHECK(should_notify_client_if_no_tasks_are_pending_);
434 check_for_completed_raster_tasks_time_ = base::TimeTicks();
436 CheckForCompletedWorkerPoolTasks();
437 CheckForCompletedUploads();
440 // Determine what client notifications to generate.
441 bool will_notify_client_that_no_tasks_required_for_activation_are_pending =
442 (should_notify_client_if_no_tasks_required_for_activation_are_pending_ &&
443 !raster_required_for_activation_finished_task_pending_ &&
444 !HasPendingTasksRequiredForActivation());
445 bool will_notify_client_that_no_tasks_are_pending =
446 (should_notify_client_if_no_tasks_are_pending_ &&
447 !raster_required_for_activation_finished_task_pending_ &&
448 !raster_finished_task_pending_ && !HasPendingTasks());
450 // Adjust the need to generate notifications before scheduling more tasks.
451 should_notify_client_if_no_tasks_required_for_activation_are_pending_ &=
452 !will_notify_client_that_no_tasks_required_for_activation_are_pending;
453 should_notify_client_if_no_tasks_are_pending_ &=
454 !will_notify_client_that_no_tasks_are_pending;
456 scheduled_raster_task_count_ = 0;
457 if (PendingRasterTaskCount())
460 TRACE_EVENT_ASYNC_STEP_INTO1(
466 TracedValue::FromValue(StateAsValue().release()));
468 // Schedule another check for completed raster tasks while there are
469 // pending raster tasks or pending uploads.
470 if (HasPendingTasks())
471 ScheduleCheckForCompletedRasterTasks();
473 // Generate client notifications.
474 if (will_notify_client_that_no_tasks_required_for_activation_are_pending) {
475 DCHECK(std::find_if(raster_tasks_required_for_activation_.begin(),
476 raster_tasks_required_for_activation_.end(),
478 raster_tasks_required_for_activation_.end());
479 client()->DidFinishRunningTasksRequiredForActivation();
481 if (will_notify_client_that_no_tasks_are_pending) {
482 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
483 DCHECK(!HasPendingTasksRequiredForActivation());
484 client()->DidFinishRunningTasks();
488 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
489 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
491 WorkerPoolTaskVector tasks;
492 WorkerPoolTaskVector tasks_required_for_activation;
494 unsigned priority = kRasterTaskPriorityBase;
498 size_t bytes_pending_upload = bytes_pending_upload_;
499 bool did_throttle_raster_tasks = false;
501 for (RasterTaskQueueIterator it(&raster_tasks_); it; ++it) {
502 internal::RasterWorkerPoolTask* task = *it;
504 // |raster_task_states_| contains the state of all tasks that we have not
505 // yet run reply callbacks for.
506 RasterTaskStateMap::iterator state_it = raster_task_states_.find(task);
507 if (state_it == raster_task_states_.end())
510 // Skip task if completed.
511 if (state_it->second == COMPLETED) {
512 DCHECK(std::find(completed_raster_tasks_.begin(),
513 completed_raster_tasks_.end(),
514 task) != completed_raster_tasks_.end());
518 // All raster tasks need to be throttled by bytes of pending uploads.
519 size_t new_bytes_pending_upload = bytes_pending_upload;
520 new_bytes_pending_upload += task->resource()->bytes();
521 if (new_bytes_pending_upload > max_bytes_pending_upload_) {
522 did_throttle_raster_tasks = true;
526 // If raster has finished, just update |bytes_pending_upload|.
527 if (state_it->second == UPLOADING) {
528 DCHECK(task->HasCompleted());
529 bytes_pending_upload = new_bytes_pending_upload;
533 // Throttle raster tasks based on kMaxScheduledRasterTasks.
534 if (tasks.container().size() >= kMaxScheduledRasterTasks) {
535 did_throttle_raster_tasks = true;
539 // Update |bytes_pending_upload| now that task has cleared all
540 // throttling limits.
541 bytes_pending_upload = new_bytes_pending_upload;
543 DCHECK(state_it->second == UNSCHEDULED || state_it->second == SCHEDULED);
544 state_it->second = SCHEDULED;
546 InsertNodeForRasterTask(&graph_, task, task->dependencies(), priority++);
548 tasks.container().push_back(task);
549 if (it.required_for_activation())
550 tasks_required_for_activation.container().push_back(task);
553 scoped_refptr<internal::WorkerPoolTask>
554 new_raster_required_for_activation_finished_task;
556 size_t scheduled_raster_task_required_for_activation_count =
557 tasks_required_for_activation.container().size();
558 DCHECK_LE(scheduled_raster_task_required_for_activation_count,
559 raster_tasks_required_for_activation_.size());
560 // Schedule OnRasterTasksRequiredForActivationFinished call only when
561 // notification is pending and throttling is not preventing all pending
562 // tasks required for activation from being scheduled.
563 if (scheduled_raster_task_required_for_activation_count ==
564 raster_tasks_required_for_activation_.size() &&
565 should_notify_client_if_no_tasks_required_for_activation_are_pending_) {
566 new_raster_required_for_activation_finished_task =
567 CreateRasterRequiredForActivationFinishedTask(
568 raster_tasks_required_for_activation_.size());
569 raster_required_for_activation_finished_task_pending_ = true;
570 InsertNodeForTask(&graph_,
571 new_raster_required_for_activation_finished_task.get(),
572 kRasterRequiredForActivationFinishedTaskPriority,
573 scheduled_raster_task_required_for_activation_count);
574 for (WorkerPoolTaskVector::ContainerType::const_iterator it =
575 tasks_required_for_activation.container().begin();
576 it != tasks_required_for_activation.container().end();
578 graph_.edges.push_back(internal::TaskGraph::Edge(
579 *it, new_raster_required_for_activation_finished_task.get()));
583 scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task;
585 size_t scheduled_raster_task_count = tasks.container().size();
586 DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());
587 // Schedule OnRasterTasksFinished call only when notification is pending
588 // and throttling is not preventing all pending tasks from being scheduled.
589 if (!did_throttle_raster_tasks &&
590 should_notify_client_if_no_tasks_are_pending_) {
591 new_raster_finished_task = CreateRasterFinishedTask();
592 raster_finished_task_pending_ = true;
593 InsertNodeForTask(&graph_,
594 new_raster_finished_task.get(),
595 kRasterFinishedTaskPriority,
596 scheduled_raster_task_count);
597 for (WorkerPoolTaskVector::ContainerType::const_iterator it =
598 tasks.container().begin();
599 it != tasks.container().end();
601 graph_.edges.push_back(
602 internal::TaskGraph::Edge(*it, new_raster_finished_task.get()));
606 SetTaskGraph(&graph_);
608 scheduled_raster_task_count_ = scheduled_raster_task_count;
610 set_raster_finished_task(new_raster_finished_task);
611 set_raster_required_for_activation_finished_task(
612 new_raster_required_for_activation_finished_task);
615 unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
616 unsigned num_completed_raster_tasks =
617 raster_tasks_with_pending_upload_.size() + completed_raster_tasks_.size();
618 DCHECK_GE(raster_task_states_.size(), num_completed_raster_tasks);
619 return raster_task_states_.size() - num_completed_raster_tasks;
622 bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
623 return PendingRasterTaskCount() || !raster_tasks_with_pending_upload_.empty();
626 bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
627 return !raster_tasks_required_for_activation_.empty();
630 const char* PixelBufferRasterWorkerPool::StateName() const {
631 if (scheduled_raster_task_count_)
632 return "rasterizing";
633 if (PendingRasterTaskCount())
635 if (!raster_tasks_with_pending_upload_.empty())
636 return "waiting_for_uploads";
641 void PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks() {
642 CollectCompletedWorkerPoolTasks(&completed_tasks_);
643 for (internal::Task::Vector::const_iterator it = completed_tasks_.begin();
644 it != completed_tasks_.end();
646 internal::WorkerPoolTask* task =
647 static_cast<internal::WorkerPoolTask*>(it->get());
649 task->WillComplete();
650 task->CompleteOnOriginThread(this);
653 completed_tasks_.clear();
656 bool PixelBufferRasterWorkerPool::IsRasterTaskRequiredForActivation(
657 internal::RasterWorkerPoolTask* task) const {
658 return raster_tasks_required_for_activation_.find(task) !=
659 raster_tasks_required_for_activation_.end();
662 scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const {
663 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
665 state->SetInteger("completed_count", completed_raster_tasks_.size());
666 state->SetInteger("pending_count", raster_task_states_.size());
667 state->SetInteger("pending_upload_count",
668 raster_tasks_with_pending_upload_.size());
669 state->SetInteger("pending_required_for_activation_count",
670 raster_tasks_required_for_activation_.size());
671 state->Set("throttle_state", ThrottleStateAsValue().release());
672 return state.PassAs<base::Value>();
675 scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
677 scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue);
679 throttle_state->SetInteger("bytes_available_for_upload",
680 max_bytes_pending_upload_ - bytes_pending_upload_);
681 throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
682 throttle_state->SetInteger("scheduled_raster_task_count",
683 scheduled_raster_task_count_);
684 return throttle_state.PassAs<base::Value>();