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"
12 #include "third_party/skia/include/core/SkBitmapDevice.h"
14 #if defined(OS_ANDROID)
15 #include "base/android/sys_utils.h"
22 class PixelBufferWorkerPoolTaskImpl
: public internal::WorkerPoolTask
{
24 typedef base::Callback
<void(bool was_canceled
, bool needs_upload
)> Reply
;
26 PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask
* task
,
32 needs_upload_(false) {
35 // Overridden from internal::WorkerPoolTask:
36 virtual void RunOnWorkerThread(unsigned thread_index
) OVERRIDE
{
37 // |buffer_| can be NULL in lost context situations.
39 // |needs_upload_| still needs to be true as task has not
44 needs_upload_
= task_
->RunOnWorkerThread(thread_index
,
46 task_
->resource()->size(),
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_
);
56 virtual ~PixelBufferWorkerPoolTaskImpl() {}
58 scoped_refptr
<internal::RasterWorkerPoolTask
> task_
;
63 DISALLOW_COPY_AND_ASSIGN(PixelBufferWorkerPoolTaskImpl
);
66 const int kCheckForCompletedRasterTasksDelayMs
= 6;
68 const size_t kMaxScheduledRasterTasks
= 48;
70 typedef base::StackVector
<internal::GraphNode
*,
71 kMaxScheduledRasterTasks
> NodeVector
;
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
;
80 node
->add_dependency();
81 dependency
->add_dependent(node
);
85 // Only used as std::find_if predicate for DCHECKs.
86 bool WasCanceled(const internal::RasterWorkerPoolTask
* task
) {
87 return task
->WasCanceled();
92 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
93 ResourceProvider
* resource_provider
,
95 size_t max_transfer_buffer_usage_bytes
)
96 : RasterWorkerPool(resource_provider
, num_threads
),
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_(
108 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
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());
116 void PixelBufferRasterWorkerPool::Shutdown() {
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();
128 // All inactive tasks needs to be canceled.
129 if (!pixel_buffer_task
&& !task
->HasFinishedRunning()) {
131 completed_tasks_
.push_back(task
);
134 DCHECK_EQ(completed_tasks_
.size(), pixel_buffer_tasks_
.size());
137 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue
* queue
) {
138 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
140 RasterWorkerPool::SetRasterTasks(queue
);
142 if (!should_notify_client_if_no_tasks_are_pending_
)
143 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
145 should_notify_client_if_no_tasks_are_pending_
= true;
146 should_notify_client_if_no_tasks_required_for_activation_are_pending_
= true;
148 tasks_required_for_activation_
.clear();
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());
159 new_pixel_buffer_tasks
[task
] = pixel_buffer_tasks_
[task
];
160 pixel_buffer_tasks_
.erase(task
);
162 if (IsRasterTaskRequiredForActivation(task
))
163 tasks_required_for_activation_
.insert(task
);
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();
173 // Move task to |new_pixel_buffer_tasks|
174 new_pixel_buffer_tasks
[task
] = pixel_buffer_task
;
176 // Inactive task can be canceled.
177 if (!pixel_buffer_task
&& !task
->HasFinishedRunning()) {
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
);
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();
194 tasks_required_for_activation_
.erase(*it
);
197 pixel_buffer_tasks_
.swap(new_pixel_buffer_tasks
);
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();
206 // Schedule new tasks.
209 // Cancel any pending check for completed raster tasks and schedule
211 check_for_completed_raster_tasks_callback_
.Cancel();
212 check_for_completed_raster_tasks_pending_
= false;
213 ScheduleCheckForCompletedRasterTasks();
215 TRACE_EVENT_ASYNC_STEP_INTO1(
216 "cc", "ScheduledTasks", this, StateName(),
217 "state", TracedValue::FromValue(StateAsValue().release()));
220 ResourceFormat
PixelBufferRasterWorkerPool::GetResourceFormat() const {
221 return resource_provider()->memory_efficient_texture_format();
224 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
225 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
227 RasterWorkerPool::CheckForCompletedTasks();
228 CheckForCompletedUploads();
231 TaskDeque completed_tasks
;
232 completed_tasks_
.swap(completed_tasks
);
234 while (!completed_tasks
.empty()) {
235 internal::RasterWorkerPoolTask
* task
= completed_tasks
.front().get();
236 DCHECK(pixel_buffer_tasks_
.find(task
) != pixel_buffer_tasks_
.end());
238 pixel_buffer_tasks_
.erase(task
);
240 task
->WillComplete();
241 task
->CompleteOnOriginThread();
244 completed_tasks
.pop_front();
248 void PixelBufferRasterWorkerPool::OnRasterTasksFinished() {
249 // |should_notify_client_if_no_tasks_are_pending_| can be set to false as
250 // a result of a scheduled CheckForCompletedRasterTasks() call. No need to
251 // perform another check in that case as we've already notified the client.
252 if (!should_notify_client_if_no_tasks_are_pending_
)
255 // Call CheckForCompletedRasterTasks() when we've finished running all
256 // raster tasks needed since last time ScheduleTasks() was called.
257 // This reduces latency between the time when all tasks have finished
258 // running and the time when the client is notified.
259 CheckForCompletedRasterTasks();
262 void PixelBufferRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
263 // Analogous to OnRasterTasksFinished(), there's no need to call
264 // CheckForCompletedRasterTasks() if the client has already been notified.
265 if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_
)
268 // This reduces latency between the time when all tasks required for
269 // activation have finished running and the time when the client is
271 CheckForCompletedRasterTasks();
274 void PixelBufferRasterWorkerPool::FlushUploads() {
275 if (!has_performed_uploads_since_last_flush_
)
278 resource_provider()->ShallowFlushIfSupported();
279 has_performed_uploads_since_last_flush_
= false;
282 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
283 TaskDeque tasks_with_completed_uploads
;
285 // First check if any have completed.
286 while (!tasks_with_pending_upload_
.empty()) {
287 internal::RasterWorkerPoolTask
* task
=
288 tasks_with_pending_upload_
.front().get();
290 // Uploads complete in the order they are issued.
291 if (!resource_provider()->DidSetPixelsComplete(task
->resource()->id()))
294 tasks_with_completed_uploads
.push_back(task
);
295 tasks_with_pending_upload_
.pop_front();
299 bool should_force_some_uploads_to_complete
=
300 shutdown_
|| client()->ShouldForceTasksRequiredForActivationToComplete();
302 if (should_force_some_uploads_to_complete
) {
303 TaskDeque tasks_with_uploads_to_force
;
304 TaskDeque::iterator it
= tasks_with_pending_upload_
.begin();
305 while (it
!= tasks_with_pending_upload_
.end()) {
306 internal::RasterWorkerPoolTask
* task
= it
->get();
307 DCHECK(pixel_buffer_tasks_
.find(task
) != pixel_buffer_tasks_
.end());
309 // Force all uploads required for activation to complete.
310 // During shutdown, force all pending uploads to complete.
311 if (shutdown_
|| IsRasterTaskRequiredForActivation(task
)) {
312 tasks_with_uploads_to_force
.push_back(task
);
313 tasks_with_completed_uploads
.push_back(task
);
314 it
= tasks_with_pending_upload_
.erase(it
);
321 // Force uploads in reverse order. Since forcing can cause a wait on
322 // all previous uploads, we would rather wait only once downstream.
323 for (TaskDeque::reverse_iterator it
= tasks_with_uploads_to_force
.rbegin();
324 it
!= tasks_with_uploads_to_force
.rend();
326 resource_provider()->ForceSetPixelsToComplete((*it
)->resource()->id());
327 has_performed_uploads_since_last_flush_
= true;
331 // Release shared memory and move tasks with completed uploads
332 // to |completed_tasks_|.
333 while (!tasks_with_completed_uploads
.empty()) {
334 internal::RasterWorkerPoolTask
* task
=
335 tasks_with_completed_uploads
.front().get();
337 // It's now safe to release the pixel buffer and the shared memory.
338 resource_provider()->ReleasePixelBuffer(task
->resource()->id());
340 bytes_pending_upload_
-= task
->resource()->bytes();
344 DCHECK(std::find(completed_tasks_
.begin(),
345 completed_tasks_
.end(),
346 task
) == completed_tasks_
.end());
347 completed_tasks_
.push_back(task
);
349 tasks_required_for_activation_
.erase(task
);
351 tasks_with_completed_uploads
.pop_front();
355 void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() {
356 if (check_for_completed_raster_tasks_pending_
)
359 check_for_completed_raster_tasks_callback_
.Reset(
360 base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks
,
361 base::Unretained(this)));
362 base::MessageLoopProxy::current()->PostDelayedTask(
364 check_for_completed_raster_tasks_callback_
.callback(),
365 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs
));
366 check_for_completed_raster_tasks_pending_
= true;
369 void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
371 "cc", "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");
373 DCHECK(should_notify_client_if_no_tasks_are_pending_
);
375 check_for_completed_raster_tasks_callback_
.Cancel();
376 check_for_completed_raster_tasks_pending_
= false;
378 RasterWorkerPool::CheckForCompletedTasks();
379 CheckForCompletedUploads();
382 // Determine what client notifications to generate.
383 bool will_notify_client_that_no_tasks_required_for_activation_are_pending
=
384 (should_notify_client_if_no_tasks_required_for_activation_are_pending_
&&
385 !HasPendingTasksRequiredForActivation());
386 bool will_notify_client_that_no_tasks_are_pending
=
387 (should_notify_client_if_no_tasks_are_pending_
&&
390 // Adjust the need to generate notifications before scheduling more tasks.
391 should_notify_client_if_no_tasks_required_for_activation_are_pending_
&=
392 !will_notify_client_that_no_tasks_required_for_activation_are_pending
;
393 should_notify_client_if_no_tasks_are_pending_
&=
394 !will_notify_client_that_no_tasks_are_pending
;
396 scheduled_raster_task_count_
= 0;
397 if (PendingRasterTaskCount())
400 TRACE_EVENT_ASYNC_STEP_INTO1(
401 "cc", "ScheduledTasks", this, StateName(),
402 "state", TracedValue::FromValue(StateAsValue().release()));
404 // Schedule another check for completed raster tasks while there are
405 // pending raster tasks or pending uploads.
406 if (HasPendingTasks())
407 ScheduleCheckForCompletedRasterTasks();
409 // Generate client notifications.
410 if (will_notify_client_that_no_tasks_required_for_activation_are_pending
) {
411 DCHECK(std::find_if(raster_tasks_required_for_activation().begin(),
412 raster_tasks_required_for_activation().end(),
414 raster_tasks_required_for_activation().end());
415 client()->DidFinishRunningTasksRequiredForActivation();
417 if (will_notify_client_that_no_tasks_are_pending
) {
418 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
419 DCHECK(!HasPendingTasksRequiredForActivation());
420 client()->DidFinishRunningTasks();
424 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
425 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
427 enum RasterTaskType
{
429 REQUIRED_FOR_ACTIVATION_TYPE
= 1,
432 NodeVector tasks
[NUM_TYPES
];
433 unsigned priority
= 2u; // 0-1 reserved for RasterFinished tasks.
436 size_t bytes_pending_upload
= bytes_pending_upload_
;
438 for (RasterTaskVector::const_iterator it
= raster_tasks().begin();
439 it
!= raster_tasks().end(); ++it
) {
440 internal::RasterWorkerPoolTask
* task
= it
->get();
442 // |pixel_buffer_tasks_| contains all tasks that have not yet completed.
443 TaskMap::iterator pixel_buffer_it
= pixel_buffer_tasks_
.find(task
);
444 if (pixel_buffer_it
== pixel_buffer_tasks_
.end())
447 // HasFinishedRunning() will return true when set pixels has completed.
448 if (task
->HasFinishedRunning()) {
449 DCHECK(std::find(completed_tasks_
.begin(),
450 completed_tasks_
.end(),
451 task
) != completed_tasks_
.end());
455 // All raster tasks need to be throttled by bytes of pending uploads.
456 size_t new_bytes_pending_upload
= bytes_pending_upload
;
457 new_bytes_pending_upload
+= task
->resource()->bytes();
458 if (new_bytes_pending_upload
> max_bytes_pending_upload_
)
461 internal::WorkerPoolTask
* pixel_buffer_task
= pixel_buffer_it
->second
.get();
463 // If raster has finished, just update |bytes_pending_upload|.
464 if (pixel_buffer_task
&& pixel_buffer_task
->HasCompleted()) {
465 bytes_pending_upload
= new_bytes_pending_upload
;
469 // Throttle raster tasks based on kMaxScheduledRasterTasks.
470 size_t scheduled_raster_task_count
=
471 tasks
[PREPAINT_TYPE
].container().size() +
472 tasks
[REQUIRED_FOR_ACTIVATION_TYPE
].container().size();
473 if (scheduled_raster_task_count
>= kMaxScheduledRasterTasks
)
476 // Update |bytes_pending_upload| now that task has cleared all
477 // throttling limits.
478 bytes_pending_upload
= new_bytes_pending_upload
;
480 RasterTaskType type
= IsRasterTaskRequiredForActivation(task
) ?
481 REQUIRED_FOR_ACTIVATION_TYPE
:
484 // Use existing pixel buffer task if available.
485 if (pixel_buffer_task
) {
486 tasks
[type
].container().push_back(
487 CreateGraphNodeForRasterTask(pixel_buffer_task
,
488 task
->dependencies(),
494 // Request a pixel buffer. This will reserve shared memory.
495 resource_provider()->AcquirePixelBuffer(task
->resource()->id());
497 // MapPixelBuffer() returns NULL if context was lost at the time
498 // AcquirePixelBuffer() was called. For simplicity we still post
499 // a raster task that is essentially a noop in these situations.
500 uint8
* buffer
= resource_provider()->MapPixelBuffer(
501 task
->resource()->id());
503 scoped_refptr
<internal::WorkerPoolTask
> new_pixel_buffer_task(
504 new PixelBufferWorkerPoolTaskImpl(
507 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted
,
508 base::Unretained(this),
509 make_scoped_refptr(task
))));
510 pixel_buffer_tasks_
[task
] = new_pixel_buffer_task
;
511 tasks
[type
].container().push_back(
512 CreateGraphNodeForRasterTask(new_pixel_buffer_task
.get(),
513 task
->dependencies(),
518 scoped_refptr
<internal::WorkerPoolTask
>
519 new_raster_required_for_activation_finished_task
;
521 size_t scheduled_raster_task_required_for_activation_count
=
522 tasks
[REQUIRED_FOR_ACTIVATION_TYPE
].container().size();
523 DCHECK_LE(scheduled_raster_task_required_for_activation_count
,
524 tasks_required_for_activation_
.size());
525 // Schedule OnRasterTasksRequiredForActivationFinished call only when
526 // notification is pending and throttling is not preventing all pending
527 // tasks required for activation from being scheduled.
528 if (scheduled_raster_task_required_for_activation_count
==
529 tasks_required_for_activation_
.size() &&
530 should_notify_client_if_no_tasks_required_for_activation_are_pending_
) {
531 new_raster_required_for_activation_finished_task
=
532 CreateRasterRequiredForActivationFinishedTask();
533 internal::GraphNode
* raster_required_for_activation_finished_node
=
534 CreateGraphNodeForTask(
535 new_raster_required_for_activation_finished_task
.get(),
538 AddDependenciesToGraphNode(
539 raster_required_for_activation_finished_node
,
540 tasks
[REQUIRED_FOR_ACTIVATION_TYPE
].container());
543 scoped_refptr
<internal::WorkerPoolTask
> new_raster_finished_task
;
545 size_t scheduled_raster_task_count
=
546 tasks
[PREPAINT_TYPE
].container().size() +
547 tasks
[REQUIRED_FOR_ACTIVATION_TYPE
].container().size();
548 DCHECK_LE(scheduled_raster_task_count
, PendingRasterTaskCount());
549 // Schedule OnRasterTasksFinished call only when notification is pending
550 // and throttling is not preventing all pending tasks from being scheduled.
551 if (scheduled_raster_task_count
== PendingRasterTaskCount() &&
552 should_notify_client_if_no_tasks_are_pending_
) {
553 new_raster_finished_task
= CreateRasterFinishedTask();
554 internal::GraphNode
* raster_finished_node
=
555 CreateGraphNodeForTask(new_raster_finished_task
.get(),
558 for (unsigned type
= 0; type
< NUM_TYPES
; ++type
) {
559 AddDependenciesToGraphNode(
560 raster_finished_node
,
561 tasks
[type
].container());
565 SetTaskGraph(&graph
);
567 scheduled_raster_task_count_
= scheduled_raster_task_count
;
569 set_raster_finished_task(new_raster_finished_task
);
570 set_raster_required_for_activation_finished_task(
571 new_raster_required_for_activation_finished_task
);
574 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted(
575 scoped_refptr
<internal::RasterWorkerPoolTask
> task
,
578 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc"),
579 "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
580 "was_canceled", was_canceled
,
581 "needs_upload", needs_upload
);
583 DCHECK(pixel_buffer_tasks_
.find(task
.get()) != pixel_buffer_tasks_
.end());
585 // Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
586 resource_provider()->UnmapPixelBuffer(task
->resource()->id());
589 resource_provider()->ReleasePixelBuffer(task
->resource()->id());
592 // When priorites change, a raster task can be canceled as a result of
593 // no longer being of high enough priority to fit in our throttled
594 // raster task budget. The task has not yet completed in this case.
595 RasterTaskVector::const_iterator it
= std::find(raster_tasks().begin(),
596 raster_tasks().end(),
598 if (it
!= raster_tasks().end()) {
599 pixel_buffer_tasks_
[task
.get()] = NULL
;
604 task
->DidRun(was_canceled
);
605 DCHECK(std::find(completed_tasks_
.begin(),
606 completed_tasks_
.end(),
607 task
) == completed_tasks_
.end());
608 completed_tasks_
.push_back(task
);
609 tasks_required_for_activation_
.erase(task
);
613 DCHECK(!was_canceled
);
615 resource_provider()->BeginSetPixels(task
->resource()->id());
616 has_performed_uploads_since_last_flush_
= true;
618 bytes_pending_upload_
+= task
->resource()->bytes();
619 tasks_with_pending_upload_
.push_back(task
);
622 unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
623 unsigned num_completed_raster_tasks
=
624 tasks_with_pending_upload_
.size() + completed_tasks_
.size();
625 DCHECK_GE(pixel_buffer_tasks_
.size(), num_completed_raster_tasks
);
626 return pixel_buffer_tasks_
.size() - num_completed_raster_tasks
;
629 bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
630 return PendingRasterTaskCount() || !tasks_with_pending_upload_
.empty();
633 bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
634 return !tasks_required_for_activation_
.empty();
637 const char* PixelBufferRasterWorkerPool::StateName() const {
638 if (scheduled_raster_task_count_
)
639 return "rasterizing";
640 if (PendingRasterTaskCount())
642 if (!tasks_with_pending_upload_
.empty())
643 return "waiting_for_uploads";
648 scoped_ptr
<base::Value
> PixelBufferRasterWorkerPool::StateAsValue() const {
649 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue
);
651 state
->SetInteger("completed_count", completed_tasks_
.size());
652 state
->SetInteger("pending_count", pixel_buffer_tasks_
.size());
653 state
->SetInteger("pending_upload_count", tasks_with_pending_upload_
.size());
654 state
->SetInteger("required_for_activation_count",
655 tasks_required_for_activation_
.size());
656 state
->Set("scheduled_state", ScheduledStateAsValue().release());
657 state
->Set("throttle_state", ThrottleStateAsValue().release());
658 return state
.PassAs
<base::Value
>();
661 scoped_ptr
<base::Value
> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
663 scoped_ptr
<base::DictionaryValue
> throttle_state(new base::DictionaryValue
);
665 throttle_state
->SetInteger("bytes_available_for_upload",
666 max_bytes_pending_upload_
- bytes_pending_upload_
);
667 throttle_state
->SetInteger("bytes_pending_upload", bytes_pending_upload_
);
668 throttle_state
->SetInteger("scheduled_raster_task_count",
669 scheduled_raster_task_count_
);
670 return throttle_state
.PassAs
<base::Value
>();