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 |