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 12 matching lines...) Expand all Loading... | |
23 #include "cc/tiles/tile.h" | 23 #include "cc/tiles/tile.h" |
24 #include "cc/tiles/tile_priority.h" | 24 #include "cc/tiles/tile_priority.h" |
25 #include "ui/gfx/geometry/point_conversions.h" | 25 #include "ui/gfx/geometry/point_conversions.h" |
26 #include "ui/gfx/geometry/rect_conversions.h" | 26 #include "ui/gfx/geometry/rect_conversions.h" |
27 #include "ui/gfx/geometry/rect_f.h" | 27 #include "ui/gfx/geometry/rect_f.h" |
28 #include "ui/gfx/geometry/safe_integer_conversions.h" | 28 #include "ui/gfx/geometry/safe_integer_conversions.h" |
29 #include "ui/gfx/geometry/size_conversions.h" | 29 #include "ui/gfx/geometry/size_conversions.h" |
30 | 30 |
31 namespace cc { | 31 namespace cc { |
32 | 32 |
33 namespace { | |
34 float SnapToOne(float n) { | |
35 return (std::abs(1.f - n) < std::numeric_limits<float>::epsilon()) ? 1.f : n; | |
36 } | |
trchen
2017/04/14 22:07:33
I doubt this function works as intended...
By def
vmpstr
2017/04/14 23:36:26
The definition of epsilon is the difference betwee
trchen
2017/04/14 23:53:43
You're right. I forgot (1-epsilon) contains only 2
vmpstr
2017/04/15 00:31:24
It just happens that when coverage scale is 7352.3
trchen
2017/04/18 21:13:46
Does this helps with the bug you're fixing? I seem
| |
37 } | |
38 | |
33 PictureLayerTiling::PictureLayerTiling( | 39 PictureLayerTiling::PictureLayerTiling( |
34 WhichTree tree, | 40 WhichTree tree, |
35 const gfx::AxisTransform2d& raster_transform, | 41 const gfx::AxisTransform2d& raster_transform, |
36 scoped_refptr<RasterSource> raster_source, | 42 scoped_refptr<RasterSource> raster_source, |
37 PictureLayerTilingClient* client, | 43 PictureLayerTilingClient* client, |
38 float min_preraster_distance, | 44 float min_preraster_distance, |
39 float max_preraster_distance) | 45 float max_preraster_distance) |
40 : raster_transform_(raster_transform), | 46 : raster_transform_(raster_transform), |
41 client_(client), | 47 client_(client), |
42 tree_(tree), | 48 tree_(tree), |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 } | 379 } |
374 | 380 |
375 PictureLayerTiling::CoverageIterator::CoverageIterator() = default; | 381 PictureLayerTiling::CoverageIterator::CoverageIterator() = default; |
376 | 382 |
377 PictureLayerTiling::CoverageIterator::CoverageIterator( | 383 PictureLayerTiling::CoverageIterator::CoverageIterator( |
378 const PictureLayerTiling* tiling, | 384 const PictureLayerTiling* tiling, |
379 float coverage_scale, | 385 float coverage_scale, |
380 const gfx::Rect& coverage_rect) | 386 const gfx::Rect& coverage_rect) |
381 : tiling_(tiling), | 387 : tiling_(tiling), |
382 coverage_rect_(coverage_rect), | 388 coverage_rect_(coverage_rect), |
389 // Note that since this iterator will map possibly large numbers, it's | |
390 // very sensitive to small differences in scale (even less than epsilon). | |
391 // It is also very likely that this coverage iterator would be used with a | |
392 // scale that matches the contents scale (since majority of the time, | |
393 // we're rasterizing high res content. As a result, snap the scale to one | |
394 // if it's within the epsilon. | |
383 coverage_to_content_( | 395 coverage_to_content_( |
384 gfx::PreScaleAxisTransform2d(tiling->raster_transform(), | 396 SnapToOne(tiling->raster_transform().scale() / coverage_scale), |
385 1.f / coverage_scale)) { | 397 tiling->raster_transform().translation()) { |
386 DCHECK(tiling_); | 398 DCHECK(tiling_); |
387 // In order to avoid artifacts in geometry_rect scaling and clamping to ints, | 399 // In order to avoid artifacts in geometry_rect scaling and clamping to ints, |
388 // the |coverage_scale| should always be at least as big as the tiling's | 400 // the |coverage_scale| should always be at least as big as the tiling's |
389 // raster scales. | 401 // raster scales. |
390 DCHECK_GE(coverage_scale, tiling_->raster_transform_.scale()); | 402 DCHECK_GE(coverage_scale, tiling_->raster_transform_.scale()); |
391 | 403 |
392 // Clamp |coverage_rect| to the bounds of this tiling's raster source. | 404 // Clamp |coverage_rect| to the bounds of this tiling's raster source. |
393 coverage_rect_max_bounds_ = | 405 coverage_rect_max_bounds_ = |
394 gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), coverage_scale); | 406 gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), coverage_scale); |
395 coverage_rect_.Intersect(gfx::Rect(coverage_rect_max_bounds_)); | 407 coverage_rect_.Intersect(gfx::Rect(coverage_rect_max_bounds_)); |
(...skipping 17 matching lines...) Expand all Loading... | |
413 // Or in integer index: | 425 // Or in integer index: |
414 // wanted_texels(integer index) = (l:99, t:189, r:280, b:371) | 426 // wanted_texels(integer index) = (l:99, t:189, r:280, b:371) |
415 gfx::RectF content_rect = | 427 gfx::RectF content_rect = |
416 coverage_to_content_.MapRect(gfx::RectF(coverage_rect_)); | 428 coverage_to_content_.MapRect(gfx::RectF(coverage_rect_)); |
417 content_rect.Offset(-0.5f, -0.5f); | 429 content_rect.Offset(-0.5f, -0.5f); |
418 gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect); | 430 gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect); |
419 | 431 |
420 const TilingData& data = tiling_->tiling_data_; | 432 const TilingData& data = tiling_->tiling_data_; |
421 left_ = data.LastBorderTileXIndexFromSrcCoord(wanted_texels.x()); | 433 left_ = data.LastBorderTileXIndexFromSrcCoord(wanted_texels.x()); |
422 top_ = data.LastBorderTileYIndexFromSrcCoord(wanted_texels.y()); | 434 top_ = data.LastBorderTileYIndexFromSrcCoord(wanted_texels.y()); |
435 | |
423 right_ = std::max( | 436 right_ = std::max( |
424 left_, data.FirstBorderTileXIndexFromSrcCoord(wanted_texels.right())); | 437 left_, data.FirstBorderTileXIndexFromSrcCoord(wanted_texels.right())); |
425 bottom_ = std::max( | 438 bottom_ = std::max( |
426 top_, data.FirstBorderTileYIndexFromSrcCoord(wanted_texels.bottom())); | 439 top_, data.FirstBorderTileYIndexFromSrcCoord(wanted_texels.bottom())); |
427 | 440 |
441 // Unfortunately due to floating point math in ToEnclosingRect, wanted_texels | |
442 // could be lying about its dimensions. For example, consider the following: | |
443 // | |
444 // float a = 192.f; | |
445 // float b = 2104670720.f; | |
446 // output("%.0f\n", static_cast<double>(a + b) - b); | |
447 // | |
448 // This code prints out 256. So if that happens to be our coverage rect | |
449 // position and dimension, then the texel extent would try to grab something | |
450 // outside of it, resulting in a DCHECK later (or empty geometry rect with | |
451 // DCHECks disabled), which is undesirable. The solution is to simply | |
452 // backtrack the value until the content rect actually intersects the texel | |
453 // extent for the values we generated. Note this only happens with | |
454 // right/bottom values. | |
455 while (!content_rect.Intersects(data.TexelExtent(right_, top_)) && | |
enne (OOO)
2017/04/14 05:35:56
Hmmm, do you think that FirstBorderTileXIndexFromS
vmpstr
2017/04/14 18:17:42
The problem is that FirstBorderTileXIndexFromSrcCo
trchen
2017/04/14 22:07:33
Just double checked FirstBorderTileXIndexFromSrcCo
vmpstr
2017/04/14 23:36:26
Yes, I meant the access to right/bottom in enclosi
trchen
2017/04/18 21:13:46
Just sync'd up with enne@ offline. We agreed that
| |
456 right_ > left_) { | |
457 --right_; | |
458 } | |
459 while (!content_rect.Intersects(data.TexelExtent(left_, bottom_)) && | |
460 bottom_ > top_) { | |
461 --bottom_; | |
462 } | |
463 | |
428 tile_i_ = left_ - 1; | 464 tile_i_ = left_ - 1; |
429 tile_j_ = top_; | 465 tile_j_ = top_; |
430 ++(*this); | 466 ++(*this); |
431 } | 467 } |
432 | 468 |
433 PictureLayerTiling::CoverageIterator::~CoverageIterator() { | 469 PictureLayerTiling::CoverageIterator::~CoverageIterator() { |
434 } | 470 } |
435 | 471 |
436 PictureLayerTiling::CoverageIterator& | 472 PictureLayerTiling::CoverageIterator& |
437 PictureLayerTiling::CoverageIterator::operator++() { | 473 PictureLayerTiling::CoverageIterator::operator++() { |
438 if (tile_j_ > bottom_) | 474 if (tile_j_ > bottom_) |
439 return *this; | 475 return *this; |
440 | 476 |
441 bool first_time = tile_i_ < left_; | 477 bool first_time = tile_i_ < left_; |
442 bool new_row = false; | 478 bool new_row = false; |
443 tile_i_++; | 479 tile_i_++; |
444 if (tile_i_ > right_) { | 480 if (tile_i_ > right_) { |
445 tile_i_ = left_; | 481 tile_i_ = left_; |
446 tile_j_++; | 482 tile_j_++; |
447 new_row = true; | 483 new_row = true; |
448 if (tile_j_ > bottom_) { | 484 if (tile_j_ > bottom_) { |
449 current_tile_ = NULL; | 485 current_tile_ = NULL; |
450 return *this; | 486 return *this; |
451 } | 487 } |
452 } | 488 } |
453 | 489 |
490 DCHECK_LT(tile_i_, tiling_->tiling_data_.num_tiles_x()); | |
491 DCHECK_LT(tile_j_, tiling_->tiling_data_.num_tiles_y()); | |
454 current_tile_ = tiling_->TileAt(tile_i_, tile_j_); | 492 current_tile_ = tiling_->TileAt(tile_i_, tile_j_); |
455 | 493 |
456 // Calculate the current geometry rect. As we reserved overlap between tiles | 494 // Calculate the current geometry rect. As we reserved overlap between tiles |
457 // to accommodate bilinear filtering and rounding errors in destination | 495 // to accommodate bilinear filtering and rounding errors in destination |
458 // space, the geometry rect might overlap on the edges. | 496 // space, the geometry rect might overlap on the edges. |
459 gfx::Rect last_geometry_rect = current_geometry_rect_; | 497 gfx::Rect last_geometry_rect = current_geometry_rect_; |
460 | 498 |
461 gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_); | 499 gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_); |
462 { | 500 { |
463 // Adjust tile extent to accommodate numerical errors. | 501 // Adjust tile extent to accommodate numerical errors. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 min_top = last_geometry_rect.bottom(); | 552 min_top = last_geometry_rect.bottom(); |
515 } else { | 553 } else { |
516 min_left = last_geometry_rect.right(); | 554 min_left = last_geometry_rect.right(); |
517 min_top = last_geometry_rect.y(); | 555 min_top = last_geometry_rect.y(); |
518 } | 556 } |
519 | 557 |
520 int inset_left = std::max(0, min_left - current_geometry_rect_.x()); | 558 int inset_left = std::max(0, min_left - current_geometry_rect_.x()); |
521 int inset_top = std::max(0, min_top - current_geometry_rect_.y()); | 559 int inset_top = std::max(0, min_top - current_geometry_rect_.y()); |
522 current_geometry_rect_.Inset(inset_left, inset_top, 0, 0); | 560 current_geometry_rect_.Inset(inset_left, inset_top, 0, 0); |
523 | 561 |
562 #if DCHECK_IS_ON() | |
enne (OOO)
2017/04/14 05:35:56
Do you need these extra #ifs?
vmpstr
2017/04/14 18:17:42
Not really, it's just everything is DCHECK in ther
| |
524 if (!new_row) { | 563 if (!new_row) { |
525 DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x()); | 564 DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x()); |
526 DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom()); | 565 DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom()); |
527 DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y()); | 566 DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y()); |
528 } | 567 } |
568 #endif | |
529 | 569 |
530 return *this; | 570 return *this; |
531 } | 571 } |
532 | 572 |
533 gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const { | 573 gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const { |
534 return current_geometry_rect_; | 574 return current_geometry_rect_; |
535 } | 575 } |
536 | 576 |
537 gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { | 577 gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { |
538 auto tex_origin = gfx::PointF( | 578 auto tex_origin = gfx::PointF( |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
577 float ideal_contents_scale, | 617 float ideal_contents_scale, |
578 const Occlusion& occlusion_in_layer_space) { | 618 const Occlusion& occlusion_in_layer_space) { |
579 // If we have, or had occlusions, mark the tiles as 'not done' to ensure that | 619 // If we have, or had occlusions, mark the tiles as 'not done' to ensure that |
580 // we reiterate the tiles for rasterization. | 620 // we reiterate the tiles for rasterization. |
581 if (occlusion_in_layer_space.HasOcclusion() || | 621 if (occlusion_in_layer_space.HasOcclusion() || |
582 current_occlusion_in_layer_space_.HasOcclusion()) { | 622 current_occlusion_in_layer_space_.HasOcclusion()) { |
583 set_all_tiles_done(false); | 623 set_all_tiles_done(false); |
584 } | 624 } |
585 | 625 |
586 const float content_to_screen_scale = | 626 const float content_to_screen_scale = |
587 ideal_contents_scale / raster_transform_.scale(); | 627 SnapToOne(ideal_contents_scale / raster_transform_.scale()); |
588 | 628 |
589 const gfx::Rect* input_rects[] = { | 629 const gfx::Rect* input_rects[] = { |
590 &visible_rect_in_layer_space, &skewport_in_layer_space, | 630 &visible_rect_in_layer_space, &skewport_in_layer_space, |
591 &soon_border_rect_in_layer_space, &eventually_rect_in_layer_space}; | 631 &soon_border_rect_in_layer_space, &eventually_rect_in_layer_space}; |
592 gfx::Rect output_rects[4]; | 632 gfx::Rect output_rects[4]; |
593 for (size_t i = 0; i < arraysize(input_rects); ++i) | 633 for (size_t i = 0; i < arraysize(input_rects); ++i) |
594 output_rects[i] = EnclosingContentsRectFromLayerRect(*input_rects[i]); | 634 output_rects[i] = EnclosingContentsRectFromLayerRect(*input_rects[i]); |
595 // Make sure the eventually rect is aligned to tile bounds. | 635 // Make sure the eventually rect is aligned to tile bounds. |
596 output_rects[3] = | 636 output_rects[3] = |
597 tiling_data_.ExpandRectIgnoringBordersToTileBounds(output_rects[3]); | 637 tiling_data_.ExpandRectIgnoringBordersToTileBounds(output_rects[3]); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
958 return ToEnclosingRect(raster_transform_.MapRect(gfx::RectF(layer_rect))); | 998 return ToEnclosingRect(raster_transform_.MapRect(gfx::RectF(layer_rect))); |
959 } | 999 } |
960 | 1000 |
961 gfx::Rect PictureLayerTiling::EnclosingLayerRectFromContentsRect( | 1001 gfx::Rect PictureLayerTiling::EnclosingLayerRectFromContentsRect( |
962 const gfx::Rect& contents_rect) const { | 1002 const gfx::Rect& contents_rect) const { |
963 return ToEnclosingRect( | 1003 return ToEnclosingRect( |
964 raster_transform_.InverseMapRect(gfx::RectF(contents_rect))); | 1004 raster_transform_.InverseMapRect(gfx::RectF(contents_rect))); |
965 } | 1005 } |
966 | 1006 |
967 } // namespace cc | 1007 } // namespace cc |
OLD | NEW |