[go: nahoru, domu]

cc: Simplify Task and its derived classes.

This patch merges ImageDecodeTask and RasterTask into TileTask, single
class defining properties specific to tasks used for tiles. Now all
the tile related tasks get derived directly from TileTask.

  RasterTaskImpl : TileTask
  ImageDecodeTaskImpl : TileTask
  ImageUploadTaskImpl : TileTask

This patch also splits (Task + TaskGraph) from TaskGraphRunner and
moves it to its own file which simplifies file include dependencies.

BUG=599863
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1890903002

Cr-Commit-Position: refs/heads/master@{#388152}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index fae8e87..cbd38be 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -372,8 +372,9 @@
     "raster/staging_buffer_pool.h",
     "raster/synchronous_task_graph_runner.cc",
     "raster/synchronous_task_graph_runner.h",
+    "raster/task.cc",
+    "raster/task.h",
     "raster/task_category.h",
-    "raster/task_graph_runner.cc",
     "raster/task_graph_runner.h",
     "raster/task_graph_work_queue.cc",
     "raster/task_graph_work_queue.h",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 7b29a6e..6031f426 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -433,8 +433,9 @@
         'raster/staging_buffer_pool.h',
         'raster/synchronous_task_graph_runner.cc',
         'raster/synchronous_task_graph_runner.h',
+        'raster/task.cc',
+        'raster/task.h',
         'raster/task_category.h',
-        'raster/task_graph_runner.cc',
         'raster/task_graph_runner.h',
         'raster/task_graph_work_queue.cc',
         'raster/task_graph_work_queue.h',
diff --git a/cc/raster/task_graph_runner.cc b/cc/raster/task.cc
similarity index 73%
rename from cc/raster/task_graph_runner.cc
rename to cc/raster/task.cc
index 4f1af43..c19e549 100644
--- a/cc/raster/task_graph_runner.cc
+++ b/cc/raster/task.cc
@@ -1,15 +1,10 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/raster/task_graph_runner.h"
+#include "cc/raster/task.h"
 
-#include <algorithm>
-#include <utility>
-
-#include "base/atomic_sequence_num.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/trace_event/trace_event.h"
+#include "base/logging.h"
 
 namespace cc {
 
diff --git a/cc/raster/task.h b/cc/raster/task.h
new file mode 100644
index 0000000..96959c1
--- /dev/null
+++ b/cc/raster/task.h
@@ -0,0 +1,93 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RASTER_TASK_H_
+#define CC_RASTER_TASK_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+// A task which can be run by a TaskGraphRunner. To run a Task, it should be
+// inserted into a TaskGraph, which can then be scheduled on the
+// TaskGraphRunner.
+class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> {
+ public:
+  typedef std::vector<scoped_refptr<Task>> Vector;
+
+  // Subclasses should implement this method. RunOnWorkerThread may be called
+  // on any thread, and subclasses are responsible for locking and thread
+  // safety.
+  virtual void RunOnWorkerThread() = 0;
+
+  void WillRun();
+  void DidRun();
+  bool HasFinishedRunning() const;
+
+ protected:
+  friend class base::RefCountedThreadSafe<Task>;
+
+  Task();
+  virtual ~Task();
+
+  bool will_run_;
+  bool did_run_;
+};
+
+// A task dependency graph describes the order in which to execute a set
+// of tasks. Dependencies are represented as edges. Each node is assigned
+// a category, a priority and a run count that matches the number of
+// dependencies. Priority range from 0 (most favorable scheduling) to UINT16_MAX
+// (least favorable). Categories range from 0 to UINT16_MAX. It is up to the
+// implementation and its consumer to determine the meaning (if any) of a
+// category. A TaskGraphRunner implementation may chose to prioritize certain
+// categories over others, regardless of the individual priorities of tasks.
+struct CC_EXPORT TaskGraph {
+  struct Node {
+    typedef std::vector<Node> Vector;
+
+    Node(Task* task,
+         uint16_t category,
+         uint16_t priority,
+         uint32_t dependencies)
+        : task(task),
+          category(category),
+          priority(priority),
+          dependencies(dependencies) {}
+
+    Task* task;
+    uint16_t category;
+    uint16_t priority;
+    uint32_t dependencies;
+  };
+
+  struct Edge {
+    typedef std::vector<Edge> Vector;
+
+    Edge(const Task* task, Task* dependent)
+        : task(task), dependent(dependent) {}
+
+    const Task* task;
+    Task* dependent;
+  };
+
+  TaskGraph();
+  TaskGraph(const TaskGraph& other);
+  ~TaskGraph();
+
+  void Swap(TaskGraph* other);
+  void Reset();
+
+  Node::Vector nodes;
+  Edge::Vector edges;
+};
+
+}  // namespace cc
+
+#endif  // CC_RASTER_TASK_H_
diff --git a/cc/raster/task_graph_runner.h b/cc/raster/task_graph_runner.h
index d5f8cee..51ac3341c 100644
--- a/cc/raster/task_graph_runner.h
+++ b/cc/raster/task_graph_runner.h
@@ -16,85 +16,10 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "cc/base/cc_export.h"
+#include "cc/raster/task.h"
 
 namespace cc {
 
-class TaskGraphRunner;
-
-// A task which can be run by a TaskGraphRunner. To run a Task, it should be
-// inserted into a TaskGraph, which can then be scheduled on the
-// TaskGraphRunner.
-class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> {
- public:
-  typedef std::vector<scoped_refptr<Task>> Vector;
-
-  // Subclasses should implement this method. RunOnWorkerThread may be called
-  // on any thread, and subclasses are responsible for locking and thread
-  // safety.
-  virtual void RunOnWorkerThread() = 0;
-
-  void WillRun();
-  void DidRun();
-  bool HasFinishedRunning() const;
-
- protected:
-  friend class base::RefCountedThreadSafe<Task>;
-
-  Task();
-  virtual ~Task();
-
-  bool will_run_;
-  bool did_run_;
-};
-
-// A task dependency graph describes the order in which to execute a set
-// of tasks. Dependencies are represented as edges. Each node is assigned
-// a category, a priority and a run count that matches the number of
-// dependencies. Priority range from 0 (most favorable scheduling) to UINT16_MAX
-// (least favorable). Categories range from 0 to UINT16_MAX. It is up to the
-// implementation and its consumer to determine the meaning (if any) of a
-// category. A TaskGraphRunner implementation may chose to prioritize certain
-// categories over others, regardless of the individual priorities of tasks.
-struct CC_EXPORT TaskGraph {
-  struct Node {
-    typedef std::vector<Node> Vector;
-
-    Node(Task* task,
-         uint16_t category,
-         uint16_t priority,
-         uint32_t dependencies)
-        : task(task),
-          category(category),
-          priority(priority),
-          dependencies(dependencies) {}
-
-    Task* task;
-    uint16_t category;
-    uint16_t priority;
-    uint32_t dependencies;
-  };
-
-  struct Edge {
-    typedef std::vector<Edge> Vector;
-
-    Edge(const Task* task, Task* dependent)
-        : task(task), dependent(dependent) {}
-
-    const Task* task;
-    Task* dependent;
-  };
-
-  TaskGraph();
-  TaskGraph(const TaskGraph& other);
-  ~TaskGraph();
-
-  void Swap(TaskGraph* other);
-  void Reset();
-
-  Node::Vector nodes;
-  Edge::Vector edges;
-};
-
 // Opaque identifier that defines a namespace of tasks.
 class CC_EXPORT NamespaceToken {
  public:
@@ -166,61 +91,6 @@
   virtual ~TaskGraphRunner() {}
 };
 
-// Helper class for iterating over all dependents of a task.
-class DependentIterator {
- public:
-  DependentIterator(TaskGraph* graph, const Task* task)
-      : graph_(graph),
-        task_(task),
-        current_index_(static_cast<size_t>(-1)),
-        current_node_(NULL) {
-    ++(*this);
-  }
-
-  TaskGraph::Node& operator->() const {
-    DCHECK_LT(current_index_, graph_->edges.size());
-    DCHECK_EQ(graph_->edges[current_index_].task, task_);
-    DCHECK(current_node_);
-    return *current_node_;
-  }
-
-  TaskGraph::Node& operator*() const {
-    DCHECK_LT(current_index_, graph_->edges.size());
-    DCHECK_EQ(graph_->edges[current_index_].task, task_);
-    DCHECK(current_node_);
-    return *current_node_;
-  }
-
-  // Note: Performance can be improved by keeping edges sorted.
-  DependentIterator& operator++() {
-    // Find next dependency edge for |task_|.
-    do {
-      ++current_index_;
-      if (current_index_ == graph_->edges.size())
-        return *this;
-    } while (graph_->edges[current_index_].task != task_);
-
-    // Now find the node for the dependent of this edge.
-    TaskGraph::Node::Vector::iterator it = std::find_if(
-        graph_->nodes.begin(), graph_->nodes.end(),
-        [this](const TaskGraph::Node& node) {
-          return node.task == graph_->edges[current_index_].dependent;
-        });
-    DCHECK(it != graph_->nodes.end());
-    current_node_ = &(*it);
-
-    return *this;
-  }
-
-  operator bool() const { return current_index_ < graph_->edges.size(); }
-
- private:
-  TaskGraph* graph_;
-  const Task* task_;
-  size_t current_index_;
-  TaskGraph::Node* current_node_;
-};
-
 }  // namespace cc
 
 #endif  // CC_RASTER_TASK_GRAPH_RUNNER_H_
diff --git a/cc/raster/task_graph_work_queue.cc b/cc/raster/task_graph_work_queue.cc
index 98413ee..aa75654 100644
--- a/cc/raster/task_graph_work_queue.cc
+++ b/cc/raster/task_graph_work_queue.cc
@@ -43,6 +43,62 @@
  private:
   uint16_t category_;
 };
+
+// Helper class for iterating over all dependents of a task.
+class DependentIterator {
+ public:
+  DependentIterator(TaskGraph* graph, const Task* task)
+      : graph_(graph),
+        task_(task),
+        current_index_(static_cast<size_t>(-1)),
+        current_node_(NULL) {
+    ++(*this);
+  }
+
+  TaskGraph::Node& operator->() const {
+    DCHECK_LT(current_index_, graph_->edges.size());
+    DCHECK_EQ(graph_->edges[current_index_].task, task_);
+    DCHECK(current_node_);
+    return *current_node_;
+  }
+
+  TaskGraph::Node& operator*() const {
+    DCHECK_LT(current_index_, graph_->edges.size());
+    DCHECK_EQ(graph_->edges[current_index_].task, task_);
+    DCHECK(current_node_);
+    return *current_node_;
+  }
+
+  // Note: Performance can be improved by keeping edges sorted.
+  DependentIterator& operator++() {
+    // Find next dependency edge for |task_|.
+    do {
+      ++current_index_;
+      if (current_index_ == graph_->edges.size())
+        return *this;
+    } while (graph_->edges[current_index_].task != task_);
+
+    // Now find the node for the dependent of this edge.
+    TaskGraph::Node::Vector::iterator it = std::find_if(
+        graph_->nodes.begin(), graph_->nodes.end(),
+        [this](const TaskGraph::Node& node) {
+          return node.task == graph_->edges[current_index_].dependent;
+        });
+    DCHECK(it != graph_->nodes.end());
+    current_node_ = &(*it);
+
+    return *this;
+  }
+
+  operator bool() const { return current_index_ < graph_->edges.size(); }
+
+ private:
+  TaskGraph* graph_;
+  const Task* task_;
+  size_t current_index_;
+  TaskGraph::Node* current_node_;
+};
+
 }  // namespace
 
 TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {}
diff --git a/cc/raster/tile_task_runner.cc b/cc/raster/tile_task_runner.cc
index e76218c..fde8ad80 100644
--- a/cc/raster/tile_task_runner.cc
+++ b/cc/raster/tile_task_runner.cc
@@ -7,8 +7,17 @@
 
 namespace cc {
 
-TileTask::TileTask() : did_schedule_(false), did_complete_(false) {
-}
+TileTask::TileTask(bool supports_concurrent_execution)
+    : supports_concurrent_execution_(supports_concurrent_execution),
+      did_schedule_(false),
+      did_complete_(false) {}
+
+TileTask::TileTask(bool supports_concurrent_execution,
+                   TileTask::Vector* dependencies)
+    : supports_concurrent_execution_(supports_concurrent_execution),
+      dependencies_(std::move(*dependencies)),
+      did_schedule_(false),
+      did_complete_(false) {}
 
 TileTask::~TileTask() {
   DCHECK(!did_schedule_);
@@ -43,26 +52,6 @@
   return did_complete_;
 }
 
-ImageDecodeTask::ImageDecodeTask() {
-}
-
-ImageDecodeTask::ImageDecodeTask(scoped_refptr<ImageDecodeTask> dependency)
-    : dependency_(std::move(dependency)) {}
-
-ImageDecodeTask::~ImageDecodeTask() {
-}
-
-bool ImageDecodeTask::SupportsConcurrentExecution() const {
-  return true;
-}
-
-RasterTask::RasterTask(ImageDecodeTask::Vector* dependencies) {
-  dependencies_.swap(*dependencies);
-}
-
-RasterTask::~RasterTask() {
-}
-
 bool TileTaskRunner::ResourceFormatRequiresSwizzle(ResourceFormat format) {
   switch (format) {
     case RGBA_8888:
diff --git a/cc/raster/tile_task_runner.h b/cc/raster/tile_task_runner.h
index dc1586a..3bda3ad 100644
--- a/cc/raster/tile_task_runner.h
+++ b/cc/raster/tile_task_runner.h
@@ -11,7 +11,7 @@
 
 #include "base/callback.h"
 #include "cc/raster/raster_buffer.h"
-#include "cc/raster/task_graph_runner.h"
+#include "cc/raster/task.h"
 #include "cc/resources/resource_format.h"
 
 namespace cc {
@@ -20,6 +20,16 @@
  public:
   typedef std::vector<scoped_refptr<TileTask>> Vector;
 
+  const TileTask::Vector& dependencies() const { return dependencies_; }
+
+  // Indicates whether this TileTask can be run at the same time as other tasks
+  // in the task graph. If false, this task will be scheduled with
+  // TASK_CATEGORY_NONCONCURRENT_FOREGROUND. The base implementation always
+  // returns true.
+  bool SupportsConcurrentExecution() const {
+    return supports_concurrent_execution_;
+  }
+
   virtual void ScheduleOnOriginThread(RasterBufferProvider* provider) = 0;
   virtual void CompleteOnOriginThread(RasterBufferProvider* provider) = 0;
 
@@ -32,49 +42,16 @@
   bool HasCompleted() const;
 
  protected:
-  TileTask();
+  explicit TileTask(bool supports_concurrent_execution);
+  TileTask(bool supports_concurrent_execution, TileTask::Vector* dependencies);
   ~TileTask() override;
 
+  const bool supports_concurrent_execution_;
+  TileTask::Vector dependencies_;
   bool did_schedule_;
   bool did_complete_;
 };
 
-class CC_EXPORT ImageDecodeTask : public TileTask {
- public:
-  typedef std::vector<scoped_refptr<ImageDecodeTask>> Vector;
-
-  // Indicates whether this ImageDecodeTask can be run at the same time as
-  // other tasks in the task graph. If false, this task will be scheduled with
-  // TASK_CATEGORY_NONCONCURRENT_FOREGROUND. The base implementation always
-  // returns true.
-  virtual bool SupportsConcurrentExecution() const;
-
-  // Returns an optional task which this task depends on. May be null.
-  const scoped_refptr<ImageDecodeTask>& dependency() { return dependency_; }
-
- protected:
-  ImageDecodeTask();
-  explicit ImageDecodeTask(scoped_refptr<ImageDecodeTask> dependency);
-  ~ImageDecodeTask() override;
-
- private:
-  scoped_refptr<ImageDecodeTask> dependency_;
-};
-
-class CC_EXPORT RasterTask : public TileTask {
- public:
-  typedef std::vector<scoped_refptr<RasterTask>> Vector;
-
-  const ImageDecodeTask::Vector& dependencies() const { return dependencies_; }
-
- protected:
-  explicit RasterTask(ImageDecodeTask::Vector* dependencies);
-  ~RasterTask() override;
-
- private:
-  ImageDecodeTask::Vector dependencies_;
-};
-
 // This interface can be used to schedule and run tile tasks.
 // The client can call CheckForCompletedTasks() at any time to dispatch
 // pending completion callbacks for all tasks that have finished running.
diff --git a/cc/raster/tile_task_worker_pool.h b/cc/raster/tile_task_worker_pool.h
index e05256ef..f4e675c 100644
--- a/cc/raster/tile_task_worker_pool.h
+++ b/cc/raster/tile_task_worker_pool.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include "cc/playback/raster_source.h"
+#include "cc/raster/task_graph_runner.h"
 #include "cc/raster/tile_task_runner.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
diff --git a/cc/raster/tile_task_worker_pool_perftest.cc b/cc/raster/tile_task_worker_pool_perftest.cc
index 2335ca7..04922d68 100644
--- a/cc/raster/tile_task_worker_pool_perftest.cc
+++ b/cc/raster/tile_task_worker_pool_perftest.cc
@@ -123,9 +123,9 @@
 static const int kWarmupRuns = 5;
 static const int kTimeCheckInterval = 10;
 
-class PerfImageDecodeTaskImpl : public ImageDecodeTask {
+class PerfImageDecodeTaskImpl : public TileTask {
  public:
-  PerfImageDecodeTaskImpl() {}
+  PerfImageDecodeTaskImpl() : TileTask(true) {}
 
   // Overridden from Task:
   void RunOnWorkerThread() override {}
@@ -148,11 +148,11 @@
   DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl);
 };
 
-class PerfRasterTaskImpl : public RasterTask {
+class PerfRasterTaskImpl : public TileTask {
  public:
   PerfRasterTaskImpl(std::unique_ptr<ScopedResource> resource,
-                     ImageDecodeTask::Vector* dependencies)
-      : RasterTask(dependencies), resource_(std::move(resource)) {}
+                     TileTask::Vector* dependencies)
+      : TileTask(true, dependencies), resource_(std::move(resource)) {}
 
   // Overridden from Task:
   void RunOnWorkerThread() override {}
@@ -184,7 +184,7 @@
 
 class TileTaskWorkerPoolPerfTestBase {
  public:
-  typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
+  typedef std::vector<scoped_refptr<TileTask>> RasterTaskVector;
 
   enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
 
@@ -197,13 +197,13 @@
                kTimeCheckInterval) {}
 
   void CreateImageDecodeTasks(unsigned num_image_decode_tasks,
-                              ImageDecodeTask::Vector* image_decode_tasks) {
+                              TileTask::Vector* image_decode_tasks) {
     for (unsigned i = 0; i < num_image_decode_tasks; ++i)
       image_decode_tasks->push_back(new PerfImageDecodeTaskImpl);
   }
 
   void CreateRasterTasks(unsigned num_raster_tasks,
-                         const ImageDecodeTask::Vector& image_decode_tasks,
+                         const TileTask::Vector& image_decode_tasks,
                          RasterTaskVector* raster_tasks) {
     const gfx::Size size(1, 1);
 
@@ -213,7 +213,7 @@
       resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
                          RGBA_8888);
 
-      ImageDecodeTask::Vector dependencies = image_decode_tasks;
+      TileTask::Vector dependencies = image_decode_tasks;
       raster_tasks->push_back(
           new PerfRasterTaskImpl(std::move(resource), &dependencies));
     }
@@ -300,7 +300,7 @@
   void RunScheduleTasksTest(const std::string& test_name,
                             unsigned num_raster_tasks,
                             unsigned num_image_decode_tasks) {
-    ImageDecodeTask::Vector image_decode_tasks;
+    TileTask::Vector image_decode_tasks;
     RasterTaskVector raster_tasks;
     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
@@ -329,7 +329,7 @@
                                      unsigned num_raster_tasks,
                                      unsigned num_image_decode_tasks) {
     const size_t kNumVersions = 2;
-    ImageDecodeTask::Vector image_decode_tasks[kNumVersions];
+    TileTask::Vector image_decode_tasks[kNumVersions];
     RasterTaskVector raster_tasks[kNumVersions];
     for (size_t i = 0; i < kNumVersions; ++i) {
       CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks[i]);
@@ -362,7 +362,7 @@
   void RunScheduleAndExecuteTasksTest(const std::string& test_name,
                                       unsigned num_raster_tasks,
                                       unsigned num_image_decode_tasks) {
-    ImageDecodeTask::Vector image_decode_tasks;
+    TileTask::Vector image_decode_tasks;
     RasterTaskVector raster_tasks;
     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
@@ -471,7 +471,7 @@
   void RunBuildTileTaskGraphTest(const std::string& test_name,
                                  unsigned num_raster_tasks,
                                  unsigned num_image_decode_tasks) {
-    ImageDecodeTask::Vector image_decode_tasks;
+    TileTask::Vector image_decode_tasks;
     RasterTaskVector raster_tasks;
     CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
     CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
diff --git a/cc/raster/tile_task_worker_pool_unittest.cc b/cc/raster/tile_task_worker_pool_unittest.cc
index e3d2ab5d..03f835c 100644
--- a/cc/raster/tile_task_worker_pool_unittest.cc
+++ b/cc/raster/tile_task_worker_pool_unittest.cc
@@ -51,14 +51,14 @@
   TILE_TASK_WORKER_POOL_TYPE_BITMAP
 };
 
-class TestRasterTaskImpl : public RasterTask {
+class TestRasterTaskImpl : public TileTask {
  public:
   typedef base::Callback<void(bool was_canceled)> Reply;
 
   TestRasterTaskImpl(const Resource* resource,
                      const Reply& reply,
-                     ImageDecodeTask::Vector* dependencies)
-      : RasterTask(dependencies),
+                     TileTask::Vector* dependencies)
+      : TileTask(true, dependencies),
         resource_(resource),
         reply_(reply),
         raster_source_(FakeRasterSource::CreateFilled(gfx::Size(1, 1))) {}
@@ -99,7 +99,7 @@
   BlockingTestRasterTaskImpl(const Resource* resource,
                              const Reply& reply,
                              base::Lock* lock,
-                             ImageDecodeTask::Vector* dependencies)
+                             TileTask::Vector* dependencies)
       : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
 
   // Overridden from Task:
@@ -125,7 +125,7 @@
     bool canceled;
   };
 
-  typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
+  typedef std::vector<scoped_refptr<TileTask>> RasterTaskVector;
 
   enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
 
@@ -210,7 +210,7 @@
                        RGBA_8888);
     const Resource* const_resource = resource.get();
 
-    ImageDecodeTask::Vector empty;
+    TileTask::Vector empty;
     tasks_.push_back(new TestRasterTaskImpl(
         const_resource,
         base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
@@ -229,7 +229,7 @@
                        RGBA_8888);
     const Resource* const_resource = resource.get();
 
-    ImageDecodeTask::Vector empty;
+    TileTask::Vector empty;
     tasks_.push_back(new BlockingTestRasterTaskImpl(
         const_resource,
         base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc
index ebc0b70a..7397ae4a3 100644
--- a/cc/test/fake_tile_manager.cc
+++ b/cc/test/fake_tile_manager.cc
@@ -26,7 +26,7 @@
   void Shutdown() override {}
   void ScheduleTasks(TaskGraph* graph) override {
     for (const auto& node : graph->nodes) {
-      RasterTask* task = static_cast<RasterTask*>(node.task);
+      TileTask* task = static_cast<TileTask*>(node.task);
 
       task->WillSchedule();
       task->ScheduleOnOriginThread(this);
@@ -36,10 +36,9 @@
     }
   }
   void CheckForCompletedTasks() override {
-    for (RasterTask::Vector::iterator it = completed_tasks_.begin();
-         it != completed_tasks_.end();
-         ++it) {
-      RasterTask* task = it->get();
+    for (TileTask::Vector::iterator it = completed_tasks_.begin();
+         it != completed_tasks_.end(); ++it) {
+      TileTask* task = it->get();
 
       task->WillComplete();
       task->CompleteOnOriginThread(this);
@@ -65,7 +64,7 @@
   void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override {}
 
  private:
-  RasterTask::Vector completed_tasks_;
+  TileTask::Vector completed_tasks_;
 };
 base::LazyInstance<FakeTileTaskRunnerImpl> g_fake_tile_task_runner =
     LAZY_INSTANCE_INITIALIZER;
diff --git a/cc/tiles/gpu_image_decode_controller.cc b/cc/tiles/gpu_image_decode_controller.cc
index ab683d6..b6aa1a6 100644
--- a/cc/tiles/gpu_image_decode_controller.cc
+++ b/cc/tiles/gpu_image_decode_controller.cc
@@ -57,12 +57,13 @@
 
 // Task which decodes an image and stores the result in discardable memory.
 // This task does not use GPU resources and can be run on any thread.
-class ImageDecodeTaskImpl : public ImageDecodeTask {
+class ImageDecodeTaskImpl : public TileTask {
  public:
   ImageDecodeTaskImpl(GpuImageDecodeController* controller,
                       const DrawImage& draw_image,
                       uint64_t source_prepare_tiles_id)
-      : controller_(controller),
+      : TileTask(true),
+        controller_(controller),
         image_(draw_image),
         image_ref_(skia::SharePtr(draw_image.image())),
         source_prepare_tiles_id_(source_prepare_tiles_id) {
@@ -97,18 +98,19 @@
 // Task which creates an image from decoded data. Typically this involves
 // uploading data to the GPU, which requires this task be run on the non-
 // concurrent thread.
-class ImageUploadTaskImpl : public ImageDecodeTask {
+class ImageUploadTaskImpl : public TileTask {
  public:
   ImageUploadTaskImpl(GpuImageDecodeController* controller,
                       const DrawImage& draw_image,
-                      scoped_refptr<ImageDecodeTask> decode_dependency,
+                      scoped_refptr<TileTask> decode_dependency,
                       uint64_t source_prepare_tiles_id)
-      : ImageDecodeTask(std::move(decode_dependency)),
+      : TileTask(false),
         controller_(controller),
         image_(draw_image),
         image_ref_(skia::SharePtr(draw_image.image())),
         source_prepare_tiles_id_(source_prepare_tiles_id) {
     DCHECK(!SkipImage(draw_image));
+    dependencies_.push_back(std::move(decode_dependency));
   }
 
   // Override from Task:
@@ -123,9 +125,6 @@
     controller_->UploadTaskCompleted(image_);
   }
 
-  // Override from ImageDecodeTask:
-  bool SupportsConcurrentExecution() const override { return false; }
-
  protected:
   ~ImageUploadTaskImpl() override {}
 
@@ -174,7 +173,7 @@
 bool GpuImageDecodeController::GetTaskForImageAndRef(
     const DrawImage& draw_image,
     uint64_t prepare_tiles_id,
-    scoped_refptr<ImageDecodeTask>* task) {
+    scoped_refptr<TileTask>* task) {
   if (SkipImage(draw_image)) {
     *task = nullptr;
     return false;
@@ -202,7 +201,7 @@
 
   // We didn't have a pre-uploaded image, so we need an upload task. Try to find
   // an existing one.
-  scoped_refptr<ImageDecodeTask>& existing_task =
+  scoped_refptr<TileTask>& existing_task =
       pending_image_upload_tasks_[image_id];
   if (existing_task) {
     // We had an existing upload task, ref the image and return the task.
@@ -387,9 +386,9 @@
 
 // Checks if an existing image decode exists. If not, returns a task to produce
 // the requested decode.
-scoped_refptr<ImageDecodeTask>
-GpuImageDecodeController::GetImageDecodeTaskAndRef(const DrawImage& draw_image,
-                                                   uint64_t prepare_tiles_id) {
+scoped_refptr<TileTask> GpuImageDecodeController::GetImageDecodeTaskAndRef(
+    const DrawImage& draw_image,
+    uint64_t prepare_tiles_id) {
   lock_.AssertAcquired();
 
   const uint32_t image_id = draw_image.image()->uniqueID();
@@ -408,7 +407,7 @@
   }
 
   // We didn't have an existing locked image, create a task to lock or decode.
-  scoped_refptr<ImageDecodeTask>& existing_task =
+  scoped_refptr<TileTask>& existing_task =
       pending_image_decode_tasks_[image_id];
   if (!existing_task) {
     // Ref image decode and create a decode task. This ref will be released in
diff --git a/cc/tiles/gpu_image_decode_controller.h b/cc/tiles/gpu_image_decode_controller.h
index 10b03e13..32b2b4c 100644
--- a/cc/tiles/gpu_image_decode_controller.h
+++ b/cc/tiles/gpu_image_decode_controller.h
@@ -61,7 +61,7 @@
   // upload task to upload the image if an exsiting image does not exist.
   bool GetTaskForImageAndRef(const DrawImage& image,
                              uint64_t prepare_tiles_id,
-                             scoped_refptr<ImageDecodeTask>* task) override;
+                             scoped_refptr<TileTask>* task) override;
   void UnrefImage(const DrawImage& image) override;
   DecodedDrawImage GetDecodedImageForDraw(const DrawImage& draw_image) override;
   void DrawWithImageFinished(const DrawImage& image,
@@ -135,9 +135,8 @@
 
   // Similar to GetTaskForImageAndRef, but gets the dependent decode task
   // rather than the upload task, if necessary.
-  scoped_refptr<ImageDecodeTask> GetImageDecodeTaskAndRef(
-      const DrawImage& image,
-      uint64_t prepare_tiles_id);
+  scoped_refptr<TileTask> GetImageDecodeTaskAndRef(const DrawImage& image,
+                                                   uint64_t prepare_tiles_id);
 
   void RefImageDecode(const DrawImage& draw_image);
   void UnrefImageDecode(const DrawImage& draw_image);
@@ -170,9 +169,9 @@
   // All members below this point must only be accessed while holding |lock_|.
   base::Lock lock_;
 
-  std::unordered_map<uint32_t, scoped_refptr<ImageDecodeTask>>
+  std::unordered_map<uint32_t, scoped_refptr<TileTask>>
       pending_image_upload_tasks_;
-  std::unordered_map<uint32_t, scoped_refptr<ImageDecodeTask>>
+  std::unordered_map<uint32_t, scoped_refptr<TileTask>>
       pending_image_decode_tasks_;
 
   ImageDataMRUCache image_data_;
diff --git a/cc/tiles/gpu_image_decode_controller_unittest.cc b/cc/tiles/gpu_image_decode_controller_unittest.cc
index fef46e9..71bc063 100644
--- a/cc/tiles/gpu_image_decode_controller_unittest.cc
+++ b/cc/tiles/gpu_image_decode_controller_unittest.cc
@@ -31,25 +31,25 @@
   return matrix;
 }
 
-void ScheduleTask(ImageDecodeTask* task) {
+void ScheduleTask(TileTask* task) {
   task->WillSchedule();
   task->ScheduleOnOriginThread(nullptr);
   task->DidSchedule();
 }
 
-void RunTask(ImageDecodeTask* task) {
+void RunTask(TileTask* task) {
   task->WillRun();
   task->RunOnWorkerThread();
   task->DidRun();
 }
 
-void CompleteTask(ImageDecodeTask* task) {
+void CompleteTask(TileTask* task) {
   task->WillComplete();
   task->CompleteOnOriginThread(nullptr);
   task->DidComplete();
 }
 
-void ProcessTask(ImageDecodeTask* task) {
+void ProcessTask(TileTask* task) {
   ScheduleTask(task);
   RunTask(task);
   CompleteTask(task);
@@ -68,7 +68,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -77,13 +77,13 @@
   DrawImage another_draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(
       another_draw_image, prepare_tiles_id, &another_task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(task.get() == another_task.get());
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ProcessTask(task.get());
 
   controller.UnrefImage(draw_image);
@@ -104,7 +104,7 @@
       first_image.get(),
       SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> first_task;
+  scoped_refptr<TileTask> first_task;
   bool need_unref = controller.GetTaskForImageAndRef(
       first_draw_image, prepare_tiles_id, &first_task);
   EXPECT_TRUE(need_unref);
@@ -115,16 +115,16 @@
       second_image.get(),
       SkIRect::MakeWH(second_image->width(), second_image->height()), quality,
       CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> second_task;
+  scoped_refptr<TileTask> second_task;
   need_unref = controller.GetTaskForImageAndRef(second_draw_image,
                                                 prepare_tiles_id, &second_task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(second_task);
   EXPECT_TRUE(first_task.get() != second_task.get());
 
-  ProcessTask(first_task->dependency().get());
+  ProcessTask(first_task->dependencies()[0].get());
   ProcessTask(first_task.get());
-  ProcessTask(second_task->dependency().get());
+  ProcessTask(second_task->dependencies()[0].get());
   ProcessTask(second_task.get());
 
   controller.UnrefImage(first_draw_image);
@@ -144,18 +144,19 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(task);
-  EXPECT_TRUE(task->dependency());
+  EXPECT_EQ(task->dependencies().size(), 1u);
+  EXPECT_TRUE(task->dependencies()[0]);
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ScheduleTask(task.get());
   RunTask(task.get());
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &another_task);
   EXPECT_TRUE(need_unref);
@@ -180,16 +181,16 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(task);
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ScheduleTask(task.get());
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &another_task);
   EXPECT_TRUE(need_unref);
@@ -203,14 +204,14 @@
   controller.UnrefImage(draw_image);
 
   // Here a new task is created.
-  scoped_refptr<ImageDecodeTask> third_task;
+  scoped_refptr<TileTask> third_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &third_task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(third_task);
   EXPECT_FALSE(third_task.get() == task.get());
 
-  ProcessTask(third_task->dependency().get());
+  ProcessTask(third_task->dependencies()[0].get());
   ProcessTask(third_task.get());
 
   controller.UnrefImage(draw_image);
@@ -230,16 +231,16 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(task);
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ScheduleTask(task.get());
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &another_task);
   EXPECT_TRUE(need_unref);
@@ -250,14 +251,14 @@
 
   // Note that here, everything is reffed, but a new task is created. This is
   // possible with repeated schedule/cancel operations.
-  scoped_refptr<ImageDecodeTask> third_task;
+  scoped_refptr<TileTask> third_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &third_task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(third_task);
   EXPECT_FALSE(third_task.get() == task.get());
 
-  ProcessTask(third_task->dependency().get());
+  ProcessTask(third_task->dependencies()[0].get());
   ProcessTask(third_task.get());
 
   // 3 Unrefs!
@@ -279,13 +280,13 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(task);
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ProcessTask(task.get());
 
   // Must hold context lock before calling GetDecodedImageForDraw /
@@ -314,13 +315,13 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
   EXPECT_TRUE(task);
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ProcessTask(task.get());
 
   // Must hold context lock before calling GetDecodedImageForDraw /
@@ -353,7 +354,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_FALSE(need_unref);
@@ -388,7 +389,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_FALSE(need_unref);
@@ -410,7 +411,7 @@
   // cache.
   controller.DrawWithImageFinished(draw_image, decoded_draw_image);
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   bool another_task_needs_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(another_task_needs_unref);
@@ -467,7 +468,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_FALSE(task);
@@ -497,7 +498,7 @@
       image.get(), SkIRect::MakeXYWH(150, 150, image->width(), image->height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_FALSE(task);
@@ -527,15 +528,15 @@
       image.get(), SkIRect::MakeXYWH(0, 0, image->width(), image->height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_NE(0u, controller.GetBytesUsedForTesting());
   EXPECT_TRUE(task);
   EXPECT_TRUE(need_unref);
 
-  ScheduleTask(task->dependency().get());
-  CompleteTask(task->dependency().get());
+  ScheduleTask(task->dependencies()[0].get());
+  CompleteTask(task->dependencies()[0].get());
   ScheduleTask(task.get());
   CompleteTask(task.get());
 
@@ -556,7 +557,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   {
     bool need_unref =
         controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
@@ -564,7 +565,7 @@
     EXPECT_TRUE(task);
   }
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ProcessTask(task.get());
 
   controller.UnrefImage(draw_image);
@@ -594,7 +595,7 @@
     EXPECT_TRUE(task);
   }
 
-  ProcessTask(task->dependency().get());
+  ProcessTask(task->dependencies()[0].get());
   ProcessTask(task.get());
 
   // The image should be in our cache after un-ref.
diff --git a/cc/tiles/image_decode_controller.h b/cc/tiles/image_decode_controller.h
index 6d3cd29a..af7c22a 100644
--- a/cc/tiles/image_decode_controller.h
+++ b/cc/tiles/image_decode_controller.h
@@ -11,14 +11,14 @@
 
 namespace cc {
 
-class ImageDecodeTask;
+class TileTask;
 
 // ImageDecodeController is responsible for generating decode tasks, decoding
 // images, storing images in cache, and being able to return the decoded images
 // when requested.
 
 // ImageDecodeController is responsible for the following things:
-// 1. Given a DrawImage, it can return an ImageDecodeTask which when run will
+// 1. Given a DrawImage, it can return an TileTask which when run will
 //    decode and cache the resulting image. If the image does not need a task to
 //    be decoded, then nullptr will be returned. The return value of the
 //    function indicates whether the image was or is going to be locked, so an
@@ -35,7 +35,7 @@
  public:
   virtual ~ImageDecodeController() {}
 
-  // Fill in an ImageDecodeTask which will decode the given image when run. In
+  // Fill in an TileTask which will decode the given image when run. In
   // case the image is already cached, fills in nullptr. Returns true if the
   // image needs to be unreffed when the caller is finished with it.
   //
@@ -43,7 +43,7 @@
   // a raster task.
   virtual bool GetTaskForImageAndRef(const DrawImage& image,
                                      uint64_t prepare_tiles_id,
-                                     scoped_refptr<ImageDecodeTask>* task) = 0;
+                                     scoped_refptr<TileTask>* task) = 0;
   // Unrefs an image. When the tile is finished, this should be called for every
   // GetTaskForImageAndRef call that returned true.
   virtual void UnrefImage(const DrawImage& image) = 0;
diff --git a/cc/tiles/software_image_decode_controller.cc b/cc/tiles/software_image_decode_controller.cc
index f05bb5d..80190b4 100644
--- a/cc/tiles/software_image_decode_controller.cc
+++ b/cc/tiles/software_image_decode_controller.cc
@@ -41,7 +41,7 @@
  public:
   AutoRemoveKeyFromTaskMap(
       std::unordered_map<SoftwareImageDecodeController::ImageKey,
-                         scoped_refptr<ImageDecodeTask>,
+                         scoped_refptr<TileTask>,
                          SoftwareImageDecodeController::ImageKeyHash>* task_map,
       const SoftwareImageDecodeController::ImageKey& key)
       : task_map_(task_map), key_(key) {}
@@ -49,18 +49,19 @@
 
  private:
   std::unordered_map<SoftwareImageDecodeController::ImageKey,
-                     scoped_refptr<ImageDecodeTask>,
+                     scoped_refptr<TileTask>,
                      SoftwareImageDecodeController::ImageKeyHash>* task_map_;
   SoftwareImageDecodeController::ImageKey key_;
 };
 
-class ImageDecodeTaskImpl : public ImageDecodeTask {
+class ImageDecodeTaskImpl : public TileTask {
  public:
   ImageDecodeTaskImpl(SoftwareImageDecodeController* controller,
                       const SoftwareImageDecodeController::ImageKey& image_key,
                       const DrawImage& image,
                       uint64_t source_prepare_tiles_id)
-      : controller_(controller),
+      : TileTask(true),
+        controller_(controller),
         image_key_(image_key),
         image_(image),
         image_ref_(skia::SharePtr(image.image())),
@@ -152,7 +153,7 @@
 bool SoftwareImageDecodeController::GetTaskForImageAndRef(
     const DrawImage& image,
     uint64_t prepare_tiles_id,
-    scoped_refptr<ImageDecodeTask>* task) {
+    scoped_refptr<TileTask>* task) {
   // If the image already exists or if we're going to create a task for it, then
   // we'll likely need to ref this image (the exception is if we're prerolling
   // the image only). That means the image is or will be in the cache. When the
@@ -179,7 +180,7 @@
   if (!CanHandleImage(key)) {
     base::AutoLock lock(lock_);
     if (prerolled_images_.count(key.image_id()) == 0) {
-      scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key];
+      scoped_refptr<TileTask>& existing_task = pending_image_tasks_[key];
       if (!existing_task) {
         existing_task = make_scoped_refptr(
             new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id));
@@ -212,7 +213,7 @@
   }
 
   // If the task exists, return it.
-  scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key];
+  scoped_refptr<TileTask>& existing_task = pending_image_tasks_[key];
   if (existing_task) {
     RefImage(key);
     *task = existing_task;
diff --git a/cc/tiles/software_image_decode_controller.h b/cc/tiles/software_image_decode_controller.h
index 9697720..8f6ed0d 100644
--- a/cc/tiles/software_image_decode_controller.h
+++ b/cc/tiles/software_image_decode_controller.h
@@ -110,7 +110,7 @@
   // ImageDecodeController overrides.
   bool GetTaskForImageAndRef(const DrawImage& image,
                              uint64_t prepare_tiles_id,
-                             scoped_refptr<ImageDecodeTask>* task) override;
+                             scoped_refptr<TileTask>* task) override;
   void UnrefImage(const DrawImage& image) override;
   DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) override;
   void DrawWithImageFinished(const DrawImage& image,
@@ -241,7 +241,7 @@
                                const char* cache_name,
                                base::trace_event::ProcessMemoryDump* pmd) const;
 
-  std::unordered_map<ImageKey, scoped_refptr<ImageDecodeTask>, ImageKeyHash>
+  std::unordered_map<ImageKey, scoped_refptr<TileTask>, ImageKeyHash>
       pending_image_tasks_;
 
   // The members below this comment can only be accessed if the lock is held to
diff --git a/cc/tiles/software_image_decode_controller_unittest.cc b/cc/tiles/software_image_decode_controller_unittest.cc
index 38246b3..cbf6e3c 100644
--- a/cc/tiles/software_image_decode_controller_unittest.cc
+++ b/cc/tiles/software_image_decode_controller_unittest.cc
@@ -359,7 +359,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -368,7 +368,7 @@
   DrawImage another_draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(
       another_draw_image, prepare_tiles_id, &another_task);
   EXPECT_TRUE(need_unref);
@@ -389,7 +389,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()),
       kHigh_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> high_quality_task;
+  scoped_refptr<TileTask> high_quality_task;
   bool need_unref = controller.GetTaskForImageAndRef(
       high_quality_draw_image, prepare_tiles_id, &high_quality_task);
   EXPECT_TRUE(need_unref);
@@ -399,7 +399,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()),
       kMedium_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> medium_quality_task;
+  scoped_refptr<TileTask> medium_quality_task;
   need_unref = controller.GetTaskForImageAndRef(
       medium_quality_draw_image, prepare_tiles_id, &medium_quality_task);
   // Medium quality isn't handled by the controller, so it won't ref it. Note
@@ -413,7 +413,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()),
       kLow_SkFilterQuality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> low_quality_task;
+  scoped_refptr<TileTask> low_quality_task;
   need_unref = controller.GetTaskForImageAndRef(
       low_quality_draw_image, prepare_tiles_id, &low_quality_task);
   EXPECT_TRUE(need_unref);
@@ -435,7 +435,7 @@
   DrawImage half_size_draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> half_size_task;
+  scoped_refptr<TileTask> half_size_task;
   bool need_unref = controller.GetTaskForImageAndRef(
       half_size_draw_image, prepare_tiles_id, &half_size_task);
   EXPECT_TRUE(need_unref);
@@ -444,7 +444,7 @@
   DrawImage quarter_size_draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> quarter_size_task;
+  scoped_refptr<TileTask> quarter_size_task;
   need_unref = controller.GetTaskForImageAndRef(
       quarter_size_draw_image, prepare_tiles_id, &quarter_size_task);
   EXPECT_TRUE(need_unref);
@@ -466,7 +466,7 @@
       first_image.get(),
       SkIRect::MakeWH(first_image->width(), first_image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> first_task;
+  scoped_refptr<TileTask> first_task;
   bool need_unref = controller.GetTaskForImageAndRef(
       first_draw_image, prepare_tiles_id, &first_task);
   EXPECT_TRUE(need_unref);
@@ -477,7 +477,7 @@
       second_image.get(),
       SkIRect::MakeWH(second_image->width(), second_image->height()), quality,
       CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> second_task;
+  scoped_refptr<TileTask> second_task;
   need_unref = controller.GetTaskForImageAndRef(second_draw_image,
                                                 prepare_tiles_id, &second_task);
   EXPECT_TRUE(need_unref);
@@ -498,7 +498,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -509,7 +509,7 @@
   task->DidSchedule();
   task->RunOnWorkerThread();
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &another_task);
   EXPECT_TRUE(need_unref);
@@ -533,7 +533,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -544,7 +544,7 @@
   task->DidSchedule();
   task->RunOnWorkerThread();
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &another_task);
   EXPECT_TRUE(need_unref);
@@ -554,7 +554,7 @@
   task->CompleteOnOriginThread(nullptr);
   task->DidComplete();
 
-  scoped_refptr<ImageDecodeTask> third_task;
+  scoped_refptr<TileTask> third_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &third_task);
   EXPECT_TRUE(need_unref);
@@ -575,7 +575,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -585,7 +585,7 @@
   task->ScheduleOnOriginThread(nullptr);
   task->DidSchedule();
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &another_task);
   EXPECT_TRUE(need_unref);
@@ -601,7 +601,7 @@
   controller.UnrefImage(draw_image);
 
   // Here a new task is created.
-  scoped_refptr<ImageDecodeTask> third_task;
+  scoped_refptr<TileTask> third_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &third_task);
   EXPECT_TRUE(need_unref);
@@ -622,7 +622,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -632,7 +632,7 @@
   task->ScheduleOnOriginThread(nullptr);
   task->DidSchedule();
 
-  scoped_refptr<ImageDecodeTask> another_task;
+  scoped_refptr<TileTask> another_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &another_task);
   EXPECT_TRUE(need_unref);
@@ -645,7 +645,7 @@
 
   // Note that here, everything is reffed, but a new task is created. This is
   // possible with repeated schedule/cancel operations.
-  scoped_refptr<ImageDecodeTask> third_task;
+  scoped_refptr<TileTask> third_task;
   need_unref = controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id,
                                                 &third_task);
   EXPECT_TRUE(need_unref);
@@ -668,7 +668,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -710,7 +710,7 @@
   DrawImage draw_image(
       image.get(), SkIRect::MakeXYWH(20, 30, image->width(), image->height()),
       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -819,7 +819,7 @@
   EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
   EXPECT_TRUE(decoded_draw_image.is_at_raster_decode());
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -873,7 +873,7 @@
   EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
   EXPECT_TRUE(decoded_draw_image.is_at_raster_decode());
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(need_unref);
@@ -916,7 +916,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_FALSE(task);
@@ -940,7 +940,7 @@
       image.get(), SkIRect::MakeXYWH(150, 150, image->width(), image->height()),
       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_FALSE(task);
@@ -964,7 +964,7 @@
       image.get(), SkIRect::MakeWH(image->width(), image->height()), quality,
       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(task);
@@ -991,7 +991,7 @@
   DrawImage draw_image(image.get(), SkIRect::MakeXYWH(10, 10, 80, 80), quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(task);
@@ -1020,7 +1020,7 @@
   DrawImage draw_image(image.get(), SkIRect::MakeXYWH(10, 10, 80, 80), quality,
                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable));
 
-  scoped_refptr<ImageDecodeTask> task;
+  scoped_refptr<TileTask> task;
   bool need_unref =
       controller.GetTaskForImageAndRef(draw_image, prepare_tiles_id, &task);
   EXPECT_TRUE(task);
diff --git a/cc/tiles/tile.h b/cc/tiles/tile.h
index f6dd675..9dc8afc 100644
--- a/cc/tiles/tile.h
+++ b/cc/tiles/tile.h
@@ -144,7 +144,7 @@
 
   unsigned scheduled_priority_;
 
-  scoped_refptr<RasterTask> raster_task_;
+  scoped_refptr<TileTask> raster_task_;
 
   DISALLOW_COPY_AND_ASSIGN(Tile);
 };
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index cec859ff..74f1707e 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -42,7 +42,7 @@
     "Compositing.%s.RasterTask.RasterUs",
     "Compositing.%s.RasterTask.RasterPixelsPerMs");
 
-class RasterTaskImpl : public RasterTask {
+class RasterTaskImpl : public TileTask {
  public:
   RasterTaskImpl(const Resource* resource,
                  scoped_refptr<RasterSource> raster_source,
@@ -59,8 +59,8 @@
                  uint64_t resource_content_id,
                  int source_frame_number,
                  const base::Callback<void(bool)>& reply,
-                 ImageDecodeTask::Vector* dependencies)
-      : RasterTask(dependencies),
+                 TileTask::Vector* dependencies)
+      : TileTask(true, dependencies),
         resource_(resource),
         raster_source_(std::move(raster_source)),
         content_rect_(content_rect),
@@ -156,15 +156,18 @@
 }
 
 void InsertNodeForDecodeTask(TaskGraph* graph,
-                             ImageDecodeTask* task,
+                             TileTask* task,
                              uint16_t category,
                              uint16_t priority) {
   uint32_t dependency_count = 0u;
-  auto* dependency = task->dependency().get();
-  if (dependency && !dependency->HasCompleted()) {
-    InsertNodeForDecodeTask(graph, dependency, category, priority);
-    graph->edges.push_back(TaskGraph::Edge(dependency, task));
-    dependency_count = 1u;
+  if (task->dependencies().size()) {
+    DCHECK_EQ(task->dependencies().size(), 1u);
+    auto* dependency = task->dependencies()[0].get();
+    if (!dependency->HasCompleted()) {
+      InsertNodeForDecodeTask(graph, dependency, category, priority);
+      graph->edges.push_back(TaskGraph::Edge(dependency, task));
+      dependency_count = 1u;
+    }
   }
   InsertNodeForTask(graph, task, task->SupportsConcurrentExecution()
                                      ? category
@@ -173,8 +176,8 @@
 }
 
 void InsertNodesForRasterTask(TaskGraph* graph,
-                              RasterTask* raster_task,
-                              const ImageDecodeTask::Vector& decode_tasks,
+                              TileTask* raster_task,
+                              const TileTask::Vector& decode_tasks,
                               size_t priority,
                               bool use_gpu_rasterization,
                               bool high_priority) {
@@ -198,9 +201,9 @@
       high_priority ? TASK_CATEGORY_FOREGROUND : TASK_CATEGORY_BACKGROUND;
 
   // Insert image decode tasks.
-  for (ImageDecodeTask::Vector::const_iterator it = decode_tasks.begin();
+  for (TileTask::Vector::const_iterator it = decode_tasks.begin();
        it != decode_tasks.end(); ++it) {
-    ImageDecodeTask* decode_task = it->get();
+    TileTask* decode_task = it->get();
 
     // Skip if already decoded.
     if (decode_task->HasCompleted())
@@ -242,7 +245,8 @@
   explicit TaskSetFinishedTaskImpl(
       base::SequencedTaskRunner* task_runner,
       const base::Closure& on_task_set_finished_callback)
-      : task_runner_(task_runner),
+      : TileTask(true),
+        task_runner_(task_runner),
         on_task_set_finished_callback_(on_task_set_finished_callback) {}
 
   // Overridden from Task:
@@ -779,7 +783,7 @@
     if (!tile->raster_task_)
       tile->raster_task_ = CreateRasterTask(prioritized_tile);
 
-    RasterTask* task = tile->raster_task_.get();
+    TileTask* task = tile->raster_task_.get();
     DCHECK(!task->HasCompleted());
 
     if (tile->required_for_activation()) {
@@ -845,7 +849,7 @@
                                ScheduledTasksStateAsValue());
 }
 
-scoped_refptr<RasterTask> TileManager::CreateRasterTask(
+scoped_refptr<TileTask> TileManager::CreateRasterTask(
     const PrioritizedTile& prioritized_tile) {
   Tile* tile = prioritized_tile.tile();
 
@@ -872,7 +876,7 @@
       prioritized_tile.priority().resolution == LOW_RESOLUTION;
 
   // Create and queue all image decode tasks that this tile depends on.
-  ImageDecodeTask::Vector decode_tasks;
+  TileTask::Vector decode_tasks;
   std::vector<DrawImage>& images = scheduled_draw_images_[tile->id()];
   images.clear();
   if (!playback_settings.skip_images) {
@@ -883,7 +887,7 @@
   // We can skip the image hijack canvas if we have no images.
   playback_settings.use_image_hijack_canvas = !images.empty();
   for (auto it = images.begin(); it != images.end();) {
-    scoped_refptr<ImageDecodeTask> task;
+    scoped_refptr<TileTask> task;
     bool need_to_unref_when_finished =
         image_decode_controller_->GetTaskForImageAndRef(
             *it, prepare_tiles_count_, &task);
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h
index 94eac03..d58d5b0 100644
--- a/cc/tiles/tile_manager.h
+++ b/cc/tiles/tile_manager.h
@@ -249,7 +249,7 @@
 
   void FreeResourcesForTile(Tile* tile);
   void FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(Tile* tile);
-  scoped_refptr<RasterTask> CreateRasterTask(
+  scoped_refptr<TileTask> CreateRasterTask(
       const PrioritizedTile& prioritized_tile);
 
   std::unique_ptr<EvictionTilePriorityQueue>
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 9feb348..ba9b674e 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -74,6 +74,7 @@
 class SwapPromise;
 class SwapPromiseMonitor;
 class SynchronousTaskGraphRunner;
+class TaskGraphRunner;
 class TextureMailboxDeleter;
 class TopControlsManager;
 class UIResourceBitmap;