tiled_layer.cc revision 868fa2fe829687343ffae624259930155e16dbd8
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2011 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/tiled_layer.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/auto_reset.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "build/build_config.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/overdraw_metrics.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/layer_impl.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/tiled_layer_impl.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/layer_updater.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/prioritized_resource.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/priority_calculator.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/trees/layer_tree_host.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect_conversions.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum predictive expansion of the visible area.
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kMaxPredictiveTilesCount = 2;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Number of rows/columns of tiles to pre-paint.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// We should increase these further as all textures are
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// prioritized and we insure performance doesn't suffer.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kPrepaintRows = 4;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kPrepaintColumns = 2;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class UpdatableTile : public LayerTilingData::Tile {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static scoped_ptr<UpdatableTile> Create(
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<LayerUpdater::Resource> updater_resource) {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return make_scoped_ptr(new UpdatableTile(updater_resource.Pass()));
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerUpdater::Resource* updater_resource() { return updater_resource_.get(); }
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrioritizedResource* managed_resource() {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return updater_resource_->texture();
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_dirty() const { return !dirty_rect.IsEmpty(); }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Reset update state for the current frame. This should occur before painting
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for all layers. Since painting one layer can invalidate another layer after
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // it has already painted, mark all non-dirty tiles as valid before painting
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // such that invalidations during painting won't prevent them from being
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // pushed.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ResetUpdateState() {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    update_rect = gfx::Rect();
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    occluded = false;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    partial_update = false;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    valid_for_frame = !is_dirty();
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This promises to update the tile and therefore also guarantees the tile
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // will be valid for this frame. dirty_rect is copied into update_rect so we
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // can continue to track re-entrant invalidations that occur during painting.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MarkForUpdate() {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    valid_for_frame = true;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    update_rect = dirty_rect;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dirty_rect = gfx::Rect();
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect dirty_rect;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect update_rect;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool partial_update;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool valid_for_frame;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool occluded;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updater_resource)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : partial_update(false),
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        valid_for_frame(false),
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        occluded(false),
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        updater_resource_(updater_resource.Pass()) {}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<LayerUpdater::Resource> updater_resource_;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UpdatableTile);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TiledLayer::TiledLayer()
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : ContentsScalingLayer(),
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      texture_format_(GL_INVALID_ENUM),
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      skips_draw_(false),
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      failed_update_(false),
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tiling_option_(AUTO_TILE) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_ =
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LayerTilingData::Create(gfx::Size(), LayerTilingData::HAS_BORDER_TEXELS);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TiledLayer::~TiledLayer() {}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<LayerImpl> TiledLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::UpdateTileSizeAndTilingOption() {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(layer_tree_host());
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size default_tile_size = layer_tree_host()->settings().default_tile_size;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size max_untiled_layer_size =
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      layer_tree_host()->settings().max_untiled_layer_size;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int layer_width = content_bounds().width();
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int layer_height = content_bounds().height();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size tile_size(std::min(default_tile_size.width(), layer_width),
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      std::min(default_tile_size.height(), layer_height));
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Tile if both dimensions large, or any one dimension large and the other
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // extends into a second tile but the total layer area isn't larger than that
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of the largest possible untiled layer. This heuristic allows for long
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // skinny layers (e.g. scrollbars) that are Nx1 tiles to minimize wasted
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // texture space but still avoids creating very large tiles.
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool any_dimension_large = layer_width > max_untiled_layer_size.width() ||
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             layer_height > max_untiled_layer_size.height();
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool any_dimension_one_tile =
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (layer_width <= default_tile_size.width() ||
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       layer_height <= default_tile_size.height()) &&
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (layer_width * layer_height) <= (max_untiled_layer_size.width() *
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       max_untiled_layer_size.height());
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool auto_tiled = any_dimension_large && !any_dimension_one_tile;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_tiled;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiling_option_ == ALWAYS_TILE)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_tiled = true;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (tiling_option_ == NEVER_TILE)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_tiled = false;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_tiled = auto_tiled;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size requested_size = is_tiled ? tile_size : content_bounds();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int max_size =
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      layer_tree_host()->GetRendererCapabilities().max_texture_size;
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  requested_size.SetToMin(gfx::Size(max_size, max_size));
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetTileSize(requested_size);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::UpdateBounds() {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size old_bounds = tiler_->bounds();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size new_bounds = content_bounds();
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (old_bounds == new_bounds)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->SetBounds(new_bounds);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invalidate any areas that the new bounds exposes.
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Region old_region = gfx::Rect(old_bounds);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Region new_region = gfx::Rect(new_bounds);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_region.Subtract(old_region);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Region::Iterator new_rects(new_region);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       new_rects.has_rect();
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       new_rects.next())
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InvalidateContentRect(new_rects.rect());
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetTileSize(gfx::Size size) { tiler_->SetTileSize(size); }
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetBorderTexelOption(
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerTilingData::BorderTexelOption border_texel_option) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->SetBorderTexelOption(border_texel_option);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::DrawsContent() const {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ContentsScalingLayer::DrawsContent())
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_more_than_one_tile =
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tiler_->num_tiles_x() > 1 || tiler_->num_tiles_y() > 1;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiling_option_ == NEVER_TILE && has_more_than_one_tile)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TiledLayer::ReduceMemoryUsage() {
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (Updater())
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Updater()->ReduceMemoryUsage();
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetIsMask(bool is_mask) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set_tiling_option(is_mask ? NEVER_TILE : AUTO_TILE);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::PushPropertiesTo(LayerImpl* layer) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentsScalingLayer::PushPropertiesTo(layer);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiled_layer->set_skips_draw(skips_draw_);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiled_layer->SetTilingData(*tiler_);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<UpdatableTile*> invalid_tiles;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != tiler_->tiles().end();
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int i = iter->first.first;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int j = iter->first.second;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // FIXME: This should not ever be null.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile->managed_resource()->have_backing_texture()) {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Evicted tiles get deleted from both layers
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      invalid_tiles.push_back(tile);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile->valid_for_frame) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Invalidated tiles are set so they can get different debug colors.
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tiled_layer->PushInvalidTile(i, j);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiled_layer->PushTileProperties(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        i,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        j,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tile->managed_resource()->resource_id(),
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tile->opaque_rect(),
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tile->managed_resource()->contents_swizzled());
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<UpdatableTile*>::const_iterator iter = invalid_tiles.begin();
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != invalid_tiles.end();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiler_->TakeTile((*iter)->i(), (*iter)->j());
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::BlocksPendingCommit() const { return true; }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PrioritizedResourceManager* TiledLayer::ResourceManager() const {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!layer_tree_host())
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return layer_tree_host()->contents_texture_manager();
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PrioritizedResource* TiledLayer::ResourceAtForTesting(int i,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                            int j) const {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdatableTile* tile = TileAt(i, j);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!tile)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return tile->managed_resource();
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetLayerTreeHost(LayerTreeHost* host) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (host && host != layer_tree_host()) {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (LayerTilingData::TileMap::const_iterator
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             iter = tiler_->tiles().begin();
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter != tiler_->tiles().end();
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++iter) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // FIXME: This should not ever be null.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->managed_resource()->SetTextureManager(
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          host->contents_texture_manager());
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentsScalingLayer::SetLayerTreeHost(host);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UpdatableTile* TiledLayer::TileAt(int i, int j) const {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<UpdatableTile*>(tiler_->TileAt(i, j));
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UpdatableTile* TiledLayer::CreateTile(int i, int j) {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateUpdaterIfNeeded();
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<UpdatableTile> tile(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile::Create(Updater()->CreateResource(ResourceManager())));
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tile->managed_resource()->SetDimensions(tiler_->tile_size(), texture_format_);
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdatableTile* added_tile = tile.get();
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j);
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  added_tile->dirty_rect = tiler_->TileRect(added_tile);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Temporary diagnostic crash.
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(added_tile);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(TileAt(i, j));
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return added_tile;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InvalidateContentRect(LayerRectToContentRect(dirty_rect));
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::InvalidateContentRect(gfx::Rect content_rect) {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateBounds();
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiler_->is_empty() || content_rect.IsEmpty() || skips_draw_)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != tiler_->tiles().end();
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(tile);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // FIXME: This should not ever be null.
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect bound = tiler_->TileRect(tile);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bound.Intersect(content_rect);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tile->dirty_rect.Union(bound);
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if tile is dirty and only part of it needs to be updated.
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::TileOnlyNeedsPartialUpdate(UpdatableTile* tile) {
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) &&
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         tile->managed_resource()->have_backing_texture();
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::UpdateTiles(int left,
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int top,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int right,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int bottom,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             ResourceUpdateQueue* queue,
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const OcclusionTracker* occlusion,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             RenderingStats* stats,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             bool* did_paint) {
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *did_paint = false;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateUpdaterIfNeeded();
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ignore_occlusions = !occlusion;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) {
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    failed_update_ = true;
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect paint_rect =
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions);
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (occlusion)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    occlusion->overdraw_metrics()->DidPaint(paint_rect);
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (paint_rect.IsEmpty())
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *did_paint = true;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateTileTextures(
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_rect, left, top, right, bottom, queue, occlusion, stats);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::MarkOcclusionsAndRequestTextures(
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int left,
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int top,
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int right,
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bottom,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OcclusionTracker* occlusion) {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There is some difficult dependancies between occlusions, recording
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // occlusion metrics and requesting memory so those are encapsulated in this
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // function: - We only want to call RequestLate on unoccluded textures (to
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // preserve memory for other layers when near OOM).  - We only want to record
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // occlusion metrics if all memory requests succeed.
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int occluded_tile_count = 0;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool succeeded = true;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorities get skipped?
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // FIXME: This should not ever be null.
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Did ResetUpdateState get skipped? Are we doing more than one occlusion
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // pass?
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!tile->occluded);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect visible_tile_rect = gfx::IntersectRects(
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tiler_->tile_bounds(i, j), visible_content_rect());
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (occlusion && occlusion->Occluded(render_target(),
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           visible_tile_rect,
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           draw_transform(),
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           draw_transform_is_animating(),
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           is_clipped(),
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           clip_rect(),
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           NULL)) {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tile->occluded = true;
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        occluded_tile_count++;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        succeeded &= tile->managed_resource()->RequestLate();
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!succeeded)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (occlusion)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    occlusion->overdraw_metrics()->DidCullTilesForUpload(occluded_tile_count);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::HaveTexturesForTiles(int left,
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int top,
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int right,
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int bottom,
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      bool ignore_occlusions) {
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorites get skipped?
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     // FIXME: This should not ever be null.
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Ensure the entire tile is dirty if we don't have the texture.
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile->managed_resource()->have_backing_texture())
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tile->dirty_rect = tiler_->TileRect(tile);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If using occlusion and the visible region of the tile is occluded,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // don't reserve a texture or update the tile.
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (tile->occluded && !ignore_occlusions)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile->managed_resource()->can_acquire_backing_texture())
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect TiledLayer::MarkTilesForUpdate(int left,
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int top,
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int right,
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int bottom,
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool ignore_occlusions) {
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect paint_rect;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorites get skipped?
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     // FIXME: This should not ever be null.
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (tile->occluded && !ignore_occlusions)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // FIXME: Decide if partial update should be allowed based on cost
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (tile->is_dirty() && layer_tree_host() &&
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          layer_tree_host()->buffered_updates()) {
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If we get a partial update, we use the same texture, otherwise return
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // the current texture backing, so we don't update visible textures
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // non-atomically.  If the current backing is in-use, it won't be
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // deleted until after the commit as the texture manager will not allow
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // deletion or recycling of in-use textures.
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (TileOnlyNeedsPartialUpdate(tile) &&
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            layer_tree_host()->RequestPartialTextureUpdate()) {
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->partial_update = true;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->dirty_rect = tiler_->TileRect(tile);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->managed_resource()->ReturnBackingTexture();
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_rect.Union(tile->dirty_rect);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->MarkForUpdate();
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return paint_rect;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::UpdateTileTextures(gfx::Rect paint_rect,
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int left,
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int top,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int right,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int bottom,
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    ResourceUpdateQueue* queue,
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    const OcclusionTracker* occlusion,
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    RenderingStats* stats) {
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update_rect should be in layer space. So we have to convert the
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // paint_rect from content space to layer space.
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float width_scale =
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paint_properties().bounds.width() /
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      static_cast<float>(content_bounds().width());
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float height_scale =
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paint_properties().bounds.height() /
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      static_cast<float>(content_bounds().height());
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  update_rect_ = gfx::ScaleRect(paint_rect, width_scale, height_scale);
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calling PrepareToUpdate() calls into WebKit to paint, which may have the
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // side effect of disabling compositing, which causes our reference to the
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // texture updater to be deleted.  However, we can't free the memory backing
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the SkCanvas until the paint finishes, so we grab a local reference here to
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // hold the updater alive until the paint completes.
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<LayerUpdater> protector(Updater());
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect painted_opaque_rect;
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Updater()->PrepareToUpdate(paint_rect,
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             tiler_->tile_size(),
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             1.f / width_scale,
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             1.f / height_scale,
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             &painted_opaque_rect,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             stats);
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorites get skipped?
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     // FIXME: This should not ever be null.
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect tile_rect = tiler_->tile_bounds(i, j);
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Use update_rect as the above loop copied the dirty rect for this frame
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // to update_rect.
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect dirty_rect = tile->update_rect;
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (dirty_rect.IsEmpty())
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Save what was painted opaque in the tile. Keep the old area if the
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // paint didn't touch it, and didn't paint some other part of the tile
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // opaque.
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect tile_painted_rect = gfx::IntersectRects(tile_rect, paint_rect);
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect tile_painted_opaque_rect =
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gfx::IntersectRects(tile_rect, painted_opaque_rect);
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile_painted_rect.IsEmpty()) {
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gfx::Rect paint_inside_tile_opaque_rect =
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            gfx::IntersectRects(tile->opaque_rect(), tile_painted_rect);
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool paint_inside_tile_opaque_rect_is_non_opaque =
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            !paint_inside_tile_opaque_rect.IsEmpty() &&
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !tile_painted_opaque_rect.Contains(paint_inside_tile_opaque_rect);
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool opaque_paint_not_inside_tile_opaque_rect =
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !tile_painted_opaque_rect.IsEmpty() &&
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !tile->opaque_rect().Contains(tile_painted_opaque_rect);
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (paint_inside_tile_opaque_rect_is_non_opaque ||
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            opaque_paint_not_inside_tile_opaque_rect)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->set_opaque_rect(tile_painted_opaque_rect);
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // source_rect starts as a full-sized tile with border texels included.
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect source_rect = tiler_->TileRect(tile);
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      source_rect.Intersect(dirty_rect);
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Paint rect not guaranteed to line up on tile boundaries, so
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // make sure that source_rect doesn't extend outside of it.
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      source_rect.Intersect(paint_rect);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->update_rect = source_rect;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (source_rect.IsEmpty())
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Point anchor = tiler_->TileRect(tile).origin();
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Calculate tile-space rectangle to upload into.
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Vector2d dest_offset = source_rect.origin() - anchor;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(dest_offset.x(), 0);
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(dest_offset.y(), 0);
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Offset from paint rectangle to this tile's dirty rectangle.
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin();
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(paint_offset.x(), 0);
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(paint_offset.y(), 0);
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width());
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height());
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->updater_resource()->Update(
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          queue, source_rect, dest_offset, tile->partial_update, stats);
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (occlusion) {
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        occlusion->overdraw_metrics()->
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DidUpload(gfx::Transform(), source_rect, tile->opaque_rect());
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This picks a small animated layer to be anything less than one viewport. This
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is specifically for page transitions which are viewport-sized layers. The
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// extra tile of padding is due to these layers being slightly larger than the
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// viewport in some cases.
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::IsSmallAnimatedLayer() const {
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!draw_transform_is_animating() && !screen_space_transform_is_animating())
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size viewport_size =
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      layer_tree_host() ? layer_tree_host()->device_viewport_size()
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        : gfx::Size();
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect content_rect(content_bounds());
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return content_rect.width() <=
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         viewport_size.width() + tiler_->tile_size().width() &&
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         content_rect.height() <=
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         viewport_size.height() + tiler_->tile_size().height();
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FIXME: Remove this and make this based on distance once distance can be
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// calculated for offscreen layers. For now, prioritize all small animated
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// layers after 512 pixels of pre-painting.
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetPriorityForTexture(gfx::Rect visible_rect,
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           gfx::Rect tile_rect,
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bool draws_to_root,
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bool is_small_animated_layer,
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           PrioritizedResource* texture) {
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int priority = PriorityCalculator::LowestPriority();
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!visible_rect.IsEmpty()) {
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    priority = PriorityCalculator::PriorityFromDistance(
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        visible_rect, tile_rect, draws_to_root);
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_small_animated_layer) {
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    priority = PriorityCalculator::max_priority(
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        priority, PriorityCalculator::SmallAnimatedLayerMinPriority());
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (priority != PriorityCalculator::LowestPriority())
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    texture->set_request_priority(priority);
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) {
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateBounds();
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetUpdateState();
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateScrollPrediction();
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiler_->has_empty_bounds())
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool draws_to_root = !render_target()->parent();
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool small_animated_layer = IsSmallAnimatedLayer();
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Minimally create the tiles in the desired pre-paint rect.
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect create_tiles_rect = IdlePaintRect();
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (small_animated_layer)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    create_tiles_rect = gfx::Rect(content_bounds());
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!create_tiles_rect.IsEmpty()) {
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int left, top, right, bottom;
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiler_->ContentRectToTileIndices(
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        create_tiles_rect, &left, &top, &right, &bottom);
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int j = top; j <= bottom; ++j) {
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (int i = left; i <= right; ++i) {
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!TileAt(i, j))
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          CreateTile(i, j);
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Now update priorities on all tiles we have in the layer, no matter where
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // they are.
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != tiler_->tiles().end();
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // FIXME: This should not ever be null.
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile)
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect tile_rect = tiler_->TileRect(tile);
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetPriorityForTexture(predicted_visible_rect_,
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          tile_rect,
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          draws_to_root,
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          small_animated_layer,
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          tile->managed_resource());
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Region TiledLayer::VisibleContentOpaqueRegion() const {
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (skips_draw_)
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Region();
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (contents_opaque())
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return visible_content_rect();
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return tiler_->OpaqueRegionInContentRect(visible_content_rect());
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::ResetUpdateState() {
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  skips_draw_ = false;
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  failed_update_ = false;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerTilingData::TileMap::const_iterator end = tiler_->tiles().end();
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != end;
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // FIXME: This should not ever be null.
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile)
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tile->ResetUpdateState();
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect ExpandRectByDelta(gfx::Rect rect, gfx::Vector2d delta) {
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width = rect.width() + std::abs(delta.x());
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int height = rect.height() + std::abs(delta.y());
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0);
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int y = rect.y() + ((delta.y() < 0) ? delta.y() : 0);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Rect(x, y, width, height);
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::UpdateScrollPrediction() {
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This scroll prediction is very primitive and should be replaced by a
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a recursive calculation on all layers which uses actual scroll/animation
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // velocities. To insure this doesn't miss-predict, we only use it to predict
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the visible_rect if:
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // - content_bounds() hasn't changed.
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // - visible_rect.size() hasn't changed.
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // These two conditions prevent rotations, scales, pinch-zooms etc. where
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the prediction would be incorrect.
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d delta = visible_content_rect().CenterPoint() -
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        previous_visible_rect_.CenterPoint();
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  predicted_scroll_ = -delta;
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  predicted_visible_rect_ = visible_content_rect();
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (previous_content_bounds_ == content_bounds() &&
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      previous_visible_rect_.size() == visible_content_rect().size()) {
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Only expand the visible rect in the major scroll direction, to prevent
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // massive paints due to diagonal scrolls.
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Vector2d major_scroll_delta =
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (std::abs(delta.x()) > std::abs(delta.y())) ?
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gfx::Vector2d(delta.x(), 0) :
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gfx::Vector2d(0, delta.y());
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    predicted_visible_rect_ =
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ExpandRectByDelta(visible_content_rect(), major_scroll_delta);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Bound the prediction to prevent unbounded paints, and clamp to content
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // bounds.
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect bound = visible_content_rect();
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount,
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                -tiler_->tile_size().height() * kMaxPredictiveTilesCount);
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bound.Intersect(gfx::Rect(content_bounds()));
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    predicted_visible_rect_.Intersect(bound);
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  previous_content_bounds_ = content_bounds();
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  previous_visible_rect_ = visible_content_rect();
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::Update(ResourceUpdateQueue* queue,
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        const OcclusionTracker* occlusion,
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        RenderingStats* stats) {
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!skips_draw_ && !failed_update_);  // Did ResetUpdateState get skipped?
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  true);
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ContentsScalingLayer::Update(queue, occlusion, stats);
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateBounds();
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiler_->has_empty_bounds() || !DrawsContent())
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool did_paint = false;
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Animation pre-paint. If the layer is small, try to paint it all
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // immediately whether or not it is occluded, to avoid paint/upload
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // hiccups while it is animating.
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsSmallAnimatedLayer()) {
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int left, top, right, bottom;
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()),
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &left,
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &top,
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &right,
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &bottom);
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateTiles(left, top, right, bottom, queue, NULL, stats, &did_paint);
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (did_paint)
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This was an attempt to paint the entire layer so if we fail it's okay,
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // just fallback on painting visible etc. below.
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    failed_update_ = false;
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (predicted_visible_rect_.IsEmpty())
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Visible painting. First occlude visible tiles and paint the non-occluded
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // tiles.
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int left, top, right, bottom;
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->ContentRectToTileIndices(
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      predicted_visible_rect_, &left, &top, &right, &bottom);
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion);
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  skips_draw_ = !UpdateTiles(
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      left, top, right, bottom, queue, occlusion, stats, &did_paint);
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (skips_draw_)
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiler_->reset();
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (skips_draw_ || did_paint)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we have already painting everything visible. Do some pre-painting while
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // idle.
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect idle_paint_content_rect = IdlePaintRect();
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (idle_paint_content_rect.IsEmpty())
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Prepaint anything that was occluded but inside the layer's visible region.
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!UpdateTiles(left, top, right, bottom, queue, NULL, stats, &did_paint) ||
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      did_paint)
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom;
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->ContentRectToTileIndices(idle_paint_content_rect,
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_left,
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_top,
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_right,
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_bottom);
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then expand outwards one row/column at a time until we find a dirty
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // row/column to update. Increment along the major and minor scroll directions
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // first.
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d delta = -predicted_scroll_;
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(),
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        delta.y() == 0 ? 1 : delta.y());
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d major_delta =
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (abs(delta.x()) > abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        : gfx::Vector2d(0, delta.y());
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d minor_delta =
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (abs(delta.x()) <= abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         : gfx::Vector2d(0, delta.y());
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta,
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              -minor_delta };
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < 4; i++) {
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].y() > 0) {
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (bottom < prepaint_bottom) {
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ++bottom;
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                left, bottom, right, bottom, queue, NULL, stats, &did_paint) ||
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            did_paint)
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].y() < 0) {
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (top > prepaint_top) {
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        --top;
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                left, top, right, top, queue, NULL, stats, &did_paint) ||
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            did_paint)
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].x() < 0) {
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (left > prepaint_left) {
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        --left;
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                left, top, left, bottom, queue, NULL, stats, &did_paint) ||
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            did_paint)
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].x() > 0) {
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (right < prepaint_right) {
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ++right;
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                right, top, right, bottom, queue, NULL, stats, &did_paint) ||
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            did_paint)
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::NeedsIdlePaint() {
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't trigger more paints if we failed (as we'll just fail again).
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (failed_update_ || visible_content_rect().IsEmpty() ||
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tiler_->has_empty_bounds() || !DrawsContent())
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect idle_paint_content_rect = IdlePaintRect();
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (idle_paint_content_rect.IsEmpty())
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int left, top, right, bottom;
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->ContentRectToTileIndices(
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      idle_paint_content_rect, &left, &top, &right, &bottom);
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorities get skipped?
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool updated = !tile->update_rect.IsEmpty();
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool can_acquire =
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->managed_resource()->can_acquire_backing_texture();
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool dirty =
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->is_dirty() || !tile->managed_resource()->have_backing_texture();
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!updated && can_acquire && dirty)
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect TiledLayer::IdlePaintRect() {
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't inflate an empty rect.
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visible_content_rect().IsEmpty())
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Rect();
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect prepaint_rect = visible_content_rect();
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns,
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      -tiler_->tile_size().height() * kPrepaintRows);
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect content_rect(content_bounds());
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prepaint_rect.Intersect(content_rect);
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return prepaint_rect;
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
900