Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1124)

Unified Diff: cc/tiles/picture_layer_tiling.cc

Issue 2816943004: cc: Fix bugs found by fuzzer due to floating point imprecision. (Closed)
Patch Set: layouttests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/tiles/picture_layer_tiling.h ('k') | cc/tiles/picture_layer_tiling_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 {
« no previous file with comments | « cc/tiles/picture_layer_tiling.h ('k') | cc/tiles/picture_layer_tiling_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698