1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "cc/resources/prioritized_tile_set.h" 6 7#include <algorithm> 8 9#include "cc/resources/managed_tile_state.h" 10#include "cc/resources/tile.h" 11 12namespace cc { 13 14class BinComparator { 15 public: 16 bool operator()(const Tile* a, 17 const Tile* b) const { 18 const ManagedTileState& ams = a->managed_state(); 19 const ManagedTileState& bms = b->managed_state(); 20 21 if (ams.priority_bin != bms.priority_bin) 22 return ams.priority_bin < bms.priority_bin; 23 24 if (ams.required_for_activation != bms.required_for_activation) 25 return ams.required_for_activation; 26 27 if (ams.resolution != bms.resolution) 28 return ams.resolution < bms.resolution; 29 30 if (ams.distance_to_visible != bms.distance_to_visible) 31 return ams.distance_to_visible < bms.distance_to_visible; 32 33 gfx::Rect a_rect = a->content_rect(); 34 gfx::Rect b_rect = b->content_rect(); 35 if (a_rect.y() != b_rect.y()) 36 return a_rect.y() < b_rect.y(); 37 return a_rect.x() < b_rect.x(); 38 } 39}; 40 41namespace { 42 43bool TilePriorityTieBreaker(const Tile* tile_i, const Tile* tile_j) { 44 // When two tiles has same priority use Id as tie breaker. 45 return tile_i->id() < tile_j->id(); 46} 47 48typedef std::vector<Tile*> TileVector; 49 50void SortBinTiles(ManagedTileBin bin, TileVector* tiles) { 51 switch (bin) { 52 case NEVER_BIN: 53 break; 54 case NOW_AND_READY_TO_DRAW_BIN: 55 std::sort(tiles->begin(), tiles->end(), TilePriorityTieBreaker); 56 break; 57 case NOW_BIN: 58 case SOON_BIN: 59 case EVENTUALLY_AND_ACTIVE_BIN: 60 case EVENTUALLY_BIN: 61 case AT_LAST_AND_ACTIVE_BIN: 62 case AT_LAST_BIN: 63 std::sort(tiles->begin(), tiles->end(), BinComparator()); 64 break; 65 default: 66 NOTREACHED(); 67 } 68} 69 70} // namespace 71 72PrioritizedTileSet::PrioritizedTileSet() { 73 for (int bin = 0; bin < NUM_BINS; ++bin) 74 bin_sorted_[bin] = true; 75} 76 77PrioritizedTileSet::~PrioritizedTileSet() {} 78 79void PrioritizedTileSet::InsertTile(Tile* tile, ManagedTileBin bin) { 80 tiles_[bin].push_back(tile); 81 bin_sorted_[bin] = false; 82} 83 84void PrioritizedTileSet::Clear() { 85 for (int bin = 0; bin < NUM_BINS; ++bin) { 86 tiles_[bin].clear(); 87 bin_sorted_[bin] = true; 88 } 89} 90 91bool PrioritizedTileSet::IsEmpty() { 92 for (int bin = 0; bin < NUM_BINS; ++bin) 93 if (!tiles_[bin].empty()) 94 return false; 95 96 return true; 97} 98 99void PrioritizedTileSet::SortBinIfNeeded(ManagedTileBin bin) { 100 if (!bin_sorted_[bin]) { 101 SortBinTiles(bin, &tiles_[bin]); 102 bin_sorted_[bin] = true; 103 } 104} 105 106PrioritizedTileSet::Iterator::Iterator( 107 PrioritizedTileSet* tile_set, bool use_priority_ordering) 108 : tile_set_(tile_set), 109 current_bin_(NOW_AND_READY_TO_DRAW_BIN), 110 use_priority_ordering_(use_priority_ordering) { 111 if (use_priority_ordering_) 112 tile_set_->SortBinIfNeeded(current_bin_); 113 iterator_ = tile_set->tiles_[current_bin_].begin(); 114 if (iterator_ == tile_set_->tiles_[current_bin_].end()) 115 AdvanceList(); 116} 117 118PrioritizedTileSet::Iterator::~Iterator() {} 119 120void PrioritizedTileSet::Iterator::DisablePriorityOrdering() { 121 use_priority_ordering_ = false; 122} 123 124PrioritizedTileSet::Iterator& 125PrioritizedTileSet::Iterator::operator++() { 126 // We can't increment past the end of the tiles. 127 DCHECK(iterator_ != tile_set_->tiles_[current_bin_].end()); 128 129 ++iterator_; 130 if (iterator_ == tile_set_->tiles_[current_bin_].end()) 131 AdvanceList(); 132 return *this; 133} 134 135Tile* PrioritizedTileSet::Iterator::operator*() { 136 DCHECK(iterator_ != tile_set_->tiles_[current_bin_].end()); 137 return *iterator_; 138} 139 140void PrioritizedTileSet::Iterator::AdvanceList() { 141 DCHECK(iterator_ == tile_set_->tiles_[current_bin_].end()); 142 143 while (current_bin_ != NEVER_BIN) { 144 current_bin_ = static_cast<ManagedTileBin>(current_bin_ + 1); 145 146 if (use_priority_ordering_) 147 tile_set_->SortBinIfNeeded(current_bin_); 148 149 iterator_ = tile_set_->tiles_[current_bin_].begin(); 150 if (iterator_ != tile_set_->tiles_[current_bin_].end()) 151 break; 152 } 153} 154 155} // namespace cc 156