| Index: cc/tiles/picture_layer_tiling.cc
|
| diff --git a/cc/tiles/picture_layer_tiling.cc b/cc/tiles/picture_layer_tiling.cc
|
| index ecf8fe1c188b29fd920f5fcf5ca84747fd932c72..2a20ddcc2e9e810cc29d33e653711be7ea59afcd 100644
|
| --- a/cc/tiles/picture_layer_tiling.cc
|
| +++ b/cc/tiles/picture_layer_tiling.cc
|
| @@ -376,9 +376,8 @@ PictureLayerTiling::CoverageIterator::CoverageIterator(
|
| const gfx::Rect& coverage_rect)
|
| : tiling_(tiling),
|
| coverage_rect_(coverage_rect),
|
| - coverage_to_content_(
|
| - gfx::PreScaleAxisTransform2d(tiling->raster_transform(),
|
| - 1.f / coverage_scale)) {
|
| + coverage_to_content_(tiling->raster_transform().scale() / coverage_scale,
|
| + tiling->raster_transform().translation()) {
|
| DCHECK(tiling_);
|
| // In order to avoid artifacts in geometry_rect scaling and clamping to ints,
|
| // the |coverage_scale| should always be at least as big as the tiling's
|
| @@ -435,25 +434,70 @@ PictureLayerTiling::CoverageIterator::operator++() {
|
| return *this;
|
|
|
| bool first_time = tile_i_ < left_;
|
| - bool new_row = false;
|
| - tile_i_++;
|
| - if (tile_i_ > right_) {
|
| - tile_i_ = left_;
|
| - tile_j_++;
|
| - new_row = true;
|
| - if (tile_j_ > bottom_) {
|
| - current_tile_ = NULL;
|
| - return *this;
|
| + while (true) {
|
| + bool new_row = false;
|
| + tile_i_++;
|
| + if (tile_i_ > right_) {
|
| + tile_i_ = left_;
|
| + tile_j_++;
|
| + new_row = true;
|
| + if (tile_j_ > bottom_) {
|
| + current_tile_ = NULL;
|
| + break;
|
| + }
|
| }
|
| - }
|
|
|
| - current_tile_ = tiling_->TileAt(tile_i_, tile_j_);
|
| + DCHECK_LT(tile_i_, tiling_->tiling_data_.num_tiles_x());
|
| + DCHECK_LT(tile_j_, tiling_->tiling_data_.num_tiles_y());
|
| + current_tile_ = tiling_->TileAt(tile_i_, tile_j_);
|
| +
|
| + gfx::Rect geometry_rect_candidate = ComputeGeometryRect();
|
| +
|
| + // This can happen due to floating point inprecision when calculating the
|
| + // |wanted_texels| area in the constructor.
|
| + if (geometry_rect_candidate.IsEmpty())
|
| + continue;
|
| +
|
| + gfx::Rect last_geometry_rect = current_geometry_rect_;
|
| + current_geometry_rect_ = geometry_rect_candidate;
|
| +
|
| + if (first_time)
|
| + break;
|
| +
|
| + // Iteration happens left->right, top->bottom. Running off the bottom-right
|
| + // edge is handled by the intersection above with dest_rect_. Here we make
|
| + // sure that the new current geometry rect doesn't overlap with the last.
|
| + int min_left;
|
| + int min_top;
|
| + if (new_row) {
|
| + min_left = coverage_rect_.x();
|
| + min_top = last_geometry_rect.bottom();
|
| + } else {
|
| + min_left = last_geometry_rect.right();
|
| + min_top = last_geometry_rect.y();
|
| + }
|
| +
|
| + int inset_left = std::max(0, min_left - current_geometry_rect_.x());
|
| + int inset_top = std::max(0, min_top - current_geometry_rect_.y());
|
| + current_geometry_rect_.Inset(inset_left, inset_top, 0, 0);
|
| +
|
| +#if DCHECK_IS_ON()
|
| + if (!new_row) {
|
| + DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x());
|
| + DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom());
|
| + DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y());
|
| + }
|
| +#endif
|
| +
|
| + break;
|
| + }
|
| + return *this;
|
| +}
|
|
|
| +gfx::Rect PictureLayerTiling::CoverageIterator::ComputeGeometryRect() const {
|
| // Calculate the current geometry rect. As we reserved overlap between tiles
|
| // to accommodate bilinear filtering and rounding errors in destination
|
| // space, the geometry rect might overlap on the edges.
|
| - gfx::Rect last_geometry_rect = current_geometry_rect_;
|
| -
|
| gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_);
|
| {
|
| // Adjust tile extent to accommodate numerical errors.
|
| @@ -470,7 +514,7 @@ PictureLayerTiling::CoverageIterator::operator++() {
|
|
|
| // Convert texel_extent to coverage scale, which is what we have to report
|
| // geometry_rect in.
|
| - current_geometry_rect_ =
|
| + gfx::Rect candidate =
|
| gfx::ToEnclosedRect(coverage_to_content_.InverseMapRect(texel_extent));
|
| {
|
| // Adjust external edges to cover the whole layer in dest space.
|
| @@ -482,48 +526,18 @@ PictureLayerTiling::CoverageIterator::operator++() {
|
| // sampled as the AA fragment shader clamps sample coordinate and
|
| // antialiasing itself.
|
| const TilingData& data = tiling_->tiling_data_;
|
| - current_geometry_rect_.Inset(tile_i_ ? 0 : -current_geometry_rect_.x(),
|
| - tile_j_ ? 0 : -current_geometry_rect_.y(),
|
| - (tile_i_ != data.num_tiles_x() - 1)
|
| - ? 0
|
| - : current_geometry_rect_.right() -
|
| - coverage_rect_max_bounds_.width(),
|
| - (tile_j_ != data.num_tiles_y() - 1)
|
| - ? 0
|
| - : current_geometry_rect_.bottom() -
|
| - coverage_rect_max_bounds_.height());
|
| + candidate.Inset(
|
| + tile_i_ ? 0 : -candidate.x(), tile_j_ ? 0 : -candidate.y(),
|
| + (tile_i_ != data.num_tiles_x() - 1)
|
| + ? 0
|
| + : candidate.right() - coverage_rect_max_bounds_.width(),
|
| + (tile_j_ != data.num_tiles_y() - 1)
|
| + ? 0
|
| + : candidate.bottom() - coverage_rect_max_bounds_.height());
|
| }
|
|
|
| - current_geometry_rect_.Intersect(coverage_rect_);
|
| - DCHECK(!current_geometry_rect_.IsEmpty());
|
| -
|
| - if (first_time)
|
| - return *this;
|
| -
|
| - // Iteration happens left->right, top->bottom. Running off the bottom-right
|
| - // edge is handled by the intersection above with dest_rect_. Here we make
|
| - // sure that the new current geometry rect doesn't overlap with the last.
|
| - int min_left;
|
| - int min_top;
|
| - if (new_row) {
|
| - min_left = coverage_rect_.x();
|
| - min_top = last_geometry_rect.bottom();
|
| - } else {
|
| - min_left = last_geometry_rect.right();
|
| - min_top = last_geometry_rect.y();
|
| - }
|
| -
|
| - int inset_left = std::max(0, min_left - current_geometry_rect_.x());
|
| - int inset_top = std::max(0, min_top - current_geometry_rect_.y());
|
| - current_geometry_rect_.Inset(inset_left, inset_top, 0, 0);
|
| -
|
| - if (!new_row) {
|
| - DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x());
|
| - DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom());
|
| - DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y());
|
| - }
|
| -
|
| - return *this;
|
| + candidate.Intersect(coverage_rect_);
|
| + return candidate;
|
| }
|
|
|
| gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const {
|
|
|