// Copyright 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/layers/tiled_layer.h"

#include <algorithm>
#include <vector>

#include "base/auto_reset.h"
#include "base/basictypes.h"
#include "build/build_config.h"
#include "cc/base/simple_enclosed_region.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/tiled_layer_impl.h"
#include "cc/resources/layer_updater.h"
#include "cc/resources/prioritized_resource.h"
#include "cc/resources/priority_calculator.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/occlusion_tracker.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace cc {

// Maximum predictive expansion of the visible area.
static const int kMaxPredictiveTilesCount = 2;

// Number of rows/columns of tiles to pre-paint.
// We should increase these further as all textures are
// prioritized and we insure performance doesn't suffer.
static const int kPrepaintRows = 4;
static const int kPrepaintColumns = 2;

class UpdatableTile : public LayerTilingData::Tile {
 public:
  static scoped_ptr<UpdatableTile> Create(
      scoped_ptr<LayerUpdater::Resource> updater_resource) {
    return make_scoped_ptr(new UpdatableTile(updater_resource.Pass()));
  }

  LayerUpdater::Resource* updater_resource() { return updater_resource_.get(); }
  PrioritizedResource* managed_resource() {
    return updater_resource_->texture();
  }

  bool is_dirty() const { return !dirty_rect.IsEmpty(); }

  // Reset update state for the current frame. This should occur before painting
  // for all layers. Since painting one layer can invalidate another layer after
  // it has already painted, mark all non-dirty tiles as valid before painting
  // such that invalidations during painting won't prevent them from being
  // pushed.
  void ResetUpdateState() {
    update_rect = gfx::Rect();
    occluded = false;
    partial_update = false;
    valid_for_frame = !is_dirty();
  }

  // This promises to update the tile and therefore also guarantees the tile
  // will be valid for this frame. dirty_rect is copied into update_rect so we
  // can continue to track re-entrant invalidations that occur during painting.
  void MarkForUpdate() {
    valid_for_frame = true;
    update_rect = dirty_rect;
    dirty_rect = gfx::Rect();
  }

  gfx::Rect dirty_rect;
  gfx::Rect update_rect;
  bool partial_update;
  bool valid_for_frame;
  bool occluded;

 private:
  explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updater_resource)
      : partial_update(false),
        valid_for_frame(false),
        occluded(false),
        updater_resource_(updater_resource.Pass()) {}

  scoped_ptr<LayerUpdater::Resource> updater_resource_;

  DISALLOW_COPY_AND_ASSIGN(UpdatableTile);
};

TiledLayer::TiledLayer()
    : ContentsScalingLayer(),
      texture_format_(RGBA_8888),
      skips_draw_(false),
      failed_update_(false),
      tiling_option_(AUTO_TILE) {
  tiler_ =
      LayerTilingData::Create(gfx::Size(), LayerTilingData::HAS_BORDER_TEXELS);
}

TiledLayer::~TiledLayer() {}

scoped_ptr<LayerImpl> TiledLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
  return TiledLayerImpl::Create(tree_impl, id());
}

void TiledLayer::UpdateTileSizeAndTilingOption() {
  DCHECK(layer_tree_host());

  gfx::Size default_tile_size = layer_tree_host()->settings().default_tile_size;
  gfx::Size max_untiled_layer_size =
      layer_tree_host()->settings().max_untiled_layer_size;
  int layer_width = content_bounds().width();
  int layer_height = content_bounds().height();

  gfx::Size tile_size(std::min(default_tile_size.width(), layer_width),
                      std::min(default_tile_size.height(), layer_height));

  // Tile if both dimensions large, or any one dimension large and the other
  // extends into a second tile but the total layer area isn't larger than that
  // of the largest possible untiled layer. This heuristic allows for long
  // skinny layers (e.g. scrollbars) that are Nx1 tiles to minimize wasted
  // texture space but still avoids creating very large tiles.
  bool any_dimension_large = layer_width > max_untiled_layer_size.width() ||
                             layer_height > max_untiled_layer_size.height();
  bool any_dimension_one_tile =
      (layer_width <= default_tile_size.width() ||
       layer_height <= default_tile_size.height()) &&
      (layer_width * layer_height) <= (max_untiled_layer_size.width() *
                                       max_untiled_layer_size.height());
  bool auto_tiled = any_dimension_large && !any_dimension_one_tile;

  bool is_tiled;
  if (tiling_option_ == ALWAYS_TILE)
    is_tiled = true;
  else if (tiling_option_ == NEVER_TILE)
    is_tiled = false;
  else
    is_tiled = auto_tiled;

  gfx::Size requested_size = is_tiled ? tile_size : content_bounds();
  const int max_size =
      layer_tree_host()->GetRendererCapabilities().max_texture_size;
  requested_size.SetToMin(gfx::Size(max_size, max_size));
  SetTileSize(requested_size);
}

void TiledLayer::UpdateBounds() {
  gfx::Size old_tiling_size = tiler_->tiling_size();
  gfx::Size new_tiling_size = content_bounds();
  if (old_tiling_size == new_tiling_size)
    return;
  tiler_->SetTilingSize(new_tiling_size);

  // Invalidate any areas that the new bounds exposes.
  Region new_region =
      SubtractRegions(gfx::Rect(new_tiling_size), gfx::Rect(old_tiling_size));
  for (Region::Iterator new_rects(new_region); new_rects.has_rect();
       new_rects.next())
    InvalidateContentRect(new_rects.rect());
  UpdateDrawsContent(HasDrawableContent());
}

void TiledLayer::SetTileSize(const gfx::Size& size) {
  tiler_->SetTileSize(size);
  UpdateDrawsContent(HasDrawableContent());
}

void TiledLayer::SetBorderTexelOption(
    LayerTilingData::BorderTexelOption border_texel_option) {
  tiler_->SetBorderTexelOption(border_texel_option);
  UpdateDrawsContent(HasDrawableContent());
}

bool TiledLayer::HasDrawableContent() const {
  bool has_more_than_one_tile =
      (tiler_->num_tiles_x() > 1) || (tiler_->num_tiles_y() > 1);

  return !(tiling_option_ == NEVER_TILE && has_more_than_one_tile) &&
         ContentsScalingLayer::HasDrawableContent();
}

void TiledLayer::ReduceMemoryUsage() {
  if (Updater())
    Updater()->ReduceMemoryUsage();
}

void TiledLayer::SetIsMask(bool is_mask) {
  set_tiling_option(is_mask ? NEVER_TILE : AUTO_TILE);
}

void TiledLayer::PushPropertiesTo(LayerImpl* layer) {
  ContentsScalingLayer::PushPropertiesTo(layer);

  TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer);

  tiled_layer->set_skips_draw(skips_draw_);
  tiled_layer->SetTilingData(*tiler_);
  std::vector<UpdatableTile*> invalid_tiles;

  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
       iter != tiler_->tiles().end();
       ++iter) {
    int i = iter->first.first;
    int j = iter->first.second;
    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    // TODO(enne): This should not ever be null.
    if (!tile)
      continue;

    if (!tile->managed_resource()->have_backing_texture()) {
      // Evicted tiles get deleted from both layers
      invalid_tiles.push_back(tile);
      continue;
    }

    if (!tile->valid_for_frame) {
      // Invalidated tiles are set so they can get different debug colors.
      tiled_layer->PushInvalidTile(i, j);
      continue;
    }

    tiled_layer->PushTileProperties(
        i,
        j,
        tile->managed_resource()->resource_id(),
        tile->managed_resource()->contents_swizzled());
  }
  for (std::vector<UpdatableTile*>::const_iterator iter = invalid_tiles.begin();
       iter != invalid_tiles.end();
       ++iter)
    tiler_->TakeTile((*iter)->i(), (*iter)->j());

  // TiledLayer must push properties every frame, since viewport state and
  // occlusion from anywhere in the tree can change what the layer decides to
  // push to the impl tree.
  needs_push_properties_ = true;
}

PrioritizedResourceManager* TiledLayer::ResourceManager() {
  if (!layer_tree_host())
    return nullptr;
  return layer_tree_host()->contents_texture_manager();
}

const PrioritizedResource* TiledLayer::ResourceAtForTesting(int i,
                                                            int j) const {
  UpdatableTile* tile = TileAt(i, j);
  if (!tile)
    return nullptr;
  return tile->managed_resource();
}

void TiledLayer::SetLayerTreeHost(LayerTreeHost* host) {
  if (host && host != layer_tree_host()) {
    for (LayerTilingData::TileMap::const_iterator
             iter = tiler_->tiles().begin();
         iter != tiler_->tiles().end();
         ++iter) {
      UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
      // TODO(enne): This should not ever be null.
      if (!tile)
        continue;
      tile->managed_resource()->SetTextureManager(
          host->contents_texture_manager());
    }
  }
  ContentsScalingLayer::SetLayerTreeHost(host);
}

UpdatableTile* TiledLayer::TileAt(int i, int j) const {
  return static_cast<UpdatableTile*>(tiler_->TileAt(i, j));
}

UpdatableTile* TiledLayer::CreateTile(int i, int j) {
  CreateUpdaterIfNeeded();

  scoped_ptr<UpdatableTile> tile(
      UpdatableTile::Create(Updater()->CreateResource(ResourceManager())));
  tile->managed_resource()->SetDimensions(tiler_->tile_size(), texture_format_);

  UpdatableTile* added_tile = tile.get();
  tiler_->AddTile(tile.Pass(), i, j);

  added_tile->dirty_rect = tiler_->TileRect(added_tile);

  // Temporary diagnostic crash.
  CHECK(added_tile);
  CHECK(TileAt(i, j));

  return added_tile;
}

void TiledLayer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) {
  InvalidateContentRect(LayerRectToContentRect(dirty_rect));
  ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect);
}

void TiledLayer::InvalidateContentRect(const gfx::Rect& content_rect) {
  UpdateBounds();
  if (tiler_->is_empty() || content_rect.IsEmpty() || skips_draw_)
    return;

  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
       iter != tiler_->tiles().end();
       ++iter) {
    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    DCHECK(tile);
    // TODO(enne): This should not ever be null.
    if (!tile)
      continue;
    gfx::Rect bound = tiler_->TileRect(tile);
    bound.Intersect(content_rect);
    tile->dirty_rect.Union(bound);
  }
}

// Returns true if tile is dirty and only part of it needs to be updated.
bool TiledLayer::TileOnlyNeedsPartialUpdate(UpdatableTile* tile) {
  return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) &&
         tile->managed_resource()->have_backing_texture();
}

bool TiledLayer::UpdateTiles(int left,
                             int top,
                             int right,
                             int bottom,
                             ResourceUpdateQueue* queue,
                             const OcclusionTracker<Layer>* occlusion,
                             bool* updated) {
  CreateUpdaterIfNeeded();

  bool ignore_occlusions = !occlusion;
  if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) {
    failed_update_ = true;
    return false;
  }

  gfx::Rect update_rect;
  gfx::Rect paint_rect;
  MarkTilesForUpdate(
    &update_rect, &paint_rect, left, top, right, bottom, ignore_occlusions);

  if (paint_rect.IsEmpty())
    return true;

  *updated = true;
  UpdateTileTextures(
      update_rect, paint_rect, left, top, right, bottom, queue, occlusion);
  return true;
}

void TiledLayer::MarkOcclusionsAndRequestTextures(
    int left,
    int top,
    int right,
    int bottom,
    const OcclusionTracker<Layer>* occlusion) {
  int occluded_tile_count = 0;
  bool succeeded = true;
  for (int j = top; j <= bottom; ++j) {
    for (int i = left; i <= right; ++i) {
      UpdatableTile* tile = TileAt(i, j);
      DCHECK(tile);  // Did SetTexturePriorities get skipped?
      // TODO(enne): This should not ever be null.
      if (!tile)
        continue;
      // Did ResetUpdateState get skipped? Are we doing more than one occlusion
      // pass?
      DCHECK(!tile->occluded);
      gfx::Rect visible_tile_rect = gfx::IntersectRects(
          tiler_->tile_bounds(i, j), visible_content_rect());
      if (!draw_transform_is_animating() && occlusion &&
          occlusion->GetCurrentOcclusionForLayer(draw_transform())
              .IsOccluded(visible_tile_rect)) {
        tile->occluded = true;
        occluded_tile_count++;
      } else {
        succeeded &= tile->managed_resource()->RequestLate();
      }
    }
  }
}

bool TiledLayer::HaveTexturesForTiles(int left,
                                      int top,
                                      int right,
                                      int bottom,
                                      bool ignore_occlusions) {
  for (int j = top; j <= bottom; ++j) {
    for (int i = left; i <= right; ++i) {
      UpdatableTile* tile = TileAt(i, j);
      DCHECK(tile);  // Did SetTexturePriorites get skipped?
                     // TODO(enne): This should not ever be null.
      if (!tile)
        continue;

      // Ensure the entire tile is dirty if we don't have the texture.
      if (!tile->managed_resource()->have_backing_texture())
        tile->dirty_rect = tiler_->TileRect(tile);

      // If using occlusion and the visible region of the tile is occluded,
      // don't reserve a texture or update the tile.
      if (tile->occluded && !ignore_occlusions)
        continue;

      if (!tile->managed_resource()->can_acquire_backing_texture())
        return false;
    }
  }
  return true;
}

void TiledLayer::MarkTilesForUpdate(gfx::Rect* update_rect,
                                    gfx::Rect* paint_rect,
                                    int left,
                                    int top,
                                    int right,
                                    int bottom,
                                    bool ignore_occlusions) {
  for (int j = top; j <= bottom; ++j) {
    for (int i = left; i <= right; ++i) {
      UpdatableTile* tile = TileAt(i, j);
      DCHECK(tile);  // Did SetTexturePriorites get skipped?
                     // TODO(enne): This should not ever be null.
      if (!tile)
        continue;
      if (tile->occluded && !ignore_occlusions)
        continue;

      // Prepare update rect from original dirty rects.
      update_rect->Union(tile->dirty_rect);

      // TODO(reveman): Decide if partial update should be allowed based on cost
      // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
      if (tile->is_dirty() &&
          !layer_tree_host()->AlwaysUsePartialTextureUpdates()) {
        // If we get a partial update, we use the same texture, otherwise return
        // the current texture backing, so we don't update visible textures
        // non-atomically.  If the current backing is in-use, it won't be
        // deleted until after the commit as the texture manager will not allow
        // deletion or recycling of in-use textures.
        if (TileOnlyNeedsPartialUpdate(tile) &&
            layer_tree_host()->RequestPartialTextureUpdate()) {
          tile->partial_update = true;
        } else {
          tile->dirty_rect = tiler_->TileRect(tile);
          tile->managed_resource()->ReturnBackingTexture();
        }
      }

      paint_rect->Union(tile->dirty_rect);
      tile->MarkForUpdate();
    }
  }
}

void TiledLayer::UpdateTileTextures(const gfx::Rect& update_rect,
                                    const gfx::Rect& paint_rect,
                                    int left,
                                    int top,
                                    int right,
                                    int bottom,
                                    ResourceUpdateQueue* queue,
                                    const OcclusionTracker<Layer>* occlusion) {
  // The update_rect should be in layer space. So we have to convert the
  // paint_rect from content space to layer space.
  float width_scale = 1 / draw_properties().contents_scale_x;
  float height_scale = 1 / draw_properties().contents_scale_y;
  update_rect_ =
      gfx::ScaleToEnclosingRect(update_rect, width_scale, height_scale);

  // Calling PrepareToUpdate() calls into WebKit to paint, which may have the
  // side effect of disabling compositing, which causes our reference to the
  // texture updater to be deleted.  However, we can't free the memory backing
  // the SkCanvas until the paint finishes, so we grab a local reference here to
  // hold the updater alive until the paint completes.
  scoped_refptr<LayerUpdater> protector(Updater());
  Updater()->PrepareToUpdate(content_bounds(),
                             paint_rect,
                             tiler_->tile_size(),
                             1.f / width_scale,
                             1.f / height_scale);

  for (int j = top; j <= bottom; ++j) {
    for (int i = left; i <= right; ++i) {
      UpdatableTile* tile = TileAt(i, j);
      DCHECK(tile);  // Did SetTexturePriorites get skipped?
                     // TODO(enne): This should not ever be null.
      if (!tile)
        continue;

      gfx::Rect tile_rect = tiler_->tile_bounds(i, j);

      // Use update_rect as the above loop copied the dirty rect for this frame
      // to update_rect.
      gfx::Rect dirty_rect = tile->update_rect;
      if (dirty_rect.IsEmpty())
        continue;

      // source_rect starts as a full-sized tile with border texels included.
      gfx::Rect source_rect = tiler_->TileRect(tile);
      source_rect.Intersect(dirty_rect);
      // Paint rect not guaranteed to line up on tile boundaries, so
      // make sure that source_rect doesn't extend outside of it.
      source_rect.Intersect(paint_rect);

      tile->update_rect = source_rect;

      if (source_rect.IsEmpty())
        continue;

      const gfx::Point anchor = tiler_->TileRect(tile).origin();

      // Calculate tile-space rectangle to upload into.
      gfx::Vector2d dest_offset = source_rect.origin() - anchor;
      CHECK_GE(dest_offset.x(), 0);
      CHECK_GE(dest_offset.y(), 0);

      // Offset from paint rectangle to this tile's dirty rectangle.
      gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin();
      CHECK_GE(paint_offset.x(), 0);
      CHECK_GE(paint_offset.y(), 0);
      CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width());
      CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height());

      tile->updater_resource()->Update(
          queue, source_rect, dest_offset, tile->partial_update);
    }
  }
}

// This picks a small animated layer to be anything less than one viewport. This
// is specifically for page transitions which are viewport-sized layers. The
// extra tile of padding is due to these layers being slightly larger than the
// viewport in some cases.
bool TiledLayer::IsSmallAnimatedLayer() const {
  if (!draw_transform_is_animating() && !screen_space_transform_is_animating())
    return false;
  gfx::Size viewport_size =
      layer_tree_host() ? layer_tree_host()->device_viewport_size()
                        : gfx::Size();
  gfx::Rect content_rect(content_bounds());
  return content_rect.width() <=
         viewport_size.width() + tiler_->tile_size().width() &&
         content_rect.height() <=
         viewport_size.height() + tiler_->tile_size().height();
}

namespace {
// TODO(epenner): Remove this and make this based on distance once distance can
// be calculated for offscreen layers. For now, prioritize all small animated
// layers after 512 pixels of pre-painting.
void SetPriorityForTexture(const gfx::Rect& visible_rect,
                           const gfx::Rect& tile_rect,
                           bool draws_to_root,
                           bool is_small_animated_layer,
                           PrioritizedResource* texture) {
  int priority = PriorityCalculator::LowestPriority();
  if (!visible_rect.IsEmpty()) {
    priority = PriorityCalculator::PriorityFromDistance(
        visible_rect, tile_rect, draws_to_root);
  }

  if (is_small_animated_layer) {
    priority = PriorityCalculator::max_priority(
        priority, PriorityCalculator::SmallAnimatedLayerMinPriority());
  }

  if (priority != PriorityCalculator::LowestPriority())
    texture->set_request_priority(priority);
}
}  // namespace

void TiledLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) {
  UpdateBounds();
  ResetUpdateState();
  UpdateScrollPrediction();

  if (tiler_->has_empty_bounds())
    return;

  bool draws_to_root = !render_target()->parent();
  bool small_animated_layer = IsSmallAnimatedLayer();

  // Minimally create the tiles in the desired pre-paint rect.
  gfx::Rect create_tiles_rect = IdlePaintRect();
  if (small_animated_layer)
    create_tiles_rect = gfx::Rect(content_bounds());
  if (!create_tiles_rect.IsEmpty()) {
    int left, top, right, bottom;
    tiler_->ContentRectToTileIndices(
        create_tiles_rect, &left, &top, &right, &bottom);
    for (int j = top; j <= bottom; ++j) {
      for (int i = left; i <= right; ++i) {
        if (!TileAt(i, j))
          CreateTile(i, j);
      }
    }
  }

  // Now update priorities on all tiles we have in the layer, no matter where
  // they are.
  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
       iter != tiler_->tiles().end();
       ++iter) {
    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    // TODO(enne): This should not ever be null.
    if (!tile)
      continue;
    gfx::Rect tile_rect = tiler_->TileRect(tile);
    SetPriorityForTexture(predicted_visible_rect_,
                          tile_rect,
                          draws_to_root,
                          small_animated_layer,
                          tile->managed_resource());
  }
}

SimpleEnclosedRegion TiledLayer::VisibleContentOpaqueRegion() const {
  if (skips_draw_)
    return SimpleEnclosedRegion();
  return Layer::VisibleContentOpaqueRegion();
}

void TiledLayer::ResetUpdateState() {
  skips_draw_ = false;
  failed_update_ = false;

  LayerTilingData::TileMap::const_iterator end = tiler_->tiles().end();
  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
       iter != end;
       ++iter) {
    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    // TODO(enne): This should not ever be null.
    if (!tile)
      continue;
    tile->ResetUpdateState();
  }
}

namespace {
gfx::Rect ExpandRectByDelta(const gfx::Rect& rect, const gfx::Vector2d& delta) {
  int width = rect.width() + std::abs(delta.x());
  int height = rect.height() + std::abs(delta.y());
  int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0);
  int y = rect.y() + ((delta.y() < 0) ? delta.y() : 0);
  return gfx::Rect(x, y, width, height);
}
}

void TiledLayer::UpdateScrollPrediction() {
  // This scroll prediction is very primitive and should be replaced by a
  // a recursive calculation on all layers which uses actual scroll/animation
  // velocities. To insure this doesn't miss-predict, we only use it to predict
  // the visible_rect if:
  // - content_bounds() hasn't changed.
  // - visible_rect.size() hasn't changed.
  // These two conditions prevent rotations, scales, pinch-zooms etc. where
  // the prediction would be incorrect.
  gfx::Vector2d delta = visible_content_rect().CenterPoint() -
                        previous_visible_rect_.CenterPoint();
  predicted_scroll_ = -delta;
  predicted_visible_rect_ = visible_content_rect();
  if (previous_content_bounds_ == content_bounds() &&
      previous_visible_rect_.size() == visible_content_rect().size()) {
    // Only expand the visible rect in the major scroll direction, to prevent
    // massive paints due to diagonal scrolls.
    gfx::Vector2d major_scroll_delta =
        (std::abs(delta.x()) > std::abs(delta.y())) ?
        gfx::Vector2d(delta.x(), 0) :
        gfx::Vector2d(0, delta.y());
    predicted_visible_rect_ =
        ExpandRectByDelta(visible_content_rect(), major_scroll_delta);

    // Bound the prediction to prevent unbounded paints, and clamp to content
    // bounds.
    gfx::Rect bound = visible_content_rect();
    bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount,
                -tiler_->tile_size().height() * kMaxPredictiveTilesCount);
    bound.Intersect(gfx::Rect(content_bounds()));
    predicted_visible_rect_.Intersect(bound);
  }
  previous_content_bounds_ = content_bounds();
  previous_visible_rect_ = visible_content_rect();
}

bool TiledLayer::Update(ResourceUpdateQueue* queue,
                        const OcclusionTracker<Layer>* occlusion) {
  DCHECK(!skips_draw_ && !failed_update_);  // Did ResetUpdateState get skipped?

  // Tiled layer always causes commits to wait for activation, as it does
  // not support pending trees.
  SetNextCommitWaitsForActivation();

  bool updated = false;

  {
    base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
                                                  true);

    updated |= ContentsScalingLayer::Update(queue, occlusion);
    UpdateBounds();
  }

  if (tiler_->has_empty_bounds() || !DrawsContent())
    return false;

  // Animation pre-paint. If the layer is small, try to paint it all
  // immediately whether or not it is occluded, to avoid paint/upload
  // hiccups while it is animating.
  if (IsSmallAnimatedLayer()) {
    int left, top, right, bottom;
    tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()),
                                     &left,
                                     &top,
                                     &right,
                                     &bottom);
    UpdateTiles(left, top, right, bottom, queue, nullptr, &updated);
    if (updated)
      return updated;
    // This was an attempt to paint the entire layer so if we fail it's okay,
    // just fallback on painting visible etc. below.
    failed_update_ = false;
  }

  if (predicted_visible_rect_.IsEmpty())
    return updated;

  // Visible painting. First occlude visible tiles and paint the non-occluded
  // tiles.
  int left, top, right, bottom;
  tiler_->ContentRectToTileIndices(
      predicted_visible_rect_, &left, &top, &right, &bottom);
  MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion);
  skips_draw_ = !UpdateTiles(
      left, top, right, bottom, queue, occlusion, &updated);
  if (skips_draw_)
    tiler_->reset();
  if (skips_draw_ || updated)
    return true;

  // If we have already painting everything visible. Do some pre-painting while
  // idle.
  gfx::Rect idle_paint_content_rect = IdlePaintRect();
  if (idle_paint_content_rect.IsEmpty())
    return updated;

  // Prepaint anything that was occluded but inside the layer's visible region.
  if (!UpdateTiles(left, top, right, bottom, queue, nullptr, &updated) ||
      updated)
    return updated;

  int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom;
  tiler_->ContentRectToTileIndices(idle_paint_content_rect,
                                   &prepaint_left,
                                   &prepaint_top,
                                   &prepaint_right,
                                   &prepaint_bottom);

  // Then expand outwards one row/column at a time until we find a dirty
  // row/column to update. Increment along the major and minor scroll directions
  // first.
  gfx::Vector2d delta = -predicted_scroll_;
  delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(),
                        delta.y() == 0 ? 1 : delta.y());
  gfx::Vector2d major_delta =
      (std::abs(delta.x()) > std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
                                        : gfx::Vector2d(0, delta.y());
  gfx::Vector2d minor_delta =
      (std::abs(delta.x()) <= std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0)
                                         : gfx::Vector2d(0, delta.y());
  gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta,
                              -minor_delta };
  for (int i = 0; i < 4; i++) {
    if (deltas[i].y() > 0) {
      while (bottom < prepaint_bottom) {
        ++bottom;
        if (!UpdateTiles(
                left, bottom, right, bottom, queue, nullptr, &updated) ||
            updated)
          return updated;
      }
    }
    if (deltas[i].y() < 0) {
      while (top > prepaint_top) {
        --top;
        if (!UpdateTiles(left, top, right, top, queue, nullptr, &updated) ||
            updated)
          return updated;
      }
    }
    if (deltas[i].x() < 0) {
      while (left > prepaint_left) {
        --left;
        if (!UpdateTiles(left, top, left, bottom, queue, nullptr, &updated) ||
            updated)
          return updated;
      }
    }
    if (deltas[i].x() > 0) {
      while (right < prepaint_right) {
        ++right;
        if (!UpdateTiles(right, top, right, bottom, queue, nullptr, &updated) ||
            updated)
          return updated;
      }
    }
  }
  return updated;
}

void TiledLayer::OnOutputSurfaceCreated() {
  // Ensure that all textures are of the right format.
  for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
       iter != tiler_->tiles().end();
       ++iter) {
    UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second);
    if (!tile)
      continue;
    PrioritizedResource* resource = tile->managed_resource();
    resource->SetDimensions(resource->size(), texture_format_);
  }
}

bool TiledLayer::NeedsIdlePaint() {
  // Don't trigger more paints if we failed (as we'll just fail again).
  if (failed_update_ || visible_content_rect().IsEmpty() ||
      tiler_->has_empty_bounds() || !DrawsContent())
    return false;

  gfx::Rect idle_paint_content_rect = IdlePaintRect();
  if (idle_paint_content_rect.IsEmpty())
    return false;

  int left, top, right, bottom;
  tiler_->ContentRectToTileIndices(
      idle_paint_content_rect, &left, &top, &right, &bottom);

  for (int j = top; j <= bottom; ++j) {
    for (int i = left; i <= right; ++i) {
      UpdatableTile* tile = TileAt(i, j);
      DCHECK(tile);  // Did SetTexturePriorities get skipped?
      if (!tile)
        continue;

      bool updated = !tile->update_rect.IsEmpty();
      bool can_acquire =
          tile->managed_resource()->can_acquire_backing_texture();
      bool dirty =
          tile->is_dirty() || !tile->managed_resource()->have_backing_texture();
      if (!updated && can_acquire && dirty)
        return true;
    }
  }
  return false;
}

gfx::Rect TiledLayer::IdlePaintRect() {
  // Don't inflate an empty rect.
  if (visible_content_rect().IsEmpty())
    return gfx::Rect();

  gfx::Rect prepaint_rect = visible_content_rect();
  prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns,
                      -tiler_->tile_size().height() * kPrepaintRows);
  gfx::Rect content_rect(content_bounds());
  prepaint_rect.Intersect(content_rect);

  return prepaint_rect;
}

}  // namespace cc
