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 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
    114   for (size_t i = 0; i < tilings_.size(); ++i) {
    115     if (tilings_[i]->contents_scale() == scale)
    116       return tilings_[i];
    117   }
    118   return NULL;
    119 }
    120 
    121 void PictureLayerTilingSet::RemoveAllTilings() {
    122   tilings_.clear();
    123 }
    124 
    125 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
    126   ScopedPtrVector<PictureLayerTiling>::iterator iter =
    127     std::find(tilings_.begin(), tilings_.end(), tiling);
    128   if (iter == tilings_.end())
    129     return;
    130   tilings_.erase(iter);
    131 }
    132 
    133 void PictureLayerTilingSet::RemoveAllTiles() {
    134   for (size_t i = 0; i < tilings_.size(); ++i)
    135     tilings_[i]->Reset();
    136 }
    137 
    138 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
    139     const PictureLayerTilingSet* set,
    140     float contents_scale,
    141     gfx::Rect content_rect,
    142     float ideal_contents_scale)
    143     : set_(set),
    144       contents_scale_(contents_scale),
    145       ideal_contents_scale_(ideal_contents_scale),
    146       current_tiling_(-1) {
    147   missing_region_.Union(content_rect);
    148 
    149   for (ideal_tiling_ = 0;
    150        static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
    151        ++ideal_tiling_) {
    152     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
    153     if (tiling->contents_scale() < ideal_contents_scale_) {
    154       if (ideal_tiling_ > 0)
    155         ideal_tiling_--;
    156       break;
    157     }
    158   }
    159 
    160   DCHECK_LE(set_->tilings_.size(),
    161             static_cast<size_t>(std::numeric_limits<int>::max()));
    162 
    163   int num_tilings = set_->tilings_.size();
    164   if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
    165     ideal_tiling_--;
    166 
    167   ++(*this);
    168 }
    169 
    170 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
    171 }
    172 
    173 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
    174   if (!tiling_iter_) {
    175     if (!region_iter_.has_rect())
    176       return gfx::Rect();
    177     return region_iter_.rect();
    178   }
    179   return tiling_iter_.geometry_rect();
    180 }
    181 
    182 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
    183   if (!tiling_iter_)
    184     return gfx::RectF();
    185   return tiling_iter_.texture_rect();
    186 }
    187 
    188 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
    189   if (!tiling_iter_)
    190     return gfx::Size();
    191   return tiling_iter_.texture_size();
    192 }
    193 
    194 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
    195   if (!tiling_iter_)
    196     return NULL;
    197   return *tiling_iter_;
    198 }
    199 
    200 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
    201   if (!tiling_iter_)
    202     return NULL;
    203   return *tiling_iter_;
    204 }
    205 
    206 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
    207   if (current_tiling_ < 0)
    208     return NULL;
    209   if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
    210     return NULL;
    211   return set_->tilings_[current_tiling_];
    212 }
    213 
    214 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
    215   // Order returned by this method is:
    216   // 1. Ideal tiling index
    217   // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
    218   // 3. Tiling index > Ideal in increasing order (lower res than ideal)
    219   // 4. Tiling index > tilings.size() (invalid index)
    220   if (current_tiling_ < 0)
    221     return ideal_tiling_;
    222   else if (current_tiling_ > ideal_tiling_)
    223     return current_tiling_ + 1;
    224   else if (current_tiling_)
    225     return current_tiling_ - 1;
    226   else
    227     return ideal_tiling_ + 1;
    228 }
    229 
    230 PictureLayerTilingSet::CoverageIterator&
    231 PictureLayerTilingSet::CoverageIterator::operator++() {
    232   bool first_time = current_tiling_ < 0;
    233 
    234   if (!*this && !first_time)
    235     return *this;
    236 
    237   if (tiling_iter_)
    238     ++tiling_iter_;
    239 
    240   // Loop until we find a valid place to stop.
    241   while (true) {
    242     while (tiling_iter_ &&
    243            (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
    244       missing_region_.Union(tiling_iter_.geometry_rect());
    245       ++tiling_iter_;
    246     }
    247     if (tiling_iter_)
    248       return *this;
    249 
    250     // If the set of current rects for this tiling is done, go to the next
    251     // tiling and set up to iterate through all of the remaining holes.
    252     // This will also happen the first time through the loop.
    253     if (!region_iter_.has_rect()) {
    254       current_tiling_ = NextTiling();
    255       current_region_.Swap(&missing_region_);
    256       missing_region_.Clear();
    257       region_iter_ = Region::Iterator(current_region_);
    258 
    259       // All done and all filled.
    260       if (!region_iter_.has_rect()) {
    261         current_tiling_ = set_->tilings_.size();
    262         return *this;
    263       }
    264 
    265       // No more valid tiles, return this checkerboard rect.
    266       if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
    267         return *this;
    268     }
    269 
    270     // Pop a rect off.  If there are no more tilings, then these will be
    271     // treated as geometry with null tiles that the caller can checkerboard.
    272     gfx::Rect last_rect = region_iter_.rect();
    273     region_iter_.next();
    274 
    275     // Done, found next checkerboard rect to return.
    276     if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
    277       return *this;
    278 
    279     // Construct a new iterator for the next tiling, but we need to loop
    280     // again until we get to a valid one.
    281     tiling_iter_ = PictureLayerTiling::CoverageIterator(
    282         set_->tilings_[current_tiling_],
    283         contents_scale_,
    284         last_rect);
    285   }
    286 
    287   return *this;
    288 }
    289 
    290 PictureLayerTilingSet::CoverageIterator::operator bool() const {
    291   return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
    292       region_iter_.has_rect();
    293 }
    294 
    295 void PictureLayerTilingSet::UpdateTilePriorities(
    296     WhichTree tree,
    297     gfx::Size device_viewport,
    298     gfx::Rect viewport_in_content_space,
    299     gfx::Rect visible_content_rect,
    300     gfx::Size last_layer_bounds,
    301     gfx::Size current_layer_bounds,
    302     float last_layer_contents_scale,
    303     float current_layer_contents_scale,
    304     const gfx::Transform& last_screen_transform,
    305     const gfx::Transform& current_screen_transform,
    306     double current_frame_time_in_seconds,
    307     size_t max_tiles_for_interest_area) {
    308   gfx::Rect viewport_in_layer_space = gfx::ScaleToEnclosingRect(
    309       viewport_in_content_space,
    310       1.f / current_layer_contents_scale);
    311   gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
    312       visible_content_rect,
    313       1.f / current_layer_contents_scale);
    314 
    315   for (size_t i = 0; i < tilings_.size(); ++i) {
    316     tilings_[i]->UpdateTilePriorities(
    317         tree,
    318         device_viewport,
    319         viewport_in_layer_space,
    320         visible_layer_rect,
    321         last_layer_bounds,
    322         current_layer_bounds,
    323         last_layer_contents_scale,
    324         current_layer_contents_scale,
    325         last_screen_transform,
    326         current_screen_transform,
    327         current_frame_time_in_seconds,
    328         max_tiles_for_interest_area);
    329   }
    330 }
    331 
    332 void PictureLayerTilingSet::DidBecomeActive() {
    333   for (size_t i = 0; i < tilings_.size(); ++i)
    334     tilings_[i]->DidBecomeActive();
    335 }
    336 
    337 void PictureLayerTilingSet::DidBecomeRecycled() {
    338   for (size_t i = 0; i < tilings_.size(); ++i)
    339     tilings_[i]->DidBecomeRecycled();
    340 }
    341 
    342 scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
    343   scoped_ptr<base::ListValue> state(new base::ListValue());
    344   for (size_t i = 0; i < tilings_.size(); ++i)
    345     state->Append(tilings_[i]->AsValue().release());
    346   return state.PassAs<base::Value>();
    347 }
    348 
    349 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
    350   size_t amount = 0;
    351   for (size_t i = 0; i < tilings_.size(); ++i)
    352     amount += tilings_[i]->GPUMemoryUsageInBytes();
    353   return amount;
    354 }
    355 
    356 }  // namespace cc
    357