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"
9 #include "base/containers/stack_container.h"
10 #include "base/debug/trace_event.h"
11 #include "cc/debug/traced_value.h"
12 #include "cc/resources/resource.h"
17 const int kCheckForCompletedRasterTasksDelayMs
= 6;
19 const size_t kMaxScheduledRasterTasks
= 48;
21 typedef base::StackVector
<internal::WorkerPoolTask
*, kMaxScheduledRasterTasks
>
27 scoped_ptr
<RasterWorkerPool
> PixelBufferRasterWorkerPool::Create(
28 base::SequencedTaskRunner
* task_runner
,
29 ResourceProvider
* resource_provider
,
30 size_t max_transfer_buffer_usage_bytes
) {
31 return make_scoped_ptr
<RasterWorkerPool
>(
32 new PixelBufferRasterWorkerPool(task_runner
,
35 max_transfer_buffer_usage_bytes
));
38 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
39 base::SequencedTaskRunner
* task_runner
,
40 internal::TaskGraphRunner
* task_graph_runner
,
41 ResourceProvider
* resource_provider
,
42 size_t max_transfer_buffer_usage_bytes
)
43 : RasterWorkerPool(task_runner
, task_graph_runner
, resource_provider
),
45 scheduled_raster_task_count_(0u),
46 raster_tasks_required_for_activation_count_(0u),
47 bytes_pending_upload_(0u),
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());
65 DCHECK_EQ(0u, raster_tasks_required_for_activation_count_
);
68 void PixelBufferRasterWorkerPool::Shutdown() {
70 RasterWorkerPool::Shutdown();
72 CheckForCompletedWorkerPoolTasks();
73 CheckForCompletedUploads();
75 weak_factory_
.InvalidateWeakPtrs();
76 check_for_completed_raster_tasks_pending_
= false;
78 for (RasterTaskState::Vector::iterator it
= raster_task_states_
.begin();
79 it
!= raster_task_states_
.end();
81 RasterTaskState
& state
= *it
;
83 // All unscheduled tasks need to be canceled.
84 if (state
.type
== RasterTaskState::UNSCHEDULED
) {
85 completed_raster_tasks_
.push_back(state
.task
);
86 state
.type
= RasterTaskState::COMPLETED
;
89 DCHECK_EQ(completed_raster_tasks_
.size(), raster_task_states_
.size());
92 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue
* queue
) {
93 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
95 DCHECK_EQ(queue
->required_for_activation_count
,
97 std::count_if(queue
->items
.begin(),
99 RasterTaskQueue::Item::IsRequiredForActivation
)));
101 if (!should_notify_client_if_no_tasks_are_pending_
)
102 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
104 should_notify_client_if_no_tasks_are_pending_
= true;
105 should_notify_client_if_no_tasks_required_for_activation_are_pending_
= true;
107 raster_tasks_required_for_activation_count_
= 0u;
109 // Update raster task state and remove items from old queue.
110 for (RasterTaskQueue::Item::Vector::const_iterator it
= queue
->items
.begin();
111 it
!= queue
->items
.end();
113 const RasterTaskQueue::Item
& item
= *it
;
114 internal::WorkerPoolTask
* task
= item
.task
;
116 // Remove any old items that are associated with this task. The result is
117 // that the old queue is left with all items not present in this queue,
118 // which we use below to determine what tasks need to be canceled.
119 RasterTaskQueue::Item::Vector::iterator old_it
=
120 std::find_if(raster_tasks_
.items
.begin(),
121 raster_tasks_
.items
.end(),
122 RasterTaskQueue::Item::TaskComparator(task
));
123 if (old_it
!= raster_tasks_
.items
.end()) {
124 std::swap(*old_it
, raster_tasks_
.items
.back());
125 raster_tasks_
.items
.pop_back();
128 RasterTaskState::Vector::iterator state_it
=
129 std::find_if(raster_task_states_
.begin(),
130 raster_task_states_
.end(),
131 RasterTaskState::TaskComparator(task
));
132 if (state_it
!= raster_task_states_
.end()) {
133 RasterTaskState
& state
= *state_it
;
135 state
.required_for_activation
= item
.required_for_activation
;
136 // |raster_tasks_required_for_activation_count| accounts for all tasks
137 // that need to complete before we can send a "ready to activate" signal.
138 // Tasks that have already completed should not be part of this count.
139 if (state
.type
!= RasterTaskState::COMPLETED
) {
140 raster_tasks_required_for_activation_count_
+=
141 item
.required_for_activation
;
146 DCHECK(!task
->HasBeenScheduled());
147 raster_task_states_
.push_back(
148 RasterTaskState(task
, item
.required_for_activation
));
149 raster_tasks_required_for_activation_count_
+= item
.required_for_activation
;
152 // Determine what tasks in old queue need to be canceled.
153 for (RasterTaskQueue::Item::Vector::const_iterator it
=
154 raster_tasks_
.items
.begin();
155 it
!= raster_tasks_
.items
.end();
157 const RasterTaskQueue::Item
& item
= *it
;
158 internal::WorkerPoolTask
* task
= item
.task
;
160 RasterTaskState::Vector::iterator state_it
=
161 std::find_if(raster_task_states_
.begin(),
162 raster_task_states_
.end(),
163 RasterTaskState::TaskComparator(task
));
164 // We've already processed completion if we can't find a RasterTaskState for
166 if (state_it
== raster_task_states_
.end())
169 RasterTaskState
& state
= *state_it
;
171 // Unscheduled task can be canceled.
172 if (state
.type
== RasterTaskState::UNSCHEDULED
) {
173 DCHECK(!task
->HasBeenScheduled());
174 DCHECK(std::find(completed_raster_tasks_
.begin(),
175 completed_raster_tasks_
.end(),
176 task
) == completed_raster_tasks_
.end());
177 completed_raster_tasks_
.push_back(task
);
178 state
.type
= RasterTaskState::COMPLETED
;
181 // No longer required for activation.
182 state
.required_for_activation
= false;
185 raster_tasks_
.Swap(queue
);
187 // Check for completed tasks when ScheduleTasks() is called as
188 // priorities might have changed and this maximizes the number
189 // of top priority tasks that are scheduled.
190 CheckForCompletedWorkerPoolTasks();
191 CheckForCompletedUploads();
194 // Schedule new tasks.
197 // Cancel any pending check for completed raster tasks and schedule
199 check_for_completed_raster_tasks_time_
= base::TimeTicks();
200 ScheduleCheckForCompletedRasterTasks();
202 TRACE_EVENT_ASYNC_STEP_INTO1(
208 TracedValue::FromValue(StateAsValue().release()));
211 unsigned PixelBufferRasterWorkerPool::GetResourceTarget() const {
212 return GL_TEXTURE_2D
;
215 ResourceFormat
PixelBufferRasterWorkerPool::GetResourceFormat() const {
216 return resource_provider()->memory_efficient_texture_format();
219 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
220 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
222 CheckForCompletedWorkerPoolTasks();
223 CheckForCompletedUploads();
226 for (TaskVector::const_iterator it
= completed_image_decode_tasks_
.begin();
227 it
!= completed_image_decode_tasks_
.end();
229 internal::WorkerPoolTask
* task
= it
->get();
230 task
->RunReplyOnOriginThread();
232 completed_image_decode_tasks_
.clear();
234 for (TaskVector::const_iterator it
= completed_raster_tasks_
.begin();
235 it
!= completed_raster_tasks_
.end();
237 internal::WorkerPoolTask
* task
= it
->get();
238 RasterTaskState::Vector::iterator state_it
=
239 std::find_if(raster_task_states_
.begin(),
240 raster_task_states_
.end(),
241 RasterTaskState::TaskComparator(task
));
242 DCHECK(state_it
!= raster_task_states_
.end());
243 DCHECK_EQ(RasterTaskState::COMPLETED
, state_it
->type
);
245 std::swap(*state_it
, raster_task_states_
.back());
246 raster_task_states_
.pop_back();
248 task
->RunReplyOnOriginThread();
250 completed_raster_tasks_
.clear();
253 SkCanvas
* PixelBufferRasterWorkerPool::AcquireCanvasForRaster(
254 internal::WorkerPoolTask
* task
,
255 const Resource
* resource
) {
256 RasterTaskState::Vector::iterator it
=
257 std::find_if(raster_task_states_
.begin(),
258 raster_task_states_
.end(),
259 RasterTaskState::TaskComparator(task
));
260 DCHECK(it
!= raster_task_states_
.end());
261 DCHECK(!it
->resource
);
262 it
->resource
= resource
;
263 resource_provider()->AcquirePixelRasterBuffer(resource
->id());
264 return resource_provider()->MapPixelRasterBuffer(resource
->id());
267 void PixelBufferRasterWorkerPool::ReleaseCanvasForRaster(
268 internal::WorkerPoolTask
* task
,
269 const Resource
* resource
) {
270 RasterTaskState::Vector::iterator it
=
271 std::find_if(raster_task_states_
.begin(),
272 raster_task_states_
.end(),
273 RasterTaskState::TaskComparator(task
));
274 DCHECK(it
!= raster_task_states_
.end());
275 DCHECK(it
->resource
== resource
);
276 resource_provider()->ReleasePixelRasterBuffer(resource
->id());
279 void PixelBufferRasterWorkerPool::OnRasterTasksFinished() {
280 // |should_notify_client_if_no_tasks_are_pending_| can be set to false as
281 // a result of a scheduled CheckForCompletedRasterTasks() call. No need to
282 // perform another check in that case as we've already notified the client.
283 if (!should_notify_client_if_no_tasks_are_pending_
)
285 raster_finished_task_pending_
= false;
287 // Call CheckForCompletedRasterTasks() when we've finished running all
288 // raster tasks needed since last time ScheduleTasks() was called.
289 // This reduces latency between the time when all tasks have finished
290 // running and the time when the client is notified.
291 CheckForCompletedRasterTasks();
294 void PixelBufferRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
295 // Analogous to OnRasterTasksFinished(), there's no need to call
296 // CheckForCompletedRasterTasks() if the client has already been notified.
297 if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_
)
299 raster_required_for_activation_finished_task_pending_
= false;
301 // This reduces latency between the time when all tasks required for
302 // activation have finished running and the time when the client is
304 CheckForCompletedRasterTasks();
307 void PixelBufferRasterWorkerPool::FlushUploads() {
308 if (!has_performed_uploads_since_last_flush_
)
311 resource_provider()->ShallowFlushIfSupported();
312 has_performed_uploads_since_last_flush_
= false;
315 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
316 TaskVector tasks_with_completed_uploads
;
318 // First check if any have completed.
319 while (!raster_tasks_with_pending_upload_
.empty()) {
320 internal::WorkerPoolTask
* task
=
321 raster_tasks_with_pending_upload_
.front().get();
322 RasterTaskState::Vector::const_iterator it
=
323 std::find_if(raster_task_states_
.begin(),
324 raster_task_states_
.end(),
325 RasterTaskState::TaskComparator(task
));
326 DCHECK(it
!= raster_task_states_
.end());
327 DCHECK_EQ(RasterTaskState::UPLOADING
, it
->type
);
329 // Uploads complete in the order they are issued.
330 if (!resource_provider()->DidSetPixelsComplete(it
->resource
->id()))
333 tasks_with_completed_uploads
.push_back(task
);
334 raster_tasks_with_pending_upload_
.pop_front();
338 bool should_force_some_uploads_to_complete
=
339 shutdown_
|| client()->ShouldForceTasksRequiredForActivationToComplete();
341 if (should_force_some_uploads_to_complete
) {
342 TaskVector tasks_with_uploads_to_force
;
343 TaskDeque::iterator it
= raster_tasks_with_pending_upload_
.begin();
344 while (it
!= raster_tasks_with_pending_upload_
.end()) {
345 internal::WorkerPoolTask
* task
= it
->get();
346 RasterTaskState::Vector::const_iterator state_it
=
347 std::find_if(raster_task_states_
.begin(),
348 raster_task_states_
.end(),
349 RasterTaskState::TaskComparator(task
));
350 DCHECK(state_it
!= raster_task_states_
.end());
352 // Force all uploads required for activation to complete.
353 // During shutdown, force all pending uploads to complete.
354 if (shutdown_
|| state_it
->required_for_activation
) {
355 tasks_with_uploads_to_force
.push_back(task
);
356 tasks_with_completed_uploads
.push_back(task
);
357 it
= raster_tasks_with_pending_upload_
.erase(it
);
364 // Force uploads in reverse order. Since forcing can cause a wait on
365 // all previous uploads, we would rather wait only once downstream.
366 for (TaskVector::reverse_iterator it
= tasks_with_uploads_to_force
.rbegin();
367 it
!= tasks_with_uploads_to_force
.rend();
369 internal::WorkerPoolTask
* task
= it
->get();
370 RasterTaskState::Vector::const_iterator state_it
=
371 std::find_if(raster_task_states_
.begin(),
372 raster_task_states_
.end(),
373 RasterTaskState::TaskComparator(task
));
374 DCHECK(state_it
!= raster_task_states_
.end());
375 DCHECK(state_it
->resource
);
377 resource_provider()->ForceSetPixelsToComplete(state_it
->resource
->id());
378 has_performed_uploads_since_last_flush_
= true;
382 // Release shared memory and move tasks with completed uploads
383 // to |completed_raster_tasks_|.
384 for (TaskVector::const_iterator it
= tasks_with_completed_uploads
.begin();
385 it
!= tasks_with_completed_uploads
.end();
387 internal::WorkerPoolTask
* task
= it
->get();
388 RasterTaskState::Vector::iterator state_it
=
389 std::find_if(raster_task_states_
.begin(),
390 raster_task_states_
.end(),
391 RasterTaskState::TaskComparator(task
));
392 DCHECK(state_it
!= raster_task_states_
.end());
393 RasterTaskState
& state
= *state_it
;
395 bytes_pending_upload_
-= state
.resource
->bytes();
397 task
->WillComplete();
398 task
->CompleteOnOriginThread(this);
401 DCHECK(std::find(completed_raster_tasks_
.begin(),
402 completed_raster_tasks_
.end(),
403 task
) == completed_raster_tasks_
.end());
404 completed_raster_tasks_
.push_back(task
);
405 state
.type
= RasterTaskState::COMPLETED
;
406 DCHECK_LE(static_cast<size_t>(state
.required_for_activation
),
407 raster_tasks_required_for_activation_count_
);
408 raster_tasks_required_for_activation_count_
-=
409 state
.required_for_activation
;
413 void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() {
414 base::TimeDelta delay
=
415 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs
);
416 if (check_for_completed_raster_tasks_time_
.is_null())
417 check_for_completed_raster_tasks_time_
= base::TimeTicks::Now() + delay
;
419 if (check_for_completed_raster_tasks_pending_
)
422 task_runner()->PostDelayedTask(
424 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks
,
425 weak_factory_
.GetWeakPtr()),
427 check_for_completed_raster_tasks_pending_
= true;
430 void PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks() {
431 if (check_for_completed_raster_tasks_time_
.is_null()) {
432 check_for_completed_raster_tasks_pending_
= false;
436 base::TimeDelta delay
=
437 check_for_completed_raster_tasks_time_
- base::TimeTicks::Now();
439 // Post another delayed task if it is not yet time to check for completed
441 if (delay
> base::TimeDelta()) {
442 task_runner()->PostDelayedTask(
444 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks
,
445 weak_factory_
.GetWeakPtr()),
450 check_for_completed_raster_tasks_pending_
= false;
451 CheckForCompletedRasterTasks();
454 void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
456 "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");
458 DCHECK(should_notify_client_if_no_tasks_are_pending_
);
459 check_for_completed_raster_tasks_time_
= base::TimeTicks();
461 CheckForCompletedWorkerPoolTasks();
462 CheckForCompletedUploads();
465 // Determine what client notifications to generate.
466 bool will_notify_client_that_no_tasks_required_for_activation_are_pending
=
467 (should_notify_client_if_no_tasks_required_for_activation_are_pending_
&&
468 !raster_required_for_activation_finished_task_pending_
&&
469 !HasPendingTasksRequiredForActivation());
470 bool will_notify_client_that_no_tasks_are_pending
=
471 (should_notify_client_if_no_tasks_are_pending_
&&
472 !raster_required_for_activation_finished_task_pending_
&&
473 !raster_finished_task_pending_
&& !HasPendingTasks());
475 // Adjust the need to generate notifications before scheduling more tasks.
476 should_notify_client_if_no_tasks_required_for_activation_are_pending_
&=
477 !will_notify_client_that_no_tasks_required_for_activation_are_pending
;
478 should_notify_client_if_no_tasks_are_pending_
&=
479 !will_notify_client_that_no_tasks_are_pending
;
481 scheduled_raster_task_count_
= 0;
482 if (PendingRasterTaskCount())
485 TRACE_EVENT_ASYNC_STEP_INTO1(
491 TracedValue::FromValue(StateAsValue().release()));
493 // Schedule another check for completed raster tasks while there are
494 // pending raster tasks or pending uploads.
495 if (HasPendingTasks())
496 ScheduleCheckForCompletedRasterTasks();
498 // Generate client notifications.
499 if (will_notify_client_that_no_tasks_required_for_activation_are_pending
) {
500 DCHECK(!HasPendingTasksRequiredForActivation());
501 client()->DidFinishRunningTasksRequiredForActivation();
503 if (will_notify_client_that_no_tasks_are_pending
) {
504 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
505 DCHECK(!HasPendingTasksRequiredForActivation());
506 client()->DidFinishRunningTasks();
510 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
511 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
513 WorkerPoolTaskVector tasks
;
514 WorkerPoolTaskVector tasks_required_for_activation
;
516 unsigned priority
= kRasterTaskPriorityBase
;
520 size_t bytes_pending_upload
= bytes_pending_upload_
;
521 bool did_throttle_raster_tasks
= false;
522 bool did_throttle_raster_tasks_required_for_activation
= false;
524 for (RasterTaskQueue::Item::Vector::const_iterator it
=
525 raster_tasks_
.items
.begin();
526 it
!= raster_tasks_
.items
.end();
528 const RasterTaskQueue::Item
& item
= *it
;
529 internal::RasterWorkerPoolTask
* task
= item
.task
;
531 // |raster_task_states_| contains the state of all tasks that we have not
532 // yet run reply callbacks for.
533 RasterTaskState::Vector::iterator state_it
=
534 std::find_if(raster_task_states_
.begin(),
535 raster_task_states_
.end(),
536 RasterTaskState::TaskComparator(task
));
537 if (state_it
== raster_task_states_
.end())
540 RasterTaskState
& state
= *state_it
;
542 // Skip task if completed.
543 if (state
.type
== RasterTaskState::COMPLETED
) {
544 DCHECK(std::find(completed_raster_tasks_
.begin(),
545 completed_raster_tasks_
.end(),
546 task
) != completed_raster_tasks_
.end());
550 // All raster tasks need to be throttled by bytes of pending uploads.
551 size_t new_bytes_pending_upload
= bytes_pending_upload
;
552 new_bytes_pending_upload
+= task
->resource()->bytes();
553 if (new_bytes_pending_upload
> max_bytes_pending_upload_
) {
554 did_throttle_raster_tasks
= true;
555 if (item
.required_for_activation
)
556 did_throttle_raster_tasks_required_for_activation
= true;
560 // If raster has finished, just update |bytes_pending_upload|.
561 if (state
.type
== RasterTaskState::UPLOADING
) {
562 DCHECK(!task
->HasCompleted());
563 bytes_pending_upload
= new_bytes_pending_upload
;
567 // Throttle raster tasks based on kMaxScheduledRasterTasks.
568 if (tasks
.container().size() >= kMaxScheduledRasterTasks
) {
569 did_throttle_raster_tasks
= true;
570 if (item
.required_for_activation
)
571 did_throttle_raster_tasks_required_for_activation
= true;
575 // Update |bytes_pending_upload| now that task has cleared all
576 // throttling limits.
577 bytes_pending_upload
= new_bytes_pending_upload
;
579 DCHECK(state
.type
== RasterTaskState::UNSCHEDULED
||
580 state
.type
== RasterTaskState::SCHEDULED
);
581 state
.type
= RasterTaskState::SCHEDULED
;
583 InsertNodeForRasterTask(&graph_
, task
, task
->dependencies(), priority
++);
585 tasks
.container().push_back(task
);
586 if (item
.required_for_activation
)
587 tasks_required_for_activation
.container().push_back(task
);
590 scoped_refptr
<internal::WorkerPoolTask
>
591 new_raster_required_for_activation_finished_task
;
593 size_t scheduled_raster_task_required_for_activation_count
=
594 tasks_required_for_activation
.container().size();
595 DCHECK_LE(scheduled_raster_task_required_for_activation_count
,
596 raster_tasks_required_for_activation_count_
);
597 // Schedule OnRasterTasksRequiredForActivationFinished call only when
598 // notification is pending and throttling is not preventing all pending
599 // tasks required for activation from being scheduled.
600 if (!did_throttle_raster_tasks_required_for_activation
&&
601 should_notify_client_if_no_tasks_required_for_activation_are_pending_
) {
602 new_raster_required_for_activation_finished_task
=
603 CreateRasterRequiredForActivationFinishedTask(
604 raster_tasks_
.required_for_activation_count
);
605 raster_required_for_activation_finished_task_pending_
= true;
606 InsertNodeForTask(&graph_
,
607 new_raster_required_for_activation_finished_task
.get(),
608 kRasterRequiredForActivationFinishedTaskPriority
,
609 scheduled_raster_task_required_for_activation_count
);
610 for (WorkerPoolTaskVector::ContainerType::const_iterator it
=
611 tasks_required_for_activation
.container().begin();
612 it
!= tasks_required_for_activation
.container().end();
614 graph_
.edges
.push_back(internal::TaskGraph::Edge(
615 *it
, new_raster_required_for_activation_finished_task
.get()));
619 scoped_refptr
<internal::WorkerPoolTask
> new_raster_finished_task
;
621 size_t scheduled_raster_task_count
= tasks
.container().size();
622 DCHECK_LE(scheduled_raster_task_count
, PendingRasterTaskCount());
623 // Schedule OnRasterTasksFinished call only when notification is pending
624 // and throttling is not preventing all pending tasks from being scheduled.
625 if (!did_throttle_raster_tasks
&&
626 should_notify_client_if_no_tasks_are_pending_
) {
627 new_raster_finished_task
= CreateRasterFinishedTask();
628 raster_finished_task_pending_
= true;
629 InsertNodeForTask(&graph_
,
630 new_raster_finished_task
.get(),
631 kRasterFinishedTaskPriority
,
632 scheduled_raster_task_count
);
633 for (WorkerPoolTaskVector::ContainerType::const_iterator it
=
634 tasks
.container().begin();
635 it
!= tasks
.container().end();
637 graph_
.edges
.push_back(
638 internal::TaskGraph::Edge(*it
, new_raster_finished_task
.get()));
642 SetTaskGraph(&graph_
);
644 scheduled_raster_task_count_
= scheduled_raster_task_count
;
646 set_raster_finished_task(new_raster_finished_task
);
647 set_raster_required_for_activation_finished_task(
648 new_raster_required_for_activation_finished_task
);
651 unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
652 unsigned num_completed_raster_tasks
=
653 raster_tasks_with_pending_upload_
.size() + completed_raster_tasks_
.size();
654 DCHECK_GE(raster_task_states_
.size(), num_completed_raster_tasks
);
655 return raster_task_states_
.size() - num_completed_raster_tasks
;
658 bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
659 return PendingRasterTaskCount() || !raster_tasks_with_pending_upload_
.empty();
662 bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
663 return !!raster_tasks_required_for_activation_count_
;
666 const char* PixelBufferRasterWorkerPool::StateName() const {
667 if (scheduled_raster_task_count_
)
668 return "rasterizing";
669 if (PendingRasterTaskCount())
671 if (!raster_tasks_with_pending_upload_
.empty())
672 return "waiting_for_uploads";
677 void PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks() {
678 CollectCompletedWorkerPoolTasks(&completed_tasks_
);
679 for (internal::Task::Vector::const_iterator it
= completed_tasks_
.begin();
680 it
!= completed_tasks_
.end();
682 internal::WorkerPoolTask
* task
=
683 static_cast<internal::WorkerPoolTask
*>(it
->get());
685 RasterTaskState::Vector::iterator state_it
=
686 std::find_if(raster_task_states_
.begin(),
687 raster_task_states_
.end(),
688 RasterTaskState::TaskComparator(task
));
689 if (state_it
== raster_task_states_
.end()) {
690 task
->WillComplete();
691 task
->CompleteOnOriginThread(this);
694 completed_image_decode_tasks_
.push_back(task
);
698 RasterTaskState
& state
= *state_it
;
699 DCHECK_EQ(RasterTaskState::SCHEDULED
, state
.type
);
700 DCHECK(state
.resource
);
702 // Balanced with MapPixelRasterBuffer() call in AcquireCanvasForRaster().
703 bool content_has_changed
=
704 resource_provider()->UnmapPixelRasterBuffer(state
.resource
->id());
706 // |content_has_changed| can be false as result of task being canceled or
707 // task implementation deciding not to modify bitmap (ie. analysis of raster
708 // commands detected content as a solid color).
709 if (!content_has_changed
) {
710 task
->WillComplete();
711 task
->CompleteOnOriginThread(this);
714 if (!task
->HasFinishedRunning()) {
715 // When priorites change, a raster task can be canceled as a result of
716 // no longer being of high enough priority to fit in our throttled
717 // raster task budget. The task has not yet completed in this case.
718 RasterTaskQueue::Item::Vector::const_iterator item_it
=
719 std::find_if(raster_tasks_
.items
.begin(),
720 raster_tasks_
.items
.end(),
721 RasterTaskQueue::Item::TaskComparator(task
));
722 if (item_it
!= raster_tasks_
.items
.end()) {
723 state
.type
= RasterTaskState::UNSCHEDULED
;
724 state
.resource
= NULL
;
729 DCHECK(std::find(completed_raster_tasks_
.begin(),
730 completed_raster_tasks_
.end(),
731 task
) == completed_raster_tasks_
.end());
732 completed_raster_tasks_
.push_back(task
);
733 state
.type
= RasterTaskState::COMPLETED
;
734 DCHECK_LE(static_cast<size_t>(state
.required_for_activation
),
735 raster_tasks_required_for_activation_count_
);
736 raster_tasks_required_for_activation_count_
-=
737 state
.required_for_activation
;
741 DCHECK(task
->HasFinishedRunning());
743 resource_provider()->BeginSetPixels(state
.resource
->id());
744 has_performed_uploads_since_last_flush_
= true;
746 bytes_pending_upload_
+= state
.resource
->bytes();
747 raster_tasks_with_pending_upload_
.push_back(task
);
748 state
.type
= RasterTaskState::UPLOADING
;
750 completed_tasks_
.clear();
753 scoped_ptr
<base::Value
> PixelBufferRasterWorkerPool::StateAsValue() const {
754 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue
);
756 state
->SetInteger("completed_count", completed_raster_tasks_
.size());
757 state
->SetInteger("pending_count", raster_task_states_
.size());
758 state
->SetInteger("pending_upload_count",
759 raster_tasks_with_pending_upload_
.size());
760 state
->SetInteger("pending_required_for_activation_count",
761 raster_tasks_required_for_activation_count_
);
762 state
->Set("throttle_state", ThrottleStateAsValue().release());
763 return state
.PassAs
<base::Value
>();
766 scoped_ptr
<base::Value
> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
768 scoped_ptr
<base::DictionaryValue
> throttle_state(new base::DictionaryValue
);
770 throttle_state
->SetInteger("bytes_available_for_upload",
771 max_bytes_pending_upload_
- bytes_pending_upload_
);
772 throttle_state
->SetInteger("bytes_pending_upload", bytes_pending_upload_
);
773 throttle_state
->SetInteger("scheduled_raster_task_count",
774 scheduled_raster_task_count_
);
775 return throttle_state
.PassAs
<base::Value
>();