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     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::SyncTilings(
     40     const PictureLayerTilingSet& other,
     41     gfx::Size new_layer_bounds,
     42     const Region& layer_invalidation,
     43     float minimum_contents_scale) {
     44   if (new_layer_bounds.IsEmpty()) {
     45     RemoveAllTilings();
     46     layer_bounds_ = new_layer_bounds;
     47     return;
     48   }
     49 
     50   tilings_.reserve(other.tilings_.size());
     51 
     52   // Remove any tilings that aren't in |other| or don't meet the minimum.
     53   for (size_t i = 0; i < tilings_.size(); ++i) {
     54     float scale = tilings_[i]->contents_scale();
     55     if (scale >= minimum_contents_scale && !!other.TilingAtScale(scale))
     56       continue;
     57     // Swap with the last element and remove it.
     58     tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
     59     tilings_.pop_back();
     60     --i;
     61   }
     62 
     63   // Add any missing tilings from |other| that meet the minimum.
     64   for (size_t i = 0; i < other.tilings_.size(); ++i) {
     65     float contents_scale = other.tilings_[i]->contents_scale();
     66     if (contents_scale < minimum_contents_scale)
     67       continue;
     68     if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
     69       this_tiling->set_resolution(other.tilings_[i]->resolution());
     70 
     71       // These two calls must come before updating the pile, because they may
     72       // destroy tiles that the new pile cannot raster.
     73       this_tiling->SetLayerBounds(new_layer_bounds);
     74       this_tiling->Invalidate(layer_invalidation);
     75 
     76       this_tiling->UpdateTilesToCurrentPile();
     77       this_tiling->CreateMissingTilesInLiveTilesRect();
     78 
     79       DCHECK(this_tiling->tile_size() ==
     80              client_->CalculateTileSize(this_tiling->ContentRect().size()));
     81       continue;
     82     }
     83     scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
     84         contents_scale,
     85         new_layer_bounds,
     86         client_);
     87     new_tiling->set_resolution(other.tilings_[i]->resolution());
     88     tilings_.push_back(new_tiling.Pass());
     89   }
     90   tilings_.sort(LargestToSmallestScaleFunctor());
     91 
     92   layer_bounds_ = new_layer_bounds;
     93 }
     94 
     95 void PictureLayerTilingSet::SetCanUseLCDText(bool can_use_lcd_text) {
     96   for (size_t i = 0; i < tilings_.size(); ++i)
     97     tilings_[i]->SetCanUseLCDText(can_use_lcd_text);
     98 }
     99 
    100 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
    101   for (size_t i = 0; i < tilings_.size(); ++i)
    102     DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
    103 
    104   tilings_.push_back(PictureLayerTiling::Create(contents_scale,
    105                                                 layer_bounds_,
    106                                                 client_));
    107   PictureLayerTiling* appended = tilings_.back();
    108 
    109   tilings_.sort(LargestToSmallestScaleFunctor());
    110   return appended;
    111 }
    112 
    113 int PictureLayerTilingSet::NumHighResTilings() const {
    114   int num_high_res = 0;
    115   for (size_t i = 0; i < tilings_.size(); ++i) {
    116     if (tilings_[i]->resolution() == HIGH_RESOLUTION)
    117       num_high_res++;
    118   }
    119   return num_high_res;
    120 }
    121 
    122 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
    123   for (size_t i = 0; i < tilings_.size(); ++i) {
    124     if (tilings_[i]->contents_scale() == scale)
    125       return tilings_[i];
    126   }
    127   return NULL;
    128 }
    129 
    130 void PictureLayerTilingSet::RemoveAllTilings() {
    131   tilings_.clear();
    132 }
    133 
    134 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
    135   ScopedPtrVector<PictureLayerTiling>::iterator iter =
    136     std::find(tilings_.begin(), tilings_.end(), tiling);
    137   if (iter == tilings_.end())
    138     return;
    139   tilings_.erase(iter);
    140 }
    141 
    142 void PictureLayerTilingSet::RemoveAllTiles() {
    143   for (size_t i = 0; i < tilings_.size(); ++i)
    144     tilings_[i]->Reset();
    145 }
    146 
    147 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
    148     const PictureLayerTilingSet* set,
    149     float contents_scale,
    150     gfx::Rect content_rect,
    151     float ideal_contents_scale)
    152     : set_(set),
    153       contents_scale_(contents_scale),
    154       ideal_contents_scale_(ideal_contents_scale),
    155       current_tiling_(-1) {
    156   missing_region_.Union(content_rect);
    157 
    158   for (ideal_tiling_ = 0;
    159        static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
    160        ++ideal_tiling_) {
    161     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
    162     if (tiling->contents_scale() < ideal_contents_scale_) {
    163       if (ideal_tiling_ > 0)
    164         ideal_tiling_--;
    165       break;
    166     }
    167   }
    168 
    169   DCHECK_LE(set_->tilings_.size(),
    170             static_cast<size_t>(std::numeric_limits<int>::max()));
    171 
    172   int num_tilings = set_->tilings_.size();
    173   if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
    174     ideal_tiling_--;
    175 
    176   ++(*this);
    177 }
    178 
    179 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
    180 }
    181 
    182 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
    183   if (!tiling_iter_) {
    184     if (!region_iter_.has_rect())
    185       return gfx::Rect();
    186     return region_iter_.rect();
    187   }
    188   return tiling_iter_.geometry_rect();
    189 }
    190 
    191 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
    192   if (!tiling_iter_)
    193     return gfx::RectF();
    194   return tiling_iter_.texture_rect();
    195 }
    196 
    197 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
    198   if (!tiling_iter_)
    199     return gfx::Size();
    200   return tiling_iter_.texture_size();
    201 }
    202 
    203 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
    204   if (!tiling_iter_)
    205     return NULL;
    206   return *tiling_iter_;
    207 }
    208 
    209 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
    210   if (!tiling_iter_)
    211     return NULL;
    212   return *tiling_iter_;
    213 }
    214 
    215 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
    216   if (current_tiling_ < 0)
    217     return NULL;
    218   if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
    219     return NULL;
    220   return set_->tilings_[current_tiling_];
    221 }
    222 
    223 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
    224   // Order returned by this method is:
    225   // 1. Ideal tiling index
    226   // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
    227   // 3. Tiling index > Ideal in increasing order (lower res than ideal)
    228   // 4. Tiling index > tilings.size() (invalid index)
    229   if (current_tiling_ < 0)
    230     return ideal_tiling_;
    231   else if (current_tiling_ > ideal_tiling_)
    232     return current_tiling_ + 1;
    233   else if (current_tiling_)
    234     return current_tiling_ - 1;
    235   else
    236     return ideal_tiling_ + 1;
    237 }
    238 
    239 PictureLayerTilingSet::CoverageIterator&
    240 PictureLayerTilingSet::CoverageIterator::operator++() {
    241   bool first_time = current_tiling_ < 0;
    242 
    243   if (!*this && !first_time)
    244     return *this;
    245 
    246   if (tiling_iter_)
    247     ++tiling_iter_;
    248 
    249   // Loop until we find a valid place to stop.
    250   while (true) {
    251     while (tiling_iter_ &&
    252            (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
    253       missing_region_.Union(tiling_iter_.geometry_rect());
    254       ++tiling_iter_;
    255     }
    256     if (tiling_iter_)
    257       return *this;
    258 
    259     // If the set of current rects for this tiling is done, go to the next
    260     // tiling and set up to iterate through all of the remaining holes.
    261     // This will also happen the first time through the loop.
    262     if (!region_iter_.has_rect()) {
    263       current_tiling_ = NextTiling();
    264       current_region_.Swap(&missing_region_);
    265       missing_region_.Clear();
    266       region_iter_ = Region::Iterator(current_region_);
    267 
    268       // All done and all filled.
    269       if (!region_iter_.has_rect()) {
    270         current_tiling_ = set_->tilings_.size();
    271         return *this;
    272       }
    273 
    274       // No more valid tiles, return this checkerboard rect.
    275       if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
    276         return *this;
    277     }
    278 
    279     // Pop a rect off.  If there are no more tilings, then these will be
    280     // treated as geometry with null tiles that the caller can checkerboard.
    281     gfx::Rect last_rect = region_iter_.rect();
    282     region_iter_.next();
    283 
    284     // Done, found next checkerboard rect to return.
    285     if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
    286       return *this;
    287 
    288     // Construct a new iterator for the next tiling, but we need to loop
    289     // again until we get to a valid one.
    290     tiling_iter_ = PictureLayerTiling::CoverageIterator(
    291         set_->tilings_[current_tiling_],
    292         contents_scale_,
    293         last_rect);
    294   }
    295 
    296   return *this;
    297 }
    298 
    299 PictureLayerTilingSet::CoverageIterator::operator bool() const {
    300   return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
    301       region_iter_.has_rect();
    302 }
    303 
    304 void PictureLayerTilingSet::UpdateTilePriorities(
    305     WhichTree tree,
    306     gfx::Size device_viewport,
    307     gfx::Rect viewport_in_content_space,
    308     gfx::Rect visible_content_rect,
    309     gfx::Size last_layer_bounds,
    310     gfx::Size current_layer_bounds,
    311     float last_layer_contents_scale,
    312     float current_layer_contents_scale,
    313     const gfx::Transform& last_screen_transform,
    314     const gfx::Transform& current_screen_transform,
    315     double current_frame_time_in_seconds,
    316     size_t max_tiles_for_interest_area) {
    317   gfx::Rect viewport_in_layer_space = gfx::ScaleToEnclosingRect(
    318       viewport_in_content_space,
    319       1.f / current_layer_contents_scale);
    320   gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
    321       visible_content_rect,
    322       1.f / current_layer_contents_scale);
    323 
    324   for (size_t i = 0; i < tilings_.size(); ++i) {
    325     tilings_[i]->UpdateTilePriorities(
    326         tree,
    327         device_viewport,
    328         viewport_in_layer_space,
    329         visible_layer_rect,
    330         last_layer_bounds,
    331         current_layer_bounds,
    332         last_layer_contents_scale,
    333         current_layer_contents_scale,
    334         last_screen_transform,
    335         current_screen_transform,
    336         current_frame_time_in_seconds,
    337         max_tiles_for_interest_area);
    338   }
    339 }
    340 
    341 void PictureLayerTilingSet::DidBecomeActive() {
    342   for (size_t i = 0; i < tilings_.size(); ++i)
    343     tilings_[i]->DidBecomeActive();
    344 }
    345 
    346 void PictureLayerTilingSet::DidBecomeRecycled() {
    347   for (size_t i = 0; i < tilings_.size(); ++i)
    348     tilings_[i]->DidBecomeRecycled();
    349 }
    350 
    351 scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
    352   scoped_ptr<base::ListValue> state(new base::ListValue());
    353   for (size_t i = 0; i < tilings_.size(); ++i)
    354     state->Append(tilings_[i]->AsValue().release());
    355   return state.PassAs<base::Value>();
    356 }
    357 
    358 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
    359   size_t amount = 0;
    360   for (size_t i = 0; i < tilings_.size(); ++i)
    361     amount += tilings_[i]->GPUMemoryUsageInBytes();
    362   return amount;
    363 }
    364 
    365 }  // namespace cc
    366