Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / cc / resources / raster_worker_pool.cc
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/raster_worker_pool.h"
6
7 #include <algorithm>
8
9 #include "base/debug/trace_event_synthetic_delay.h"
10 #include "base/json/json_writer.h"
11 #include "base/lazy_instance.h"
12 #include "base/metrics/histogram.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/values.h"
15 #include "cc/debug/devtools_instrumentation.h"
16 #include "cc/debug/traced_value.h"
17 #include "cc/resources/picture_pile_impl.h"
18 #include "cc/resources/resource.h"
19 #include "cc/resources/resource_provider.h"
20 #include "gpu/command_buffer/client/gles2_interface.h"
21 #include "skia/ext/paint_simplifier.h"
22 #include "third_party/skia/include/core/SkBitmap.h"
23 #include "third_party/skia/include/core/SkPixelRef.h"
24 #include "third_party/skia/include/gpu/GrContext.h"
25
26 namespace cc {
27 namespace {
28
29 // Subclass of Allocator that takes a suitably allocated pointer and uses
30 // it as the pixel memory for the bitmap.
31 class IdentityAllocator : public SkBitmap::Allocator {
32  public:
33   explicit IdentityAllocator(void* buffer) : buffer_(buffer) {}
34   virtual bool allocPixelRef(SkBitmap* dst, SkColorTable*) OVERRIDE {
35     dst->setPixels(buffer_);
36     return true;
37   }
38
39  private:
40   void* buffer_;
41 };
42
43 // Flag to indicate whether we should try and detect that
44 // a tile is of solid color.
45 const bool kUseColorEstimator = true;
46
47 // Synthetic delay for raster tasks that are required for activation. Global to
48 // avoid static initializer on critical path.
49 struct RasterRequiredForActivationSyntheticDelayInitializer {
50   RasterRequiredForActivationSyntheticDelayInitializer()
51       : delay(base::debug::TraceEventSyntheticDelay::Lookup(
52             "cc.RasterRequiredForActivation")) {}
53   base::debug::TraceEventSyntheticDelay* delay;
54 };
55 static base::LazyInstance<RasterRequiredForActivationSyntheticDelayInitializer>
56     g_raster_required_for_activation_delay = LAZY_INSTANCE_INITIALIZER;
57
58 class DisableLCDTextFilter : public SkDrawFilter {
59  public:
60   // SkDrawFilter interface.
61   virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE {
62     if (type != SkDrawFilter::kText_Type)
63       return true;
64
65     paint->setLCDRenderText(false);
66     return true;
67   }
68 };
69
70 class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
71  public:
72   RasterWorkerPoolTaskImpl(const Resource* resource,
73                            PicturePileImpl* picture_pile,
74                            const gfx::Rect& content_rect,
75                            float contents_scale,
76                            RasterMode raster_mode,
77                            TileResolution tile_resolution,
78                            int layer_id,
79                            const void* tile_id,
80                            int source_frame_number,
81                            RenderingStatsInstrumentation* rendering_stats,
82                            const RasterWorkerPool::RasterTask::Reply& reply,
83                            internal::WorkerPoolTask::Vector* dependencies,
84                            ContextProvider* context_provider)
85       : internal::RasterWorkerPoolTask(resource, dependencies),
86         picture_pile_(picture_pile),
87         content_rect_(content_rect),
88         contents_scale_(contents_scale),
89         raster_mode_(raster_mode),
90         tile_resolution_(tile_resolution),
91         layer_id_(layer_id),
92         tile_id_(tile_id),
93         source_frame_number_(source_frame_number),
94         rendering_stats_(rendering_stats),
95         reply_(reply),
96         context_provider_(context_provider),
97         canvas_(NULL) {}
98
99   // Overridden from internal::Task:
100   virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
101     TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::RunOnWorkerThread");
102
103     DCHECK(picture_pile_);
104     Analyze(picture_pile_->GetCloneForDrawingOnThread(thread_index));
105     if (!canvas_ || analysis_.is_solid_color)
106       return;
107     Raster(picture_pile_->GetCloneForDrawingOnThread(thread_index));
108   }
109
110   // Overridden from internal::WorkerPoolTask:
111   virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
112       OVERRIDE {
113     DCHECK(!canvas_);
114     canvas_ = client->AcquireCanvasForRaster(this);
115   }
116   virtual void RunOnOriginThread() OVERRIDE {
117     TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::RunOnOriginThread");
118
119     Analyze(picture_pile_);
120     if (!canvas_ || analysis_.is_solid_color)
121       return;
122     // TODO(alokp): Use a trace macro to push/pop markers.
123     // Using push/pop functions directly incurs cost to evaluate function
124     // arguments even when tracing is disabled.
125     DCHECK(context_provider_);
126     context_provider_->ContextGL()->PushGroupMarkerEXT(
127         0,
128         base::StringPrintf(
129             "Raster-%d-%d-%p", source_frame_number_, layer_id_, tile_id_)
130             .c_str());
131     Raster(picture_pile_);
132     context_provider_->ContextGL()->PopGroupMarkerEXT();
133   }
134   virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
135       OVERRIDE {
136     canvas_ = NULL;
137     client->OnRasterCompleted(this, analysis_);
138   }
139   virtual void RunReplyOnOriginThread() OVERRIDE {
140     DCHECK(!canvas_);
141     reply_.Run(analysis_, !HasFinishedRunning());
142   }
143
144  protected:
145   virtual ~RasterWorkerPoolTaskImpl() { DCHECK(!canvas_); }
146
147  private:
148   scoped_ptr<base::Value> DataAsValue() const {
149     scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
150     res->Set("tile_id", TracedValue::CreateIDRef(tile_id_).release());
151     res->Set("resolution", TileResolutionAsValue(tile_resolution_).release());
152     res->SetInteger("source_frame_number", source_frame_number_);
153     res->SetInteger("layer_id", layer_id_);
154     return res.PassAs<base::Value>();
155   }
156
157   void Analyze(PicturePileImpl* picture_pile) {
158     TRACE_EVENT1("cc",
159                  "RasterWorkerPoolTaskImpl::Analyze",
160                  "data",
161                  TracedValue::FromValue(DataAsValue().release()));
162
163     DCHECK(picture_pile);
164
165     picture_pile->AnalyzeInRect(
166         content_rect_, contents_scale_, &analysis_, rendering_stats_);
167
168     // Record the solid color prediction.
169     UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
170                           analysis_.is_solid_color);
171
172     // Clear the flag if we're not using the estimator.
173     analysis_.is_solid_color &= kUseColorEstimator;
174   }
175
176   void Raster(PicturePileImpl* picture_pile) {
177     TRACE_EVENT2(
178         "cc",
179         "RasterWorkerPoolTaskImpl::Raster",
180         "data",
181         TracedValue::FromValue(DataAsValue().release()),
182         "raster_mode",
183         TracedValue::FromValue(RasterModeAsValue(raster_mode_).release()));
184
185     devtools_instrumentation::ScopedLayerTask raster_task(
186         devtools_instrumentation::kRasterTask, layer_id_);
187
188     skia::RefPtr<SkDrawFilter> draw_filter;
189     switch (raster_mode_) {
190       case LOW_QUALITY_RASTER_MODE:
191         draw_filter = skia::AdoptRef(new skia::PaintSimplifier);
192         break;
193       case HIGH_QUALITY_NO_LCD_RASTER_MODE:
194         draw_filter = skia::AdoptRef(new DisableLCDTextFilter);
195         break;
196       case HIGH_QUALITY_RASTER_MODE:
197         break;
198       case NUM_RASTER_MODES:
199       default:
200         NOTREACHED();
201     }
202     canvas_->setDrawFilter(draw_filter.get());
203
204     base::TimeDelta prev_rasterize_time =
205         rendering_stats_->impl_thread_rendering_stats().rasterize_time;
206
207     // Only record rasterization time for highres tiles, because
208     // lowres tiles are not required for activation and therefore
209     // introduce noise in the measurement (sometimes they get rasterized
210     // before we draw and sometimes they aren't)
211     RenderingStatsInstrumentation* stats =
212         tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL;
213     DCHECK(picture_pile);
214     picture_pile->RasterToBitmap(
215         canvas_, content_rect_, contents_scale_, stats);
216
217     if (rendering_stats_->record_rendering_stats()) {
218       base::TimeDelta current_rasterize_time =
219           rendering_stats_->impl_thread_rendering_stats().rasterize_time;
220       HISTOGRAM_CUSTOM_COUNTS(
221           "Renderer4.PictureRasterTimeUS",
222           (current_rasterize_time - prev_rasterize_time).InMicroseconds(),
223           0,
224           100000,
225           100);
226     }
227   }
228
229   PicturePileImpl::Analysis analysis_;
230   scoped_refptr<PicturePileImpl> picture_pile_;
231   gfx::Rect content_rect_;
232   float contents_scale_;
233   RasterMode raster_mode_;
234   TileResolution tile_resolution_;
235   int layer_id_;
236   const void* tile_id_;
237   int source_frame_number_;
238   RenderingStatsInstrumentation* rendering_stats_;
239   const RasterWorkerPool::RasterTask::Reply reply_;
240   ContextProvider* context_provider_;
241   SkCanvas* canvas_;
242
243   DISALLOW_COPY_AND_ASSIGN(RasterWorkerPoolTaskImpl);
244 };
245
246 class ImageDecodeWorkerPoolTaskImpl : public internal::WorkerPoolTask {
247  public:
248   ImageDecodeWorkerPoolTaskImpl(SkPixelRef* pixel_ref,
249                                 int layer_id,
250                                 RenderingStatsInstrumentation* rendering_stats,
251                                 const RasterWorkerPool::Task::Reply& reply)
252       : pixel_ref_(skia::SharePtr(pixel_ref)),
253         layer_id_(layer_id),
254         rendering_stats_(rendering_stats),
255         reply_(reply) {}
256
257   // Overridden from internal::Task:
258   virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
259     TRACE_EVENT0("cc", "ImageDecodeWorkerPoolTaskImpl::RunOnWorkerThread");
260     Decode();
261   }
262
263   // Overridden from internal::WorkerPoolTask:
264   virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
265       OVERRIDE {}
266   virtual void RunOnOriginThread() OVERRIDE {
267     TRACE_EVENT0("cc", "ImageDecodeWorkerPoolTaskImpl::RunOnOriginThread");
268     Decode();
269   }
270   virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
271       OVERRIDE {
272     client->OnImageDecodeCompleted(this);
273   }
274   virtual void RunReplyOnOriginThread() OVERRIDE {
275     reply_.Run(!HasFinishedRunning());
276   }
277
278  protected:
279   virtual ~ImageDecodeWorkerPoolTaskImpl() {}
280
281  private:
282   void Decode() {
283     devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
284         pixel_ref_.get());
285     // This will cause the image referred to by pixel ref to be decoded.
286     pixel_ref_->lockPixels();
287     pixel_ref_->unlockPixels();
288   }
289
290   skia::RefPtr<SkPixelRef> pixel_ref_;
291   int layer_id_;
292   RenderingStatsInstrumentation* rendering_stats_;
293   const RasterWorkerPool::Task::Reply reply_;
294
295   DISALLOW_COPY_AND_ASSIGN(ImageDecodeWorkerPoolTaskImpl);
296 };
297
298 class RasterFinishedWorkerPoolTaskImpl : public internal::WorkerPoolTask {
299  public:
300   typedef base::Callback<void(const internal::WorkerPoolTask* source)> Callback;
301
302   explicit RasterFinishedWorkerPoolTaskImpl(
303       const Callback& on_raster_finished_callback)
304       : origin_loop_(base::MessageLoopProxy::current().get()),
305         on_raster_finished_callback_(on_raster_finished_callback) {}
306
307   // Overridden from internal::Task:
308   virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
309     TRACE_EVENT0("cc", "RasterFinishedWorkerPoolTaskImpl::RunOnWorkerThread");
310     RasterFinished();
311   }
312
313   // Overridden from internal::WorkerPoolTask:
314   virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
315       OVERRIDE {}
316   virtual void RunOnOriginThread() OVERRIDE {
317     TRACE_EVENT0("cc", "RasterFinishedWorkerPoolTaskImpl::RunOnOriginThread");
318     RasterFinished();
319   }
320   virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
321       OVERRIDE {}
322   virtual void RunReplyOnOriginThread() OVERRIDE {}
323
324  protected:
325   virtual ~RasterFinishedWorkerPoolTaskImpl() {}
326
327   void RasterFinished() {
328     origin_loop_->PostTask(
329         FROM_HERE,
330         base::Bind(
331             &RasterFinishedWorkerPoolTaskImpl::OnRasterFinishedOnOriginThread,
332             this));
333   }
334
335  private:
336   void OnRasterFinishedOnOriginThread() const {
337     on_raster_finished_callback_.Run(this);
338   }
339
340   scoped_refptr<base::MessageLoopProxy> origin_loop_;
341   const Callback on_raster_finished_callback_;
342
343   DISALLOW_COPY_AND_ASSIGN(RasterFinishedWorkerPoolTaskImpl);
344 };
345
346 class RasterRequiredForActivationFinishedWorkerPoolTaskImpl
347     : public RasterFinishedWorkerPoolTaskImpl {
348  public:
349   RasterRequiredForActivationFinishedWorkerPoolTaskImpl(
350       const Callback& on_raster_finished_callback,
351       size_t tasks_required_for_activation_count)
352       : RasterFinishedWorkerPoolTaskImpl(on_raster_finished_callback),
353         tasks_required_for_activation_count_(
354             tasks_required_for_activation_count) {
355     if (tasks_required_for_activation_count_) {
356       g_raster_required_for_activation_delay.Get().delay->BeginParallel(
357           &activation_delay_end_time_);
358     }
359   }
360
361   // Overridden from internal::Task:
362   virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
363     TRACE_EVENT0("cc",
364                  "RasterRequiredForActivationFinishedWorkerPoolTaskImpl::"
365                  "RunOnWorkerThread");
366     RunRasterFinished();
367   }
368
369   // Overridden from internal::WorkerPoolTask:
370   virtual void RunOnOriginThread() OVERRIDE {
371     TRACE_EVENT0("cc",
372                  "RasterRequiredForActivationFinishedWorkerPoolTaskImpl::"
373                  "RunOnOriginThread");
374     RunRasterFinished();
375   }
376
377  private:
378   virtual ~RasterRequiredForActivationFinishedWorkerPoolTaskImpl() {}
379
380   void RunRasterFinished() {
381     if (tasks_required_for_activation_count_) {
382       g_raster_required_for_activation_delay.Get().delay->EndParallel(
383           activation_delay_end_time_);
384     }
385     RasterFinished();
386   }
387
388   base::TimeTicks activation_delay_end_time_;
389   const size_t tasks_required_for_activation_count_;
390
391   DISALLOW_COPY_AND_ASSIGN(
392       RasterRequiredForActivationFinishedWorkerPoolTaskImpl);
393 };
394
395 class RasterTaskGraphRunner : public internal::TaskGraphRunner {
396  public:
397   RasterTaskGraphRunner()
398       : internal::TaskGraphRunner(RasterWorkerPool::GetNumRasterThreads(),
399                                   "CompositorRaster") {}
400 };
401 base::LazyInstance<RasterTaskGraphRunner>::Leaky g_task_graph_runner =
402     LAZY_INSTANCE_INITIALIZER;
403
404 const int kDefaultNumRasterThreads = 1;
405
406 int g_num_raster_threads = 0;
407
408 }  // namespace
409
410 namespace internal {
411
412 WorkerPoolTask::WorkerPoolTask() : did_schedule_(false), did_complete_(false) {}
413
414 WorkerPoolTask::~WorkerPoolTask() {
415   DCHECK(!did_schedule_);
416   DCHECK(!did_run_ || did_complete_);
417 }
418
419 void WorkerPoolTask::WillSchedule() { DCHECK(!did_schedule_); }
420
421 void WorkerPoolTask::DidSchedule() {
422   did_schedule_ = true;
423   did_complete_ = false;
424 }
425
426 bool WorkerPoolTask::HasBeenScheduled() const { return did_schedule_; }
427
428 void WorkerPoolTask::WillComplete() { DCHECK(!did_complete_); }
429
430 void WorkerPoolTask::DidComplete() {
431   DCHECK(did_schedule_);
432   DCHECK(!did_complete_);
433   did_schedule_ = false;
434   did_complete_ = true;
435 }
436
437 bool WorkerPoolTask::HasCompleted() const { return did_complete_; }
438
439 RasterWorkerPoolTask::RasterWorkerPoolTask(
440     const Resource* resource,
441     internal::WorkerPoolTask::Vector* dependencies)
442     : resource_(resource) {
443   dependencies_.swap(*dependencies);
444 }
445
446 RasterWorkerPoolTask::~RasterWorkerPoolTask() {}
447
448 }  // namespace internal
449
450 RasterWorkerPool::Task::Set::Set() {}
451
452 RasterWorkerPool::Task::Set::~Set() {}
453
454 void RasterWorkerPool::Task::Set::Insert(const Task& task) {
455   DCHECK(!task.is_null());
456   tasks_.push_back(task.internal_);
457 }
458
459 RasterWorkerPool::Task::Task() {}
460
461 RasterWorkerPool::Task::Task(internal::WorkerPoolTask* internal)
462     : internal_(internal) {}
463
464 RasterWorkerPool::Task::~Task() {}
465
466 void RasterWorkerPool::Task::Reset() { internal_ = NULL; }
467
468 RasterWorkerPool::RasterTask::Queue::QueuedTask::QueuedTask(
469     internal::RasterWorkerPoolTask* task,
470     bool required_for_activation)
471     : task(task), required_for_activation(required_for_activation) {}
472
473 RasterWorkerPool::RasterTask::Queue::QueuedTask::~QueuedTask() {}
474
475 RasterWorkerPool::RasterTask::Queue::Queue()
476     : required_for_activation_count_(0u) {}
477
478 RasterWorkerPool::RasterTask::Queue::~Queue() {}
479
480 void RasterWorkerPool::RasterTask::Queue::Reset() {
481   tasks_.clear();
482   required_for_activation_count_ = 0u;
483 }
484
485 void RasterWorkerPool::RasterTask::Queue::Append(const RasterTask& task,
486                                                  bool required_for_activation) {
487   DCHECK(!task.is_null());
488   tasks_.push_back(QueuedTask(task.internal_, required_for_activation));
489   required_for_activation_count_ += required_for_activation;
490 }
491
492 void RasterWorkerPool::RasterTask::Queue::Swap(Queue* other) {
493   tasks_.swap(other->tasks_);
494   std::swap(required_for_activation_count_,
495             other->required_for_activation_count_);
496 }
497
498 RasterWorkerPool::RasterTask::RasterTask() {}
499
500 RasterWorkerPool::RasterTask::RasterTask(
501     internal::RasterWorkerPoolTask* internal)
502     : internal_(internal) {}
503
504 void RasterWorkerPool::RasterTask::Reset() { internal_ = NULL; }
505
506 RasterWorkerPool::RasterTask::~RasterTask() {}
507
508 // This allows an external rasterize on-demand system to run raster tasks
509 // with highest priority using the same task graph runner instance.
510 unsigned RasterWorkerPool::kOnDemandRasterTaskPriority = 0u;
511 // Task priorities that make sure raster finished tasks run before any
512 // remaining raster tasks.
513 unsigned RasterWorkerPool::kRasterFinishedTaskPriority = 2u;
514 unsigned RasterWorkerPool::kRasterRequiredForActivationFinishedTaskPriority =
515     1u;
516 unsigned RasterWorkerPool::kRasterTaskPriorityBase = 3u;
517
518 RasterWorkerPool::RasterWorkerPool(internal::TaskGraphRunner* task_graph_runner,
519                                    ResourceProvider* resource_provider)
520     : task_graph_runner_(task_graph_runner),
521       client_(NULL),
522       resource_provider_(resource_provider),
523       weak_ptr_factory_(this) {
524   if (task_graph_runner_)
525     namespace_token_ = task_graph_runner_->GetNamespaceToken();
526 }
527
528 RasterWorkerPool::~RasterWorkerPool() {}
529
530 // static
531 void RasterWorkerPool::SetNumRasterThreads(int num_threads) {
532   DCHECK_LT(0, num_threads);
533   DCHECK_EQ(0, g_num_raster_threads);
534
535   g_num_raster_threads = num_threads;
536 }
537
538 // static
539 int RasterWorkerPool::GetNumRasterThreads() {
540   if (!g_num_raster_threads)
541     g_num_raster_threads = kDefaultNumRasterThreads;
542
543   return g_num_raster_threads;
544 }
545
546 // static
547 internal::TaskGraphRunner* RasterWorkerPool::GetTaskGraphRunner() {
548   return g_task_graph_runner.Pointer();
549 }
550
551 // static
552 RasterWorkerPool::RasterTask RasterWorkerPool::CreateRasterTask(
553     const Resource* resource,
554     PicturePileImpl* picture_pile,
555     const gfx::Rect& content_rect,
556     float contents_scale,
557     RasterMode raster_mode,
558     TileResolution tile_resolution,
559     int layer_id,
560     const void* tile_id,
561     int source_frame_number,
562     RenderingStatsInstrumentation* rendering_stats,
563     const RasterTask::Reply& reply,
564     Task::Set* dependencies,
565     ContextProvider* context_provider) {
566   return RasterTask(new RasterWorkerPoolTaskImpl(resource,
567                                                  picture_pile,
568                                                  content_rect,
569                                                  contents_scale,
570                                                  raster_mode,
571                                                  tile_resolution,
572                                                  layer_id,
573                                                  tile_id,
574                                                  source_frame_number,
575                                                  rendering_stats,
576                                                  reply,
577                                                  &dependencies->tasks_,
578                                                  context_provider));
579 }
580
581 // static
582 RasterWorkerPool::Task RasterWorkerPool::CreateImageDecodeTask(
583     SkPixelRef* pixel_ref,
584     int layer_id,
585     RenderingStatsInstrumentation* rendering_stats,
586     const Task::Reply& reply) {
587   return Task(new ImageDecodeWorkerPoolTaskImpl(
588       pixel_ref, layer_id, rendering_stats, reply));
589 }
590
591 void RasterWorkerPool::SetClient(RasterWorkerPoolClient* client) {
592   client_ = client;
593 }
594
595 void RasterWorkerPool::Shutdown() {
596   TRACE_EVENT0("cc", "RasterWorkerPool::Shutdown");
597
598   if (task_graph_runner_) {
599     internal::TaskGraph empty;
600     task_graph_runner_->SetTaskGraph(namespace_token_, &empty);
601     task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
602   }
603
604   weak_ptr_factory_.InvalidateWeakPtrs();
605 }
606
607 void RasterWorkerPool::SetTaskGraph(internal::TaskGraph* graph) {
608   TRACE_EVENT0("cc", "RasterWorkerPool::SetTaskGraph");
609
610   DCHECK(task_graph_runner_);
611   for (internal::TaskGraph::Node::Vector::iterator it = graph->nodes.begin();
612        it != graph->nodes.end();
613        ++it) {
614     internal::TaskGraph::Node& node = *it;
615     internal::WorkerPoolTask* task =
616         static_cast<internal::WorkerPoolTask*>(node.task);
617
618     if (!task->HasBeenScheduled()) {
619       task->WillSchedule();
620       task->ScheduleOnOriginThread(this);
621       task->DidSchedule();
622     }
623   }
624
625   task_graph_runner_->SetTaskGraph(namespace_token_, graph);
626 }
627
628 void RasterWorkerPool::CollectCompletedWorkerPoolTasks(
629     internal::Task::Vector* completed_tasks) {
630   DCHECK(task_graph_runner_);
631   task_graph_runner_->CollectCompletedTasks(namespace_token_, completed_tasks);
632 }
633
634 scoped_refptr<internal::WorkerPoolTask>
635 RasterWorkerPool::CreateRasterFinishedTask() {
636   return make_scoped_refptr(new RasterFinishedWorkerPoolTaskImpl(base::Bind(
637       &RasterWorkerPool::OnRasterFinished, weak_ptr_factory_.GetWeakPtr())));
638 }
639
640 scoped_refptr<internal::WorkerPoolTask>
641 RasterWorkerPool::CreateRasterRequiredForActivationFinishedTask(
642     size_t tasks_required_for_activation_count) {
643   return make_scoped_refptr(
644       new RasterRequiredForActivationFinishedWorkerPoolTaskImpl(
645           base::Bind(&RasterWorkerPool::OnRasterRequiredForActivationFinished,
646                      weak_ptr_factory_.GetWeakPtr()),
647           tasks_required_for_activation_count));
648 }
649
650 void RasterWorkerPool::RunTaskOnOriginThread(internal::WorkerPoolTask* task) {
651   task->WillSchedule();
652   task->ScheduleOnOriginThread(this);
653   task->DidSchedule();
654
655   task->WillRun();
656   task->RunOnOriginThread();
657   task->DidRun();
658
659   task->WillComplete();
660   task->CompleteOnOriginThread(this);
661   task->DidComplete();
662 }
663
664 void RasterWorkerPool::OnRasterFinished(
665     const internal::WorkerPoolTask* source) {
666   TRACE_EVENT0("cc", "RasterWorkerPool::OnRasterFinished");
667
668   // Early out if current |raster_finished_task_| is not the source.
669   if (source != raster_finished_task_.get())
670     return;
671
672   OnRasterTasksFinished();
673 }
674
675 void RasterWorkerPool::OnRasterRequiredForActivationFinished(
676     const internal::WorkerPoolTask* source) {
677   TRACE_EVENT0("cc", "RasterWorkerPool::OnRasterRequiredForActivationFinished");
678
679   // Early out if current |raster_required_for_activation_finished_task_|
680   // is not the source.
681   if (source != raster_required_for_activation_finished_task_.get())
682     return;
683
684   OnRasterTasksRequiredForActivationFinished();
685 }
686
687 // static
688 void RasterWorkerPool::InsertNodeForTask(internal::TaskGraph* graph,
689                                          internal::WorkerPoolTask* task,
690                                          unsigned priority,
691                                          size_t dependencies) {
692   DCHECK(std::find_if(graph->nodes.begin(),
693                       graph->nodes.end(),
694                       internal::TaskGraph::Node::TaskComparator(task)) ==
695          graph->nodes.end());
696   graph->nodes.push_back(
697       internal::TaskGraph::Node(task, priority, dependencies));
698 }
699
700 // static
701 void RasterWorkerPool::InsertNodeForRasterTask(
702     internal::TaskGraph* graph,
703     internal::WorkerPoolTask* raster_task,
704     const internal::WorkerPoolTask::Vector& decode_tasks,
705     unsigned priority) {
706   size_t dependencies = 0u;
707
708   // Insert image decode tasks.
709   for (internal::WorkerPoolTask::Vector::const_iterator it =
710            decode_tasks.begin();
711        it != decode_tasks.end();
712        ++it) {
713     internal::WorkerPoolTask* decode_task = it->get();
714
715     // Skip if already decoded.
716     if (decode_task->HasCompleted())
717       continue;
718
719     dependencies++;
720
721     // Add decode task if it doesn't already exists in graph.
722     internal::TaskGraph::Node::Vector::iterator decode_it =
723         std::find_if(graph->nodes.begin(),
724                      graph->nodes.end(),
725                      internal::TaskGraph::Node::TaskComparator(decode_task));
726     if (decode_it == graph->nodes.end())
727       InsertNodeForTask(graph, decode_task, priority, 0u);
728
729     graph->edges.push_back(internal::TaskGraph::Edge(decode_task, raster_task));
730   }
731
732   InsertNodeForTask(graph, raster_task, priority, dependencies);
733 }
734
735 }  // namespace cc