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);
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(enne): 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());
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // TiledLayer must push properties every frame, since viewport state and
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // occlusion from anywhere in the tree can change what the layer decides to
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // push to the impl tree.
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  needs_push_properties_ = true;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::BlocksPendingCommit() const { return true; }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PrioritizedResourceManager* TiledLayer::ResourceManager() const {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!layer_tree_host())
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return layer_tree_host()->contents_texture_manager();
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PrioritizedResource* TiledLayer::ResourceAtForTesting(int i,
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                            int j) const {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdatableTile* tile = TileAt(i, j);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!tile)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return tile->managed_resource();
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetLayerTreeHost(LayerTreeHost* host) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (host && host != layer_tree_host()) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (LayerTilingData::TileMap::const_iterator
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             iter = tiler_->tiles().begin();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter != tiler_->tiles().end();
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++iter) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // TODO(enne): This should not ever be null.
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->managed_resource()->SetTextureManager(
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          host->contents_texture_manager());
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentsScalingLayer::SetLayerTreeHost(host);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UpdatableTile* TiledLayer::TileAt(int i, int j) const {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<UpdatableTile*>(tiler_->TileAt(i, j));
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UpdatableTile* TiledLayer::CreateTile(int i, int j) {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateUpdaterIfNeeded();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<UpdatableTile> tile(
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile::Create(Updater()->CreateResource(ResourceManager())));
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tile->managed_resource()->SetDimensions(tiler_->tile_size(), texture_format_);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdatableTile* added_tile = tile.get();
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  added_tile->dirty_rect = tiler_->TileRect(added_tile);
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Temporary diagnostic crash.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(added_tile);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(TileAt(i, j));
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return added_tile;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InvalidateContentRect(LayerRectToContentRect(dirty_rect));
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::InvalidateContentRect(gfx::Rect content_rect) {
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateBounds();
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiler_->is_empty() || content_rect.IsEmpty() || skips_draw_)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != tiler_->tiles().end();
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(tile);
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(enne): This should not ever be null.
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect bound = tiler_->TileRect(tile);
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bound.Intersect(content_rect);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tile->dirty_rect.Union(bound);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if tile is dirty and only part of it needs to be updated.
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::TileOnlyNeedsPartialUpdate(UpdatableTile* tile) {
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) &&
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         tile->managed_resource()->have_backing_texture();
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::UpdateTiles(int left,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int top,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int right,
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int bottom,
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             ResourceUpdateQueue* queue,
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const OcclusionTracker* occlusion,
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             bool* updated) {
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateUpdaterIfNeeded();
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ignore_occlusions = !occlusion;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) {
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    failed_update_ = true;
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect paint_rect =
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions);
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (occlusion)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    occlusion->overdraw_metrics()->DidPaint(paint_rect);
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (paint_rect.IsEmpty())
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  *updated = true;
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateTileTextures(
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      paint_rect, left, top, right, bottom, queue, occlusion);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::MarkOcclusionsAndRequestTextures(
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int left,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int top,
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int right,
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bottom,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OcclusionTracker* occlusion) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There is some difficult dependancies between occlusions, recording
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // occlusion metrics and requesting memory so those are encapsulated in this
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // function: - We only want to call RequestLate on unoccluded textures (to
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // preserve memory for other layers when near OOM).  - We only want to record
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // occlusion metrics if all memory requests succeed.
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int occluded_tile_count = 0;
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool succeeded = true;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorities get skipped?
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // TODO(enne): This should not ever be null.
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Did ResetUpdateState get skipped? Are we doing more than one occlusion
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // pass?
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(!tile->occluded);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect visible_tile_rect = gfx::IntersectRects(
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tiler_->tile_bounds(i, j), visible_content_rect());
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (occlusion && occlusion->Occluded(render_target(),
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           visible_tile_rect,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           draw_transform(),
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           draw_transform_is_animating(),
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           is_clipped(),
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           clip_rect(),
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           NULL)) {
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tile->occluded = true;
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        occluded_tile_count++;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        succeeded &= tile->managed_resource()->RequestLate();
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!succeeded)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (occlusion)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    occlusion->overdraw_metrics()->DidCullTilesForUpload(occluded_tile_count);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::HaveTexturesForTiles(int left,
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int top,
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int right,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int bottom,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      bool ignore_occlusions) {
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorites get skipped?
410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     // TODO(enne): This should not ever be null.
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Ensure the entire tile is dirty if we don't have the texture.
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile->managed_resource()->have_backing_texture())
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tile->dirty_rect = tiler_->TileRect(tile);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If using occlusion and the visible region of the tile is occluded,
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // don't reserve a texture or update the tile.
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (tile->occluded && !ignore_occlusions)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile->managed_resource()->can_acquire_backing_texture())
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect TiledLayer::MarkTilesForUpdate(int left,
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int top,
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int right,
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int bottom,
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool ignore_occlusions) {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect paint_rect;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorites get skipped?
440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     // TODO(enne): This should not ever be null.
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (tile->occluded && !ignore_occlusions)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // TODO(reveman): Decide if partial update should be allowed based on cost
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (tile->is_dirty() && layer_tree_host() &&
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          layer_tree_host()->buffered_updates()) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If we get a partial update, we use the same texture, otherwise return
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // the current texture backing, so we don't update visible textures
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // non-atomically.  If the current backing is in-use, it won't be
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // deleted until after the commit as the texture manager will not allow
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // deletion or recycling of in-use textures.
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (TileOnlyNeedsPartialUpdate(tile) &&
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            layer_tree_host()->RequestPartialTextureUpdate()) {
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->partial_update = true;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->dirty_rect = tiler_->TileRect(tile);
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->managed_resource()->ReturnBackingTexture();
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_rect.Union(tile->dirty_rect);
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->MarkForUpdate();
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return paint_rect;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::UpdateTileTextures(gfx::Rect paint_rect,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int left,
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int top,
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int right,
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int bottom,
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    ResourceUpdateQueue* queue,
476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    const OcclusionTracker* occlusion) {
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The update_rect should be in layer space. So we have to convert the
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // paint_rect from content space to layer space.
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float width_scale =
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paint_properties().bounds.width() /
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      static_cast<float>(content_bounds().width());
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float height_scale =
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paint_properties().bounds.height() /
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      static_cast<float>(content_bounds().height());
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  update_rect_ = gfx::ScaleRect(paint_rect, width_scale, height_scale);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calling PrepareToUpdate() calls into WebKit to paint, which may have the
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // side effect of disabling compositing, which causes our reference to the
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // texture updater to be deleted.  However, we can't free the memory backing
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the SkCanvas until the paint finishes, so we grab a local reference here to
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // hold the updater alive until the paint completes.
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<LayerUpdater> protector(Updater());
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect painted_opaque_rect;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Updater()->PrepareToUpdate(paint_rect,
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             tiler_->tile_size(),
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             1.f / width_scale,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             1.f / height_scale,
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             &painted_opaque_rect);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorites get skipped?
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     // TODO(enne): This should not ever be null.
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect tile_rect = tiler_->tile_bounds(i, j);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Use update_rect as the above loop copied the dirty rect for this frame
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // to update_rect.
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect dirty_rect = tile->update_rect;
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (dirty_rect.IsEmpty())
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Save what was painted opaque in the tile. Keep the old area if the
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // paint didn't touch it, and didn't paint some other part of the tile
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // opaque.
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect tile_painted_rect = gfx::IntersectRects(tile_rect, paint_rect);
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect tile_painted_opaque_rect =
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gfx::IntersectRects(tile_rect, painted_opaque_rect);
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile_painted_rect.IsEmpty()) {
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gfx::Rect paint_inside_tile_opaque_rect =
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            gfx::IntersectRects(tile->opaque_rect(), tile_painted_rect);
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool paint_inside_tile_opaque_rect_is_non_opaque =
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            !paint_inside_tile_opaque_rect.IsEmpty() &&
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !tile_painted_opaque_rect.Contains(paint_inside_tile_opaque_rect);
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool opaque_paint_not_inside_tile_opaque_rect =
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !tile_painted_opaque_rect.IsEmpty() &&
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !tile->opaque_rect().Contains(tile_painted_opaque_rect);
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (paint_inside_tile_opaque_rect_is_non_opaque ||
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            opaque_paint_not_inside_tile_opaque_rect)
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->set_opaque_rect(tile_painted_opaque_rect);
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // source_rect starts as a full-sized tile with border texels included.
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect source_rect = tiler_->TileRect(tile);
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      source_rect.Intersect(dirty_rect);
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Paint rect not guaranteed to line up on tile boundaries, so
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // make sure that source_rect doesn't extend outside of it.
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      source_rect.Intersect(paint_rect);
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->update_rect = source_rect;
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (source_rect.IsEmpty())
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const gfx::Point anchor = tiler_->TileRect(tile).origin();
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Calculate tile-space rectangle to upload into.
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Vector2d dest_offset = source_rect.origin() - anchor;
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(dest_offset.x(), 0);
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(dest_offset.y(), 0);
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Offset from paint rectangle to this tile's dirty rectangle.
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin();
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(paint_offset.x(), 0);
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_GE(paint_offset.y(), 0);
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width());
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height());
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tile->updater_resource()->Update(
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          queue, source_rect, dest_offset, tile->partial_update);
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (occlusion) {
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        occlusion->overdraw_metrics()->
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DidUpload(gfx::Transform(), source_rect, tile->opaque_rect());
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This picks a small animated layer to be anything less than one viewport. This
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is specifically for page transitions which are viewport-sized layers. The
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// extra tile of padding is due to these layers being slightly larger than the
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// viewport in some cases.
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::IsSmallAnimatedLayer() const {
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!draw_transform_is_animating() && !screen_space_transform_is_animating())
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size viewport_size =
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      layer_tree_host() ? layer_tree_host()->device_viewport_size()
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        : gfx::Size();
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect content_rect(content_bounds());
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return content_rect.width() <=
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         viewport_size.width() + tiler_->tile_size().width() &&
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         content_rect.height() <=
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         viewport_size.height() + tiler_->tile_size().height();
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(epenner): Remove this and make this based on distance once distance can
592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be calculated for offscreen layers. For now, prioritize all small animated
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// layers after 512 pixels of pre-painting.
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetPriorityForTexture(gfx::Rect visible_rect,
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           gfx::Rect tile_rect,
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bool draws_to_root,
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bool is_small_animated_layer,
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           PrioritizedResource* texture) {
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int priority = PriorityCalculator::LowestPriority();
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!visible_rect.IsEmpty()) {
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    priority = PriorityCalculator::PriorityFromDistance(
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        visible_rect, tile_rect, draws_to_root);
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_small_animated_layer) {
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    priority = PriorityCalculator::max_priority(
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        priority, PriorityCalculator::SmallAnimatedLayerMinPriority());
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (priority != PriorityCalculator::LowestPriority())
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    texture->set_request_priority(priority);
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) {
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateBounds();
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetUpdateState();
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateScrollPrediction();
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiler_->has_empty_bounds())
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool draws_to_root = !render_target()->parent();
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool small_animated_layer = IsSmallAnimatedLayer();
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Minimally create the tiles in the desired pre-paint rect.
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect create_tiles_rect = IdlePaintRect();
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (small_animated_layer)
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    create_tiles_rect = gfx::Rect(content_bounds());
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!create_tiles_rect.IsEmpty()) {
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int left, top, right, bottom;
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiler_->ContentRectToTileIndices(
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        create_tiles_rect, &left, &top, &right, &bottom);
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int j = top; j <= bottom; ++j) {
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (int i = left; i <= right; ++i) {
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!TileAt(i, j))
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          CreateTile(i, j);
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Now update priorities on all tiles we have in the layer, no matter where
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // they are.
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != tiler_->tiles().end();
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(enne): This should not ever be null.
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect tile_rect = tiler_->TileRect(tile);
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetPriorityForTexture(predicted_visible_rect_,
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          tile_rect,
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          draws_to_root,
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          small_animated_layer,
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          tile->managed_resource());
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Region TiledLayer::VisibleContentOpaqueRegion() const {
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (skips_draw_)
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Region();
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (contents_opaque())
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return visible_content_rect();
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return tiler_->OpaqueRegionInContentRect(visible_content_rect());
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::ResetUpdateState() {
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  skips_draw_ = false;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  failed_update_ = false;
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerTilingData::TileMap::const_iterator end = tiler_->tiles().end();
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != end;
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(enne): This should not ever be null.
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!tile)
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tile->ResetUpdateState();
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect ExpandRectByDelta(gfx::Rect rect, gfx::Vector2d delta) {
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width = rect.width() + std::abs(delta.x());
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int height = rect.height() + std::abs(delta.y());
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int y = rect.y() + ((delta.y() < 0) ? delta.y() : 0);
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Rect(x, y, width, height);
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TiledLayer::UpdateScrollPrediction() {
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This scroll prediction is very primitive and should be replaced by a
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a recursive calculation on all layers which uses actual scroll/animation
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // velocities. To insure this doesn't miss-predict, we only use it to predict
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the visible_rect if:
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // - content_bounds() hasn't changed.
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // - visible_rect.size() hasn't changed.
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // These two conditions prevent rotations, scales, pinch-zooms etc. where
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the prediction would be incorrect.
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d delta = visible_content_rect().CenterPoint() -
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        previous_visible_rect_.CenterPoint();
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  predicted_scroll_ = -delta;
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  predicted_visible_rect_ = visible_content_rect();
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (previous_content_bounds_ == content_bounds() &&
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      previous_visible_rect_.size() == visible_content_rect().size()) {
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Only expand the visible rect in the major scroll direction, to prevent
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // massive paints due to diagonal scrolls.
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Vector2d major_scroll_delta =
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (std::abs(delta.x()) > std::abs(delta.y())) ?
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gfx::Vector2d(delta.x(), 0) :
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gfx::Vector2d(0, delta.y());
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    predicted_visible_rect_ =
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ExpandRectByDelta(visible_content_rect(), major_scroll_delta);
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Bound the prediction to prevent unbounded paints, and clamp to content
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // bounds.
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect bound = visible_content_rect();
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount,
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                -tiler_->tile_size().height() * kMaxPredictiveTilesCount);
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bound.Intersect(gfx::Rect(content_bounds()));
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    predicted_visible_rect_.Intersect(bound);
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  previous_content_bounds_ = content_bounds();
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  previous_visible_rect_ = visible_content_rect();
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool TiledLayer::Update(ResourceUpdateQueue* queue,
731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        const OcclusionTracker* occlusion) {
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!skips_draw_ && !failed_update_);  // Did ResetUpdateState get skipped?
733a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
734a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool updated = false;
735a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  true);
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
740a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    updated |= ContentsScalingLayer::Update(queue, occlusion);
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdateBounds();
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (tiler_->has_empty_bounds() || !DrawsContent())
7457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Animation pre-paint. If the layer is small, try to paint it all
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // immediately whether or not it is occluded, to avoid paint/upload
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // hiccups while it is animating.
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsSmallAnimatedLayer()) {
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int left, top, right, bottom;
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()),
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &left,
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &top,
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &right,
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     &bottom);
757a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    UpdateTiles(left, top, right, bottom, queue, NULL, &updated);
758a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (updated)
759a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return updated;
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This was an attempt to paint the entire layer so if we fail it's okay,
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // just fallback on painting visible etc. below.
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    failed_update_ = false;
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (predicted_visible_rect_.IsEmpty())
766a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return updated;
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Visible painting. First occlude visible tiles and paint the non-occluded
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // tiles.
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int left, top, right, bottom;
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->ContentRectToTileIndices(
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      predicted_visible_rect_, &left, &top, &right, &bottom);
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion);
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  skips_draw_ = !UpdateTiles(
775a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      left, top, right, bottom, queue, occlusion, &updated);
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (skips_draw_)
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tiler_->reset();
778a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (skips_draw_ || updated)
7797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return true;
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we have already painting everything visible. Do some pre-painting while
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // idle.
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect idle_paint_content_rect = IdlePaintRect();
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (idle_paint_content_rect.IsEmpty())
785a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return updated;
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Prepaint anything that was occluded but inside the layer's visible region.
788a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!UpdateTiles(left, top, right, bottom, queue, NULL, &updated) ||
789a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      updated)
790a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return updated;
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom;
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->ContentRectToTileIndices(idle_paint_content_rect,
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_left,
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_top,
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_right,
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   &prepaint_bottom);
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then expand outwards one row/column at a time until we find a dirty
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // row/column to update. Increment along the major and minor scroll directions
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // first.
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d delta = -predicted_scroll_;
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(),
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        delta.y() == 0 ? 1 : delta.y());
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d major_delta =
806558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      (std::abs(delta.x()) > std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        : gfx::Vector2d(0, delta.y());
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d minor_delta =
809558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      (std::abs(delta.x()) <= std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         : gfx::Vector2d(0, delta.y());
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta,
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              -minor_delta };
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < 4; i++) {
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].y() > 0) {
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (bottom < prepaint_bottom) {
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ++bottom;
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
818a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                left, bottom, right, bottom, queue, NULL, &updated) ||
819a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            updated)
820a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          return updated;
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].y() < 0) {
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (top > prepaint_top) {
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        --top;
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
827a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                left, top, right, top, queue, NULL, &updated) ||
828a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            updated)
829a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          return updated;
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].x() < 0) {
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (left > prepaint_left) {
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        --left;
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
836a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                left, top, left, bottom, queue, NULL, &updated) ||
837a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            updated)
838a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          return updated;
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deltas[i].x() > 0) {
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      while (right < prepaint_right) {
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ++right;
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!UpdateTiles(
845a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                right, top, right, bottom, queue, NULL, &updated) ||
846a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            updated)
847a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          return updated;
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
851a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return updated;
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TiledLayer::NeedsIdlePaint() {
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't trigger more paints if we failed (as we'll just fail again).
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (failed_update_ || visible_content_rect().IsEmpty() ||
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tiler_->has_empty_bounds() || !DrawsContent())
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect idle_paint_content_rect = IdlePaintRect();
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (idle_paint_content_rect.IsEmpty())
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int left, top, right, bottom;
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tiler_->ContentRectToTileIndices(
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      idle_paint_content_rect, &left, &top, &right, &bottom);
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int j = top; j <= bottom; ++j) {
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = left; i <= right; ++i) {
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatableTile* tile = TileAt(i, j);
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(tile);  // Did SetTexturePriorities get skipped?
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!tile)
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool updated = !tile->update_rect.IsEmpty();
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool can_acquire =
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->managed_resource()->can_acquire_backing_texture();
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool dirty =
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          tile->is_dirty() || !tile->managed_resource()->have_backing_texture();
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!updated && can_acquire && dirty)
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect TiledLayer::IdlePaintRect() {
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't inflate an empty rect.
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visible_content_rect().IsEmpty())
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return gfx::Rect();
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect prepaint_rect = visible_content_rect();
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns,
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      -tiler_->tile_size().height() * kPrepaintRows);
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect content_rect(content_bounds());
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prepaint_rect.Intersect(content_rect);
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return prepaint_rect;
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
902