pixel_buffer_raster_worker_pool.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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 "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"
13
14#if defined(OS_ANDROID)
15#include "base/android/sys_utils.h"
16#endif
17
18namespace cc {
19
20namespace {
21
22class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask {
23 public:
24  typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply;
25
26  PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task,
27                                uint8_t* buffer,
28                                const Reply& reply)
29      : task_(task),
30        buffer_(buffer),
31        reply_(reply),
32        needs_upload_(false) {
33  }
34
35  // Overridden from internal::WorkerPoolTask:
36  virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
37    // |buffer_| can be NULL in lost context situations.
38    if (!buffer_) {
39      // |needs_upload_| still needs to be true as task has not
40      // been canceled.
41      needs_upload_ = true;
42      return;
43    }
44    SkBitmap bitmap;
45    bitmap.setConfig(SkBitmap::kARGB_8888_Config,
46                     task_->resource()->size().width(),
47                     task_->resource()->size().height());
48    bitmap.setPixels(buffer_);
49    SkBitmapDevice device(bitmap);
50    needs_upload_ = task_->RunOnWorkerThread(&device, thread_index);
51  }
52  virtual void CompleteOnOriginThread() OVERRIDE {
53    // |needs_upload_| must be be false if task didn't run.
54    DCHECK(HasFinishedRunning() || !needs_upload_);
55    reply_.Run(!HasFinishedRunning(), needs_upload_);
56  }
57
58 private:
59  virtual ~PixelBufferWorkerPoolTaskImpl() {}
60
61  scoped_refptr<internal::RasterWorkerPoolTask> task_;
62  uint8_t* buffer_;
63  const Reply reply_;
64  bool needs_upload_;
65
66  DISALLOW_COPY_AND_ASSIGN(PixelBufferWorkerPoolTaskImpl);
67};
68
69const int kCheckForCompletedRasterTasksDelayMs = 6;
70
71const size_t kMaxScheduledRasterTasks = 48;
72
73typedef base::StackVector<internal::GraphNode*,
74                          kMaxScheduledRasterTasks> NodeVector;
75
76void AddDependenciesToGraphNode(
77    internal::GraphNode* node,
78    const NodeVector::ContainerType& dependencies) {
79  for (NodeVector::ContainerType::const_iterator it = dependencies.begin();
80       it != dependencies.end(); ++it) {
81    internal::GraphNode* dependency = *it;
82
83    node->add_dependency();
84    dependency->add_dependent(node);
85  }
86}
87
88// Only used as std::find_if predicate for DCHECKs.
89bool WasCanceled(const internal::RasterWorkerPoolTask* task) {
90  return task->WasCanceled();
91}
92
93}  // namespace
94
95PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
96    ResourceProvider* resource_provider,
97    size_t num_threads,
98    size_t max_transfer_buffer_usage_bytes)
99    : RasterWorkerPool(resource_provider, num_threads),
100      shutdown_(false),
101      scheduled_raster_task_count_(0),
102      bytes_pending_upload_(0),
103      max_bytes_pending_upload_(max_transfer_buffer_usage_bytes),
104      has_performed_uploads_since_last_flush_(false),
105      check_for_completed_raster_tasks_pending_(false),
106      should_notify_client_if_no_tasks_are_pending_(false),
107      should_notify_client_if_no_tasks_required_for_activation_are_pending_(
108          false) {
109}
110
111PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
112  DCHECK(shutdown_);
113  DCHECK(!check_for_completed_raster_tasks_pending_);
114  DCHECK_EQ(0u, pixel_buffer_tasks_.size());
115  DCHECK_EQ(0u, tasks_with_pending_upload_.size());
116  DCHECK_EQ(0u, completed_tasks_.size());
117}
118
119void PixelBufferRasterWorkerPool::Shutdown() {
120  shutdown_ = true;
121  RasterWorkerPool::Shutdown();
122  RasterWorkerPool::CheckForCompletedTasks();
123  CheckForCompletedUploads();
124  check_for_completed_raster_tasks_callback_.Cancel();
125  check_for_completed_raster_tasks_pending_ = false;
126  for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
127       it != pixel_buffer_tasks_.end(); ++it) {
128    internal::RasterWorkerPoolTask* task = it->first;
129    internal::WorkerPoolTask* pixel_buffer_task = it->second.get();
130
131    // All inactive tasks needs to be canceled.
132    if (!pixel_buffer_task && !task->HasFinishedRunning()) {
133      task->DidRun(true);
134      completed_tasks_.push_back(task);
135    }
136  }
137  DCHECK_EQ(completed_tasks_.size(), pixel_buffer_tasks_.size());
138}
139
140void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
141  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
142
143  RasterWorkerPool::SetRasterTasks(queue);
144
145  if (!should_notify_client_if_no_tasks_are_pending_)
146    TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
147
148  should_notify_client_if_no_tasks_are_pending_ = true;
149  should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true;
150
151  // Build new pixel buffer task set.
152  TaskMap new_pixel_buffer_tasks;
153  for (RasterTaskVector::const_iterator it = raster_tasks().begin();
154       it != raster_tasks().end(); ++it) {
155    internal::RasterWorkerPoolTask* task = it->get();
156    DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end());
157    DCHECK(!task->HasCompleted());
158
159    // Use existing pixel buffer task if available.
160    TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task);
161    if (pixel_buffer_it == pixel_buffer_tasks_.end()) {
162      new_pixel_buffer_tasks[task] = NULL;
163      continue;
164    }
165
166    new_pixel_buffer_tasks[task] = pixel_buffer_it->second;
167    pixel_buffer_tasks_.erase(task);
168  }
169
170  // Transfer remaining pixel buffer tasks to |new_pixel_buffer_tasks|
171  // and cancel all remaining inactive tasks.
172  for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
173       it != pixel_buffer_tasks_.end(); ++it) {
174    internal::RasterWorkerPoolTask* task = it->first;
175    internal::WorkerPoolTask* pixel_buffer_task = it->second.get();
176
177    // Move task to |new_pixel_buffer_tasks|
178    new_pixel_buffer_tasks[task] = pixel_buffer_task;
179
180    // Inactive task can be canceled.
181    if (!pixel_buffer_task && !task->HasFinishedRunning()) {
182      task->DidRun(true);
183      DCHECK(std::find(completed_tasks_.begin(),
184                       completed_tasks_.end(),
185                       task) == completed_tasks_.end());
186      completed_tasks_.push_back(task);
187    }
188  }
189
190  tasks_required_for_activation_.clear();
191  for (TaskMap::iterator it = new_pixel_buffer_tasks.begin();
192       it != new_pixel_buffer_tasks.end(); ++it) {
193    internal::RasterWorkerPoolTask* task = it->first;
194    if (IsRasterTaskRequiredForActivation(task))
195      tasks_required_for_activation_.insert(task);
196  }
197
198  // |tasks_required_for_activation_| contains all tasks that need to
199  // complete before we can send a "ready to activate" signal. Tasks
200  // that have already completed should not be part of this set.
201  for (TaskDeque::const_iterator it = completed_tasks_.begin();
202       it != completed_tasks_.end(); ++it) {
203    tasks_required_for_activation_.erase(*it);
204  }
205
206  pixel_buffer_tasks_.swap(new_pixel_buffer_tasks);
207
208  // Check for completed tasks when ScheduleTasks() is called as
209  // priorities might have changed and this maximizes the number
210  // of top priority tasks that are scheduled.
211  RasterWorkerPool::CheckForCompletedTasks();
212  CheckForCompletedUploads();
213  FlushUploads();
214
215  // Schedule new tasks.
216  ScheduleMoreTasks();
217
218  // Cancel any pending check for completed raster tasks and schedule
219  // another check.
220  check_for_completed_raster_tasks_callback_.Cancel();
221  check_for_completed_raster_tasks_pending_ = false;
222  ScheduleCheckForCompletedRasterTasks();
223
224  TRACE_EVENT_ASYNC_STEP1(
225      "cc", "ScheduledTasks", this, StateName(),
226      "state", TracedValue::FromValue(StateAsValue().release()));
227}
228
229GLenum PixelBufferRasterWorkerPool::GetResourceFormat() const {
230  return resource_provider()->best_texture_format();
231}
232
233void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
234  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
235
236  RasterWorkerPool::CheckForCompletedTasks();
237  CheckForCompletedUploads();
238  FlushUploads();
239
240  TaskDeque completed_tasks;
241  completed_tasks_.swap(completed_tasks);
242
243  while (!completed_tasks.empty()) {
244    internal::RasterWorkerPoolTask* task = completed_tasks.front().get();
245    DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
246
247    pixel_buffer_tasks_.erase(task);
248
249    task->WillComplete();
250    task->CompleteOnOriginThread();
251    task->DidComplete();
252
253    completed_tasks.pop_front();
254  }
255}
256
257void PixelBufferRasterWorkerPool::OnRasterTasksFinished() {
258  // |should_notify_client_if_no_tasks_are_pending_| can be set to false as
259  // a result of a scheduled CheckForCompletedRasterTasks() call. No need to
260  // perform another check in that case as we've already notified the client.
261  if (!should_notify_client_if_no_tasks_are_pending_)
262    return;
263
264  // Call CheckForCompletedRasterTasks() when we've finished running all
265  // raster tasks needed since last time ScheduleTasks() was called.
266  // This reduces latency between the time when all tasks have finished
267  // running and the time when the client is notified.
268  CheckForCompletedRasterTasks();
269}
270
271void PixelBufferRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() {
272  // Analogous to OnRasterTasksFinished(), there's no need to call
273  // CheckForCompletedRasterTasks() if the client has already been notified.
274  if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_)
275    return;
276
277  // This reduces latency between the time when all tasks required for
278  // activation have finished running and the time when the client is
279  // notified.
280  CheckForCompletedRasterTasks();
281}
282
283void PixelBufferRasterWorkerPool::FlushUploads() {
284  if (!has_performed_uploads_since_last_flush_)
285    return;
286
287  resource_provider()->ShallowFlushIfSupported();
288  has_performed_uploads_since_last_flush_ = false;
289}
290
291void PixelBufferRasterWorkerPool::CheckForCompletedUploads() {
292  TaskDeque tasks_with_completed_uploads;
293
294  // First check if any have completed.
295  while (!tasks_with_pending_upload_.empty()) {
296    internal::RasterWorkerPoolTask* task =
297        tasks_with_pending_upload_.front().get();
298
299    // Uploads complete in the order they are issued.
300    if (!resource_provider()->DidSetPixelsComplete(task->resource()->id()))
301      break;
302
303    tasks_with_completed_uploads.push_back(task);
304    tasks_with_pending_upload_.pop_front();
305  }
306
307  DCHECK(client());
308  bool should_force_some_uploads_to_complete =
309      shutdown_ || client()->ShouldForceTasksRequiredForActivationToComplete();
310
311  if (should_force_some_uploads_to_complete) {
312    TaskDeque tasks_with_uploads_to_force;
313    TaskDeque::iterator it = tasks_with_pending_upload_.begin();
314    while (it != tasks_with_pending_upload_.end()) {
315      internal::RasterWorkerPoolTask* task = it->get();
316      DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
317
318      // Force all uploads required for activation to complete.
319      // During shutdown, force all pending uploads to complete.
320      if (shutdown_ || IsRasterTaskRequiredForActivation(task)) {
321        tasks_with_uploads_to_force.push_back(task);
322        tasks_with_completed_uploads.push_back(task);
323        it = tasks_with_pending_upload_.erase(it);
324        continue;
325      }
326
327      ++it;
328    }
329
330    // Force uploads in reverse order. Since forcing can cause a wait on
331    // all previous uploads, we would rather wait only once downstream.
332    for (TaskDeque::reverse_iterator it = tasks_with_uploads_to_force.rbegin();
333         it != tasks_with_uploads_to_force.rend();
334         ++it) {
335      resource_provider()->ForceSetPixelsToComplete((*it)->resource()->id());
336      has_performed_uploads_since_last_flush_ = true;
337    }
338  }
339
340  // Release shared memory and move tasks with completed uploads
341  // to |completed_tasks_|.
342  while (!tasks_with_completed_uploads.empty()) {
343    internal::RasterWorkerPoolTask* task =
344        tasks_with_completed_uploads.front().get();
345
346    // It's now safe to release the pixel buffer and the shared memory.
347    resource_provider()->ReleasePixelBuffer(task->resource()->id());
348
349    bytes_pending_upload_ -= task->resource()->bytes();
350
351    task->DidRun(false);
352
353    DCHECK(std::find(completed_tasks_.begin(),
354                     completed_tasks_.end(),
355                     task) == completed_tasks_.end());
356    completed_tasks_.push_back(task);
357
358    tasks_required_for_activation_.erase(task);
359
360    tasks_with_completed_uploads.pop_front();
361  }
362}
363
364void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() {
365  if (check_for_completed_raster_tasks_pending_)
366    return;
367
368  check_for_completed_raster_tasks_callback_.Reset(
369      base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks,
370                 base::Unretained(this)));
371  base::MessageLoopProxy::current()->PostDelayedTask(
372      FROM_HERE,
373      check_for_completed_raster_tasks_callback_.callback(),
374      base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs));
375  check_for_completed_raster_tasks_pending_ = true;
376}
377
378void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
379  TRACE_EVENT0(
380      "cc", "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");
381
382  DCHECK(should_notify_client_if_no_tasks_are_pending_);
383
384  check_for_completed_raster_tasks_callback_.Cancel();
385  check_for_completed_raster_tasks_pending_ = false;
386
387  RasterWorkerPool::CheckForCompletedTasks();
388  CheckForCompletedUploads();
389  FlushUploads();
390
391  // Determine what client notifications to generate.
392  bool will_notify_client_that_no_tasks_required_for_activation_are_pending =
393      (should_notify_client_if_no_tasks_required_for_activation_are_pending_ &&
394       !HasPendingTasksRequiredForActivation());
395  bool will_notify_client_that_no_tasks_are_pending =
396      (should_notify_client_if_no_tasks_are_pending_ &&
397       !HasPendingTasks());
398
399  // Adjust the need to generate notifications before scheduling more tasks.
400  should_notify_client_if_no_tasks_required_for_activation_are_pending_ &=
401      !will_notify_client_that_no_tasks_required_for_activation_are_pending;
402  should_notify_client_if_no_tasks_are_pending_ &=
403      !will_notify_client_that_no_tasks_are_pending;
404
405  scheduled_raster_task_count_ = 0;
406  if (PendingRasterTaskCount())
407    ScheduleMoreTasks();
408
409  TRACE_EVENT_ASYNC_STEP1(
410      "cc", "ScheduledTasks", this, StateName(),
411      "state", TracedValue::FromValue(StateAsValue().release()));
412
413  // Schedule another check for completed raster tasks while there are
414  // pending raster tasks or pending uploads.
415  if (HasPendingTasks())
416    ScheduleCheckForCompletedRasterTasks();
417
418  // Generate client notifications.
419  if (will_notify_client_that_no_tasks_required_for_activation_are_pending) {
420    DCHECK(std::find_if(raster_tasks_required_for_activation().begin(),
421                        raster_tasks_required_for_activation().end(),
422                        WasCanceled) ==
423          raster_tasks_required_for_activation().end());
424    client()->DidFinishRunningTasksRequiredForActivation();
425  }
426  if (will_notify_client_that_no_tasks_are_pending) {
427    TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
428    DCHECK(!HasPendingTasksRequiredForActivation());
429    client()->DidFinishRunningTasks();
430  }
431}
432
433void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
434  TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
435
436  enum RasterTaskType {
437    PREPAINT_TYPE = 0,
438    REQUIRED_FOR_ACTIVATION_TYPE = 1,
439    NUM_TYPES = 2
440  };
441  NodeVector tasks[NUM_TYPES];
442  unsigned priority = 2u;  // 0-1 reserved for RasterFinished tasks.
443  TaskGraph graph;
444
445  size_t bytes_pending_upload = bytes_pending_upload_;
446
447  for (RasterTaskVector::const_iterator it = raster_tasks().begin();
448       it != raster_tasks().end(); ++it) {
449    internal::RasterWorkerPoolTask* task = it->get();
450
451    // |pixel_buffer_tasks_| contains all tasks that have not yet completed.
452    TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task);
453    if (pixel_buffer_it == pixel_buffer_tasks_.end())
454      continue;
455
456    // HasFinishedRunning() will return true when set pixels has completed.
457    if (task->HasFinishedRunning()) {
458      DCHECK(std::find(completed_tasks_.begin(),
459                       completed_tasks_.end(),
460                       task) != completed_tasks_.end());
461      continue;
462    }
463
464    // All raster tasks need to be throttled by bytes of pending uploads.
465    size_t new_bytes_pending_upload = bytes_pending_upload;
466    new_bytes_pending_upload += task->resource()->bytes();
467    if (new_bytes_pending_upload > max_bytes_pending_upload_)
468      break;
469
470    internal::WorkerPoolTask* pixel_buffer_task = pixel_buffer_it->second.get();
471
472    // If raster has finished, just update |bytes_pending_upload|.
473    if (pixel_buffer_task && pixel_buffer_task->HasCompleted()) {
474      bytes_pending_upload = new_bytes_pending_upload;
475      continue;
476    }
477
478    // Throttle raster tasks based on kMaxScheduledRasterTasks.
479    size_t scheduled_raster_task_count =
480        tasks[PREPAINT_TYPE].container().size() +
481        tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
482    if (scheduled_raster_task_count >= kMaxScheduledRasterTasks)
483      break;
484
485    // Update |bytes_pending_upload| now that task has cleared all
486    // throttling limits.
487    bytes_pending_upload = new_bytes_pending_upload;
488
489    RasterTaskType type = IsRasterTaskRequiredForActivation(task) ?
490        REQUIRED_FOR_ACTIVATION_TYPE :
491        PREPAINT_TYPE;
492
493    // Use existing pixel buffer task if available.
494    if (pixel_buffer_task) {
495      tasks[type].container().push_back(
496          CreateGraphNodeForRasterTask(pixel_buffer_task,
497                                       task->dependencies(),
498                                       priority++,
499                                       &graph));
500      continue;
501    }
502
503    // Request a pixel buffer. This will reserve shared memory.
504    resource_provider()->AcquirePixelBuffer(task->resource()->id());
505
506    // MapPixelBuffer() returns NULL if context was lost at the time
507    // AcquirePixelBuffer() was called. For simplicity we still post
508    // a raster task that is essentially a noop in these situations.
509    uint8* buffer = resource_provider()->MapPixelBuffer(
510        task->resource()->id());
511
512    scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task(
513        new PixelBufferWorkerPoolTaskImpl(
514            task,
515            buffer,
516            base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted,
517                       base::Unretained(this),
518                       make_scoped_refptr(task))));
519    pixel_buffer_tasks_[task] = new_pixel_buffer_task;
520    tasks[type].container().push_back(
521        CreateGraphNodeForRasterTask(new_pixel_buffer_task.get(),
522                                     task->dependencies(),
523                                     priority++,
524                                     &graph));
525  }
526
527  scoped_refptr<internal::WorkerPoolTask>
528      new_raster_required_for_activation_finished_task;
529
530  size_t scheduled_raster_task_required_for_activation_count =
531        tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
532  DCHECK_LE(scheduled_raster_task_required_for_activation_count,
533            tasks_required_for_activation_.size());
534  // Schedule OnRasterTasksRequiredForActivationFinished call only when
535  // notification is pending and throttling is not preventing all pending
536  // tasks required for activation from being scheduled.
537  if (scheduled_raster_task_required_for_activation_count ==
538      tasks_required_for_activation_.size() &&
539      should_notify_client_if_no_tasks_required_for_activation_are_pending_) {
540    new_raster_required_for_activation_finished_task =
541        CreateRasterRequiredForActivationFinishedTask();
542    internal::GraphNode* raster_required_for_activation_finished_node =
543        CreateGraphNodeForTask(
544            new_raster_required_for_activation_finished_task.get(),
545            0u,  // Priority 0
546            &graph);
547    AddDependenciesToGraphNode(
548        raster_required_for_activation_finished_node,
549        tasks[REQUIRED_FOR_ACTIVATION_TYPE].container());
550  }
551
552  scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task;
553
554  size_t scheduled_raster_task_count =
555      tasks[PREPAINT_TYPE].container().size() +
556      tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
557  DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());
558  // Schedule OnRasterTasksFinished call only when notification is pending
559  // and throttling is not preventing all pending tasks from being scheduled.
560  if (scheduled_raster_task_count == PendingRasterTaskCount() &&
561      should_notify_client_if_no_tasks_are_pending_) {
562    new_raster_finished_task = CreateRasterFinishedTask();
563    internal::GraphNode* raster_finished_node =
564        CreateGraphNodeForTask(new_raster_finished_task.get(),
565                               1u,  // Priority 1
566                               &graph);
567    for (unsigned type = 0; type < NUM_TYPES; ++type) {
568      AddDependenciesToGraphNode(
569          raster_finished_node,
570          tasks[type].container());
571    }
572  }
573
574  SetTaskGraph(&graph);
575
576  scheduled_raster_task_count_ = scheduled_raster_task_count;
577
578  set_raster_finished_task(new_raster_finished_task);
579  set_raster_required_for_activation_finished_task(
580      new_raster_required_for_activation_finished_task);
581}
582
583void PixelBufferRasterWorkerPool::OnRasterTaskCompleted(
584    scoped_refptr<internal::RasterWorkerPoolTask> task,
585    bool was_canceled,
586    bool needs_upload) {
587  TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc"),
588               "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
589               "was_canceled", was_canceled,
590               "needs_upload", needs_upload);
591
592  DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end());
593
594  // Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
595  resource_provider()->UnmapPixelBuffer(task->resource()->id());
596
597  if (!needs_upload) {
598    resource_provider()->ReleasePixelBuffer(task->resource()->id());
599
600    if (was_canceled) {
601      // When priorites change, a raster task can be canceled as a result of
602      // no longer being of high enough priority to fit in our throttled
603      // raster task budget. The task has not yet completed in this case.
604      RasterTaskVector::const_iterator it = std::find(raster_tasks().begin(),
605                                                      raster_tasks().end(),
606                                                      task);
607      if (it != raster_tasks().end()) {
608        pixel_buffer_tasks_[task.get()] = NULL;
609        return;
610      }
611    }
612
613    task->DidRun(was_canceled);
614    DCHECK(std::find(completed_tasks_.begin(),
615                     completed_tasks_.end(),
616                     task) == completed_tasks_.end());
617    completed_tasks_.push_back(task);
618    tasks_required_for_activation_.erase(task);
619    return;
620  }
621
622  DCHECK(!was_canceled);
623
624  resource_provider()->BeginSetPixels(task->resource()->id());
625  has_performed_uploads_since_last_flush_ = true;
626
627  bytes_pending_upload_ += task->resource()->bytes();
628  tasks_with_pending_upload_.push_back(task);
629}
630
631unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
632  unsigned num_completed_raster_tasks =
633      tasks_with_pending_upload_.size() + completed_tasks_.size();
634  DCHECK_GE(pixel_buffer_tasks_.size(), num_completed_raster_tasks);
635  return pixel_buffer_tasks_.size() - num_completed_raster_tasks;
636}
637
638bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
639  return PendingRasterTaskCount() || !tasks_with_pending_upload_.empty();
640}
641
642bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
643  return !tasks_required_for_activation_.empty();
644}
645
646const char* PixelBufferRasterWorkerPool::StateName() const {
647  if (scheduled_raster_task_count_)
648    return "rasterizing";
649  if (PendingRasterTaskCount())
650    return "throttled";
651  if (!tasks_with_pending_upload_.empty())
652    return "waiting_for_uploads";
653
654  return "finishing";
655}
656
657scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const {
658  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
659
660  state->SetInteger("completed_count", completed_tasks_.size());
661  state->SetInteger("pending_count", pixel_buffer_tasks_.size());
662  state->SetInteger("pending_upload_count", tasks_with_pending_upload_.size());
663  state->SetInteger("required_for_activation_count",
664                    tasks_required_for_activation_.size());
665  state->Set("scheduled_state", ScheduledStateAsValue().release());
666  state->Set("throttle_state", ThrottleStateAsValue().release());
667  return state.PassAs<base::Value>();
668}
669
670scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
671    const {
672  scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue);
673
674  throttle_state->SetInteger("bytes_available_for_upload",
675                             max_bytes_pending_upload_ - bytes_pending_upload_);
676  throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
677  throttle_state->SetInteger("scheduled_raster_task_count",
678                             scheduled_raster_task_count_);
679  return throttle_state.PassAs<base::Value>();
680}
681
682}  // namespace cc
683