Reject XMLHTTPRequests Without HTTP Status Success
[chromium-blink-merge.git] / cc / resources / pixel_buffer_raster_worker_pool.cc
blob80ddcd961a1fc1fd41ff14451a55bd1473b263b6
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 <algorithm>
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"
14 namespace cc {
15 namespace {
17 const int kCheckForCompletedRasterTasksDelayMs = 6;
19 const size_t kMaxScheduledRasterTasks = 48;
21 typedef base::StackVector<internal::WorkerPoolTask*, kMaxScheduledRasterTasks>
22 WorkerPoolTaskVector;
24 } // namespace
26 // static
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,
33 GetTaskGraphRunner(),
34 resource_provider,
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),
44 shutdown_(false),
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_(
53 false),
54 raster_finished_task_pending_(false),
55 raster_required_for_activation_finished_task_pending_(false),
56 weak_factory_(this) {}
58 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
59 DCHECK(shutdown_);
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() {
69 shutdown_ = true;
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();
80 ++it) {
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,
96 static_cast<size_t>(
97 std::count_if(queue->items.begin(),
98 queue->items.end(),
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();
112 ++it) {
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;
143 continue;
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();
156 ++it) {
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
165 // this task.
166 if (state_it == raster_task_states_.end())
167 continue;
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();
192 FlushUploads();
194 // Schedule new tasks.
195 ScheduleMoreTasks();
197 // Cancel any pending check for completed raster tasks and schedule
198 // another check.
199 check_for_completed_raster_tasks_time_ = base::TimeTicks();
200 ScheduleCheckForCompletedRasterTasks();
202 TRACE_EVENT_ASYNC_STEP_INTO1(
203 "cc",
204 "ScheduledTasks",
205 this,
206 StateName(),
207 "state",
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();
224 FlushUploads();
226 for (TaskVector::const_iterator it = completed_image_decode_tasks_.begin();
227 it != completed_image_decode_tasks_.end();
228 ++it) {
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();
236 ++it) {
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_)
284 return;
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_)
298 return;
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
303 // notified.
304 CheckForCompletedRasterTasks();
307 void PixelBufferRasterWorkerPool::FlushUploads() {
308 if (!has_performed_uploads_since_last_flush_)
309 return;
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()))
331 break;
333 tasks_with_completed_uploads.push_back(task);
334 raster_tasks_with_pending_upload_.pop_front();
337 DCHECK(client());
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);
358 continue;
361 ++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();
368 ++it) {
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();
386 ++it) {
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);
399 task->DidComplete();
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_)
420 return;
422 task_runner()->PostDelayedTask(
423 FROM_HERE,
424 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
425 weak_factory_.GetWeakPtr()),
426 delay);
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;
433 return;
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
440 // raster tasks.
441 if (delay > base::TimeDelta()) {
442 task_runner()->PostDelayedTask(
443 FROM_HERE,
444 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
445 weak_factory_.GetWeakPtr()),
446 delay);
447 return;
450 check_for_completed_raster_tasks_pending_ = false;
451 CheckForCompletedRasterTasks();
454 void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
455 TRACE_EVENT0("cc",
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();
463 FlushUploads();
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())
483 ScheduleMoreTasks();
485 TRACE_EVENT_ASYNC_STEP_INTO1(
486 "cc",
487 "ScheduledTasks",
488 this,
489 StateName(),
490 "state",
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;
518 graph_.Reset();
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();
527 ++it) {
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())
538 continue;
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());
547 continue;
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;
557 continue;
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;
564 continue;
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;
572 continue;
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();
613 ++it) {
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();
636 ++it) {
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())
670 return "throttled";
671 if (!raster_tasks_with_pending_upload_.empty())
672 return "waiting_for_uploads";
674 return "finishing";
677 void PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks() {
678 CollectCompletedWorkerPoolTasks(&completed_tasks_);
679 for (internal::Task::Vector::const_iterator it = completed_tasks_.begin();
680 it != completed_tasks_.end();
681 ++it) {
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);
692 task->DidComplete();
694 completed_image_decode_tasks_.push_back(task);
695 continue;
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);
712 task->DidComplete();
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;
725 continue;
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;
738 continue;
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()
767 const {
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>();
778 } // namespace cc