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 |