pixel_buffer_raster_worker_pool.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/resources/pixel_buffer_raster_worker_pool.h"
6
7#include <algorithm>
8
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"
13
14namespace cc {
15namespace {
16
17const int kCheckForCompletedRasterTasksDelayMs = 6;
18
19const size_t kMaxScheduledRasterTasks = 48;
20
21typedef base::StackVector<internal::WorkerPoolTask*, kMaxScheduledRasterTasks>
22    WorkerPoolTaskVector;
23
24}  // namespace
25
26// static
27scoped_ptr<PixelBufferRasterWorkerPool> PixelBufferRasterWorkerPool::Create(
28    base::SequencedTaskRunner* task_runner,
29    ResourceProvider* resource_provider,
30    size_t max_transfer_buffer_usage_bytes) {
31  return make_scoped_ptr(
32      new PixelBufferRasterWorkerPool(task_runner,
33                                      GetTaskGraphRunner(),
34                                      resource_provider,
35                                      max_transfer_buffer_usage_bytes));
36}
37
38PixelBufferRasterWorkerPool::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    : task_runner_(task_runner),
44      task_graph_runner_(task_graph_runner),
45      namespace_token_(task_graph_runner->GetNamespaceToken()),
46      resource_provider_(resource_provider),
47      shutdown_(false),
48      scheduled_raster_task_count_(0u),
49      raster_tasks_required_for_activation_count_(0u),
50      bytes_pending_upload_(0u),
51      max_bytes_pending_upload_(max_transfer_buffer_usage_bytes),
52      has_performed_uploads_since_last_flush_(false),
53      check_for_completed_raster_tasks_pending_(false),
54      should_notify_client_if_no_tasks_are_pending_(false),
55      should_notify_client_if_no_tasks_required_for_activation_are_pending_(
56          false),
57      raster_finished_task_pending_(false),
58      raster_required_for_activation_finished_task_pending_(false),
59      raster_finished_weak_ptr_factory_(this),
60      weak_ptr_factory_(this) {}
61
62PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
63  DCHECK(!check_for_completed_raster_tasks_pending_);
64  DCHECK_EQ(0u, raster_task_states_.size());
65  DCHECK_EQ(0u, raster_tasks_with_pending_upload_.size());
66  DCHECK_EQ(0u, completed_raster_tasks_.size());
67  DCHECK_EQ(0u, completed_image_decode_tasks_.size());
68  DCHECK_EQ(0u, raster_tasks_required_for_activation_count_);
69}
70
71void PixelBufferRasterWorkerPool::SetClient(RasterWorkerPoolClient* client) {
72  client_ = client;
73}
74
75void PixelBufferRasterWorkerPool::Shutdown() {
76  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::Shutdown");
77
78  shutdown_ = true;
79
80  internal::TaskGraph empty;
81  task_graph_runner_->ScheduleTasks(namespace_token_, &empty);
82  task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
83
84  CheckForCompletedWorkerPoolTasks();
85  CheckForCompletedUploads();
86
87  check_for_completed_raster_tasks_pending_ = false;
88
89  for (RasterTaskState::Vector::iterator it = raster_task_states_.begin();
90       it != raster_task_states_.end();
91       ++it) {
92    RasterTaskState& state = *it;
93
94    // All unscheduled tasks need to be canceled.
95    if (state.type == RasterTaskState::UNSCHEDULED) {
96      completed_raster_tasks_.push_back(state.task);
97      state.type = RasterTaskState::COMPLETED;
98    }
99  }
100  DCHECK_EQ(completed_raster_tasks_.size(), raster_task_states_.size());
101}
102
103void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) {
104  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
105
106  DCHECK_EQ(queue->required_for_activation_count,
107            static_cast<size_t>(
108                std::count_if(queue->items.begin(),
109                              queue->items.end(),
110                              RasterTaskQueue::Item::IsRequiredForActivation)));
111
112  if (!should_notify_client_if_no_tasks_are_pending_)
113    TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
114
115  should_notify_client_if_no_tasks_are_pending_ = true;
116  should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true;
117
118  raster_tasks_required_for_activation_count_ = 0u;
119
120  // Update raster task state and remove items from old queue.
121  for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin();
122       it != queue->items.end();
123       ++it) {
124    const RasterTaskQueue::Item& item = *it;
125    internal::WorkerPoolTask* task = item.task;
126
127    // Remove any old items that are associated with this task. The result is
128    // that the old queue is left with all items not present in this queue,
129    // which we use below to determine what tasks need to be canceled.
130    RasterTaskQueue::Item::Vector::iterator old_it =
131        std::find_if(raster_tasks_.items.begin(),
132                     raster_tasks_.items.end(),
133                     RasterTaskQueue::Item::TaskComparator(task));
134    if (old_it != raster_tasks_.items.end()) {
135      std::swap(*old_it, raster_tasks_.items.back());
136      raster_tasks_.items.pop_back();
137    }
138
139    RasterTaskState::Vector::iterator state_it =
140        std::find_if(raster_task_states_.begin(),
141                     raster_task_states_.end(),
142                     RasterTaskState::TaskComparator(task));
143    if (state_it != raster_task_states_.end()) {
144      RasterTaskState& state = *state_it;
145
146      state.required_for_activation = item.required_for_activation;
147      // |raster_tasks_required_for_activation_count| accounts for all tasks
148      // that need to complete before we can send a "ready to activate" signal.
149      // Tasks that have already completed should not be part of this count.
150      if (state.type != RasterTaskState::COMPLETED) {
151        raster_tasks_required_for_activation_count_ +=
152            item.required_for_activation;
153      }
154      continue;
155    }
156
157    DCHECK(!task->HasBeenScheduled());
158    raster_task_states_.push_back(
159        RasterTaskState(task, item.required_for_activation));
160    raster_tasks_required_for_activation_count_ += item.required_for_activation;
161  }
162
163  // Determine what tasks in old queue need to be canceled.
164  for (RasterTaskQueue::Item::Vector::const_iterator it =
165           raster_tasks_.items.begin();
166       it != raster_tasks_.items.end();
167       ++it) {
168    const RasterTaskQueue::Item& item = *it;
169    internal::WorkerPoolTask* task = item.task;
170
171    RasterTaskState::Vector::iterator state_it =
172        std::find_if(raster_task_states_.begin(),
173                     raster_task_states_.end(),
174                     RasterTaskState::TaskComparator(task));
175    // We've already processed completion if we can't find a RasterTaskState for
176    // this task.
177    if (state_it == raster_task_states_.end())
178      continue;
179
180    RasterTaskState& state = *state_it;
181
182    // Unscheduled task can be canceled.
183    if (state.type == RasterTaskState::UNSCHEDULED) {
184      DCHECK(!task->HasBeenScheduled());
185      DCHECK(std::find(completed_raster_tasks_.begin(),
186                       completed_raster_tasks_.end(),
187                       task) == completed_raster_tasks_.end());
188      completed_raster_tasks_.push_back(task);
189      state.type = RasterTaskState::COMPLETED;
190    }
191
192    // No longer required for activation.
193    state.required_for_activation = false;
194  }
195
196  raster_tasks_.Swap(queue);
197
198  // Check for completed tasks when ScheduleTasks() is called as
199  // priorities might have changed and this maximizes the number
200  // of top priority tasks that are scheduled.
201  CheckForCompletedWorkerPoolTasks();
202  CheckForCompletedUploads();
203  FlushUploads();
204
205  // Schedule new tasks.
206  ScheduleMoreTasks();
207
208  // Cancel any pending check for completed raster tasks and schedule
209  // another check.
210  check_for_completed_raster_tasks_time_ = base::TimeTicks();
211  ScheduleCheckForCompletedRasterTasks();
212
213  TRACE_EVENT_ASYNC_STEP_INTO1(
214      "cc",
215      "ScheduledTasks",
216      this,
217      StateName(),
218      "state",
219      TracedValue::FromValue(StateAsValue().release()));
220}
221
222unsigned PixelBufferRasterWorkerPool::GetResourceTarget() const {
223  return GL_TEXTURE_2D;
224}
225
226ResourceFormat PixelBufferRasterWorkerPool::GetResourceFormat() const {
227  return resource_provider_->memory_efficient_texture_format();
228}
229
230void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
231  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
232
233  CheckForCompletedWorkerPoolTasks();
234  CheckForCompletedUploads();
235  FlushUploads();
236
237  for (internal::WorkerPoolTask::Vector::const_iterator it =
238           completed_image_decode_tasks_.begin();
239       it != completed_image_decode_tasks_.end();
240       ++it) {
241    internal::WorkerPoolTask* task = it->get();
242    task->RunReplyOnOriginThread();
243  }
244  completed_image_decode_tasks_.clear();
245
246  for (internal::WorkerPoolTask::Vector::const_iterator it =
247           completed_raster_tasks_.begin();
248       it != completed_raster_tasks_.end();
249       ++it) {
250    internal::WorkerPoolTask* task = it->get();
251    RasterTaskState::Vector::iterator state_it =
252        std::find_if(raster_task_states_.begin(),
253                     raster_task_states_.end(),
254                     RasterTaskState::TaskComparator(task));
255    DCHECK(state_it != raster_task_states_.end());
256    DCHECK_EQ(RasterTaskState::COMPLETED, state_it->type);
257
258    std::swap(*state_it, raster_task_states_.back());
259    raster_task_states_.pop_back();
260
261    task->RunReplyOnOriginThread();
262  }
263  completed_raster_tasks_.clear();
264}
265
266SkCanvas* PixelBufferRasterWorkerPool::AcquireCanvasForRaster(
267    internal::WorkerPoolTask* task,
268    const Resource* resource) {
269  RasterTaskState::Vector::iterator it =
270      std::find_if(raster_task_states_.begin(),
271                   raster_task_states_.end(),
272                   RasterTaskState::TaskComparator(task));
273  DCHECK(it != raster_task_states_.end());
274  DCHECK(!it->resource);
275  it->resource = resource;
276  resource_provider_->AcquirePixelRasterBuffer(resource->id());
277  return resource_provider_->MapPixelRasterBuffer(resource->id());
278}
279
280void PixelBufferRasterWorkerPool::ReleaseCanvasForRaster(
281    internal::WorkerPoolTask* task,
282    const Resource* resource) {
283  RasterTaskState::Vector::iterator it =
284      std::find_if(raster_task_states_.begin(),
285                   raster_task_states_.end(),
286                   RasterTaskState::TaskComparator(task));
287  DCHECK(it != raster_task_states_.end());
288  DCHECK(it->resource == resource);
289  resource_provider_->ReleasePixelRasterBuffer(resource->id());
290}
291
292void PixelBufferRasterWorkerPool::OnRasterFinished() {
293  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::OnRasterFinished");
294
295  // |should_notify_client_if_no_tasks_are_pending_| can be set to false as
296  // a result of a scheduled CheckForCompletedRasterTasks() call. No need to
297  // perform another check in that case as we've already notified the client.
298  if (!should_notify_client_if_no_tasks_are_pending_)
299    return;
300  raster_finished_task_pending_ = false;
301
302  // Call CheckForCompletedRasterTasks() when we've finished running all
303  // raster tasks needed since last time ScheduleTasks() was called.
304  // This reduces latency between the time when all tasks have finished
305  // running and the time when the client is notified.
306  CheckForCompletedRasterTasks();
307}
308
309void PixelBufferRasterWorkerPool::OnRasterRequiredForActivationFinished() {
310  TRACE_EVENT0(
311      "cc",
312      "PixelBufferRasterWorkerPool::OnRasterRequiredForActivationFinished");
313
314  // Analogous to OnRasterTasksFinished(), there's no need to call
315  // CheckForCompletedRasterTasks() if the client has already been notified.
316  if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_)
317    return;
318  raster_required_for_activation_finished_task_pending_ = false;
319
320  // This reduces latency between the time when all tasks required for
321  // activation have finished running and the time when the client is
322  // notified.
323  CheckForCompletedRasterTasks();
324}
325
326void PixelBufferRasterWorkerPool::FlushUploads() {
327  if (!has_performed_uploads_since_last_flush_)
328    return;
329
330  resource_provider_->ShallowFlushIfSupported();
331  has_performed_uploads_since_last_flush_ = false;
332}
333
334void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
335  internal::WorkerPoolTask::Vector tasks_with_completed_uploads;
336
337  // First check if any have completed.
338  while (!raster_tasks_with_pending_upload_.empty()) {
339    internal::WorkerPoolTask* task =
340        raster_tasks_with_pending_upload_.front().get();
341    RasterTaskState::Vector::const_iterator it =
342        std::find_if(raster_task_states_.begin(),
343                     raster_task_states_.end(),
344                     RasterTaskState::TaskComparator(task));
345    DCHECK(it != raster_task_states_.end());
346    DCHECK_EQ(RasterTaskState::UPLOADING, it->type);
347
348    // Uploads complete in the order they are issued.
349    if (!resource_provider_->DidSetPixelsComplete(it->resource->id()))
350      break;
351
352    tasks_with_completed_uploads.push_back(task);
353    raster_tasks_with_pending_upload_.pop_front();
354  }
355
356  DCHECK(client_);
357  bool should_force_some_uploads_to_complete =
358      shutdown_ || client_->ShouldForceTasksRequiredForActivationToComplete();
359
360  if (should_force_some_uploads_to_complete) {
361    internal::WorkerPoolTask::Vector tasks_with_uploads_to_force;
362    TaskDeque::iterator it = raster_tasks_with_pending_upload_.begin();
363    while (it != raster_tasks_with_pending_upload_.end()) {
364      internal::WorkerPoolTask* task = it->get();
365      RasterTaskState::Vector::const_iterator state_it =
366          std::find_if(raster_task_states_.begin(),
367                       raster_task_states_.end(),
368                       RasterTaskState::TaskComparator(task));
369      DCHECK(state_it != raster_task_states_.end());
370
371      // Force all uploads required for activation to complete.
372      // During shutdown, force all pending uploads to complete.
373      if (shutdown_ || state_it->required_for_activation) {
374        tasks_with_uploads_to_force.push_back(task);
375        tasks_with_completed_uploads.push_back(task);
376        it = raster_tasks_with_pending_upload_.erase(it);
377        continue;
378      }
379
380      ++it;
381    }
382
383    // Force uploads in reverse order. Since forcing can cause a wait on
384    // all previous uploads, we would rather wait only once downstream.
385    for (internal::WorkerPoolTask::Vector::reverse_iterator it =
386             tasks_with_uploads_to_force.rbegin();
387         it != tasks_with_uploads_to_force.rend();
388         ++it) {
389      internal::WorkerPoolTask* task = it->get();
390      RasterTaskState::Vector::const_iterator state_it =
391          std::find_if(raster_task_states_.begin(),
392                       raster_task_states_.end(),
393                       RasterTaskState::TaskComparator(task));
394      DCHECK(state_it != raster_task_states_.end());
395      DCHECK(state_it->resource);
396
397      resource_provider_->ForceSetPixelsToComplete(state_it->resource->id());
398      has_performed_uploads_since_last_flush_ = true;
399    }
400  }
401
402  // Release shared memory and move tasks with completed uploads
403  // to |completed_raster_tasks_|.
404  for (internal::WorkerPoolTask::Vector::const_iterator it =
405           tasks_with_completed_uploads.begin();
406       it != tasks_with_completed_uploads.end();
407       ++it) {
408    internal::WorkerPoolTask* task = it->get();
409    RasterTaskState::Vector::iterator state_it =
410        std::find_if(raster_task_states_.begin(),
411                     raster_task_states_.end(),
412                     RasterTaskState::TaskComparator(task));
413    DCHECK(state_it != raster_task_states_.end());
414    RasterTaskState& state = *state_it;
415
416    bytes_pending_upload_ -= state.resource->bytes();
417
418    task->WillComplete();
419    task->CompleteOnOriginThread(this);
420    task->DidComplete();
421
422    DCHECK(std::find(completed_raster_tasks_.begin(),
423                     completed_raster_tasks_.end(),
424                     task) == completed_raster_tasks_.end());
425    completed_raster_tasks_.push_back(task);
426    state.type = RasterTaskState::COMPLETED;
427    DCHECK_LE(static_cast<size_t>(state.required_for_activation),
428              raster_tasks_required_for_activation_count_);
429    raster_tasks_required_for_activation_count_ -=
430        state.required_for_activation;
431  }
432}
433
434void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() {
435  base::TimeDelta delay =
436      base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs);
437  if (check_for_completed_raster_tasks_time_.is_null())
438    check_for_completed_raster_tasks_time_ = base::TimeTicks::Now() + delay;
439
440  if (check_for_completed_raster_tasks_pending_)
441    return;
442
443  task_runner_->PostDelayedTask(
444      FROM_HERE,
445      base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
446                 weak_ptr_factory_.GetWeakPtr()),
447      delay);
448  check_for_completed_raster_tasks_pending_ = true;
449}
450
451void PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks() {
452  if (check_for_completed_raster_tasks_time_.is_null()) {
453    check_for_completed_raster_tasks_pending_ = false;
454    return;
455  }
456
457  base::TimeDelta delay =
458      check_for_completed_raster_tasks_time_ - base::TimeTicks::Now();
459
460  // Post another delayed task if it is not yet time to check for completed
461  // raster tasks.
462  if (delay > base::TimeDelta()) {
463    task_runner_->PostDelayedTask(
464        FROM_HERE,
465        base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
466                   weak_ptr_factory_.GetWeakPtr()),
467        delay);
468    return;
469  }
470
471  check_for_completed_raster_tasks_pending_ = false;
472  CheckForCompletedRasterTasks();
473}
474
475void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
476  TRACE_EVENT0("cc",
477               "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");
478
479  DCHECK(should_notify_client_if_no_tasks_are_pending_);
480  check_for_completed_raster_tasks_time_ = base::TimeTicks();
481
482  CheckForCompletedWorkerPoolTasks();
483  CheckForCompletedUploads();
484  FlushUploads();
485
486  // Determine what client notifications to generate.
487  bool will_notify_client_that_no_tasks_required_for_activation_are_pending =
488      (should_notify_client_if_no_tasks_required_for_activation_are_pending_ &&
489       !raster_required_for_activation_finished_task_pending_ &&
490       !HasPendingTasksRequiredForActivation());
491  bool will_notify_client_that_no_tasks_are_pending =
492      (should_notify_client_if_no_tasks_are_pending_ &&
493       !raster_required_for_activation_finished_task_pending_ &&
494       !raster_finished_task_pending_ && !HasPendingTasks());
495
496  // Adjust the need to generate notifications before scheduling more tasks.
497  should_notify_client_if_no_tasks_required_for_activation_are_pending_ &=
498      !will_notify_client_that_no_tasks_required_for_activation_are_pending;
499  should_notify_client_if_no_tasks_are_pending_ &=
500      !will_notify_client_that_no_tasks_are_pending;
501
502  scheduled_raster_task_count_ = 0;
503  if (PendingRasterTaskCount())
504    ScheduleMoreTasks();
505
506  TRACE_EVENT_ASYNC_STEP_INTO1(
507      "cc",
508      "ScheduledTasks",
509      this,
510      StateName(),
511      "state",
512      TracedValue::FromValue(StateAsValue().release()));
513
514  // Schedule another check for completed raster tasks while there are
515  // pending raster tasks or pending uploads.
516  if (HasPendingTasks())
517    ScheduleCheckForCompletedRasterTasks();
518
519  // Generate client notifications.
520  if (will_notify_client_that_no_tasks_required_for_activation_are_pending) {
521    DCHECK(!HasPendingTasksRequiredForActivation());
522    client_->DidFinishRunningTasksRequiredForActivation();
523  }
524  if (will_notify_client_that_no_tasks_are_pending) {
525    TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
526    DCHECK(!HasPendingTasksRequiredForActivation());
527    client_->DidFinishRunningTasks();
528  }
529}
530
531void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
532  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
533
534  WorkerPoolTaskVector tasks;
535  WorkerPoolTaskVector tasks_required_for_activation;
536
537  unsigned priority = kRasterTaskPriorityBase;
538
539  graph_.Reset();
540
541  size_t bytes_pending_upload = bytes_pending_upload_;
542  bool did_throttle_raster_tasks = false;
543  bool did_throttle_raster_tasks_required_for_activation = false;
544
545  for (RasterTaskQueue::Item::Vector::const_iterator it =
546           raster_tasks_.items.begin();
547       it != raster_tasks_.items.end();
548       ++it) {
549    const RasterTaskQueue::Item& item = *it;
550    internal::RasterWorkerPoolTask* task = item.task;
551
552    // |raster_task_states_| contains the state of all tasks that we have not
553    // yet run reply callbacks for.
554    RasterTaskState::Vector::iterator state_it =
555        std::find_if(raster_task_states_.begin(),
556                     raster_task_states_.end(),
557                     RasterTaskState::TaskComparator(task));
558    if (state_it == raster_task_states_.end())
559      continue;
560
561    RasterTaskState& state = *state_it;
562
563    // Skip task if completed.
564    if (state.type == RasterTaskState::COMPLETED) {
565      DCHECK(std::find(completed_raster_tasks_.begin(),
566                       completed_raster_tasks_.end(),
567                       task) != completed_raster_tasks_.end());
568      continue;
569    }
570
571    // All raster tasks need to be throttled by bytes of pending uploads.
572    size_t new_bytes_pending_upload = bytes_pending_upload;
573    new_bytes_pending_upload += task->resource()->bytes();
574    if (new_bytes_pending_upload > max_bytes_pending_upload_) {
575      did_throttle_raster_tasks = true;
576      if (item.required_for_activation)
577        did_throttle_raster_tasks_required_for_activation = true;
578      continue;
579    }
580
581    // If raster has finished, just update |bytes_pending_upload|.
582    if (state.type == RasterTaskState::UPLOADING) {
583      DCHECK(!task->HasCompleted());
584      bytes_pending_upload = new_bytes_pending_upload;
585      continue;
586    }
587
588    // Throttle raster tasks based on kMaxScheduledRasterTasks.
589    if (tasks.container().size() >= kMaxScheduledRasterTasks) {
590      did_throttle_raster_tasks = true;
591      if (item.required_for_activation)
592        did_throttle_raster_tasks_required_for_activation = true;
593      continue;
594    }
595
596    // Update |bytes_pending_upload| now that task has cleared all
597    // throttling limits.
598    bytes_pending_upload = new_bytes_pending_upload;
599
600    DCHECK(state.type == RasterTaskState::UNSCHEDULED ||
601           state.type == RasterTaskState::SCHEDULED);
602    state.type = RasterTaskState::SCHEDULED;
603
604    InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++);
605
606    tasks.container().push_back(task);
607    if (item.required_for_activation)
608      tasks_required_for_activation.container().push_back(task);
609  }
610
611  // Cancel existing OnRasterFinished callbacks.
612  raster_finished_weak_ptr_factory_.InvalidateWeakPtrs();
613
614  scoped_refptr<internal::WorkerPoolTask>
615      new_raster_required_for_activation_finished_task;
616
617  size_t scheduled_raster_task_required_for_activation_count =
618      tasks_required_for_activation.container().size();
619  DCHECK_LE(scheduled_raster_task_required_for_activation_count,
620            raster_tasks_required_for_activation_count_);
621  // Schedule OnRasterTasksRequiredForActivationFinished call only when
622  // notification is pending and throttling is not preventing all pending
623  // tasks required for activation from being scheduled.
624  if (!did_throttle_raster_tasks_required_for_activation &&
625      should_notify_client_if_no_tasks_required_for_activation_are_pending_) {
626    new_raster_required_for_activation_finished_task =
627        CreateRasterRequiredForActivationFinishedTask(
628            raster_tasks_.required_for_activation_count,
629            task_runner_.get(),
630            base::Bind(&PixelBufferRasterWorkerPool::
631                           OnRasterRequiredForActivationFinished,
632                       raster_finished_weak_ptr_factory_.GetWeakPtr()));
633    raster_required_for_activation_finished_task_pending_ = true;
634    InsertNodeForTask(&graph_,
635                      new_raster_required_for_activation_finished_task.get(),
636                      kRasterRequiredForActivationFinishedTaskPriority,
637                      scheduled_raster_task_required_for_activation_count);
638    for (WorkerPoolTaskVector::ContainerType::const_iterator it =
639             tasks_required_for_activation.container().begin();
640         it != tasks_required_for_activation.container().end();
641         ++it) {
642      graph_.edges.push_back(internal::TaskGraph::Edge(
643          *it, new_raster_required_for_activation_finished_task.get()));
644    }
645  }
646
647  scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task;
648
649  size_t scheduled_raster_task_count = tasks.container().size();
650  DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());
651  // Schedule OnRasterTasksFinished call only when notification is pending
652  // and throttling is not preventing all pending tasks from being scheduled.
653  if (!did_throttle_raster_tasks &&
654      should_notify_client_if_no_tasks_are_pending_) {
655    new_raster_finished_task = CreateRasterFinishedTask(
656        task_runner_.get(),
657        base::Bind(&PixelBufferRasterWorkerPool::OnRasterFinished,
658                   raster_finished_weak_ptr_factory_.GetWeakPtr()));
659    raster_finished_task_pending_ = true;
660    InsertNodeForTask(&graph_,
661                      new_raster_finished_task.get(),
662                      kRasterFinishedTaskPriority,
663                      scheduled_raster_task_count);
664    for (WorkerPoolTaskVector::ContainerType::const_iterator it =
665             tasks.container().begin();
666         it != tasks.container().end();
667         ++it) {
668      graph_.edges.push_back(
669          internal::TaskGraph::Edge(*it, new_raster_finished_task.get()));
670    }
671  }
672
673  ScheduleTasksOnOriginThread(this, &graph_);
674  task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
675
676  scheduled_raster_task_count_ = scheduled_raster_task_count;
677
678  raster_finished_task_ = new_raster_finished_task;
679  raster_required_for_activation_finished_task_ =
680      new_raster_required_for_activation_finished_task;
681}
682
683unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
684  unsigned num_completed_raster_tasks =
685      raster_tasks_with_pending_upload_.size() + completed_raster_tasks_.size();
686  DCHECK_GE(raster_task_states_.size(), num_completed_raster_tasks);
687  return raster_task_states_.size() - num_completed_raster_tasks;
688}
689
690bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
691  return PendingRasterTaskCount() || !raster_tasks_with_pending_upload_.empty();
692}
693
694bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
695  return !!raster_tasks_required_for_activation_count_;
696}
697
698const char* PixelBufferRasterWorkerPool::StateName() const {
699  if (scheduled_raster_task_count_)
700    return "rasterizing";
701  if (PendingRasterTaskCount())
702    return "throttled";
703  if (!raster_tasks_with_pending_upload_.empty())
704    return "waiting_for_uploads";
705
706  return "finishing";
707}
708
709void PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks() {
710  TRACE_EVENT0("cc",
711               "PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks");
712
713  task_graph_runner_->CollectCompletedTasks(namespace_token_,
714                                            &completed_tasks_);
715  for (internal::Task::Vector::const_iterator it = completed_tasks_.begin();
716       it != completed_tasks_.end();
717       ++it) {
718    internal::WorkerPoolTask* task =
719        static_cast<internal::WorkerPoolTask*>(it->get());
720
721    RasterTaskState::Vector::iterator state_it =
722        std::find_if(raster_task_states_.begin(),
723                     raster_task_states_.end(),
724                     RasterTaskState::TaskComparator(task));
725    if (state_it == raster_task_states_.end()) {
726      task->WillComplete();
727      task->CompleteOnOriginThread(this);
728      task->DidComplete();
729
730      completed_image_decode_tasks_.push_back(task);
731      continue;
732    }
733
734    RasterTaskState& state = *state_it;
735    DCHECK_EQ(RasterTaskState::SCHEDULED, state.type);
736    DCHECK(state.resource);
737
738    // Balanced with MapPixelRasterBuffer() call in AcquireCanvasForRaster().
739    bool content_has_changed =
740        resource_provider_->UnmapPixelRasterBuffer(state.resource->id());
741
742    // |content_has_changed| can be false as result of task being canceled or
743    // task implementation deciding not to modify bitmap (ie. analysis of raster
744    // commands detected content as a solid color).
745    if (!content_has_changed) {
746      task->WillComplete();
747      task->CompleteOnOriginThread(this);
748      task->DidComplete();
749
750      if (!task->HasFinishedRunning()) {
751        // When priorites change, a raster task can be canceled as a result of
752        // no longer being of high enough priority to fit in our throttled
753        // raster task budget. The task has not yet completed in this case.
754        RasterTaskQueue::Item::Vector::const_iterator item_it =
755            std::find_if(raster_tasks_.items.begin(),
756                         raster_tasks_.items.end(),
757                         RasterTaskQueue::Item::TaskComparator(task));
758        if (item_it != raster_tasks_.items.end()) {
759          state.type = RasterTaskState::UNSCHEDULED;
760          state.resource = NULL;
761          continue;
762        }
763      }
764
765      DCHECK(std::find(completed_raster_tasks_.begin(),
766                       completed_raster_tasks_.end(),
767                       task) == completed_raster_tasks_.end());
768      completed_raster_tasks_.push_back(task);
769      state.type = RasterTaskState::COMPLETED;
770      DCHECK_LE(static_cast<size_t>(state.required_for_activation),
771                raster_tasks_required_for_activation_count_);
772      raster_tasks_required_for_activation_count_ -=
773          state.required_for_activation;
774      continue;
775    }
776
777    DCHECK(task->HasFinishedRunning());
778
779    resource_provider_->BeginSetPixels(state.resource->id());
780    has_performed_uploads_since_last_flush_ = true;
781
782    bytes_pending_upload_ += state.resource->bytes();
783    raster_tasks_with_pending_upload_.push_back(task);
784    state.type = RasterTaskState::UPLOADING;
785  }
786  completed_tasks_.clear();
787}
788
789scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const {
790  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
791
792  state->SetInteger("completed_count", completed_raster_tasks_.size());
793  state->SetInteger("pending_count", raster_task_states_.size());
794  state->SetInteger("pending_upload_count",
795                    raster_tasks_with_pending_upload_.size());
796  state->SetInteger("pending_required_for_activation_count",
797                    raster_tasks_required_for_activation_count_);
798  state->Set("throttle_state", ThrottleStateAsValue().release());
799  return state.PassAs<base::Value>();
800}
801
802scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
803    const {
804  scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue);
805
806  throttle_state->SetInteger("bytes_available_for_upload",
807                             max_bytes_pending_upload_ - bytes_pending_upload_);
808  throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
809  throttle_state->SetInteger("scheduled_raster_task_count",
810                             scheduled_raster_task_count_);
811  return throttle_state.PassAs<base::Value>();
812}
813
814}  // namespace cc
815