cc: Move LayerEvictionTileIterator to a separate file and make it a queue

In line with LayerRasterTileIterator patch, this patch removes
PictureLayerImpl::LayerEvictionTileIterator, moves it to a separate
file, renames it to TilingSetEvictionQueue, makes its functionality be
more queue-like instead of iterator-like and merges
PictureLayerTiling::TilingEvictionTileIterator into it (as those two
iterators were so tightly coupled).

Also, this patch adds a PLI::CreateEvictionQueue to get a eviction queue
for the layer.

This hides a bit more details of PLTS from PLI and avoid duplicating
eviction category handling in multiple different iterator classes.

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

Cr-Commit-Position: refs/heads/master@{#305972}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 366f576..af0aa30 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -424,6 +424,8 @@
     "resources/tile_manager.h",
     "resources/tile_priority.cc",
     "resources/tile_priority.h",
+    "resources/tiling_set_eviction_queue.cc",
+    "resources/tiling_set_eviction_queue.h",
     "resources/transferable_resource.cc",
     "resources/transferable_resource.h",
     "resources/ui_resource_bitmap.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 046d43ca..26a50bf5 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -453,6 +453,8 @@
         'resources/tile_manager.h',
         'resources/tile_priority.cc',
         'resources/tile_priority.h',
+        'resources/tiling_set_eviction_queue.cc',
+        'resources/tiling_set_eviction_queue.h',
         'resources/transferable_resource.cc',
         'resources/transferable_resource.h',
         'resources/ui_resource_bitmap.cc',
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 0eb96214..1827bea 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -98,6 +98,14 @@
   layer_tree_impl()->UnregisterPictureLayerImpl(this);
 }
 
+scoped_ptr<TilingSetEvictionQueue> PictureLayerImpl::CreateEvictionQueue(
+    TreePriority tree_priority) {
+  if (!tilings_)
+    return make_scoped_ptr(new TilingSetEvictionQueue());
+  return make_scoped_ptr(
+      new TilingSetEvictionQueue(tilings_.get(), tree_priority));
+}
+
 const char* PictureLayerImpl::LayerTypeAsString() const {
   return "cc::PictureLayerImpl";
 }
@@ -1475,158 +1483,4 @@
   }
 }
 
-PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
-    : layer_(nullptr),
-      tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES),
-      current_category_(PictureLayerTiling::EVENTUALLY),
-      current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
-      current_tiling_(0u) {
-}
-
-PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
-    PictureLayerImpl* layer,
-    TreePriority tree_priority)
-    : layer_(layer),
-      tree_priority_(tree_priority),
-      current_category_(PictureLayerTiling::EVENTUALLY),
-      current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
-      current_tiling_(0u) {
-  // Early out if the layer has no tilings.
-  if (!layer_->tilings_ || !layer_->tilings_->num_tilings())
-    return;
-
-  current_tiling_ = CurrentTilingRange().start - 1u;
-  do {
-    if (!AdvanceToNextTiling())
-      break;
-
-    current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator(
-        layer_->tilings_->tiling_at(CurrentTilingIndex()),
-        tree_priority,
-        current_category_);
-  } while (!current_iterator_);
-}
-
-PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {
-}
-
-Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
-  DCHECK(*this);
-  return *current_iterator_;
-}
-
-const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const {
-  DCHECK(*this);
-  return *current_iterator_;
-}
-
-PictureLayerImpl::LayerEvictionTileIterator&
-PictureLayerImpl::LayerEvictionTileIterator::
-operator++() {
-  DCHECK(*this);
-  ++current_iterator_;
-  while (!current_iterator_) {
-    if (!AdvanceToNextTiling())
-      break;
-
-    current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator(
-        layer_->tilings_->tiling_at(CurrentTilingIndex()),
-        tree_priority_,
-        current_category_);
-  }
-  return *this;
-}
-
-PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
-  return !!current_iterator_;
-}
-
-bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextCategory() {
-  switch (current_category_) {
-    case PictureLayerTiling::EVENTUALLY:
-      current_category_ =
-          PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION;
-      return true;
-    case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
-      current_category_ = PictureLayerTiling::SOON;
-      return true;
-    case PictureLayerTiling::SOON:
-      current_category_ = PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION;
-      return true;
-    case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION:
-      current_category_ = PictureLayerTiling::NOW;
-      return true;
-    case PictureLayerTiling::NOW:
-      current_category_ = PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION;
-      return true;
-    case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION:
-      return false;
-  }
-  NOTREACHED();
-  return false;
-}
-
-bool
-PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTilingRangeType() {
-  switch (current_tiling_range_type_) {
-    case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
-      current_tiling_range_type_ = PictureLayerTilingSet::LOWER_THAN_LOW_RES;
-      return true;
-    case PictureLayerTilingSet::LOWER_THAN_LOW_RES:
-      current_tiling_range_type_ =
-          PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES;
-      return true;
-    case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
-      current_tiling_range_type_ = PictureLayerTilingSet::LOW_RES;
-      return true;
-    case PictureLayerTilingSet::LOW_RES:
-      current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES;
-      return true;
-    case PictureLayerTilingSet::HIGH_RES:
-      if (!AdvanceToNextCategory())
-        return false;
-
-      current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES;
-      return true;
-  }
-  NOTREACHED();
-  return false;
-}
-
-bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTiling() {
-  DCHECK_NE(current_tiling_, CurrentTilingRange().end);
-  ++current_tiling_;
-  while (current_tiling_ == CurrentTilingRange().end) {
-    if (!AdvanceToNextTilingRangeType())
-      return false;
-
-    current_tiling_ = CurrentTilingRange().start;
-  }
-  return true;
-}
-
-PictureLayerTilingSet::TilingRange
-PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingRange() const {
-  return layer_->tilings_->GetTilingRange(current_tiling_range_type_);
-}
-
-size_t PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndex() const {
-  DCHECK_NE(current_tiling_, CurrentTilingRange().end);
-  switch (current_tiling_range_type_) {
-    case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
-    case PictureLayerTilingSet::LOW_RES:
-    case PictureLayerTilingSet::HIGH_RES:
-      return current_tiling_;
-    // Tilings in the following ranges are accessed in reverse order.
-    case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
-    case PictureLayerTilingSet::LOWER_THAN_LOW_RES: {
-      PictureLayerTilingSet::TilingRange tiling_range = CurrentTilingRange();
-      size_t current_tiling_range_offset = current_tiling_ - tiling_range.start;
-      return tiling_range.end - 1 - current_tiling_range_offset;
-    }
-  }
-  NOTREACHED();
-  return 0;
-}
-
 }  // namespace cc
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 9a775463..d8ab036 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -15,6 +15,7 @@
 #include "cc/resources/picture_layer_tiling.h"
 #include "cc/resources/picture_layer_tiling_set.h"
 #include "cc/resources/picture_pile_impl.h"
+#include "cc/resources/tiling_set_eviction_queue.h"
 #include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkPicture.h"
 
@@ -67,40 +68,14 @@
     PictureLayerTiling::TilingRasterTileIterator iterators_[NUM_ITERATORS];
   };
 
-  class CC_EXPORT LayerEvictionTileIterator {
-   public:
-    LayerEvictionTileIterator();
-    LayerEvictionTileIterator(PictureLayerImpl* layer,
-                              TreePriority tree_priority);
-    ~LayerEvictionTileIterator();
-
-    Tile* operator*();
-    const Tile* operator*() const;
-    LayerEvictionTileIterator& operator++();
-    operator bool() const;
-
-   private:
-    bool AdvanceToNextCategory();
-    bool AdvanceToNextTilingRangeType();
-    bool AdvanceToNextTiling();
-
-    PictureLayerTilingSet::TilingRange CurrentTilingRange() const;
-    size_t CurrentTilingIndex() const;
-
-    PictureLayerImpl* layer_;
-    TreePriority tree_priority_;
-
-    PictureLayerTiling::EvictionCategory current_category_;
-    PictureLayerTilingSet::TilingRangeType current_tiling_range_type_;
-    size_t current_tiling_;
-    PictureLayerTiling::TilingEvictionTileIterator current_iterator_;
-  };
-
   static scoped_ptr<PictureLayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
     return make_scoped_ptr(new PictureLayerImpl(tree_impl, id));
   }
   ~PictureLayerImpl() override;
 
+  scoped_ptr<TilingSetEvictionQueue> CreateEvictionQueue(
+      TreePriority tree_priority);
+
   // LayerImpl overrides.
   const char* LayerTypeAsString() const override;
   scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc
index 1f98a68..bfb5703 100644
--- a/cc/layers/picture_layer_impl_perftest.cc
+++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -115,7 +115,7 @@
                            true);
   }
 
-  void RunEvictionIteratorConstructAndIterateTest(
+  void RunEvictionQueueConstructAndIterateTest(
       const std::string& test_name,
       int num_tiles,
       const gfx::Size& viewport_size) {
@@ -129,12 +129,12 @@
     timer_.Reset();
     do {
       int count = num_tiles;
-      PictureLayerImpl::LayerEvictionTileIterator it(
-          pending_layer_, priorities[priority_count]);
+      scoped_ptr<TilingSetEvictionQueue> queue =
+          pending_layer_->CreateEvictionQueue(priorities[priority_count]);
       while (count--) {
-        ASSERT_TRUE(it) << "count: " << count;
-        ASSERT_TRUE(*it != nullptr) << "count: " << count;
-        ++it;
+        ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count;
+        ASSERT_TRUE(queue->Top() != nullptr) << "count: " << count;
+        queue->Pop();
       }
       priority_count = (priority_count + 1) % arraysize(priorities);
       timer_.NextLap();
@@ -148,8 +148,8 @@
                            true);
   }
 
-  void RunEvictionIteratorConstructTest(const std::string& test_name,
-                                        const gfx::Rect& viewport) {
+  void RunEvictionQueueConstructTest(const std::string& test_name,
+                                     const gfx::Rect& viewport) {
     host_impl_.SetViewportSize(viewport.size());
     pending_layer_->SetScrollOffset(
         gfx::ScrollOffset(viewport.x(), viewport.y()));
@@ -161,8 +161,8 @@
     int priority_count = 0;
     timer_.Reset();
     do {
-      PictureLayerImpl::LayerEvictionTileIterator it(
-          pending_layer_, priorities[priority_count]);
+      scoped_ptr<TilingSetEvictionQueue> queue =
+          pending_layer_->CreateEvictionQueue(priorities[priority_count]);
       priority_count = (priority_count + 1) % arraysize(priorities);
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
@@ -225,6 +225,7 @@
                                  gfx::Rect(9999, 0, 100, 100));
 }
 
+// TODO(e_hakkinen): Rename these tests once the perf numbers are in.
 TEST_F(PictureLayerImplPerfTest, LayerEvictionTileIteratorConstructAndIterate) {
   SetupPendingTree(gfx::Size(10000, 10000), gfx::Size(256, 256));
 
@@ -240,16 +241,17 @@
   ASSERT_TRUE(host_impl_.tile_manager() != nullptr);
   host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
 
-  RunEvictionIteratorConstructAndIterateTest(
+  RunEvictionQueueConstructAndIterateTest(
       "32_100x100", 32, gfx::Size(100, 100));
-  RunEvictionIteratorConstructAndIterateTest(
+  RunEvictionQueueConstructAndIterateTest(
       "32_500x500", 32, gfx::Size(500, 500));
-  RunEvictionIteratorConstructAndIterateTest(
+  RunEvictionQueueConstructAndIterateTest(
       "64_100x100", 64, gfx::Size(100, 100));
-  RunEvictionIteratorConstructAndIterateTest(
+  RunEvictionQueueConstructAndIterateTest(
       "64_500x500", 64, gfx::Size(500, 500));
 }
 
+// TODO(e_hakkinen): Rename these tests once the perf numbers are in.
 TEST_F(PictureLayerImplPerfTest, LayerEvictionTileIteratorConstruct) {
   SetupPendingTree(gfx::Size(10000, 10000), gfx::Size(256, 256));
 
@@ -265,11 +267,9 @@
   ASSERT_TRUE(host_impl_.tile_manager() != nullptr);
   host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
 
-  RunEvictionIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
-  RunEvictionIteratorConstructTest("5000_0_100x100",
-                                   gfx::Rect(5000, 0, 100, 100));
-  RunEvictionIteratorConstructTest("9999_0_100x100",
-                                   gfx::Rect(9999, 0, 100, 100));
+  RunEvictionQueueConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
+  RunEvictionQueueConstructTest("5000_0_100x100", gfx::Rect(5000, 0, 100, 100));
+  RunEvictionQueueConstructTest("9999_0_100x100", gfx::Rect(9999, 0, 100, 100));
 }
 
 }  // namespace
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 246e6258..d18e97a 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -2903,7 +2903,7 @@
   EXPECT_EQ(0u, high_res_tile_count);
 }
 
-TEST_F(PictureLayerImplTest, LayerEvictionTileIterator) {
+TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) {
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(1000, 1000);
 
@@ -2964,14 +2964,10 @@
   EXPECT_GT(number_of_marked_tiles, 1u);
   EXPECT_GT(number_of_unmarked_tiles, 1u);
 
-  // Empty iterator.
-  PictureLayerImpl::LayerEvictionTileIterator it;
-  EXPECT_FALSE(it);
-
   // Tiles don't have resources yet.
-  it = PictureLayerImpl::LayerEvictionTileIterator(
-      pending_layer_, SAME_PRIORITY_FOR_BOTH_TREES);
-  EXPECT_FALSE(it);
+  scoped_ptr<TilingSetEvictionQueue> queue =
+      pending_layer_->CreateEvictionQueue(SAME_PRIORITY_FOR_BOTH_TREES);
+  EXPECT_TRUE(queue->IsEmpty());
 
   host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
 
@@ -2980,11 +2976,9 @@
   size_t scale_index = 0;
   bool reached_visible = false;
   Tile* last_tile = nullptr;
-  for (it = PictureLayerImpl::LayerEvictionTileIterator(
-           pending_layer_, SAME_PRIORITY_FOR_BOTH_TREES);
-       it;
-       ++it) {
-    Tile* tile = *it;
+  queue = pending_layer_->CreateEvictionQueue(SAME_PRIORITY_FOR_BOTH_TREES);
+  while (!queue->IsEmpty()) {
+    Tile* tile = queue->Top();
     if (!last_tile)
       last_tile = tile;
 
@@ -3022,6 +3016,7 @@
     }
 
     last_tile = tile;
+    queue->Pop();
   }
 
   EXPECT_TRUE(reached_visible);
@@ -3029,8 +3024,8 @@
 
   scale_index = 0;
   bool reached_required = false;
-  for (; it; ++it) {
-    Tile* tile = *it;
+  while (!queue->IsEmpty()) {
+    Tile* tile = queue->Top();
     EXPECT_TRUE(tile);
 
     TilePriority priority = tile->priority(PENDING_TREE);
@@ -3051,6 +3046,7 @@
 
     EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]);
     unique_tiles.insert(tile);
+    queue->Pop();
   }
 
   EXPECT_TRUE(reached_required);
@@ -3841,12 +3837,10 @@
       size_t occluded_tile_count = 0u;
       Tile* last_tile = nullptr;
 
-      for (PictureLayerImpl::LayerEvictionTileIterator it =
-               PictureLayerImpl::LayerEvictionTileIterator(layer,
-                                                           tree_priority);
-           it;
-           ++it) {
-        Tile* tile = *it;
+      scoped_ptr<TilingSetEvictionQueue> queue =
+          layer->CreateEvictionQueue(tree_priority);
+      while (!queue->IsEmpty()) {
+        Tile* tile = queue->Top();
         if (!last_tile)
           last_tile = tile;
 
@@ -3874,6 +3868,7 @@
           }
         }
         last_tile = tile;
+        queue->Pop();
       }
       EXPECT_EQ(expected_occluded_tile_count[priority_count],
                 occluded_tile_count);
diff --git a/cc/resources/eviction_tile_priority_queue.cc b/cc/resources/eviction_tile_priority_queue.cc
index 9f05e81..4d66987 100644
--- a/cc/resources/eviction_tile_priority_queue.cc
+++ b/cc/resources/eviction_tile_priority_queue.cc
@@ -14,8 +14,8 @@
       : tree_priority_(tree_priority) {}
 
   bool operator()(
-      const EvictionTilePriorityQueue::PairedPictureLayerQueue* a,
-      const EvictionTilePriorityQueue::PairedPictureLayerQueue* b) const {
+      const EvictionTilePriorityQueue::PairedTilingSetQueue* a,
+      const EvictionTilePriorityQueue::PairedTilingSetQueue* b) const {
     // Note that in this function, we have to return true if and only if
     // b is strictly lower priority than a. Note that for the sake of
     // completeness, empty queue is considered to have lowest priority.
@@ -23,15 +23,15 @@
       return b->IsEmpty() < a->IsEmpty();
 
     WhichTree a_tree = a->NextTileIteratorTree(tree_priority_);
-    const PictureLayerImpl::LayerEvictionTileIterator* a_iterator =
-        a_tree == ACTIVE_TREE ? &a->active_iterator : &a->pending_iterator;
+    const TilingSetEvictionQueue* a_queue =
+        a_tree == ACTIVE_TREE ? a->active_queue.get() : a->pending_queue.get();
 
     WhichTree b_tree = b->NextTileIteratorTree(tree_priority_);
-    const PictureLayerImpl::LayerEvictionTileIterator* b_iterator =
-        b_tree == ACTIVE_TREE ? &b->active_iterator : &b->pending_iterator;
+    const TilingSetEvictionQueue* b_queue =
+        b_tree == ACTIVE_TREE ? b->active_queue.get() : b->pending_queue.get();
 
-    const Tile* a_tile = **a_iterator;
-    const Tile* b_tile = **b_iterator;
+    const Tile* a_tile = a_queue->Top();
+    const Tile* b_tile = b_queue->Top();
 
     const TilePriority& a_priority =
         a_tile->priority_for_tree_priority(tree_priority_);
@@ -94,7 +94,7 @@
        it != paired_layers.end();
        ++it) {
     paired_queues_.push_back(
-        make_scoped_ptr(new PairedPictureLayerQueue(*it, tree_priority_)));
+        make_scoped_ptr(new PairedTilingSetQueue(*it, tree_priority_)));
   }
 
   paired_queues_.make_heap(EvictionOrderComparator(tree_priority_));
@@ -117,94 +117,89 @@
   DCHECK(!IsEmpty());
 
   paired_queues_.pop_heap(EvictionOrderComparator(tree_priority_));
-  PairedPictureLayerQueue* paired_queue = paired_queues_.back();
+  PairedTilingSetQueue* paired_queue = paired_queues_.back();
   paired_queue->Pop(tree_priority_);
   paired_queues_.push_heap(EvictionOrderComparator(tree_priority_));
 }
 
-EvictionTilePriorityQueue::PairedPictureLayerQueue::PairedPictureLayerQueue() {
+EvictionTilePriorityQueue::PairedTilingSetQueue::PairedTilingSetQueue() {
 }
 
-EvictionTilePriorityQueue::PairedPictureLayerQueue::PairedPictureLayerQueue(
+EvictionTilePriorityQueue::PairedTilingSetQueue::PairedTilingSetQueue(
     const PictureLayerImpl::Pair& layer_pair,
-    TreePriority tree_priority)
-    : active_iterator(
-          layer_pair.active
-              ? PictureLayerImpl::LayerEvictionTileIterator(layer_pair.active,
-                                                            tree_priority)
-              : PictureLayerImpl::LayerEvictionTileIterator()),
-      pending_iterator(
-          layer_pair.pending
-              ? PictureLayerImpl::LayerEvictionTileIterator(layer_pair.pending,
-                                                            tree_priority)
-              : PictureLayerImpl::LayerEvictionTileIterator()) {
+    TreePriority tree_priority) {
+  if (layer_pair.active)
+    active_queue = layer_pair.active->CreateEvictionQueue(tree_priority);
+  if (layer_pair.pending)
+    pending_queue = layer_pair.pending->CreateEvictionQueue(tree_priority);
 }
 
-EvictionTilePriorityQueue::PairedPictureLayerQueue::~PairedPictureLayerQueue() {
+EvictionTilePriorityQueue::PairedTilingSetQueue::~PairedTilingSetQueue() {
 }
 
-bool EvictionTilePriorityQueue::PairedPictureLayerQueue::IsEmpty() const {
-  return !active_iterator && !pending_iterator;
+bool EvictionTilePriorityQueue::PairedTilingSetQueue::IsEmpty() const {
+  return (!active_queue || active_queue->IsEmpty()) &&
+         (!pending_queue || pending_queue->IsEmpty());
 }
 
-Tile* EvictionTilePriorityQueue::PairedPictureLayerQueue::Top(
+Tile* EvictionTilePriorityQueue::PairedTilingSetQueue::Top(
     TreePriority tree_priority) {
   DCHECK(!IsEmpty());
 
   WhichTree next_tree = NextTileIteratorTree(tree_priority);
-  PictureLayerImpl::LayerEvictionTileIterator* next_iterator =
-      next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
-  DCHECK(*next_iterator);
+  TilingSetEvictionQueue* next_queue =
+      next_tree == ACTIVE_TREE ? active_queue.get() : pending_queue.get();
+  DCHECK(next_queue && !next_queue->IsEmpty());
 
-  Tile* tile = **next_iterator;
+  Tile* tile = next_queue->Top();
   DCHECK(std::find(returned_shared_tiles.begin(),
                    returned_shared_tiles.end(),
                    tile) == returned_shared_tiles.end());
   return tile;
 }
 
-void EvictionTilePriorityQueue::PairedPictureLayerQueue::Pop(
+void EvictionTilePriorityQueue::PairedTilingSetQueue::Pop(
     TreePriority tree_priority) {
   DCHECK(!IsEmpty());
 
   WhichTree next_tree = NextTileIteratorTree(tree_priority);
-  PictureLayerImpl::LayerEvictionTileIterator* next_iterator =
-      next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
-  DCHECK(*next_iterator);
-  returned_shared_tiles.push_back(**next_iterator);
-  ++(*next_iterator);
+  TilingSetEvictionQueue* next_queue =
+      next_tree == ACTIVE_TREE ? active_queue.get() : pending_queue.get();
+  DCHECK(next_queue && !next_queue->IsEmpty());
+  returned_shared_tiles.push_back(next_queue->Top());
+  next_queue->Pop();
 
   if (IsEmpty())
     return;
 
   next_tree = NextTileIteratorTree(tree_priority);
-  next_iterator =
-      next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+  next_queue =
+      next_tree == ACTIVE_TREE ? active_queue.get() : pending_queue.get();
   while (std::find(returned_shared_tiles.begin(),
                    returned_shared_tiles.end(),
-                   **next_iterator) != returned_shared_tiles.end()) {
-    ++(*next_iterator);
+                   next_queue->Top()) != returned_shared_tiles.end()) {
+    next_queue->Pop();
     if (IsEmpty())
       break;
     next_tree = NextTileIteratorTree(tree_priority);
-    next_iterator =
-        next_tree == ACTIVE_TREE ? &active_iterator : &pending_iterator;
+    next_queue =
+        next_tree == ACTIVE_TREE ? active_queue.get() : pending_queue.get();
   }
 }
 
 WhichTree
-EvictionTilePriorityQueue::PairedPictureLayerQueue::NextTileIteratorTree(
+EvictionTilePriorityQueue::PairedTilingSetQueue::NextTileIteratorTree(
     TreePriority tree_priority) const {
   DCHECK(!IsEmpty());
 
   // If we only have one iterator with tiles, return it.
-  if (!active_iterator)
+  if (!active_queue || active_queue->IsEmpty())
     return PENDING_TREE;
-  if (!pending_iterator)
+  if (!pending_queue || pending_queue->IsEmpty())
     return ACTIVE_TREE;
 
-  const Tile* active_tile = *active_iterator;
-  const Tile* pending_tile = *pending_iterator;
+  const Tile* active_tile = active_queue->Top();
+  const Tile* pending_tile = pending_queue->Top();
   if (active_tile == pending_tile)
     return ACTIVE_TREE;
 
diff --git a/cc/resources/eviction_tile_priority_queue.h b/cc/resources/eviction_tile_priority_queue.h
index e91f0d2..6f5d9645 100644
--- a/cc/resources/eviction_tile_priority_queue.h
+++ b/cc/resources/eviction_tile_priority_queue.h
@@ -11,16 +11,17 @@
 #include "cc/base/cc_export.h"
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/resources/tile_priority.h"
+#include "cc/resources/tiling_set_eviction_queue.h"
 
 namespace cc {
 
 class CC_EXPORT EvictionTilePriorityQueue {
  public:
-  struct PairedPictureLayerQueue {
-    PairedPictureLayerQueue();
-    PairedPictureLayerQueue(const PictureLayerImpl::Pair& layer_pair,
-                            TreePriority tree_priority);
-    ~PairedPictureLayerQueue();
+  struct PairedTilingSetQueue {
+    PairedTilingSetQueue();
+    PairedTilingSetQueue(const PictureLayerImpl::Pair& layer_pair,
+                         TreePriority tree_priority);
+    ~PairedTilingSetQueue();
 
     bool IsEmpty() const;
     Tile* Top(TreePriority tree_priority);
@@ -28,8 +29,8 @@
 
     WhichTree NextTileIteratorTree(TreePriority tree_priority) const;
 
-    PictureLayerImpl::LayerEvictionTileIterator active_iterator;
-    PictureLayerImpl::LayerEvictionTileIterator pending_iterator;
+    scoped_ptr<TilingSetEvictionQueue> active_queue;
+    scoped_ptr<TilingSetEvictionQueue> pending_queue;
 
     // TODO(vmpstr): Investigate removing this.
     std::vector<Tile*> returned_shared_tiles;
@@ -48,9 +49,9 @@
 
  private:
   // TODO(vmpstr): This is potentially unnecessary if it becomes the case that
-  // PairedPictureLayerQueue is fast enough to copy. In that case, we can use
-  // objects directly (ie std::vector<PairedPictureLayerQueue>).
-  ScopedPtrVector<PairedPictureLayerQueue> paired_queues_;
+  // PairedTilingSetQueue is fast enough to copy. In that case, we can use
+  // objects directly (ie std::vector<PairedTilingSetQueue>).
+  ScopedPtrVector<PairedTilingSetQueue> paired_queues_;
   TreePriority tree_priority_;
 
   DISALLOW_COPY_AND_ASSIGN(EvictionTilePriorityQueue);
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index 9d8ea84..e9e3b86 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -1216,50 +1216,4 @@
   return *this;
 }
 
-PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator()
-    : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) {
-}
-
-PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator(
-    PictureLayerTiling* tiling,
-    TreePriority tree_priority,
-    EvictionCategory category)
-    : eviction_tiles_(tiling->GetEvictionTiles(tree_priority, category)),
-      // Note: initializing to "0 - 1" works as overflow is well defined for
-      // unsigned integers.
-      current_eviction_tiles_index_(static_cast<size_t>(0) - 1) {
-  DCHECK(eviction_tiles_);
-  ++(*this);
-}
-
-PictureLayerTiling::TilingEvictionTileIterator::~TilingEvictionTileIterator() {
-}
-
-PictureLayerTiling::TilingEvictionTileIterator::operator bool() const {
-  return eviction_tiles_ &&
-         current_eviction_tiles_index_ != eviction_tiles_->size();
-}
-
-Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() {
-  DCHECK(*this);
-  return (*eviction_tiles_)[current_eviction_tiles_index_];
-}
-
-const Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() const {
-  DCHECK(*this);
-  return (*eviction_tiles_)[current_eviction_tiles_index_];
-}
-
-PictureLayerTiling::TilingEvictionTileIterator&
-PictureLayerTiling::TilingEvictionTileIterator::
-operator++() {
-  DCHECK(*this);
-  do {
-    ++current_eviction_tiles_index_;
-  } while (current_eviction_tiles_index_ != eviction_tiles_->size() &&
-           !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources());
-
-  return *this;
-}
-
 }  // namespace cc
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index e1ccde4..daa04851 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -118,24 +118,6 @@
     TilingData::SpiralDifferenceIterator spiral_iterator_;
   };
 
-  class CC_EXPORT TilingEvictionTileIterator {
-   public:
-    TilingEvictionTileIterator();
-    TilingEvictionTileIterator(PictureLayerTiling* tiling,
-                               TreePriority tree_priority,
-                               EvictionCategory category);
-    ~TilingEvictionTileIterator();
-
-    operator bool() const;
-    const Tile* operator*() const;
-    Tile* operator*();
-    TilingEvictionTileIterator& operator++();
-
-   private:
-    const std::vector<Tile*>* eviction_tiles_;
-    size_t current_eviction_tiles_index_;
-  };
-
   ~PictureLayerTiling();
 
   // Create a tiling with no tiles.  CreateTiles must be called to add some.
@@ -299,7 +281,7 @@
  protected:
   friend class CoverageIterator;
   friend class TilingRasterTileIterator;
-  friend class TilingEvictionTileIterator;
+  friend class TilingSetEvictionQueue;
 
   typedef std::pair<int, int> TileMapKey;
   typedef base::hash_map<TileMapKey, scoped_refptr<Tile>> TileMap;
diff --git a/cc/resources/picture_layer_tiling_perftest.cc b/cc/resources/picture_layer_tiling_perftest.cc
index 55d495be..3944e46 100644
--- a/cc/resources/picture_layer_tiling_perftest.cc
+++ b/cc/resources/picture_layer_tiling_perftest.cc
@@ -178,98 +178,6 @@
                            true);
   }
 
-  void RunEvictionIteratorConstructTest(const std::string& test_name,
-                                        const gfx::Rect& viewport) {
-    gfx::Size bounds(viewport.size());
-    picture_layer_tiling_ =
-        PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
-    picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
-    picture_layer_tiling_->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
-                                                    Occlusion());
-
-    timer_.Reset();
-    TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
-                                 SMOOTHNESS_TAKES_PRIORITY,
-                                 NEW_CONTENT_TAKES_PRIORITY};
-    int priority_count = 0;
-    do {
-      PictureLayerTiling::TilingEvictionTileIterator it(
-          picture_layer_tiling_.get(),
-          priorities[priority_count],
-          PictureLayerTiling::NOW);
-      priority_count = (priority_count + 1) % arraysize(priorities);
-      timer_.NextLap();
-    } while (!timer_.HasTimeLimitExpired());
-
-    perf_test::PrintResult("tiling_eviction_tile_iterator_construct",
-                           "",
-                           test_name,
-                           timer_.LapsPerSecond(),
-                           "runs/s",
-                           true);
-  }
-
-  void RunEvictionIteratorConstructAndIterateTest(const std::string& test_name,
-                                                  int num_tiles,
-                                                  const gfx::Rect& viewport) {
-    gfx::Size bounds(10000, 10000);
-    picture_layer_tiling_ =
-        PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
-    picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
-    picture_layer_tiling_->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
-                                                    Occlusion());
-
-    TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
-                                 SMOOTHNESS_TAKES_PRIORITY,
-                                 NEW_CONTENT_TAKES_PRIORITY};
-
-    // Ensure all tiles have resources.
-    std::vector<Tile*> all_tiles = picture_layer_tiling_->AllTilesForTesting();
-    for (std::vector<Tile*>::iterator tile_it = all_tiles.begin();
-         tile_it != all_tiles.end();
-         ++tile_it) {
-      Tile* tile = *tile_it;
-      ManagedTileState::DrawInfo& draw_info = tile->draw_info();
-      draw_info.SetResourceForTesting(
-          ScopedResource::Create(resource_provider_.get()).Pass());
-    }
-
-    int priority_count = 0;
-    timer_.Reset();
-    do {
-      int count = num_tiles;
-      PictureLayerTiling::TilingEvictionTileIterator it(
-          picture_layer_tiling_.get(),
-          priorities[priority_count],
-          PictureLayerTiling::EVENTUALLY);
-      while (count--) {
-        ASSERT_TRUE(it) << "count: " << count;
-        ASSERT_TRUE(*it != NULL) << "count: " << count;
-        ++it;
-      }
-      priority_count = (priority_count + 1) % arraysize(priorities);
-      timer_.NextLap();
-    } while (!timer_.HasTimeLimitExpired());
-
-    // Remove all resources from tiles to make sure the tile version destructor
-    // doesn't complain.
-    for (std::vector<Tile*>::iterator tile_it = all_tiles.begin();
-         tile_it != all_tiles.end();
-         ++tile_it) {
-      Tile* tile = *tile_it;
-      ManagedTileState::DrawInfo& draw_info = tile->draw_info();
-      draw_info.SetResourceForTesting(nullptr);
-    }
-
-    perf_test::PrintResult(
-        "tiling_eviction_tile_iterator_construct_and_iterate",
-        "",
-        test_name,
-        timer_.LapsPerSecond(),
-        "runs/s",
-        true);
-  }
-
  private:
   FakePictureLayerTilingClient picture_layer_tiling_client_;
   scoped_ptr<PictureLayerTiling> picture_layer_tiling_;
@@ -333,27 +241,6 @@
       "64_500x500", 64, gfx::Rect(0, 0, 500, 500));
 }
 
-TEST_F(PictureLayerTilingPerfTest, TilingEvictionTileIteratorConstruct) {
-  RunEvictionIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
-  RunEvictionIteratorConstructTest("50_0_100x100", gfx::Rect(50, 0, 100, 100));
-  RunEvictionIteratorConstructTest("100_0_100x100",
-                                   gfx::Rect(100, 0, 100, 100));
-  RunEvictionIteratorConstructTest("150_0_100x100",
-                                   gfx::Rect(150, 0, 100, 100));
-}
-
-TEST_F(PictureLayerTilingPerfTest,
-       TilingEvictionTileIteratorConstructAndIterate) {
-  RunEvictionIteratorConstructAndIterateTest(
-      "32_100x100", 32, gfx::Rect(0, 0, 100, 100));
-  RunEvictionIteratorConstructAndIterateTest(
-      "32_500x500", 32, gfx::Rect(0, 0, 500, 500));
-  RunEvictionIteratorConstructAndIterateTest(
-      "64_100x100", 64, gfx::Rect(0, 0, 100, 100));
-  RunEvictionIteratorConstructAndIterateTest(
-      "64_500x500", 64, gfx::Rect(0, 0, 500, 500));
-}
-
 }  // namespace
 
 }  // namespace cc
diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc
index b982dc1..9190b98 100644
--- a/cc/resources/picture_layer_tiling_unittest.cc
+++ b/cc/resources/picture_layer_tiling_unittest.cc
@@ -1247,102 +1247,6 @@
   EXPECT_EQ(exists, tile != NULL) << geometry_rect.ToString();
 }
 
-TEST(PictureLayerTilingTest, TilingEvictionTileIteratorStaticViewport) {
-  FakeOutputSurfaceClient output_surface_client;
-  scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
-  CHECK(output_surface->BindToClient(&output_surface_client));
-  TestSharedBitmapManager shared_bitmap_manager;
-  scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
-      output_surface.get(), &shared_bitmap_manager, NULL, NULL, 0, false, 1);
-
-  FakePictureLayerTilingClient client(resource_provider.get());
-  scoped_ptr<TestablePictureLayerTiling> tiling;
-
-  gfx::Rect viewport(50, 50, 100, 100);
-  gfx::Size layer_bounds(2000, 2000);
-
-  client.SetTileSize(gfx::Size(30, 30));
-  client.set_tree(ACTIVE_TREE);
-
-  tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
-  tiling->ComputeTilePriorityRects(viewport, 1.0f, 1.0, Occlusion());
-  tiling->UpdateAllTilePrioritiesForTesting();
-
-  PictureLayerTiling::TilingRasterTileIterator empty_iterator;
-  EXPECT_FALSE(empty_iterator);
-
-  std::vector<Tile*> all_tiles = tiling->AllTilesForTesting();
-
-  PictureLayerTiling::TilingEvictionTileIterator it(
-      tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::NOW);
-
-  // Tiles don't have resources to evict.
-  EXPECT_FALSE(it);
-
-  // Sanity check.
-  EXPECT_EQ(5184u, all_tiles.size());
-
-  client.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
-
-  std::set<Tile*> all_tiles_set(all_tiles.begin(), all_tiles.end());
-
-  std::set<Tile*> eviction_tiles;
-
-  it = PictureLayerTiling::TilingEvictionTileIterator(
-      tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::EVENTUALLY);
-  EXPECT_TRUE(it);
-  for (; it; ++it) {
-    Tile* tile = *it;
-    EXPECT_TRUE(tile);
-    EXPECT_EQ(TilePriority::EVENTUALLY,
-              tile->priority(ACTIVE_TREE).priority_bin);
-    EXPECT_FALSE(tile->required_for_activation());
-    eviction_tiles.insert(tile);
-  }
-
-  it = PictureLayerTiling::TilingEvictionTileIterator(
-      tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::SOON);
-  EXPECT_TRUE(it);
-  for (; it; ++it) {
-    Tile* tile = *it;
-    EXPECT_TRUE(tile);
-    EXPECT_EQ(TilePriority::SOON, tile->priority(ACTIVE_TREE).priority_bin);
-    EXPECT_FALSE(tile->required_for_activation());
-    eviction_tiles.insert(tile);
-  }
-
-  it = PictureLayerTiling::TilingEvictionTileIterator(
-      tiling.get(), SMOOTHNESS_TAKES_PRIORITY, PictureLayerTiling::NOW);
-  EXPECT_TRUE(it);
-  for (; it; ++it) {
-    Tile* tile = *it;
-    EXPECT_TRUE(tile);
-    EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin);
-    EXPECT_FALSE(tile->required_for_activation());
-    eviction_tiles.insert(tile);
-  }
-
-  it = PictureLayerTiling::TilingEvictionTileIterator(
-      tiling.get(),
-      SMOOTHNESS_TAKES_PRIORITY,
-      PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION);
-  EXPECT_FALSE(it);
-
-  EXPECT_GT(all_tiles_set.size(), 0u);
-  EXPECT_EQ(all_tiles_set, eviction_tiles);
-
-  EXPECT_TRUE(tiling->eviction_tiles_cache_valid());
-  tiling->RemoveTileAt(0, 0, nullptr);
-  EXPECT_FALSE(tiling->eviction_tiles_cache_valid());
-
-  it = PictureLayerTiling::TilingEvictionTileIterator(
-      tiling.get(), SMOOTHNESS_TAKES_PRIORITY,
-      PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION);
-  EXPECT_TRUE(tiling->eviction_tiles_cache_valid());
-  tiling->Reset();
-  EXPECT_FALSE(tiling->eviction_tiles_cache_valid());
-}
-
 TEST_F(PictureLayerTilingIteratorTest, TilesExist) {
   gfx::Size layer_bounds(1099, 801);
   Initialize(gfx::Size(100, 100), 1.f, layer_bounds);
diff --git a/cc/resources/tiling_set_eviction_queue.cc b/cc/resources/tiling_set_eviction_queue.cc
new file mode 100644
index 0000000..8c5ff52
--- /dev/null
+++ b/cc/resources/tiling_set_eviction_queue.cc
@@ -0,0 +1,197 @@
+// Copyright 2014 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/resources/tiling_set_eviction_queue.h"
+
+namespace cc {
+
+TilingSetEvictionQueue::TilingSetEvictionQueue()
+    : tiling_set_(nullptr),
+      tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES),
+      current_category_(PictureLayerTiling::EVENTUALLY),
+      current_tiling_index_(0u),
+      current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
+      current_eviction_tile_(nullptr),
+      eviction_tiles_(nullptr),
+      next_eviction_tile_index_(0u) {
+}
+
+TilingSetEvictionQueue::TilingSetEvictionQueue(
+    PictureLayerTilingSet* tiling_set,
+    TreePriority tree_priority)
+    : tiling_set_(tiling_set),
+      tree_priority_(tree_priority),
+      current_category_(PictureLayerTiling::EVENTUALLY),
+      current_tiling_index_(0u),
+      current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
+      current_eviction_tile_(nullptr),
+      eviction_tiles_(nullptr),
+      next_eviction_tile_index_(0u) {
+  DCHECK(tiling_set_);
+
+  // Early out if the layer has no tilings.
+  if (!tiling_set_->num_tilings())
+    return;
+
+  current_tiling_index_ = CurrentTilingRange().start - 1u;
+  AdvanceToNextValidTiling();
+}
+
+TilingSetEvictionQueue::~TilingSetEvictionQueue() {
+}
+
+bool TilingSetEvictionQueue::IsEmpty() const {
+  return !current_eviction_tile_;
+}
+
+void TilingSetEvictionQueue::Pop() {
+  DCHECK(!IsEmpty());
+
+  if (!AdvanceToNextEvictionTile())
+    AdvanceToNextValidTiling();
+}
+
+Tile* TilingSetEvictionQueue::Top() {
+  DCHECK(!IsEmpty());
+  return current_eviction_tile_;
+}
+
+const Tile* TilingSetEvictionQueue::Top() const {
+  DCHECK(!IsEmpty());
+  return current_eviction_tile_;
+}
+
+bool TilingSetEvictionQueue::AdvanceToNextCategory() {
+  // Advance to the next category. This is done only after all tiling range
+  // types within the previous category have been gone through.
+  DCHECK_EQ(current_tiling_range_type_, PictureLayerTilingSet::HIGH_RES);
+
+  switch (current_category_) {
+    case PictureLayerTiling::EVENTUALLY:
+      current_category_ =
+          PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION;
+      return true;
+    case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
+      current_category_ = PictureLayerTiling::SOON;
+      return true;
+    case PictureLayerTiling::SOON:
+      current_category_ = PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION;
+      return true;
+    case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION:
+      current_category_ = PictureLayerTiling::NOW;
+      return true;
+    case PictureLayerTiling::NOW:
+      current_category_ = PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION;
+      return true;
+    case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION:
+      return false;
+  }
+  NOTREACHED();
+  return false;
+}
+
+bool TilingSetEvictionQueue::AdvanceToNextEvictionTile() {
+  // Advance to the next eviction tile within the current category and tiling.
+  // This is done while advancing to a new tiling (in which case the next
+  // eviction tile index is 0) and while popping the current tile (in which
+  // case the next eviction tile index is greater than 0).
+  DCHECK_EQ(next_eviction_tile_index_ > 0, current_eviction_tile_ != nullptr);
+
+  while (next_eviction_tile_index_ < eviction_tiles_->size()) {
+    Tile* tile = (*eviction_tiles_)[next_eviction_tile_index_];
+    ++next_eviction_tile_index_;
+    if (tile->HasResources()) {
+      current_eviction_tile_ = tile;
+      return true;
+    }
+  }
+
+  current_eviction_tile_ = nullptr;
+  return false;
+}
+
+bool TilingSetEvictionQueue::AdvanceToNextTilingRangeType() {
+  // Advance to the next tiling range type within the current category or to
+  // the first tiling range type within the next category. This is done only
+  // after all tilings within the previous tiling range type have been gone
+  // through.
+  DCHECK_EQ(current_tiling_index_, CurrentTilingRange().end);
+
+  switch (current_tiling_range_type_) {
+    case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
+      current_tiling_range_type_ = PictureLayerTilingSet::LOWER_THAN_LOW_RES;
+      return true;
+    case PictureLayerTilingSet::LOWER_THAN_LOW_RES:
+      current_tiling_range_type_ =
+          PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES;
+      return true;
+    case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
+      current_tiling_range_type_ = PictureLayerTilingSet::LOW_RES;
+      return true;
+    case PictureLayerTilingSet::LOW_RES:
+      current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES;
+      return true;
+    case PictureLayerTilingSet::HIGH_RES:
+      if (!AdvanceToNextCategory())
+        return false;
+
+      current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES;
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
+bool TilingSetEvictionQueue::AdvanceToNextValidTiling() {
+  // Advance to the next tiling within current tiling range type or to
+  // the first tiling within the next tiling range type or category until
+  // the next eviction tile is found. This is done only after all eviction
+  // tiles within the previous tiling within the current category and tiling
+  // range type have been gone through.
+  DCHECK(!current_eviction_tile_);
+  DCHECK_NE(current_tiling_index_, CurrentTilingRange().end);
+
+  for (;;) {
+    ++current_tiling_index_;
+    while (current_tiling_index_ == CurrentTilingRange().end) {
+      if (!AdvanceToNextTilingRangeType())
+        return false;
+      current_tiling_index_ = CurrentTilingRange().start;
+    }
+
+    PictureLayerTiling* tiling = tiling_set_->tiling_at(CurrentTilingIndex());
+    eviction_tiles_ =
+        tiling->GetEvictionTiles(tree_priority_, current_category_);
+    next_eviction_tile_index_ = 0u;
+    if (AdvanceToNextEvictionTile())
+      return true;
+  }
+}
+
+PictureLayerTilingSet::TilingRange
+TilingSetEvictionQueue::CurrentTilingRange() const {
+  return tiling_set_->GetTilingRange(current_tiling_range_type_);
+}
+
+size_t TilingSetEvictionQueue::CurrentTilingIndex() const {
+  DCHECK_NE(current_tiling_index_, CurrentTilingRange().end);
+  switch (current_tiling_range_type_) {
+    case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
+    case PictureLayerTilingSet::LOW_RES:
+    case PictureLayerTilingSet::HIGH_RES:
+      return current_tiling_index_;
+    // Tilings in the following ranges are accessed in reverse order.
+    case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
+    case PictureLayerTilingSet::LOWER_THAN_LOW_RES: {
+      PictureLayerTilingSet::TilingRange tiling_range = CurrentTilingRange();
+      size_t current_tiling_range_offset =
+          current_tiling_index_ - tiling_range.start;
+      return tiling_range.end - 1 - current_tiling_range_offset;
+    }
+  }
+  NOTREACHED();
+  return 0;
+}
+
+}
diff --git a/cc/resources/tiling_set_eviction_queue.h b/cc/resources/tiling_set_eviction_queue.h
new file mode 100644
index 0000000..f88ce3bd
--- /dev/null
+++ b/cc/resources/tiling_set_eviction_queue.h
@@ -0,0 +1,48 @@
+// Copyright 2014 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_RESOURCES_TILING_SET_EVICTION_QUEUE_H_
+#define CC_RESOURCES_TILING_SET_EVICTION_QUEUE_H_
+
+#include "cc/base/cc_export.h"
+#include "cc/resources/picture_layer_tiling_set.h"
+
+namespace cc {
+
+class CC_EXPORT TilingSetEvictionQueue {
+ public:
+  TilingSetEvictionQueue();
+  TilingSetEvictionQueue(PictureLayerTilingSet* tiling_set,
+                         TreePriority tree_priority);
+  ~TilingSetEvictionQueue();
+
+  Tile* Top();
+  const Tile* Top() const;
+  void Pop();
+  bool IsEmpty() const;
+
+ private:
+  bool AdvanceToNextCategory();
+  bool AdvanceToNextEvictionTile();
+  bool AdvanceToNextTilingRangeType();
+  bool AdvanceToNextValidTiling();
+
+  PictureLayerTilingSet::TilingRange CurrentTilingRange() const;
+  size_t CurrentTilingIndex() const;
+
+  PictureLayerTilingSet* tiling_set_;
+  TreePriority tree_priority_;
+
+  PictureLayerTiling::EvictionCategory current_category_;
+  size_t current_tiling_index_;
+  PictureLayerTilingSet::TilingRangeType current_tiling_range_type_;
+  Tile* current_eviction_tile_;
+
+  const std::vector<Tile*>* eviction_tiles_;
+  size_t next_eviction_tile_index_;
+};
+
+}  // namespace cc
+
+#endif  // CC_RESOURCES_TILING_SET_RASTER_QUEUE_H_