| 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 11 matching lines...) Expand all Loading... |
| 22 #include "cc/tiles/prioritized_tile.h" | 22 #include "cc/tiles/prioritized_tile.h" |
| 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 namespace { | |
| 33 | |
| 34 const float kSoonBorderDistanceViewportPercentage = 0.15f; | |
| 35 const float kMaxSoonBorderDistanceInScreenPixels = 312.f; | |
| 36 | |
| 37 } // namespace | |
| 38 | |
| 39 std::unique_ptr<PictureLayerTiling> PictureLayerTiling::Create( | |
| 40 WhichTree tree, | |
| 41 float contents_scale, | |
| 42 scoped_refptr<RasterSource> raster_source, | |
| 43 PictureLayerTilingClient* client, | |
| 44 size_t tiling_interest_area_padding, | |
| 45 float skewport_target_time_in_seconds, | |
| 46 int skewport_extrapolation_limit_in_content_pixels) { | |
| 47 return base::WrapUnique(new PictureLayerTiling( | |
| 48 tree, contents_scale, raster_source, client, tiling_interest_area_padding, | |
| 49 skewport_target_time_in_seconds, | |
| 50 skewport_extrapolation_limit_in_content_pixels)); | |
| 51 } | |
| 52 | 32 |
| 53 PictureLayerTiling::PictureLayerTiling( | 33 PictureLayerTiling::PictureLayerTiling( |
| 54 WhichTree tree, | 34 WhichTree tree, |
| 55 float contents_scale, | 35 float contents_scale, |
| 56 scoped_refptr<RasterSource> raster_source, | 36 scoped_refptr<RasterSource> raster_source, |
| 57 PictureLayerTilingClient* client, | 37 PictureLayerTilingClient* client) |
| 58 size_t tiling_interest_area_padding, | 38 : contents_scale_(contents_scale), |
| 59 float skewport_target_time_in_seconds, | |
| 60 int skewport_extrapolation_limit_in_content_pixels) | |
| 61 : tiling_interest_area_padding_(tiling_interest_area_padding), | |
| 62 skewport_target_time_in_seconds_(skewport_target_time_in_seconds), | |
| 63 skewport_extrapolation_limit_in_content_pixels_( | |
| 64 skewport_extrapolation_limit_in_content_pixels), | |
| 65 contents_scale_(contents_scale), | |
| 66 client_(client), | 39 client_(client), |
| 67 tree_(tree), | 40 tree_(tree), |
| 68 raster_source_(raster_source), | 41 raster_source_(raster_source), |
| 69 resolution_(NON_IDEAL_RESOLUTION), | 42 resolution_(NON_IDEAL_RESOLUTION), |
| 70 may_contain_low_resolution_tiles_(false), | 43 may_contain_low_resolution_tiles_(false), |
| 71 tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), | 44 tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), |
| 72 can_require_tiles_for_activation_(false), | 45 can_require_tiles_for_activation_(false), |
| 73 current_content_to_screen_scale_(0.f), | 46 current_content_to_screen_scale_(0.f), |
| 74 has_visible_rect_tiles_(false), | 47 has_visible_rect_tiles_(false), |
| 75 has_skewport_rect_tiles_(false), | 48 has_skewport_rect_tiles_(false), |
| 76 has_soon_border_rect_tiles_(false), | 49 has_soon_border_rect_tiles_(false), |
| 77 has_eventually_rect_tiles_(false), | 50 has_eventually_rect_tiles_(false), |
| 78 all_tiles_done_(true), | 51 all_tiles_done_(true) { |
| 79 invalidated_since_last_compute_priority_rects_(false) { | |
| 80 DCHECK(!raster_source->IsSolidColor()); | 52 DCHECK(!raster_source->IsSolidColor()); |
| 81 gfx::Size content_bounds = | 53 gfx::Size content_bounds = |
| 82 gfx::ScaleToCeiledSize(raster_source_->GetSize(), contents_scale); | 54 gfx::ScaleToCeiledSize(raster_source_->GetSize(), contents_scale); |
| 83 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); | 55 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); |
| 84 | 56 |
| 85 DCHECK(!gfx::ScaleToFlooredSize(raster_source_->GetSize(), contents_scale) | 57 DCHECK(!gfx::ScaleToFlooredSize(raster_source_->GetSize(), contents_scale) |
| 86 .IsEmpty()) | 58 .IsEmpty()) |
| 87 << "Tiling created with scale too small as contents become empty." | 59 << "Tiling created with scale too small as contents become empty." |
| 88 << " Layer bounds: " << raster_source_->GetSize().ToString() | 60 << " Layer bounds: " << raster_source_->GetSize().ToString() |
| 89 << " Contents scale: " << contents_scale; | 61 << " Contents scale: " << contents_scale; |
| 90 | 62 |
| 91 tiling_data_.SetTilingSize(content_bounds); | 63 tiling_data_.SetTilingSize(content_bounds); |
| 92 tiling_data_.SetMaxTextureSize(tile_size); | 64 tiling_data_.SetMaxTextureSize(tile_size); |
| 93 } | 65 } |
| 94 | 66 |
| 95 PictureLayerTiling::~PictureLayerTiling() { | 67 PictureLayerTiling::~PictureLayerTiling() { |
| 96 } | 68 } |
| 97 | 69 |
| 98 // static | |
| 99 float PictureLayerTiling::CalculateSoonBorderDistance( | |
| 100 const gfx::Rect& visible_rect_in_content_space, | |
| 101 float content_to_screen_scale) { | |
| 102 float max_dimension = std::max(visible_rect_in_content_space.width(), | |
| 103 visible_rect_in_content_space.height()); | |
| 104 return std::min( | |
| 105 kMaxSoonBorderDistanceInScreenPixels / content_to_screen_scale, | |
| 106 max_dimension * kSoonBorderDistanceViewportPercentage); | |
| 107 } | |
| 108 | |
| 109 Tile* PictureLayerTiling::CreateTile(const Tile::CreateInfo& info) { | 70 Tile* PictureLayerTiling::CreateTile(const Tile::CreateInfo& info) { |
| 110 const int i = info.tiling_i_index; | 71 const int i = info.tiling_i_index; |
| 111 const int j = info.tiling_j_index; | 72 const int j = info.tiling_j_index; |
| 112 TileMapKey key(i, j); | 73 TileMapKey key(i, j); |
| 113 DCHECK(tiles_.find(key) == tiles_.end()); | 74 DCHECK(tiles_.find(key) == tiles_.end()); |
| 114 | 75 |
| 115 if (!raster_source_->CoversRect(info.enclosing_layer_rect)) | 76 if (!raster_source_->CoversRect(info.enclosing_layer_rect)) |
| 116 return nullptr; | 77 return nullptr; |
| 117 | 78 |
| 118 all_tiles_done_ = false; | 79 all_tiles_done_ = false; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 for (int i = before_left; i <= before_right; ++i) { | 243 for (int i = before_left; i <= before_right; ++i) { |
| 283 Tile::CreateInfo info = CreateInfoForTile(i, after_bottom); | 244 Tile::CreateInfo info = CreateInfoForTile(i, after_bottom); |
| 284 if (ShouldCreateTileAt(info)) | 245 if (ShouldCreateTileAt(info)) |
| 285 CreateTile(info); | 246 CreateTile(info); |
| 286 } | 247 } |
| 287 } | 248 } |
| 288 } | 249 } |
| 289 | 250 |
| 290 void PictureLayerTiling::Invalidate(const Region& layer_invalidation) { | 251 void PictureLayerTiling::Invalidate(const Region& layer_invalidation) { |
| 291 DCHECK(tree_ != ACTIVE_TREE || !client_->GetPendingOrActiveTwinTiling(this)); | 252 DCHECK(tree_ != ACTIVE_TREE || !client_->GetPendingOrActiveTwinTiling(this)); |
| 292 invalidated_since_last_compute_priority_rects_ = true; | |
| 293 RemoveTilesInRegion(layer_invalidation, true /* recreate tiles */); | 253 RemoveTilesInRegion(layer_invalidation, true /* recreate tiles */); |
| 294 } | 254 } |
| 295 | 255 |
| 296 void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation, | 256 void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation, |
| 297 bool recreate_tiles) { | 257 bool recreate_tiles) { |
| 298 // We only invalidate the active tiling when it's orphaned: it has no pending | 258 // We only invalidate the active tiling when it's orphaned: it has no pending |
| 299 // twin, so it's slated for removal in the future. | 259 // twin, so it's slated for removal in the future. |
| 300 if (live_tiles_rect_.IsEmpty()) | 260 if (live_tiles_rect_.IsEmpty()) |
| 301 return; | 261 return; |
| 302 // Pick 16 for the size of the SmallMap before it promotes to a unordered_map. | 262 // Pick 16 for the size of the SmallMap before it promotes to a unordered_map. |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 tiles_.erase(found); | 528 tiles_.erase(found); |
| 569 return true; | 529 return true; |
| 570 } | 530 } |
| 571 | 531 |
| 572 void PictureLayerTiling::Reset() { | 532 void PictureLayerTiling::Reset() { |
| 573 live_tiles_rect_ = gfx::Rect(); | 533 live_tiles_rect_ = gfx::Rect(); |
| 574 tiles_.clear(); | 534 tiles_.clear(); |
| 575 all_tiles_done_ = true; | 535 all_tiles_done_ = true; |
| 576 } | 536 } |
| 577 | 537 |
| 578 gfx::Rect PictureLayerTiling::ComputeSkewport( | 538 void PictureLayerTiling::ComputeTilePriorityRects( |
| 579 double current_frame_time_in_seconds, | 539 const gfx::Rect& visible_rect_in_layer_space, |
| 580 const gfx::Rect& visible_rect_in_content_space) const { | 540 const gfx::Rect& skewport_in_layer_space, |
| 581 gfx::Rect skewport = visible_rect_in_content_space; | 541 const gfx::Rect& soon_border_rect_in_layer_space, |
| 582 if (skewport.IsEmpty()) | 542 const gfx::Rect& eventually_rect_in_layer_space, |
| 583 return skewport; | |
| 584 | |
| 585 if (visible_rect_history_[1].frame_time_in_seconds == 0.0) | |
| 586 return skewport; | |
| 587 | |
| 588 double time_delta = current_frame_time_in_seconds - | |
| 589 visible_rect_history_[1].frame_time_in_seconds; | |
| 590 if (time_delta == 0.0) | |
| 591 return skewport; | |
| 592 | |
| 593 double extrapolation_multiplier = | |
| 594 skewport_target_time_in_seconds_ / time_delta; | |
| 595 | |
| 596 int old_x = visible_rect_history_[1].visible_rect_in_content_space.x(); | |
| 597 int old_y = visible_rect_history_[1].visible_rect_in_content_space.y(); | |
| 598 int old_right = | |
| 599 visible_rect_history_[1].visible_rect_in_content_space.right(); | |
| 600 int old_bottom = | |
| 601 visible_rect_history_[1].visible_rect_in_content_space.bottom(); | |
| 602 | |
| 603 int new_x = visible_rect_in_content_space.x(); | |
| 604 int new_y = visible_rect_in_content_space.y(); | |
| 605 int new_right = visible_rect_in_content_space.right(); | |
| 606 int new_bottom = visible_rect_in_content_space.bottom(); | |
| 607 | |
| 608 // Compute the maximum skewport based on | |
| 609 // |skewport_extrapolation_limit_in_content_pixels_|. | |
| 610 gfx::Rect max_skewport = skewport; | |
| 611 max_skewport.Inset(-skewport_extrapolation_limit_in_content_pixels_, | |
| 612 -skewport_extrapolation_limit_in_content_pixels_); | |
| 613 | |
| 614 // Inset the skewport by the needed adjustment. | |
| 615 skewport.Inset(extrapolation_multiplier * (new_x - old_x), | |
| 616 extrapolation_multiplier * (new_y - old_y), | |
| 617 extrapolation_multiplier * (old_right - new_right), | |
| 618 extrapolation_multiplier * (old_bottom - new_bottom)); | |
| 619 | |
| 620 // Ensure that visible rect is contained in the skewport. | |
| 621 skewport.Union(visible_rect_in_content_space); | |
| 622 | |
| 623 // Clip the skewport to |max_skewport|. This needs to happen after the | |
| 624 // union in case intersecting would have left the empty rect. | |
| 625 skewport.Intersect(max_skewport); | |
| 626 | |
| 627 // Due to limits in int's representation, it is possible that the two | |
| 628 // operations above (union and intersect) result in an empty skewport. To | |
| 629 // avoid any unpleasant situations like that, union the visible rect again to | |
| 630 // ensure that skewport.Contains(visible_rect_in_content_space) is always | |
| 631 // true. | |
| 632 skewport.Union(visible_rect_in_content_space); | |
| 633 | |
| 634 return skewport; | |
| 635 } | |
| 636 | |
| 637 bool PictureLayerTiling::ComputeTilePriorityRects( | |
| 638 const gfx::Rect& viewport_in_layer_space, | |
| 639 float ideal_contents_scale, | 543 float ideal_contents_scale, |
| 640 double current_frame_time_in_seconds, | |
| 641 const Occlusion& occlusion_in_layer_space) { | 544 const Occlusion& occlusion_in_layer_space) { |
| 642 // If we have, or had occlusions, mark the tiles as 'not done' to ensure that | 545 // If we have, or had occlusions, mark the tiles as 'not done' to ensure that |
| 643 // we reiterate the tiles for rasterization. | 546 // we reiterate the tiles for rasterization. |
| 644 if (occlusion_in_layer_space.HasOcclusion() || | 547 if (occlusion_in_layer_space.HasOcclusion() || |
| 645 current_occlusion_in_layer_space_.HasOcclusion()) { | 548 current_occlusion_in_layer_space_.HasOcclusion()) { |
| 646 set_all_tiles_done(false); | 549 set_all_tiles_done(false); |
| 647 } | 550 } |
| 648 | 551 |
| 649 bool invalidated = invalidated_since_last_compute_priority_rects_; | |
| 650 invalidated_since_last_compute_priority_rects_ = false; | |
| 651 if (!NeedsUpdateForFrameAtTimeAndViewport(current_frame_time_in_seconds, | |
| 652 viewport_in_layer_space)) { | |
| 653 // This should never be zero for the purposes of has_ever_been_updated(). | |
| 654 DCHECK_NE(current_frame_time_in_seconds, 0.0); | |
| 655 return invalidated; | |
| 656 } | |
| 657 | |
| 658 const float content_to_screen_scale = ideal_contents_scale / contents_scale_; | 552 const float content_to_screen_scale = ideal_contents_scale / contents_scale_; |
| 659 | 553 |
| 660 // We want to compute the visible rect and eventually rect from it in the | 554 const gfx::Rect* input_rects[] = { |
| 661 // space of the tiling. But the visible rect (viewport) can be arbitrarily | 555 &visible_rect_in_layer_space, &skewport_in_layer_space, |
| 662 // positioned, so be careful when scaling it since we can exceed integer | 556 &soon_border_rect_in_layer_space, &eventually_rect_in_layer_space}; |
| 663 // bounds. | 557 gfx::Rect output_rects[4]; |
| 664 gfx::Rect eventually_rect; | 558 for (size_t i = 0; i < arraysize(input_rects); ++i) { |
| 665 gfx::Rect visible_rect_in_content_space; | 559 output_rects[i] = gfx::ToEnclosingRect( |
| 560 gfx::ScaleRect(gfx::RectF(*input_rects[i]), contents_scale_)); |
| 561 } |
| 562 // Make sure the eventually rect is aligned to tile bounds. |
| 563 output_rects[3] = |
| 564 tiling_data_.ExpandRectIgnoringBordersToTileBounds(output_rects[3]); |
| 666 | 565 |
| 667 // We keep things as floats in here. | 566 SetTilePriorityRects(content_to_screen_scale, output_rects[0], |
| 668 { | 567 output_rects[1], output_rects[2], output_rects[3], |
| 669 gfx::RectF visible_rectf_in_content_space = | |
| 670 gfx::ScaleRect(gfx::RectF(viewport_in_layer_space), contents_scale_); | |
| 671 | |
| 672 // Determine if the eventually rect will even touch the tiling, if it's too | |
| 673 // far away just treat it as empty so we don't exceed integer bounds. | |
| 674 const float pad_in_content_space = | |
| 675 tiling_interest_area_padding_ / content_to_screen_scale; | |
| 676 gfx::RectF eventually_rectf = visible_rectf_in_content_space; | |
| 677 // If the visible rect is empty, keep the eventually rect as empty. | |
| 678 if (!eventually_rectf.IsEmpty()) { | |
| 679 eventually_rectf.Inset(-pad_in_content_space, -pad_in_content_space); | |
| 680 | |
| 681 // If the eventually rect will touch the tiling, then we convert back to | |
| 682 // integers and set the visible and eventually rects. | |
| 683 auto bounds = gfx::RectF(gfx::SizeF(tiling_size())); | |
| 684 if (eventually_rectf.Intersects(bounds)) { | |
| 685 visible_rect_in_content_space = | |
| 686 gfx::ToEnclosingRect(visible_rectf_in_content_space); | |
| 687 eventually_rect = gfx::ToEnclosingRect(eventually_rectf); | |
| 688 } | |
| 689 } | |
| 690 } | |
| 691 DCHECK_EQ(visible_rect_in_content_space.IsEmpty(), eventually_rect.IsEmpty()); | |
| 692 | |
| 693 // Now we have an empty visible/eventually rect if it's not useful and a | |
| 694 // non-empty one if it is. We can compute the final eventually rect. | |
| 695 eventually_rect = | |
| 696 tiling_data_.ExpandRectIgnoringBordersToTileBounds(eventually_rect); | |
| 697 | |
| 698 DCHECK(eventually_rect.IsEmpty() || | |
| 699 gfx::Rect(tiling_size()).Contains(eventually_rect)) | |
| 700 << "tiling_size: " << tiling_size().ToString() | |
| 701 << " eventually_rect: " << eventually_rect.ToString(); | |
| 702 | |
| 703 if (tiling_size().IsEmpty()) { | |
| 704 UpdateVisibleRectHistory(current_frame_time_in_seconds, | |
| 705 visible_rect_in_content_space); | |
| 706 last_viewport_in_layer_space_ = viewport_in_layer_space; | |
| 707 return false; | |
| 708 } | |
| 709 | |
| 710 // Calculate the skewport. | |
| 711 gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds, | |
| 712 visible_rect_in_content_space); | |
| 713 DCHECK(skewport.Contains(visible_rect_in_content_space)); | |
| 714 | |
| 715 // Calculate the soon border rect. | |
| 716 gfx::Rect soon_border_rect = visible_rect_in_content_space; | |
| 717 float border = CalculateSoonBorderDistance(visible_rect_in_content_space, | |
| 718 content_to_screen_scale); | |
| 719 soon_border_rect.Inset(-border, -border, -border, -border); | |
| 720 | |
| 721 UpdateVisibleRectHistory(current_frame_time_in_seconds, | |
| 722 visible_rect_in_content_space); | |
| 723 last_viewport_in_layer_space_ = viewport_in_layer_space; | |
| 724 | |
| 725 SetTilePriorityRects(content_to_screen_scale, visible_rect_in_content_space, | |
| 726 skewport, soon_border_rect, eventually_rect, | |
| 727 occlusion_in_layer_space); | 568 occlusion_in_layer_space); |
| 728 SetLiveTilesRect(eventually_rect); | 569 SetLiveTilesRect(output_rects[3]); |
| 729 return true; | |
| 730 } | 570 } |
| 731 | 571 |
| 732 void PictureLayerTiling::SetTilePriorityRects( | 572 void PictureLayerTiling::SetTilePriorityRects( |
| 733 float content_to_screen_scale, | 573 float content_to_screen_scale, |
| 734 const gfx::Rect& visible_rect_in_content_space, | 574 const gfx::Rect& visible_rect_in_content_space, |
| 735 const gfx::Rect& skewport, | 575 const gfx::Rect& skewport, |
| 736 const gfx::Rect& soon_border_rect, | 576 const gfx::Rect& soon_border_rect, |
| 737 const gfx::Rect& eventually_rect, | 577 const gfx::Rect& eventually_rect, |
| 738 const Occlusion& occlusion_in_layer_space) { | 578 const Occlusion& occlusion_in_layer_space) { |
| 739 current_visible_rect_ = visible_rect_in_content_space; | 579 current_visible_rect_ = visible_rect_in_content_space; |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { | 879 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { |
| 1040 size_t amount = 0; | 880 size_t amount = 0; |
| 1041 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 881 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 1042 const Tile* tile = it->second.get(); | 882 const Tile* tile = it->second.get(); |
| 1043 amount += tile->GPUMemoryUsageInBytes(); | 883 amount += tile->GPUMemoryUsageInBytes(); |
| 1044 } | 884 } |
| 1045 return amount; | 885 return amount; |
| 1046 } | 886 } |
| 1047 | 887 |
| 1048 } // namespace cc | 888 } // namespace cc |
| OLD | NEW |