| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/tiles/picture_layer_tiling.h" | 5 #include "cc/tiles/picture_layer_tiling.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cmath> | 10 #include <cmath> |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 } | 369 } |
| 370 | 370 |
| 371 PictureLayerTiling::CoverageIterator::CoverageIterator() = default; | 371 PictureLayerTiling::CoverageIterator::CoverageIterator() = default; |
| 372 | 372 |
| 373 PictureLayerTiling::CoverageIterator::CoverageIterator( | 373 PictureLayerTiling::CoverageIterator::CoverageIterator( |
| 374 const PictureLayerTiling* tiling, | 374 const PictureLayerTiling* tiling, |
| 375 float coverage_scale, | 375 float coverage_scale, |
| 376 const gfx::Rect& coverage_rect) | 376 const gfx::Rect& coverage_rect) |
| 377 : tiling_(tiling), | 377 : tiling_(tiling), |
| 378 coverage_rect_(coverage_rect), | 378 coverage_rect_(coverage_rect), |
| 379 coverage_to_content_( | 379 coverage_to_content_(tiling->raster_transform().scale() / coverage_scale, |
| 380 gfx::PreScaleAxisTransform2d(tiling->raster_transform(), | 380 tiling->raster_transform().translation()) { |
| 381 1.f / coverage_scale)) { | |
| 382 DCHECK(tiling_); | 381 DCHECK(tiling_); |
| 383 // In order to avoid artifacts in geometry_rect scaling and clamping to ints, | 382 // In order to avoid artifacts in geometry_rect scaling and clamping to ints, |
| 384 // the |coverage_scale| should always be at least as big as the tiling's | 383 // the |coverage_scale| should always be at least as big as the tiling's |
| 385 // raster scales. | 384 // raster scales. |
| 386 DCHECK_GE(coverage_scale, tiling_->raster_transform_.scale()); | 385 DCHECK_GE(coverage_scale, tiling_->raster_transform_.scale()); |
| 387 | 386 |
| 388 // Clamp |coverage_rect| to the bounds of this tiling's raster source. | 387 // Clamp |coverage_rect| to the bounds of this tiling's raster source. |
| 389 coverage_rect_max_bounds_ = | 388 coverage_rect_max_bounds_ = |
| 390 gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), coverage_scale); | 389 gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), coverage_scale); |
| 391 coverage_rect_.Intersect(gfx::Rect(coverage_rect_max_bounds_)); | 390 coverage_rect_.Intersect(gfx::Rect(coverage_rect_max_bounds_)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 | 427 |
| 429 PictureLayerTiling::CoverageIterator::~CoverageIterator() { | 428 PictureLayerTiling::CoverageIterator::~CoverageIterator() { |
| 430 } | 429 } |
| 431 | 430 |
| 432 PictureLayerTiling::CoverageIterator& | 431 PictureLayerTiling::CoverageIterator& |
| 433 PictureLayerTiling::CoverageIterator::operator++() { | 432 PictureLayerTiling::CoverageIterator::operator++() { |
| 434 if (tile_j_ > bottom_) | 433 if (tile_j_ > bottom_) |
| 435 return *this; | 434 return *this; |
| 436 | 435 |
| 437 bool first_time = tile_i_ < left_; | 436 bool first_time = tile_i_ < left_; |
| 438 bool new_row = false; | 437 while (true) { |
| 439 tile_i_++; | 438 bool new_row = false; |
| 440 if (tile_i_ > right_) { | 439 tile_i_++; |
| 441 tile_i_ = left_; | 440 if (tile_i_ > right_) { |
| 442 tile_j_++; | 441 tile_i_ = left_; |
| 443 new_row = true; | 442 tile_j_++; |
| 444 if (tile_j_ > bottom_) { | 443 new_row = true; |
| 445 current_tile_ = NULL; | 444 if (tile_j_ > bottom_) { |
| 446 return *this; | 445 current_tile_ = NULL; |
| 446 break; |
| 447 } |
| 447 } | 448 } |
| 449 |
| 450 DCHECK_LT(tile_i_, tiling_->tiling_data_.num_tiles_x()); |
| 451 DCHECK_LT(tile_j_, tiling_->tiling_data_.num_tiles_y()); |
| 452 current_tile_ = tiling_->TileAt(tile_i_, tile_j_); |
| 453 |
| 454 gfx::Rect geometry_rect_candidate = ComputeGeometryRect(); |
| 455 |
| 456 // This can happen due to floating point inprecision when calculating the |
| 457 // |wanted_texels| area in the constructor. |
| 458 if (geometry_rect_candidate.IsEmpty()) |
| 459 continue; |
| 460 |
| 461 gfx::Rect last_geometry_rect = current_geometry_rect_; |
| 462 current_geometry_rect_ = geometry_rect_candidate; |
| 463 |
| 464 if (first_time) |
| 465 break; |
| 466 |
| 467 // Iteration happens left->right, top->bottom. Running off the bottom-right |
| 468 // edge is handled by the intersection above with dest_rect_. Here we make |
| 469 // sure that the new current geometry rect doesn't overlap with the last. |
| 470 int min_left; |
| 471 int min_top; |
| 472 if (new_row) { |
| 473 min_left = coverage_rect_.x(); |
| 474 min_top = last_geometry_rect.bottom(); |
| 475 } else { |
| 476 min_left = last_geometry_rect.right(); |
| 477 min_top = last_geometry_rect.y(); |
| 478 } |
| 479 |
| 480 int inset_left = std::max(0, min_left - current_geometry_rect_.x()); |
| 481 int inset_top = std::max(0, min_top - current_geometry_rect_.y()); |
| 482 current_geometry_rect_.Inset(inset_left, inset_top, 0, 0); |
| 483 |
| 484 #if DCHECK_IS_ON() |
| 485 if (!new_row) { |
| 486 DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x()); |
| 487 DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom()); |
| 488 DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y()); |
| 489 } |
| 490 #endif |
| 491 |
| 492 break; |
| 448 } | 493 } |
| 494 return *this; |
| 495 } |
| 449 | 496 |
| 450 current_tile_ = tiling_->TileAt(tile_i_, tile_j_); | 497 gfx::Rect PictureLayerTiling::CoverageIterator::ComputeGeometryRect() const { |
| 451 | |
| 452 // Calculate the current geometry rect. As we reserved overlap between tiles | 498 // Calculate the current geometry rect. As we reserved overlap between tiles |
| 453 // to accommodate bilinear filtering and rounding errors in destination | 499 // to accommodate bilinear filtering and rounding errors in destination |
| 454 // space, the geometry rect might overlap on the edges. | 500 // space, the geometry rect might overlap on the edges. |
| 455 gfx::Rect last_geometry_rect = current_geometry_rect_; | |
| 456 | |
| 457 gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_); | 501 gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_); |
| 458 { | 502 { |
| 459 // Adjust tile extent to accommodate numerical errors. | 503 // Adjust tile extent to accommodate numerical errors. |
| 460 // | 504 // |
| 461 // Allow the tile to overreach by 1/1024 texels to avoid seams between | 505 // Allow the tile to overreach by 1/1024 texels to avoid seams between |
| 462 // tiles. The constant 1/1024 is picked by the fact that with bilinear | 506 // tiles. The constant 1/1024 is picked by the fact that with bilinear |
| 463 // filtering, the maximum error in color value introduced by clamping | 507 // filtering, the maximum error in color value introduced by clamping |
| 464 // error in both u/v axis can't exceed | 508 // error in both u/v axis can't exceed |
| 465 // 255 * (1 - (1 - 1/1024) * (1 - 1/1024)) ~= 0.498 | 509 // 255 * (1 - (1 - 1/1024) * (1 - 1/1024)) ~= 0.498 |
| 466 // i.e. The color value can never flip over a rounding threshold. | 510 // i.e. The color value can never flip over a rounding threshold. |
| 467 constexpr float epsilon = 1.f / 1024.f; | 511 constexpr float epsilon = 1.f / 1024.f; |
| 468 texel_extent.Inset(-epsilon, -epsilon); | 512 texel_extent.Inset(-epsilon, -epsilon); |
| 469 } | 513 } |
| 470 | 514 |
| 471 // Convert texel_extent to coverage scale, which is what we have to report | 515 // Convert texel_extent to coverage scale, which is what we have to report |
| 472 // geometry_rect in. | 516 // geometry_rect in. |
| 473 current_geometry_rect_ = | 517 gfx::Rect candidate = |
| 474 gfx::ToEnclosedRect(coverage_to_content_.InverseMapRect(texel_extent)); | 518 gfx::ToEnclosedRect(coverage_to_content_.InverseMapRect(texel_extent)); |
| 475 { | 519 { |
| 476 // Adjust external edges to cover the whole layer in dest space. | 520 // Adjust external edges to cover the whole layer in dest space. |
| 477 // | 521 // |
| 478 // For external edges, extend the tile to scaled layer bounds. This is | 522 // For external edges, extend the tile to scaled layer bounds. This is |
| 479 // needed to fully cover the coverage space because the sample extent | 523 // needed to fully cover the coverage space because the sample extent |
| 480 // doesn't cover the last 0.5 texel to layer edge, and also the coverage | 524 // doesn't cover the last 0.5 texel to layer edge, and also the coverage |
| 481 // space can be rounded up for up to 1 pixel. This overhang will never be | 525 // space can be rounded up for up to 1 pixel. This overhang will never be |
| 482 // sampled as the AA fragment shader clamps sample coordinate and | 526 // sampled as the AA fragment shader clamps sample coordinate and |
| 483 // antialiasing itself. | 527 // antialiasing itself. |
| 484 const TilingData& data = tiling_->tiling_data_; | 528 const TilingData& data = tiling_->tiling_data_; |
| 485 current_geometry_rect_.Inset(tile_i_ ? 0 : -current_geometry_rect_.x(), | 529 candidate.Inset( |
| 486 tile_j_ ? 0 : -current_geometry_rect_.y(), | 530 tile_i_ ? 0 : -candidate.x(), tile_j_ ? 0 : -candidate.y(), |
| 487 (tile_i_ != data.num_tiles_x() - 1) | 531 (tile_i_ != data.num_tiles_x() - 1) |
| 488 ? 0 | 532 ? 0 |
| 489 : current_geometry_rect_.right() - | 533 : candidate.right() - coverage_rect_max_bounds_.width(), |
| 490 coverage_rect_max_bounds_.width(), | 534 (tile_j_ != data.num_tiles_y() - 1) |
| 491 (tile_j_ != data.num_tiles_y() - 1) | 535 ? 0 |
| 492 ? 0 | 536 : candidate.bottom() - coverage_rect_max_bounds_.height()); |
| 493 : current_geometry_rect_.bottom() - | |
| 494 coverage_rect_max_bounds_.height()); | |
| 495 } | 537 } |
| 496 | 538 |
| 497 current_geometry_rect_.Intersect(coverage_rect_); | 539 candidate.Intersect(coverage_rect_); |
| 498 DCHECK(!current_geometry_rect_.IsEmpty()); | 540 return candidate; |
| 499 | |
| 500 if (first_time) | |
| 501 return *this; | |
| 502 | |
| 503 // Iteration happens left->right, top->bottom. Running off the bottom-right | |
| 504 // edge is handled by the intersection above with dest_rect_. Here we make | |
| 505 // sure that the new current geometry rect doesn't overlap with the last. | |
| 506 int min_left; | |
| 507 int min_top; | |
| 508 if (new_row) { | |
| 509 min_left = coverage_rect_.x(); | |
| 510 min_top = last_geometry_rect.bottom(); | |
| 511 } else { | |
| 512 min_left = last_geometry_rect.right(); | |
| 513 min_top = last_geometry_rect.y(); | |
| 514 } | |
| 515 | |
| 516 int inset_left = std::max(0, min_left - current_geometry_rect_.x()); | |
| 517 int inset_top = std::max(0, min_top - current_geometry_rect_.y()); | |
| 518 current_geometry_rect_.Inset(inset_left, inset_top, 0, 0); | |
| 519 | |
| 520 if (!new_row) { | |
| 521 DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x()); | |
| 522 DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom()); | |
| 523 DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y()); | |
| 524 } | |
| 525 | |
| 526 return *this; | |
| 527 } | 541 } |
| 528 | 542 |
| 529 gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const { | 543 gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const { |
| 530 return current_geometry_rect_; | 544 return current_geometry_rect_; |
| 531 } | 545 } |
| 532 | 546 |
| 533 gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { | 547 gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { |
| 534 auto tex_origin = gfx::PointF( | 548 auto tex_origin = gfx::PointF( |
| 535 tiling_->tiling_data_.TileBoundsWithBorder(tile_i_, tile_j_).origin()); | 549 tiling_->tiling_data_.TileBoundsWithBorder(tile_i_, tile_j_).origin()); |
| 536 | 550 |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 return ToEnclosingRect(raster_transform_.MapRect(gfx::RectF(layer_rect))); | 993 return ToEnclosingRect(raster_transform_.MapRect(gfx::RectF(layer_rect))); |
| 980 } | 994 } |
| 981 | 995 |
| 982 gfx::Rect PictureLayerTiling::EnclosingLayerRectFromContentsRect( | 996 gfx::Rect PictureLayerTiling::EnclosingLayerRectFromContentsRect( |
| 983 const gfx::Rect& contents_rect) const { | 997 const gfx::Rect& contents_rect) const { |
| 984 return ToEnclosingRect( | 998 return ToEnclosingRect( |
| 985 raster_transform_.InverseMapRect(gfx::RectF(contents_rect))); | 999 raster_transform_.InverseMapRect(gfx::RectF(contents_rect))); |
| 986 } | 1000 } |
| 987 | 1001 |
| 988 } // namespace cc | 1002 } // namespace cc |
| OLD | NEW |