Home | History | Annotate | Download | only in layers
      1 // Copyright 2011 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/layers/tiled_layer.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "base/auto_reset.h"
     11 #include "base/basictypes.h"
     12 #include "build/build_config.h"
     13 #include "cc/base/simple_enclosed_region.h"
     14 #include "cc/layers/layer_impl.h"
     15 #include "cc/layers/tiled_layer_impl.h"
     16 #include "cc/resources/layer_updater.h"
     17 #include "cc/resources/prioritized_resource.h"
     18 #include "cc/resources/priority_calculator.h"
     19 #include "cc/trees/layer_tree_host.h"
     20 #include "cc/trees/occlusion_tracker.h"
     21 #include "third_party/khronos/GLES2/gl2.h"
     22 #include "ui/gfx/rect_conversions.h"
     23 
     24 namespace cc {
     25 
     26 // Maximum predictive expansion of the visible area.
     27 static const int kMaxPredictiveTilesCount = 2;
     28 
     29 // Number of rows/columns of tiles to pre-paint.
     30 // We should increase these further as all textures are
     31 // prioritized and we insure performance doesn't suffer.
     32 static const int kPrepaintRows = 4;
     33 static const int kPrepaintColumns = 2;
     34 
     35 class UpdatableTile : public LayerTilingData::Tile {
     36  public:
     37   static scoped_ptr<UpdatableTile> Create(
     38       scoped_ptr<LayerUpdater::Resource> updater_resource) {
     39     return make_scoped_ptr(new UpdatableTile(updater_resource.Pass()));
     40   }
     41 
     42   LayerUpdater::Resource* updater_resource() { return updater_resource_.get(); }
     43   PrioritizedResource* managed_resource() {
     44     return updater_resource_->texture();
     45   }
     46 
     47   bool is_dirty() const { return !dirty_rect.IsEmpty(); }
     48 
     49   // Reset update state for the current frame. This should occur before painting
     50   // for all layers. Since painting one layer can invalidate another layer after
     51   // it has already painted, mark all non-dirty tiles as valid before painting
     52   // such that invalidations during painting won't prevent them from being
     53   // pushed.
     54   void ResetUpdateState() {
     55     update_rect = gfx::Rect();
     56     occluded = false;
     57     partial_update = false;
     58     valid_for_frame = !is_dirty();
     59   }
     60 
     61   // This promises to update the tile and therefore also guarantees the tile
     62   // will be valid for this frame. dirty_rect is copied into update_rect so we
     63   // can continue to track re-entrant invalidations that occur during painting.
     64   void MarkForUpdate() {
     65     valid_for_frame = true;
     66     update_rect = dirty_rect;
     67     dirty_rect = gfx::Rect();
     68   }
     69 
     70   gfx::Rect dirty_rect;
     71   gfx::Rect update_rect;
     72   bool partial_update;
     73   bool valid_for_frame;
     74   bool occluded;
     75 
     76  private:
     77   explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updater_resource)
     78       : partial_update(false),
     79         valid_for_frame(false),
     80         occluded(false),
     81         updater_resource_(updater_resource.Pass()) {}
     82 
     83   scoped_ptr<LayerUpdater::Resource> updater_resource_;
     84 
     85   DISALLOW_COPY_AND_ASSIGN(UpdatableTile);
     86 };
     87 
     88 TiledLayer::TiledLayer()
     89     : ContentsScalingLayer(),
     90       texture_format_(RGBA_8888),
     91       skips_draw_(false),
     92       failed_update_(false),
     93       tiling_option_(AUTO_TILE) {
     94   tiler_ =
     95       LayerTilingData::Create(gfx::Size(), LayerTilingData::HAS_BORDER_TEXELS);
     96 }
     97 
     98 TiledLayer::~TiledLayer() {}
     99 
    100 scoped_ptr<LayerImpl> TiledLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
    101   return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
    102 }
    103 
    104 void TiledLayer::UpdateTileSizeAndTilingOption() {
    105   DCHECK(layer_tree_host());
    106 
    107   gfx::Size default_tile_size = layer_tree_host()->settings().default_tile_size;
    108   gfx::Size max_untiled_layer_size =
    109       layer_tree_host()->settings().max_untiled_layer_size;
    110   int layer_width = content_bounds().width();
    111   int layer_height = content_bounds().height();
    112 
    113   gfx::Size tile_size(std::min(default_tile_size.width(), layer_width),
    114                       std::min(default_tile_size.height(), layer_height));
    115 
    116   // Tile if both dimensions large, or any one dimension large and the other
    117   // extends into a second tile but the total layer area isn't larger than that
    118   // of the largest possible untiled layer. This heuristic allows for long
    119   // skinny layers (e.g. scrollbars) that are Nx1 tiles to minimize wasted
    120   // texture space but still avoids creating very large tiles.
    121   bool any_dimension_large = layer_width > max_untiled_layer_size.width() ||
    122                              layer_height > max_untiled_layer_size.height();
    123   bool any_dimension_one_tile =
    124       (layer_width <= default_tile_size.width() ||
    125        layer_height <= default_tile_size.height()) &&
    126       (layer_width * layer_height) <= (max_untiled_layer_size.width() *
    127                                        max_untiled_layer_size.height());
    128   bool auto_tiled = any_dimension_large && !any_dimension_one_tile;
    129 
    130   bool is_tiled;
    131   if (tiling_option_ == ALWAYS_TILE)
    132     is_tiled = true;
    133   else if (tiling_option_ == NEVER_TILE)
    134     is_tiled = false;
    135   else
    136     is_tiled = auto_tiled;
    137 
    138   gfx::Size requested_size = is_tiled ? tile_size : content_bounds();
    139   const int max_size =
    140       layer_tree_host()->GetRendererCapabilities().max_texture_size;
    141   requested_size.SetToMin(gfx::Size(max_size, max_size));
    142   SetTileSize(requested_size);
    143 }
    144 
    145 void TiledLayer::UpdateBounds() {
    146   gfx::Size old_tiling_size = tiler_->tiling_size();
    147   gfx::Size new_tiling_size = content_bounds();
    148   if (old_tiling_size == new_tiling_size)
    149     return;
    150   tiler_->SetTilingSize(new_tiling_size);
    151 
    152   // Invalidate any areas that the new bounds exposes.
    153   Region new_region =
    154       SubtractRegions(gfx::Rect(new_tiling_size), gfx::Rect(old_tiling_size));
    155   for (Region::Iterator new_rects(new_region); new_rects.has_rect();
    156        new_rects.next())
    157     InvalidateContentRect(new_rects.rect());
    158   UpdateDrawsContent(HasDrawableContent());
    159 }
    160 
    161 void TiledLayer::SetTileSize(const gfx::Size& size) {
    162   tiler_->SetTileSize(size);
    163   UpdateDrawsContent(HasDrawableContent());
    164 }
    165 
    166 void TiledLayer::SetBorderTexelOption(
    167     LayerTilingData::BorderTexelOption border_texel_option) {
    168   tiler_->SetBorderTexelOption(border_texel_option);
    169   UpdateDrawsContent(HasDrawableContent());
    170 }
    171 
    172 bool TiledLayer::HasDrawableContent() const {
    173   bool has_more_than_one_tile =
    174       (tiler_->num_tiles_x() > 1) || (tiler_->num_tiles_y() > 1);
    175 
    176   return !(tiling_option_ == NEVER_TILE && has_more_than_one_tile) &&
    177          ContentsScalingLayer::HasDrawableContent();
    178 }
    179 
    180 void TiledLayer::ReduceMemoryUsage() {
    181   if (Updater())
    182     Updater()->ReduceMemoryUsage();
    183 }
    184 
    185 void TiledLayer::SetIsMask(bool is_mask) {
    186   set_tiling_option(is_mask ? NEVER_TILE : AUTO_TILE);
    187 }
    188 
    189 void TiledLayer::PushPropertiesTo(LayerImpl* layer) {
    190   ContentsScalingLayer::PushPropertiesTo(layer);
    191 
    192   TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer);
    193 
    194   tiled_layer->set_skips_draw(skips_draw_);
    195   tiled_layer->SetTilingData(*tiler_);
    196   std::vector<UpdatableTile*> invalid_tiles;
    197 
    198   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
    199        iter != tiler_->tiles().end();
    200        ++iter) {
    201     int i = iter->first.first;
    202     int j = iter->first.second;
    203     UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    204     // TODO(enne): This should not ever be null.
    205     if (!tile)
    206       continue;
    207 
    208     if (!tile->managed_resource()->have_backing_texture()) {
    209       // Evicted tiles get deleted from both layers
    210       invalid_tiles.push_back(tile);
    211       continue;
    212     }
    213 
    214     if (!tile->valid_for_frame) {
    215       // Invalidated tiles are set so they can get different debug colors.
    216       tiled_layer->PushInvalidTile(i, j);
    217       continue;
    218     }
    219 
    220     tiled_layer->PushTileProperties(
    221         i,
    222         j,
    223         tile->managed_resource()->resource_id(),
    224         tile->managed_resource()->contents_swizzled());
    225   }
    226   for (std::vector<UpdatableTile*>::const_iterator iter = invalid_tiles.begin();
    227        iter != invalid_tiles.end();
    228        ++iter)
    229     tiler_->TakeTile((*iter)->i(), (*iter)->j());
    230 
    231   // TiledLayer must push properties every frame, since viewport state and
    232   // occlusion from anywhere in the tree can change what the layer decides to
    233   // push to the impl tree.
    234   needs_push_properties_ = true;
    235 }
    236 
    237 PrioritizedResourceManager* TiledLayer::ResourceManager() {
    238   if (!layer_tree_host())
    239     return NULL;
    240   return layer_tree_host()->contents_texture_manager();
    241 }
    242 
    243 const PrioritizedResource* TiledLayer::ResourceAtForTesting(int i,
    244                                                             int j) const {
    245   UpdatableTile* tile = TileAt(i, j);
    246   if (!tile)
    247     return NULL;
    248   return tile->managed_resource();
    249 }
    250 
    251 void TiledLayer::SetLayerTreeHost(LayerTreeHost* host) {
    252   if (host && host != layer_tree_host()) {
    253     for (LayerTilingData::TileMap::const_iterator
    254              iter = tiler_->tiles().begin();
    255          iter != tiler_->tiles().end();
    256          ++iter) {
    257       UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    258       // TODO(enne): This should not ever be null.
    259       if (!tile)
    260         continue;
    261       tile->managed_resource()->SetTextureManager(
    262           host->contents_texture_manager());
    263     }
    264   }
    265   ContentsScalingLayer::SetLayerTreeHost(host);
    266 }
    267 
    268 UpdatableTile* TiledLayer::TileAt(int i, int j) const {
    269   return static_cast<UpdatableTile*>(tiler_->TileAt(i, j));
    270 }
    271 
    272 UpdatableTile* TiledLayer::CreateTile(int i, int j) {
    273   CreateUpdaterIfNeeded();
    274 
    275   scoped_ptr<UpdatableTile> tile(
    276       UpdatableTile::Create(Updater()->CreateResource(ResourceManager())));
    277   tile->managed_resource()->SetDimensions(tiler_->tile_size(), texture_format_);
    278 
    279   UpdatableTile* added_tile = tile.get();
    280   tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j);
    281 
    282   added_tile->dirty_rect = tiler_->TileRect(added_tile);
    283 
    284   // Temporary diagnostic crash.
    285   CHECK(added_tile);
    286   CHECK(TileAt(i, j));
    287 
    288   return added_tile;
    289 }
    290 
    291 void TiledLayer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) {
    292   InvalidateContentRect(LayerRectToContentRect(dirty_rect));
    293   ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect);
    294 }
    295 
    296 void TiledLayer::InvalidateContentRect(const gfx::Rect& content_rect) {
    297   UpdateBounds();
    298   if (tiler_->is_empty() || content_rect.IsEmpty() || skips_draw_)
    299     return;
    300 
    301   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
    302        iter != tiler_->tiles().end();
    303        ++iter) {
    304     UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    305     DCHECK(tile);
    306     // TODO(enne): This should not ever be null.
    307     if (!tile)
    308       continue;
    309     gfx::Rect bound = tiler_->TileRect(tile);
    310     bound.Intersect(content_rect);
    311     tile->dirty_rect.Union(bound);
    312   }
    313 }
    314 
    315 // Returns true if tile is dirty and only part of it needs to be updated.
    316 bool TiledLayer::TileOnlyNeedsPartialUpdate(UpdatableTile* tile) {
    317   return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) &&
    318          tile->managed_resource()->have_backing_texture();
    319 }
    320 
    321 bool TiledLayer::UpdateTiles(int left,
    322                              int top,
    323                              int right,
    324                              int bottom,
    325                              ResourceUpdateQueue* queue,
    326                              const OcclusionTracker<Layer>* occlusion,
    327                              bool* updated) {
    328   CreateUpdaterIfNeeded();
    329 
    330   bool ignore_occlusions = !occlusion;
    331   if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) {
    332     failed_update_ = true;
    333     return false;
    334   }
    335 
    336   gfx::Rect update_rect;
    337   gfx::Rect paint_rect;
    338   MarkTilesForUpdate(
    339     &update_rect, &paint_rect, left, top, right, bottom, ignore_occlusions);
    340 
    341   if (paint_rect.IsEmpty())
    342     return true;
    343 
    344   *updated = true;
    345   UpdateTileTextures(
    346       update_rect, paint_rect, left, top, right, bottom, queue, occlusion);
    347   return true;
    348 }
    349 
    350 void TiledLayer::MarkOcclusionsAndRequestTextures(
    351     int left,
    352     int top,
    353     int right,
    354     int bottom,
    355     const OcclusionTracker<Layer>* occlusion) {
    356   int occluded_tile_count = 0;
    357   bool succeeded = true;
    358   for (int j = top; j <= bottom; ++j) {
    359     for (int i = left; i <= right; ++i) {
    360       UpdatableTile* tile = TileAt(i, j);
    361       DCHECK(tile);  // Did SetTexturePriorities get skipped?
    362       // TODO(enne): This should not ever be null.
    363       if (!tile)
    364         continue;
    365       // Did ResetUpdateState get skipped? Are we doing more than one occlusion
    366       // pass?
    367       DCHECK(!tile->occluded);
    368       gfx::Rect visible_tile_rect = gfx::IntersectRects(
    369           tiler_->tile_bounds(i, j), visible_content_rect());
    370       if (!draw_transform_is_animating() && occlusion &&
    371           occlusion->GetCurrentOcclusionForLayer(draw_transform())
    372               .IsOccluded(visible_tile_rect)) {
    373         tile->occluded = true;
    374         occluded_tile_count++;
    375       } else {
    376         succeeded &= tile->managed_resource()->RequestLate();
    377       }
    378     }
    379   }
    380 }
    381 
    382 bool TiledLayer::HaveTexturesForTiles(int left,
    383                                       int top,
    384                                       int right,
    385                                       int bottom,
    386                                       bool ignore_occlusions) {
    387   for (int j = top; j <= bottom; ++j) {
    388     for (int i = left; i <= right; ++i) {
    389       UpdatableTile* tile = TileAt(i, j);
    390       DCHECK(tile);  // Did SetTexturePriorites get skipped?
    391                      // TODO(enne): This should not ever be null.
    392       if (!tile)
    393         continue;
    394 
    395       // Ensure the entire tile is dirty if we don't have the texture.
    396       if (!tile->managed_resource()->have_backing_texture())
    397         tile->dirty_rect = tiler_->TileRect(tile);
    398 
    399       // If using occlusion and the visible region of the tile is occluded,
    400       // don't reserve a texture or update the tile.
    401       if (tile->occluded && !ignore_occlusions)
    402         continue;
    403 
    404       if (!tile->managed_resource()->can_acquire_backing_texture())
    405         return false;
    406     }
    407   }
    408   return true;
    409 }
    410 
    411 void TiledLayer::MarkTilesForUpdate(gfx::Rect* update_rect,
    412                                     gfx::Rect* paint_rect,
    413                                     int left,
    414                                     int top,
    415                                     int right,
    416                                     int bottom,
    417                                     bool ignore_occlusions) {
    418   for (int j = top; j <= bottom; ++j) {
    419     for (int i = left; i <= right; ++i) {
    420       UpdatableTile* tile = TileAt(i, j);
    421       DCHECK(tile);  // Did SetTexturePriorites get skipped?
    422                      // TODO(enne): This should not ever be null.
    423       if (!tile)
    424         continue;
    425       if (tile->occluded && !ignore_occlusions)
    426         continue;
    427 
    428       // Prepare update rect from original dirty rects.
    429       update_rect->Union(tile->dirty_rect);
    430 
    431       // TODO(reveman): Decide if partial update should be allowed based on cost
    432       // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
    433       if (tile->is_dirty() &&
    434           !layer_tree_host()->AlwaysUsePartialTextureUpdates()) {
    435         // If we get a partial update, we use the same texture, otherwise return
    436         // the current texture backing, so we don't update visible textures
    437         // non-atomically.  If the current backing is in-use, it won't be
    438         // deleted until after the commit as the texture manager will not allow
    439         // deletion or recycling of in-use textures.
    440         if (TileOnlyNeedsPartialUpdate(tile) &&
    441             layer_tree_host()->RequestPartialTextureUpdate()) {
    442           tile->partial_update = true;
    443         } else {
    444           tile->dirty_rect = tiler_->TileRect(tile);
    445           tile->managed_resource()->ReturnBackingTexture();
    446         }
    447       }
    448 
    449       paint_rect->Union(tile->dirty_rect);
    450       tile->MarkForUpdate();
    451     }
    452   }
    453 }
    454 
    455 void TiledLayer::UpdateTileTextures(const gfx::Rect& update_rect,
    456                                     const gfx::Rect& paint_rect,
    457                                     int left,
    458                                     int top,
    459                                     int right,
    460                                     int bottom,
    461                                     ResourceUpdateQueue* queue,
    462                                     const OcclusionTracker<Layer>* occlusion) {
    463   // The update_rect should be in layer space. So we have to convert the
    464   // paint_rect from content space to layer space.
    465   float width_scale = 1 / draw_properties().contents_scale_x;
    466   float height_scale = 1 / draw_properties().contents_scale_y;
    467   update_rect_ = gfx::ScaleRect(update_rect, width_scale, height_scale);
    468 
    469   // Calling PrepareToUpdate() calls into WebKit to paint, which may have the
    470   // side effect of disabling compositing, which causes our reference to the
    471   // texture updater to be deleted.  However, we can't free the memory backing
    472   // the SkCanvas until the paint finishes, so we grab a local reference here to
    473   // hold the updater alive until the paint completes.
    474   scoped_refptr<LayerUpdater> protector(Updater());
    475   Updater()->PrepareToUpdate(content_bounds(),
    476                              paint_rect,
    477                              tiler_->tile_size(),
    478                              1.f / width_scale,
    479                              1.f / height_scale);
    480 
    481   for (int j = top; j <= bottom; ++j) {
    482     for (int i = left; i <= right; ++i) {
    483       UpdatableTile* tile = TileAt(i, j);
    484       DCHECK(tile);  // Did SetTexturePriorites get skipped?
    485                      // TODO(enne): This should not ever be null.
    486       if (!tile)
    487         continue;
    488 
    489       gfx::Rect tile_rect = tiler_->tile_bounds(i, j);
    490 
    491       // Use update_rect as the above loop copied the dirty rect for this frame
    492       // to update_rect.
    493       gfx::Rect dirty_rect = tile->update_rect;
    494       if (dirty_rect.IsEmpty())
    495         continue;
    496 
    497       // source_rect starts as a full-sized tile with border texels included.
    498       gfx::Rect source_rect = tiler_->TileRect(tile);
    499       source_rect.Intersect(dirty_rect);
    500       // Paint rect not guaranteed to line up on tile boundaries, so
    501       // make sure that source_rect doesn't extend outside of it.
    502       source_rect.Intersect(paint_rect);
    503 
    504       tile->update_rect = source_rect;
    505 
    506       if (source_rect.IsEmpty())
    507         continue;
    508 
    509       const gfx::Point anchor = tiler_->TileRect(tile).origin();
    510 
    511       // Calculate tile-space rectangle to upload into.
    512       gfx::Vector2d dest_offset = source_rect.origin() - anchor;
    513       CHECK_GE(dest_offset.x(), 0);
    514       CHECK_GE(dest_offset.y(), 0);
    515 
    516       // Offset from paint rectangle to this tile's dirty rectangle.
    517       gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin();
    518       CHECK_GE(paint_offset.x(), 0);
    519       CHECK_GE(paint_offset.y(), 0);
    520       CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width());
    521       CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height());
    522 
    523       tile->updater_resource()->Update(
    524           queue, source_rect, dest_offset, tile->partial_update);
    525     }
    526   }
    527 }
    528 
    529 // This picks a small animated layer to be anything less than one viewport. This
    530 // is specifically for page transitions which are viewport-sized layers. The
    531 // extra tile of padding is due to these layers being slightly larger than the
    532 // viewport in some cases.
    533 bool TiledLayer::IsSmallAnimatedLayer() const {
    534   if (!draw_transform_is_animating() && !screen_space_transform_is_animating())
    535     return false;
    536   gfx::Size viewport_size =
    537       layer_tree_host() ? layer_tree_host()->device_viewport_size()
    538                         : gfx::Size();
    539   gfx::Rect content_rect(content_bounds());
    540   return content_rect.width() <=
    541          viewport_size.width() + tiler_->tile_size().width() &&
    542          content_rect.height() <=
    543          viewport_size.height() + tiler_->tile_size().height();
    544 }
    545 
    546 namespace {
    547 // TODO(epenner): Remove this and make this based on distance once distance can
    548 // be calculated for offscreen layers. For now, prioritize all small animated
    549 // layers after 512 pixels of pre-painting.
    550 void SetPriorityForTexture(const gfx::Rect& visible_rect,
    551                            const gfx::Rect& tile_rect,
    552                            bool draws_to_root,
    553                            bool is_small_animated_layer,
    554                            PrioritizedResource* texture) {
    555   int priority = PriorityCalculator::LowestPriority();
    556   if (!visible_rect.IsEmpty()) {
    557     priority = PriorityCalculator::PriorityFromDistance(
    558         visible_rect, tile_rect, draws_to_root);
    559   }
    560 
    561   if (is_small_animated_layer) {
    562     priority = PriorityCalculator::max_priority(
    563         priority, PriorityCalculator::SmallAnimatedLayerMinPriority());
    564   }
    565 
    566   if (priority != PriorityCalculator::LowestPriority())
    567     texture->set_request_priority(priority);
    568 }
    569 }  // namespace
    570 
    571 void TiledLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) {
    572   UpdateBounds();
    573   ResetUpdateState();
    574   UpdateScrollPrediction();
    575 
    576   if (tiler_->has_empty_bounds())
    577     return;
    578 
    579   bool draws_to_root = !render_target()->parent();
    580   bool small_animated_layer = IsSmallAnimatedLayer();
    581 
    582   // Minimally create the tiles in the desired pre-paint rect.
    583   gfx::Rect create_tiles_rect = IdlePaintRect();
    584   if (small_animated_layer)
    585     create_tiles_rect = gfx::Rect(content_bounds());
    586   if (!create_tiles_rect.IsEmpty()) {
    587     int left, top, right, bottom;
    588     tiler_->ContentRectToTileIndices(
    589         create_tiles_rect, &left, &top, &right, &bottom);
    590     for (int j = top; j <= bottom; ++j) {
    591       for (int i = left; i <= right; ++i) {
    592         if (!TileAt(i, j))
    593           CreateTile(i, j);
    594       }
    595     }
    596   }
    597 
    598   // Now update priorities on all tiles we have in the layer, no matter where
    599   // they are.
    600   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
    601        iter != tiler_->tiles().end();
    602        ++iter) {
    603     UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    604     // TODO(enne): This should not ever be null.
    605     if (!tile)
    606       continue;
    607     gfx::Rect tile_rect = tiler_->TileRect(tile);
    608     SetPriorityForTexture(predicted_visible_rect_,
    609                           tile_rect,
    610                           draws_to_root,
    611                           small_animated_layer,
    612                           tile->managed_resource());
    613   }
    614 }
    615 
    616 SimpleEnclosedRegion TiledLayer::VisibleContentOpaqueRegion() const {
    617   if (skips_draw_)
    618     return SimpleEnclosedRegion();
    619   return Layer::VisibleContentOpaqueRegion();
    620 }
    621 
    622 void TiledLayer::ResetUpdateState() {
    623   skips_draw_ = false;
    624   failed_update_ = false;
    625 
    626   LayerTilingData::TileMap::const_iterator end = tiler_->tiles().end();
    627   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
    628        iter != end;
    629        ++iter) {
    630     UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    631     // TODO(enne): This should not ever be null.
    632     if (!tile)
    633       continue;
    634     tile->ResetUpdateState();
    635   }
    636 }
    637 
    638 namespace {
    639 gfx::Rect ExpandRectByDelta(const gfx::Rect& rect, const gfx::Vector2d& delta) {
    640   int width = rect.width() + std::abs(delta.x());
    641   int height = rect.height() + std::abs(delta.y());
    642   int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0);
    643   int y = rect.y() + ((delta.y() < 0) ? delta.y() : 0);
    644   return gfx::Rect(x, y, width, height);
    645 }
    646 }
    647 
    648 void TiledLayer::UpdateScrollPrediction() {
    649   // This scroll prediction is very primitive and should be replaced by a
    650   // a recursive calculation on all layers which uses actual scroll/animation
    651   // velocities. To insure this doesn't miss-predict, we only use it to predict
    652   // the visible_rect if:
    653   // - content_bounds() hasn't changed.
    654   // - visible_rect.size() hasn't changed.
    655   // These two conditions prevent rotations, scales, pinch-zooms etc. where
    656   // the prediction would be incorrect.
    657   gfx::Vector2d delta = visible_content_rect().CenterPoint() -
    658                         previous_visible_rect_.CenterPoint();
    659   predicted_scroll_ = -delta;
    660   predicted_visible_rect_ = visible_content_rect();
    661   if (previous_content_bounds_ == content_bounds() &&
    662       previous_visible_rect_.size() == visible_content_rect().size()) {
    663     // Only expand the visible rect in the major scroll direction, to prevent
    664     // massive paints due to diagonal scrolls.
    665     gfx::Vector2d major_scroll_delta =
    666         (std::abs(delta.x()) > std::abs(delta.y())) ?
    667         gfx::Vector2d(delta.x(), 0) :
    668         gfx::Vector2d(0, delta.y());
    669     predicted_visible_rect_ =
    670         ExpandRectByDelta(visible_content_rect(), major_scroll_delta);
    671 
    672     // Bound the prediction to prevent unbounded paints, and clamp to content
    673     // bounds.
    674     gfx::Rect bound = visible_content_rect();
    675     bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount,
    676                 -tiler_->tile_size().height() * kMaxPredictiveTilesCount);
    677     bound.Intersect(gfx::Rect(content_bounds()));
    678     predicted_visible_rect_.Intersect(bound);
    679   }
    680   previous_content_bounds_ = content_bounds();
    681   previous_visible_rect_ = visible_content_rect();
    682 }
    683 
    684 bool TiledLayer::Update(ResourceUpdateQueue* queue,
    685                         const OcclusionTracker<Layer>* occlusion) {
    686   DCHECK(!skips_draw_ && !failed_update_);  // Did ResetUpdateState get skipped?
    687 
    688   // Tiled layer always causes commits to wait for activation, as it does
    689   // not support pending trees.
    690   SetNextCommitWaitsForActivation();
    691 
    692   bool updated = false;
    693 
    694   {
    695     base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
    696                                                   true);
    697 
    698     updated |= ContentsScalingLayer::Update(queue, occlusion);
    699     UpdateBounds();
    700   }
    701 
    702   if (tiler_->has_empty_bounds() || !DrawsContent())
    703     return false;
    704 
    705   // Animation pre-paint. If the layer is small, try to paint it all
    706   // immediately whether or not it is occluded, to avoid paint/upload
    707   // hiccups while it is animating.
    708   if (IsSmallAnimatedLayer()) {
    709     int left, top, right, bottom;
    710     tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()),
    711                                      &left,
    712                                      &top,
    713                                      &right,
    714                                      &bottom);
    715     UpdateTiles(left, top, right, bottom, queue, NULL, &updated);
    716     if (updated)
    717       return updated;
    718     // This was an attempt to paint the entire layer so if we fail it's okay,
    719     // just fallback on painting visible etc. below.
    720     failed_update_ = false;
    721   }
    722 
    723   if (predicted_visible_rect_.IsEmpty())
    724     return updated;
    725 
    726   // Visible painting. First occlude visible tiles and paint the non-occluded
    727   // tiles.
    728   int left, top, right, bottom;
    729   tiler_->ContentRectToTileIndices(
    730       predicted_visible_rect_, &left, &top, &right, &bottom);
    731   MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion);
    732   skips_draw_ = !UpdateTiles(
    733       left, top, right, bottom, queue, occlusion, &updated);
    734   if (skips_draw_)
    735     tiler_->reset();
    736   if (skips_draw_ || updated)
    737     return true;
    738 
    739   // If we have already painting everything visible. Do some pre-painting while
    740   // idle.
    741   gfx::Rect idle_paint_content_rect = IdlePaintRect();
    742   if (idle_paint_content_rect.IsEmpty())
    743     return updated;
    744 
    745   // Prepaint anything that was occluded but inside the layer's visible region.
    746   if (!UpdateTiles(left, top, right, bottom, queue, NULL, &updated) ||
    747       updated)
    748     return updated;
    749 
    750   int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom;
    751   tiler_->ContentRectToTileIndices(idle_paint_content_rect,
    752                                    &prepaint_left,
    753                                    &prepaint_top,
    754                                    &prepaint_right,
    755                                    &prepaint_bottom);
    756 
    757   // Then expand outwards one row/column at a time until we find a dirty
    758   // row/column to update. Increment along the major and minor scroll directions
    759   // first.
    760   gfx::Vector2d delta = -predicted_scroll_;
    761   delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(),
    762                         delta.y() == 0 ? 1 : delta.y());
    763   gfx::Vector2d major_delta =
    764       (std::abs(delta.x()) > std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
    765                                         : gfx::Vector2d(0, delta.y());
    766   gfx::Vector2d minor_delta =
    767       (std::abs(delta.x()) <= std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
    768                                          : gfx::Vector2d(0, delta.y());
    769   gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta,
    770                               -minor_delta };
    771   for (int i = 0; i < 4; i++) {
    772     if (deltas[i].y() > 0) {
    773       while (bottom < prepaint_bottom) {
    774         ++bottom;
    775         if (!UpdateTiles(
    776                 left, bottom, right, bottom, queue, NULL, &updated) ||
    777             updated)
    778           return updated;
    779       }
    780     }
    781     if (deltas[i].y() < 0) {
    782       while (top > prepaint_top) {
    783         --top;
    784         if (!UpdateTiles(
    785                 left, top, right, top, queue, NULL, &updated) ||
    786             updated)
    787           return updated;
    788       }
    789     }
    790     if (deltas[i].x() < 0) {
    791       while (left > prepaint_left) {
    792         --left;
    793         if (!UpdateTiles(
    794                 left, top, left, bottom, queue, NULL, &updated) ||
    795             updated)
    796           return updated;
    797       }
    798     }
    799     if (deltas[i].x() > 0) {
    800       while (right < prepaint_right) {
    801         ++right;
    802         if (!UpdateTiles(
    803                 right, top, right, bottom, queue, NULL, &updated) ||
    804             updated)
    805           return updated;
    806       }
    807     }
    808   }
    809   return updated;
    810 }
    811 
    812 void TiledLayer::OnOutputSurfaceCreated() {
    813   // Ensure that all textures are of the right format.
    814   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
    815        iter != tiler_->tiles().end();
    816        ++iter) {
    817     UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    818     if (!tile)
    819       continue;
    820     PrioritizedResource* resource = tile->managed_resource();
    821     resource->SetDimensions(resource->size(), texture_format_);
    822   }
    823 }
    824 
    825 bool TiledLayer::NeedsIdlePaint() {
    826   // Don't trigger more paints if we failed (as we'll just fail again).
    827   if (failed_update_ || visible_content_rect().IsEmpty() ||
    828       tiler_->has_empty_bounds() || !DrawsContent())
    829     return false;
    830 
    831   gfx::Rect idle_paint_content_rect = IdlePaintRect();
    832   if (idle_paint_content_rect.IsEmpty())
    833     return false;
    834 
    835   int left, top, right, bottom;
    836   tiler_->ContentRectToTileIndices(
    837       idle_paint_content_rect, &left, &top, &right, &bottom);
    838 
    839   for (int j = top; j <= bottom; ++j) {
    840     for (int i = left; i <= right; ++i) {
    841       UpdatableTile* tile = TileAt(i, j);
    842       DCHECK(tile);  // Did SetTexturePriorities get skipped?
    843       if (!tile)
    844         continue;
    845 
    846       bool updated = !tile->update_rect.IsEmpty();
    847       bool can_acquire =
    848           tile->managed_resource()->can_acquire_backing_texture();
    849       bool dirty =
    850           tile->is_dirty() || !tile->managed_resource()->have_backing_texture();
    851       if (!updated && can_acquire && dirty)
    852         return true;
    853     }
    854   }
    855   return false;
    856 }
    857 
    858 gfx::Rect TiledLayer::IdlePaintRect() {
    859   // Don't inflate an empty rect.
    860   if (visible_content_rect().IsEmpty())
    861     return gfx::Rect();
    862 
    863   gfx::Rect prepaint_rect = visible_content_rect();
    864   prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns,
    865                       -tiler_->tile_size().height() * kPrepaintRows);
    866   gfx::Rect content_rect(content_bounds());
    867   prepaint_rect.Intersect(content_rect);
    868 
    869   return prepaint_rect;
    870 }
    871 
    872 }  // namespace cc
    873