Home | History | Annotate | Download | only in resources
      1 // Copyright 2012 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/picture_layer_tiling_set.h"
      6 
      7 #include <limits>
      8 
      9 namespace cc {
     10 
     11 namespace {
     12 
     13 class LargestToSmallestScaleFunctor {
     14  public:
     15   bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
     16     return left->contents_scale() > right->contents_scale();
     17   }
     18 };
     19 
     20 }  // namespace
     21 
     22 
     23 PictureLayerTilingSet::PictureLayerTilingSet(
     24     PictureLayerTilingClient* client,
     25     const gfx::Size& layer_bounds)
     26     : client_(client),
     27       layer_bounds_(layer_bounds) {
     28 }
     29 
     30 PictureLayerTilingSet::~PictureLayerTilingSet() {
     31 }
     32 
     33 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
     34   client_ = client;
     35   for (size_t i = 0; i < tilings_.size(); ++i)
     36     tilings_[i]->SetClient(client_);
     37 }
     38 
     39 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
     40   for (size_t i = 0; i < tilings_.size(); ++i)
     41     tilings_[i]->RemoveTilesInRegion(region);
     42 }
     43 
     44 bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
     45                                         const gfx::Size& new_layer_bounds,
     46                                         const Region& layer_invalidation,
     47                                         float minimum_contents_scale) {
     48   if (new_layer_bounds.IsEmpty()) {
     49     RemoveAllTilings();
     50     layer_bounds_ = new_layer_bounds;
     51     return false;
     52   }
     53 
     54   tilings_.reserve(other.tilings_.size());
     55 
     56   // Remove any tilings that aren't in |other| or don't meet the minimum.
     57   for (size_t i = 0; i < tilings_.size(); ++i) {
     58     float scale = tilings_[i]->contents_scale();
     59     if (scale >= minimum_contents_scale && !!other.TilingAtScale(scale))
     60       continue;
     61     // Swap with the last element and remove it.
     62     tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
     63     tilings_.pop_back();
     64     --i;
     65   }
     66 
     67   bool have_high_res_tiling = false;
     68 
     69   // Add any missing tilings from |other| that meet the minimum.
     70   for (size_t i = 0; i < other.tilings_.size(); ++i) {
     71     float contents_scale = other.tilings_[i]->contents_scale();
     72     if (contents_scale < minimum_contents_scale)
     73       continue;
     74     if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
     75       this_tiling->set_resolution(other.tilings_[i]->resolution());
     76 
     77       this_tiling->UpdateTilesToCurrentPile(layer_invalidation,
     78                                             new_layer_bounds);
     79       this_tiling->CreateMissingTilesInLiveTilesRect();
     80       if (this_tiling->resolution() == HIGH_RESOLUTION)
     81         have_high_res_tiling = true;
     82 
     83       DCHECK(this_tiling->tile_size() ==
     84              client_->CalculateTileSize(this_tiling->tiling_size()))
     85           << "tile_size: " << this_tiling->tile_size().ToString()
     86           << " tiling_size: " << this_tiling->tiling_size().ToString()
     87           << " CalculateTileSize: "
     88           << client_->CalculateTileSize(this_tiling->tiling_size()).ToString();
     89       continue;
     90     }
     91     scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
     92         contents_scale,
     93         new_layer_bounds,
     94         client_);
     95     new_tiling->set_resolution(other.tilings_[i]->resolution());
     96     if (new_tiling->resolution() == HIGH_RESOLUTION)
     97       have_high_res_tiling = true;
     98     tilings_.push_back(new_tiling.Pass());
     99   }
    100   tilings_.sort(LargestToSmallestScaleFunctor());
    101 
    102   layer_bounds_ = new_layer_bounds;
    103   return have_high_res_tiling;
    104 }
    105 
    106 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
    107   for (size_t i = 0; i < tilings_.size(); ++i)
    108     DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
    109 
    110   tilings_.push_back(PictureLayerTiling::Create(contents_scale,
    111                                                 layer_bounds_,
    112                                                 client_));
    113   PictureLayerTiling* appended = tilings_.back();
    114 
    115   tilings_.sort(LargestToSmallestScaleFunctor());
    116   return appended;
    117 }
    118 
    119 int PictureLayerTilingSet::NumHighResTilings() const {
    120   int num_high_res = 0;
    121   for (size_t i = 0; i < tilings_.size(); ++i) {
    122     if (tilings_[i]->resolution() == HIGH_RESOLUTION)
    123       num_high_res++;
    124   }
    125   return num_high_res;
    126 }
    127 
    128 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
    129   for (size_t i = 0; i < tilings_.size(); ++i) {
    130     if (tilings_[i]->contents_scale() == scale)
    131       return tilings_[i];
    132   }
    133   return NULL;
    134 }
    135 
    136 void PictureLayerTilingSet::RemoveAllTilings() {
    137   tilings_.clear();
    138 }
    139 
    140 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
    141   ScopedPtrVector<PictureLayerTiling>::iterator iter =
    142     std::find(tilings_.begin(), tilings_.end(), tiling);
    143   if (iter == tilings_.end())
    144     return;
    145   tilings_.erase(iter);
    146 }
    147 
    148 void PictureLayerTilingSet::RemoveAllTiles() {
    149   for (size_t i = 0; i < tilings_.size(); ++i)
    150     tilings_[i]->Reset();
    151 }
    152 
    153 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
    154     const PictureLayerTilingSet* set,
    155     float contents_scale,
    156     const gfx::Rect& content_rect,
    157     float ideal_contents_scale)
    158     : set_(set),
    159       contents_scale_(contents_scale),
    160       ideal_contents_scale_(ideal_contents_scale),
    161       current_tiling_(-1) {
    162   missing_region_.Union(content_rect);
    163 
    164   for (ideal_tiling_ = 0;
    165        static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
    166        ++ideal_tiling_) {
    167     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
    168     if (tiling->contents_scale() < ideal_contents_scale_) {
    169       if (ideal_tiling_ > 0)
    170         ideal_tiling_--;
    171       break;
    172     }
    173   }
    174 
    175   DCHECK_LE(set_->tilings_.size(),
    176             static_cast<size_t>(std::numeric_limits<int>::max()));
    177 
    178   int num_tilings = set_->tilings_.size();
    179   if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
    180     ideal_tiling_--;
    181 
    182   ++(*this);
    183 }
    184 
    185 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
    186 }
    187 
    188 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
    189   if (!tiling_iter_) {
    190     if (!region_iter_.has_rect())
    191       return gfx::Rect();
    192     return region_iter_.rect();
    193   }
    194   return tiling_iter_.geometry_rect();
    195 }
    196 
    197 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
    198   if (!tiling_iter_)
    199     return gfx::RectF();
    200   return tiling_iter_.texture_rect();
    201 }
    202 
    203 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
    204   if (!tiling_iter_)
    205     return gfx::Size();
    206   return tiling_iter_.texture_size();
    207 }
    208 
    209 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
    210   if (!tiling_iter_)
    211     return NULL;
    212   return *tiling_iter_;
    213 }
    214 
    215 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
    216   if (!tiling_iter_)
    217     return NULL;
    218   return *tiling_iter_;
    219 }
    220 
    221 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
    222   if (current_tiling_ < 0)
    223     return NULL;
    224   if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
    225     return NULL;
    226   return set_->tilings_[current_tiling_];
    227 }
    228 
    229 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
    230   // Order returned by this method is:
    231   // 1. Ideal tiling index
    232   // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
    233   // 3. Tiling index > Ideal in increasing order (lower res than ideal)
    234   // 4. Tiling index > tilings.size() (invalid index)
    235   if (current_tiling_ < 0)
    236     return ideal_tiling_;
    237   else if (current_tiling_ > ideal_tiling_)
    238     return current_tiling_ + 1;
    239   else if (current_tiling_)
    240     return current_tiling_ - 1;
    241   else
    242     return ideal_tiling_ + 1;
    243 }
    244 
    245 PictureLayerTilingSet::CoverageIterator&
    246 PictureLayerTilingSet::CoverageIterator::operator++() {
    247   bool first_time = current_tiling_ < 0;
    248 
    249   if (!*this && !first_time)
    250     return *this;
    251 
    252   if (tiling_iter_)
    253     ++tiling_iter_;
    254 
    255   // Loop until we find a valid place to stop.
    256   while (true) {
    257     while (tiling_iter_ &&
    258            (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
    259       missing_region_.Union(tiling_iter_.geometry_rect());
    260       ++tiling_iter_;
    261     }
    262     if (tiling_iter_)
    263       return *this;
    264 
    265     // If the set of current rects for this tiling is done, go to the next
    266     // tiling and set up to iterate through all of the remaining holes.
    267     // This will also happen the first time through the loop.
    268     if (!region_iter_.has_rect()) {
    269       current_tiling_ = NextTiling();
    270       current_region_.Swap(&missing_region_);
    271       missing_region_.Clear();
    272       region_iter_ = Region::Iterator(current_region_);
    273 
    274       // All done and all filled.
    275       if (!region_iter_.has_rect()) {
    276         current_tiling_ = set_->tilings_.size();
    277         return *this;
    278       }
    279 
    280       // No more valid tiles, return this checkerboard rect.
    281       if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
    282         return *this;
    283     }
    284 
    285     // Pop a rect off.  If there are no more tilings, then these will be
    286     // treated as geometry with null tiles that the caller can checkerboard.
    287     gfx::Rect last_rect = region_iter_.rect();
    288     region_iter_.next();
    289 
    290     // Done, found next checkerboard rect to return.
    291     if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
    292       return *this;
    293 
    294     // Construct a new iterator for the next tiling, but we need to loop
    295     // again until we get to a valid one.
    296     tiling_iter_ = PictureLayerTiling::CoverageIterator(
    297         set_->tilings_[current_tiling_],
    298         contents_scale_,
    299         last_rect);
    300   }
    301 
    302   return *this;
    303 }
    304 
    305 PictureLayerTilingSet::CoverageIterator::operator bool() const {
    306   return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
    307       region_iter_.has_rect();
    308 }
    309 
    310 void PictureLayerTilingSet::DidBecomeActive() {
    311   for (size_t i = 0; i < tilings_.size(); ++i)
    312     tilings_[i]->DidBecomeActive();
    313 }
    314 
    315 void PictureLayerTilingSet::DidBecomeRecycled() {
    316   for (size_t i = 0; i < tilings_.size(); ++i)
    317     tilings_[i]->DidBecomeRecycled();
    318 }
    319 
    320 void PictureLayerTilingSet::AsValueInto(base::debug::TracedValue* state) const {
    321   for (size_t i = 0; i < tilings_.size(); ++i) {
    322     state->BeginDictionary();
    323     tilings_[i]->AsValueInto(state);
    324     state->EndDictionary();
    325   }
    326 }
    327 
    328 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
    329   size_t amount = 0;
    330   for (size_t i = 0; i < tilings_.size(); ++i)
    331     amount += tilings_[i]->GPUMemoryUsageInBytes();
    332   return amount;
    333 }
    334 
    335 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange(
    336     TilingRangeType type) const {
    337   // Doesn't seem to be the case right now but if it ever becomes a performance
    338   // problem to compute these ranges each time this function is called, we can
    339   // compute them only when the tiling set has changed instead.
    340   TilingRange high_res_range(0, 0);
    341   TilingRange low_res_range(tilings_.size(), tilings_.size());
    342   for (size_t i = 0; i < tilings_.size(); ++i) {
    343     const PictureLayerTiling* tiling = tilings_[i];
    344     if (tiling->resolution() == HIGH_RESOLUTION)
    345       high_res_range = TilingRange(i, i + 1);
    346     if (tiling->resolution() == LOW_RESOLUTION)
    347       low_res_range = TilingRange(i, i + 1);
    348   }
    349 
    350   switch (type) {
    351     case HIGHER_THAN_HIGH_RES:
    352       return TilingRange(0, high_res_range.start);
    353     case HIGH_RES:
    354       return high_res_range;
    355     case BETWEEN_HIGH_AND_LOW_RES:
    356       return TilingRange(high_res_range.end, low_res_range.start);
    357     case LOW_RES:
    358       return low_res_range;
    359     case LOWER_THAN_LOW_RES:
    360       return TilingRange(low_res_range.end, tilings_.size());
    361   }
    362 
    363   NOTREACHED();
    364   return TilingRange(0, 0);
    365 }
    366 
    367 }  // namespace cc
    368