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