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