| Index: cc/base/tiling_data.cc | 
| diff --git a/cc/base/tiling_data.cc b/cc/base/tiling_data.cc | 
| index edfecc9a4f64b8794fa976dc0f1163defaa491b0..bcc4cc24a7a4d9eb0c5f9a001e7c2c0972f6936c 100644 | 
| --- a/cc/base/tiling_data.cc | 
| +++ b/cc/base/tiling_data.cc | 
| @@ -6,6 +6,8 @@ | 
|  | 
| #include <algorithm> | 
|  | 
| +#include "base/command_line.h" | 
| +#include "cc/base/switches.h" | 
| #include "ui/gfx/geometry/rect.h" | 
| #include "ui/gfx/geometry/rect_f.h" | 
| #include "ui/gfx/geometry/vector2d.h" | 
| @@ -92,6 +94,36 @@ int TilingData::TileYIndexFromSrcCoord(int src_position) const { | 
| return std::min(std::max(y, 0), num_tiles_y_ - 1); | 
| } | 
|  | 
| +int TilingData::TileAbsoluteXIndexFromSrcCoord(int src_position) const { | 
| +  int inner_tile_width = max_texture_size_.width() - 2 * border_texels_; | 
| +  if (inner_tile_width <= 0) | 
| +    return 0; | 
| + | 
| +  int max_width = inner_tile_width * num_tiles_x_ + 2 * border_texels_; | 
| +  if (src_position >= 0 && src_position < max_width) | 
| +    return TileXIndexFromSrcCoord(src_position); | 
| + | 
| +  if (src_position >= max_width) | 
| +    return num_tiles_x_ + (src_position - max_width) / inner_tile_width; | 
| + | 
| +  return (src_position + 1) / inner_tile_width - 1; | 
| +} | 
| + | 
| +int TilingData::TileAbsoluteYIndexFromSrcCoord(int src_position) const { | 
| +  int inner_tile_height = max_texture_size_.height() - 2 * border_texels_; | 
| +  if (inner_tile_height <= 0) | 
| +    return 0; | 
| + | 
| +  int max_height = inner_tile_height * num_tiles_y_ + 2 * border_texels_; | 
| +  if (src_position >= 0 && src_position < max_height) | 
| +    return TileYIndexFromSrcCoord(src_position); | 
| + | 
| +  if (src_position >= max_height) | 
| +    return num_tiles_y_ + (src_position - max_height) / inner_tile_height; | 
| + | 
| +  return (src_position + 1) / inner_tile_height - 1; | 
| +} | 
| + | 
| int TilingData::FirstBorderTileXIndexFromSrcCoord(int src_position) const { | 
| if (num_tiles_x_ <= 1) | 
| return 0; | 
| @@ -176,6 +208,41 @@ IndexRect TilingData::TileAroundIndexRect(const gfx::Rect& center_rect) const { | 
| return IndexRect(around_left, around_right, around_top, around_bottom); | 
| } | 
|  | 
| +IndexRect TilingData::TileAroundAbsoluteIndexRect( | 
| +    const gfx::Rect& center_rect) const { | 
| +  if (center_rect.IsEmpty()) { | 
| +    // Default around rect is assumed to be at top-left corner of tile at | 
| +    // (0, 0). | 
| +    return IndexRect(-2, 0, -2, 0); | 
| +  } | 
| + | 
| +  gfx::Rect tiling_rect(tiling_size()); | 
| + | 
| +  int around_left = TileAbsoluteXIndexFromSrcCoord(center_rect.x()); | 
| +  int around_top = TileAbsoluteYIndexFromSrcCoord(center_rect.y()); | 
| +  int right_src_coord = center_rect.right() - 1; | 
| +  int around_right = TileAbsoluteXIndexFromSrcCoord(right_src_coord) + 1; | 
| +  int bottom_src_coord = center_rect.bottom() - 1; | 
| +  int around_bottom = TileAbsoluteYIndexFromSrcCoord(bottom_src_coord) + 1; | 
| + | 
| +  // For left and top indices check if tiling size is smaller than tile size. In | 
| +  // such case if center rect is not intersecting the tiling rect and if center | 
| +  // rect is right (or below) to the tiling rect, then around tile index is same | 
| +  // as the index returned by TileAbsolute(X|Y)IndexFromSrcCoord(). | 
| +  if (!(num_tiles_x() == 1 && around_left == 0 && | 
| +        !tiling_rect.Intersects(center_rect) && | 
| +        tiling_rect.right() < center_rect.x())) { | 
| +    around_left -= 1; | 
| +  } | 
| +  if (!(num_tiles_y() == 1 && around_top == 0 && | 
| +        !tiling_rect.Intersects(center_rect) && | 
| +        tiling_rect.bottom() < center_rect.y())) { | 
| +    around_top -= 1; | 
| +  } | 
| + | 
| +  return IndexRect(around_left, around_right, around_top, around_bottom); | 
| +} | 
| + | 
| gfx::Rect TilingData::ExpandRectIgnoringBordersToTileBounds( | 
| const gfx::Rect& rect) const { | 
| if (rect.IsEmpty() || has_empty_bounds()) | 
| @@ -349,6 +416,10 @@ void TilingData::RecomputeNumTiles() { | 
| max_texture_size_.height(), tiling_size_.height(), border_texels_); | 
| } | 
|  | 
| +bool TilingData::IsPyramidSequenceEnabled() { | 
| +  return true; | 
| +} | 
| + | 
| TilingData::BaseIterator::BaseIterator() : index_x_(-1), index_y_(-1) { | 
| } | 
|  | 
| @@ -535,39 +606,90 @@ TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator( | 
| const TilingData* tiling_data, | 
| const gfx::Rect& consider_rect, | 
| const gfx::Rect& ignore_rect, | 
| -    const gfx::Rect& center_rect) | 
| -    : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect) { | 
| +    const gfx::Rect& center_rect, | 
| +    const bool use_pyramid_sequence) | 
| +    : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect), | 
| +      use_pyramid_sequence_(use_pyramid_sequence) { | 
| if (!HasConsiderRect()) { | 
| done(); | 
| return; | 
| } | 
|  | 
| -  IndexRect around_index_rect = tiling_data->TileAroundIndexRect(center_rect); | 
| -  DCHECK(around_index_rect.is_valid()); | 
| +  if (use_pyramid_sequence_) { | 
| +    IndexRect around_index_rect = | 
| +        tiling_data->TileAroundAbsoluteIndexRect(center_rect); | 
|  | 
| -  spiral_iterator_ = SpiralIterator(around_index_rect, consider_index_rect_, | 
| -                                    ignore_index_rect_); | 
| +    DCHECK(around_index_rect.is_valid()); | 
| +    pyramid_sequence_ = PyramidSequence( | 
| +        around_index_rect, consider_index_rect_, ignore_index_rect_, | 
| +        tiling_data->max_texture_size().width(), | 
| +        tiling_data->max_texture_size().height()); | 
|  | 
| -  if (!spiral_iterator_) { | 
| -    done(); | 
| -    return; | 
| -  } | 
| +    iterator_ = pyramid_sequence_.Begin(); | 
| + | 
| +    if (!iterator_) { | 
| +      done(); | 
| +      return; | 
| +    } | 
| + | 
| +    index_x_ = iterator_.index_x(); | 
| +    index_y_ = iterator_.index_y(); | 
| +    DCHECK(consider_index_rect_.Contains(index_x_, index_y_) && | 
| +           !ignore_index_rect_.Contains(index_x_, index_y_)); | 
| +  } else { | 
| +    IndexRect around_index_rect = tiling_data->TileAroundIndexRect(center_rect); | 
| +    DCHECK(around_index_rect.is_valid()); | 
| + | 
| +    spiral_iterator_ = SpiralIterator(around_index_rect, consider_index_rect_, | 
| +                                      ignore_index_rect_); | 
|  | 
| -  index_x_ = spiral_iterator_.index_x(); | 
| -  index_y_ = spiral_iterator_.index_y(); | 
| +    if (!spiral_iterator_) { | 
| +      done(); | 
| +      return; | 
| +    } | 
| + | 
| +    index_x_ = spiral_iterator_.index_x(); | 
| +    index_y_ = spiral_iterator_.index_y(); | 
| +  } | 
| } | 
|  | 
| +TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator( | 
| +    const TilingData::SpiralDifferenceIterator& other) = default; | 
| + | 
| +TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator( | 
| +    TilingData::SpiralDifferenceIterator&& other) = default; | 
| + | 
| +TilingData::SpiralDifferenceIterator::~SpiralDifferenceIterator() {} | 
| + | 
| +TilingData::SpiralDifferenceIterator& TilingData::SpiralDifferenceIterator:: | 
| +operator=(const TilingData::SpiralDifferenceIterator& other) = default; | 
| + | 
| +TilingData::SpiralDifferenceIterator& TilingData::SpiralDifferenceIterator:: | 
| +operator=(TilingData::SpiralDifferenceIterator&& other) = default; | 
| + | 
| TilingData::SpiralDifferenceIterator& TilingData::SpiralDifferenceIterator:: | 
| operator++() { | 
| -  ++spiral_iterator_; | 
| +  if (use_pyramid_sequence_) { | 
| +    ++iterator_; | 
|  | 
| -  if (!spiral_iterator_) { | 
| -    done(); | 
| -    return *this; | 
| -  } | 
| +    if (!iterator_) { | 
| +      done(); | 
| +      return *this; | 
| +    } | 
| + | 
| +    index_x_ = iterator_.index_x(); | 
| +    index_y_ = iterator_.index_y(); | 
| +  } else { | 
| +    ++spiral_iterator_; | 
| + | 
| +    if (!spiral_iterator_) { | 
| +      done(); | 
| +      return *this; | 
| +    } | 
|  | 
| -  index_x_ = spiral_iterator_.index_x(); | 
| -  index_y_ = spiral_iterator_.index_y(); | 
| +    index_x_ = spiral_iterator_.index_x(); | 
| +    index_y_ = spiral_iterator_.index_y(); | 
| +  } | 
|  | 
| return *this; | 
| } | 
| @@ -580,40 +702,93 @@ TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator( | 
| const TilingData* tiling_data, | 
| const gfx::Rect& consider_rect, | 
| const gfx::Rect& ignore_rect, | 
| -    const gfx::Rect& center_rect) | 
| -    : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect) { | 
| +    const gfx::Rect& center_rect, | 
| +    const bool use_pyramid_sequence) | 
| +    : BaseDifferenceIterator(tiling_data, consider_rect, ignore_rect), | 
| +      use_pyramid_sequence_(use_pyramid_sequence) { | 
| if (!HasConsiderRect()) { | 
| done(); | 
| return; | 
| } | 
|  | 
| -  IndexRect around_index_rect = tiling_data->TileAroundIndexRect(center_rect); | 
| -  DCHECK(around_index_rect.is_valid()); | 
| +  if (use_pyramid_sequence_) { | 
| +    IndexRect around_index_rect = | 
| +        tiling_data->TileAroundAbsoluteIndexRect(center_rect); | 
| +    DCHECK(around_index_rect.is_valid()); | 
| +    pyramid_sequence_ = PyramidSequence( | 
| +        around_index_rect, consider_index_rect_, ignore_index_rect_, | 
| +        tiling_data->max_texture_size().width(), | 
| +        tiling_data->max_texture_size().height()); | 
|  | 
| -  reverse_spiral_iterator_ = ReverseSpiralIterator( | 
| -      around_index_rect, consider_index_rect_, ignore_index_rect_); | 
| +    reverse_iterator_ = pyramid_sequence_.ReverseBegin(); | 
|  | 
| -  if (!reverse_spiral_iterator_) { | 
| -    done(); | 
| -    return; | 
| -  } | 
| +    if (!reverse_iterator_) { | 
| +      done(); | 
| +      return; | 
| +    } | 
| + | 
| +    index_x_ = reverse_iterator_.index_x(); | 
| +    index_y_ = reverse_iterator_.index_y(); | 
| +    DCHECK(consider_index_rect_.Contains(index_x_, index_y_) && | 
| +           !ignore_index_rect_.Contains(index_x_, index_y_)); | 
| +  } else { | 
| +    IndexRect around_index_rect = tiling_data->TileAroundIndexRect(center_rect); | 
| +    DCHECK(around_index_rect.is_valid()); | 
| + | 
| +    reverse_spiral_iterator_ = ReverseSpiralIterator( | 
| +        around_index_rect, consider_index_rect_, ignore_index_rect_); | 
| + | 
| +    if (!reverse_spiral_iterator_) { | 
| +      done(); | 
| +      return; | 
| +    } | 
|  | 
| -  index_x_ = reverse_spiral_iterator_.index_x(); | 
| -  index_y_ = reverse_spiral_iterator_.index_y(); | 
| +    index_x_ = reverse_spiral_iterator_.index_x(); | 
| +    index_y_ = reverse_spiral_iterator_.index_y(); | 
| +  } | 
| } | 
|  | 
| +TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator( | 
| +    const TilingData::ReverseSpiralDifferenceIterator& other) = default; | 
| + | 
| +TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator( | 
| +    TilingData::ReverseSpiralDifferenceIterator&& other) = default; | 
| + | 
| +TilingData::ReverseSpiralDifferenceIterator:: | 
| +    ~ReverseSpiralDifferenceIterator() {} | 
| + | 
| +TilingData::ReverseSpiralDifferenceIterator& | 
| +TilingData::ReverseSpiralDifferenceIterator::operator=( | 
| +    const TilingData::ReverseSpiralDifferenceIterator& other) = default; | 
| + | 
| +TilingData::ReverseSpiralDifferenceIterator& | 
| +TilingData::ReverseSpiralDifferenceIterator::operator=( | 
| +    TilingData::ReverseSpiralDifferenceIterator&& other) = default; | 
| + | 
| TilingData::ReverseSpiralDifferenceIterator& | 
| TilingData::ReverseSpiralDifferenceIterator:: | 
| operator++() { | 
| -  ++reverse_spiral_iterator_; | 
| +  if (use_pyramid_sequence_) { | 
| +    ++reverse_iterator_; | 
|  | 
| -  if (!reverse_spiral_iterator_) { | 
| -    done(); | 
| -    return *this; | 
| -  } | 
| +    if (!reverse_iterator_) { | 
| +      done(); | 
| +      return *this; | 
| +    } | 
|  | 
| -  index_x_ = reverse_spiral_iterator_.index_x(); | 
| -  index_y_ = reverse_spiral_iterator_.index_y(); | 
| +    index_x_ = reverse_iterator_.index_x(); | 
| +    index_y_ = reverse_iterator_.index_y(); | 
| +  } else { | 
| +    ++reverse_spiral_iterator_; | 
| + | 
| +    if (!reverse_spiral_iterator_) { | 
| +      done(); | 
| +      return *this; | 
| +    } | 
| + | 
| +    index_x_ = reverse_spiral_iterator_.index_x(); | 
| +    index_y_ = reverse_spiral_iterator_.index_y(); | 
| +  } | 
|  | 
| return *this; | 
| } | 
|  |