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/resources/picture_layer_tiling.h" | 5 #include "cc/resources/picture_layer_tiling.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <limits> | 9 #include <limits> |
10 #include <set> | 10 #include <set> |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 return a_is_occluded; | 47 return a_is_occluded; |
48 | 48 |
49 // Or if a is farther away from visible. | 49 // Or if a is farther away from visible. |
50 return a_priority.distance_to_visible > b_priority.distance_to_visible; | 50 return a_priority.distance_to_visible > b_priority.distance_to_visible; |
51 } | 51 } |
52 | 52 |
53 private: | 53 private: |
54 TreePriority tree_priority_; | 54 TreePriority tree_priority_; |
55 }; | 55 }; |
56 | 56 |
57 void ReleaseTile(Tile* tile, WhichTree tree) { | |
58 // Reset priority as tile is ref-counted and might still be used | |
59 // even though we no longer hold a reference to it here anymore. | |
60 tile->SetPriority(tree, TilePriority()); | |
61 tile->set_shared(false); | |
62 } | |
63 | |
64 } // namespace | 57 } // namespace |
65 | 58 |
66 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( | 59 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( |
67 float contents_scale, | 60 float contents_scale, |
68 const gfx::Size& layer_bounds, | 61 const gfx::Size& layer_bounds, |
69 PictureLayerTilingClient* client) { | 62 PictureLayerTilingClient* client) { |
70 return make_scoped_ptr(new PictureLayerTiling(contents_scale, | 63 return make_scoped_ptr(new PictureLayerTiling(contents_scale, |
71 layer_bounds, | 64 layer_bounds, |
72 client)); | 65 client)); |
73 } | 66 } |
74 | 67 |
75 PictureLayerTiling::PictureLayerTiling(float contents_scale, | 68 PictureLayerTiling::PictureLayerTiling(float contents_scale, |
76 const gfx::Size& layer_bounds, | 69 const gfx::Size& layer_bounds, |
77 PictureLayerTilingClient* client) | 70 PictureLayerTilingClient* client) |
78 : contents_scale_(contents_scale), | 71 : contents_scale_(contents_scale), |
79 layer_bounds_(layer_bounds), | 72 layer_bounds_(layer_bounds), |
80 resolution_(NON_IDEAL_RESOLUTION), | 73 resolution_(NON_IDEAL_RESOLUTION), |
81 client_(client), | 74 client_(client), |
82 tiling_data_(gfx::Size(), gfx::Size(), true), | 75 tiling_data_(gfx::Size(), gfx::Size(), true), |
83 last_impl_frame_time_in_seconds_(0.0), | 76 last_impl_frame_time_in_seconds_(0.0), |
| 77 content_to_screen_scale_(0.f), |
| 78 can_require_tiles_for_activation_(false), |
84 has_visible_rect_tiles_(false), | 79 has_visible_rect_tiles_(false), |
85 has_skewport_rect_tiles_(false), | 80 has_skewport_rect_tiles_(false), |
86 has_soon_border_rect_tiles_(false), | 81 has_soon_border_rect_tiles_(false), |
87 has_eventually_rect_tiles_(false), | 82 has_eventually_rect_tiles_(false), |
88 eviction_tiles_cache_valid_(false), | 83 eviction_tiles_cache_valid_(false), |
89 eviction_cache_tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES) { | 84 eviction_cache_tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES) { |
90 gfx::Size content_bounds = | 85 gfx::Size content_bounds = |
91 gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); | 86 gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); |
92 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); | 87 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); |
93 if (tile_size.IsEmpty()) { | 88 if (tile_size.IsEmpty()) { |
94 layer_bounds_ = gfx::Size(); | 89 layer_bounds_ = gfx::Size(); |
95 content_bounds = gfx::Size(); | 90 content_bounds = gfx::Size(); |
96 } | 91 } |
97 | 92 |
98 DCHECK(!gfx::ToFlooredSize( | 93 DCHECK(!gfx::ToFlooredSize( |
99 gfx::ScaleSize(layer_bounds, contents_scale)).IsEmpty()) << | 94 gfx::ScaleSize(layer_bounds, contents_scale)).IsEmpty()) << |
100 "Tiling created with scale too small as contents become empty." << | 95 "Tiling created with scale too small as contents become empty." << |
101 " Layer bounds: " << layer_bounds.ToString() << | 96 " Layer bounds: " << layer_bounds.ToString() << |
102 " Contents scale: " << contents_scale; | 97 " Contents scale: " << contents_scale; |
103 | 98 |
104 tiling_data_.SetTilingSize(content_bounds); | 99 tiling_data_.SetTilingSize(content_bounds); |
105 tiling_data_.SetMaxTextureSize(tile_size); | 100 tiling_data_.SetMaxTextureSize(tile_size); |
106 } | 101 } |
107 | 102 |
108 PictureLayerTiling::~PictureLayerTiling() { | 103 PictureLayerTiling::~PictureLayerTiling() { |
109 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) | 104 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) |
110 ReleaseTile(it->second.get(), client_->GetTree()); | 105 it->second->set_shared(false); |
111 } | 106 } |
112 | 107 |
113 void PictureLayerTiling::SetClient(PictureLayerTilingClient* client) { | 108 void PictureLayerTiling::SetClient(PictureLayerTilingClient* client) { |
114 client_ = client; | 109 client_ = client; |
115 } | 110 } |
116 | 111 |
117 Tile* PictureLayerTiling::CreateTile(int i, | 112 Tile* PictureLayerTiling::CreateTile(int i, |
118 int j, | 113 int j, |
119 const PictureLayerTiling* twin_tiling) { | 114 const PictureLayerTiling* twin_tiling) { |
120 TileMapKey key(i, j); | 115 TileMapKey key(i, j); |
121 DCHECK(tiles_.find(key) == tiles_.end()); | 116 DCHECK(tiles_.find(key) == tiles_.end()); |
122 | 117 |
123 gfx::Rect paint_rect = tiling_data_.TileBoundsWithBorder(i, j); | 118 gfx::Rect paint_rect = tiling_data_.TileBoundsWithBorder(i, j); |
124 gfx::Rect tile_rect = paint_rect; | 119 gfx::Rect tile_rect = paint_rect; |
125 tile_rect.set_size(tiling_data_.max_texture_size()); | 120 tile_rect.set_size(tiling_data_.max_texture_size()); |
126 | 121 |
127 // Check our twin for a valid tile. | 122 // Check our twin for a valid tile. |
128 if (twin_tiling && | 123 if (twin_tiling && |
129 tiling_data_.max_texture_size() == | 124 tiling_data_.max_texture_size() == |
130 twin_tiling->tiling_data_.max_texture_size()) { | 125 twin_tiling->tiling_data_.max_texture_size()) { |
131 if (Tile* candidate_tile = twin_tiling->TileAt(i, j)) { | 126 if (Tile* candidate_tile = twin_tiling->TileAt(i, j)) { |
132 gfx::Rect rect = | 127 gfx::Rect rect = |
133 gfx::ScaleToEnclosingRect(paint_rect, 1.0f / contents_scale_); | 128 gfx::ScaleToEnclosingRect(paint_rect, 1.0f / contents_scale_); |
134 if (!client_->GetInvalidation()->Intersects(rect)) { | 129 if (!client_->GetInvalidation()->Intersects(rect)) { |
135 DCHECK(!candidate_tile->is_shared()); | 130 DCHECK(!candidate_tile->is_shared()); |
| 131 DCHECK_EQ(i, candidate_tile->tiling_i_index()); |
| 132 DCHECK_EQ(j, candidate_tile->tiling_j_index()); |
136 candidate_tile->set_shared(true); | 133 candidate_tile->set_shared(true); |
137 tiles_[key] = candidate_tile; | 134 tiles_[key] = candidate_tile; |
138 return candidate_tile; | 135 return candidate_tile; |
139 } | 136 } |
140 } | 137 } |
141 } | 138 } |
142 | 139 |
143 // Create a new tile because our twin didn't have a valid one. | 140 // Create a new tile because our twin didn't have a valid one. |
144 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); | 141 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); |
145 if (tile.get()) { | 142 if (tile.get()) { |
146 DCHECK(!tile->is_shared()); | 143 DCHECK(!tile->is_shared()); |
| 144 tile->set_tiling_index(i, j); |
147 tiles_[key] = tile; | 145 tiles_[key] = tile; |
148 } | 146 } |
149 return tile.get(); | 147 return tile.get(); |
150 } | 148 } |
151 | 149 |
152 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { | 150 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
153 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); | 151 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
154 bool include_borders = false; | 152 bool include_borders = false; |
155 for (TilingData::Iterator iter( | 153 for (TilingData::Iterator iter( |
156 &tiling_data_, live_tiles_rect_, include_borders); | 154 &tiling_data_, live_tiles_rect_, include_borders); |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 gfx::Size PictureLayerTiling::CoverageIterator::texture_size() const { | 457 gfx::Size PictureLayerTiling::CoverageIterator::texture_size() const { |
460 return tiling_->tiling_data_.max_texture_size(); | 458 return tiling_->tiling_data_.max_texture_size(); |
461 } | 459 } |
462 | 460 |
463 bool PictureLayerTiling::RemoveTileAt(int i, | 461 bool PictureLayerTiling::RemoveTileAt(int i, |
464 int j, | 462 int j, |
465 PictureLayerTiling* recycled_twin) { | 463 PictureLayerTiling* recycled_twin) { |
466 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); | 464 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); |
467 if (found == tiles_.end()) | 465 if (found == tiles_.end()) |
468 return false; | 466 return false; |
469 ReleaseTile(found->second.get(), client_->GetTree()); | 467 found->second->set_shared(false); |
470 tiles_.erase(found); | 468 tiles_.erase(found); |
471 if (recycled_twin) { | 469 if (recycled_twin) { |
472 // Recycled twin does not also have a recycled twin, so pass NULL. | 470 // Recycled twin does not also have a recycled twin, so pass NULL. |
473 recycled_twin->RemoveTileAt(i, j, NULL); | 471 recycled_twin->RemoveTileAt(i, j, NULL); |
474 } | 472 } |
475 return true; | 473 return true; |
476 } | 474 } |
477 | 475 |
478 void PictureLayerTiling::Reset() { | 476 void PictureLayerTiling::Reset() { |
479 live_tiles_rect_ = gfx::Rect(); | 477 live_tiles_rect_ = gfx::Rect(); |
480 PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); | 478 PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); |
481 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 479 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
482 ReleaseTile(it->second.get(), client_->GetTree()); | 480 it->second->set_shared(false); |
483 if (recycled_twin) | 481 if (recycled_twin) |
484 recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); | 482 recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); |
485 } | 483 } |
486 tiles_.clear(); | 484 tiles_.clear(); |
487 } | 485 } |
488 | 486 |
489 gfx::Rect PictureLayerTiling::ComputeSkewport( | 487 gfx::Rect PictureLayerTiling::ComputeSkewport( |
490 double current_frame_time_in_seconds, | 488 double current_frame_time_in_seconds, |
491 const gfx::Rect& visible_rect_in_content_space) const { | 489 const gfx::Rect& visible_rect_in_content_space) const { |
492 gfx::Rect skewport = visible_rect_in_content_space; | 490 gfx::Rect skewport = visible_rect_in_content_space; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 extrapolation_multiplier * (old_bottom - new_bottom)); | 525 extrapolation_multiplier * (old_bottom - new_bottom)); |
528 | 526 |
529 // Clip the skewport to |max_skewport|. | 527 // Clip the skewport to |max_skewport|. |
530 skewport.Intersect(max_skewport); | 528 skewport.Intersect(max_skewport); |
531 | 529 |
532 // Finally, ensure that visible rect is contained in the skewport. | 530 // Finally, ensure that visible rect is contained in the skewport. |
533 skewport.Union(visible_rect_in_content_space); | 531 skewport.Union(visible_rect_in_content_space); |
534 return skewport; | 532 return skewport; |
535 } | 533 } |
536 | 534 |
537 void PictureLayerTiling::UpdateTilePriorities( | 535 void PictureLayerTiling::ComputeTilePriorityRects( |
538 WhichTree tree, | 536 WhichTree tree, |
539 const gfx::Rect& viewport_in_layer_space, | 537 const gfx::Rect& viewport_in_layer_space, |
540 float ideal_contents_scale, | 538 float ideal_contents_scale, |
541 double current_frame_time_in_seconds, | 539 double current_frame_time_in_seconds, |
542 const Occlusion& occlusion_in_layer_space) { | 540 const Occlusion& occlusion_in_layer_space) { |
543 if (!NeedsUpdateForFrameAtTime(current_frame_time_in_seconds)) { | 541 if (!NeedsUpdateForFrameAtTime(current_frame_time_in_seconds)) { |
544 // This should never be zero for the purposes of has_ever_been_updated(). | 542 // This should never be zero for the purposes of has_ever_been_updated(). |
545 DCHECK_NE(current_frame_time_in_seconds, 0.0); | 543 DCHECK_NE(current_frame_time_in_seconds, 0.0); |
546 return; | 544 return; |
547 } | 545 } |
548 | 546 |
549 gfx::Rect visible_rect_in_content_space = | 547 gfx::Rect visible_rect_in_content_space = |
550 gfx::ScaleToEnclosingRect(viewport_in_layer_space, contents_scale_); | 548 gfx::ScaleToEnclosingRect(viewport_in_layer_space, contents_scale_); |
551 | 549 |
552 if (tiling_size().IsEmpty()) { | 550 if (tiling_size().IsEmpty()) { |
553 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; | 551 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
554 last_visible_rect_in_content_space_ = visible_rect_in_content_space; | 552 last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
555 return; | 553 return; |
556 } | 554 } |
557 | 555 |
| 556 // Calculate the skewport. |
| 557 gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds, |
| 558 visible_rect_in_content_space); |
| 559 DCHECK(skewport.Contains(visible_rect_in_content_space)); |
| 560 |
| 561 // Calculate the eventually/live tiles rect. |
558 size_t max_tiles_for_interest_area = client_->GetMaxTilesForInterestArea(); | 562 size_t max_tiles_for_interest_area = client_->GetMaxTilesForInterestArea(); |
559 | 563 |
560 gfx::Size tile_size = tiling_data_.max_texture_size(); | 564 gfx::Size tile_size = tiling_data_.max_texture_size(); |
561 int64 eventually_rect_area = | 565 int64 eventually_rect_area = |
562 max_tiles_for_interest_area * tile_size.width() * tile_size.height(); | 566 max_tiles_for_interest_area * tile_size.width() * tile_size.height(); |
563 | 567 |
564 gfx::Rect skewport = ComputeSkewport(current_frame_time_in_seconds, | |
565 visible_rect_in_content_space); | |
566 DCHECK(skewport.Contains(visible_rect_in_content_space)); | |
567 | |
568 gfx::Rect eventually_rect = | 568 gfx::Rect eventually_rect = |
569 ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space, | 569 ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space, |
570 eventually_rect_area, | 570 eventually_rect_area, |
571 gfx::Rect(tiling_size()), | 571 gfx::Rect(tiling_size()), |
572 &expansion_cache_); | 572 &expansion_cache_); |
573 | 573 |
574 DCHECK(eventually_rect.IsEmpty() || | 574 DCHECK(eventually_rect.IsEmpty() || |
575 gfx::Rect(tiling_size()).Contains(eventually_rect)) | 575 gfx::Rect(tiling_size()).Contains(eventually_rect)) |
576 << "tiling_size: " << tiling_size().ToString() | 576 << "tiling_size: " << tiling_size().ToString() |
577 << " eventually_rect: " << eventually_rect.ToString(); | 577 << " eventually_rect: " << eventually_rect.ToString(); |
578 | 578 |
| 579 // Calculate the soon border rect. |
| 580 content_to_screen_scale_ = ideal_contents_scale / contents_scale_; |
| 581 gfx::Rect soon_border_rect = visible_rect_in_content_space; |
| 582 float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale_; |
| 583 soon_border_rect.Inset(-border, -border, -border, -border); |
| 584 |
| 585 // Update the tiling state. |
579 SetLiveTilesRect(eventually_rect); | 586 SetLiveTilesRect(eventually_rect); |
580 | 587 |
581 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; | 588 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
582 last_visible_rect_in_content_space_ = visible_rect_in_content_space; | 589 last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
583 | 590 |
584 eviction_tiles_cache_valid_ = false; | 591 eviction_tiles_cache_valid_ = false; |
585 | 592 |
586 TilePriority now_priority(resolution_, TilePriority::NOW, 0); | |
587 float content_to_screen_scale = ideal_contents_scale / contents_scale_; | |
588 | |
589 // Assign now priority to all visible tiles. | |
590 bool include_borders = false; | |
591 has_visible_rect_tiles_ = false; | |
592 for (TilingData::Iterator iter( | |
593 &tiling_data_, visible_rect_in_content_space, include_borders); | |
594 iter; | |
595 ++iter) { | |
596 TileMap::iterator find = tiles_.find(iter.index()); | |
597 if (find == tiles_.end()) | |
598 continue; | |
599 has_visible_rect_tiles_ = true; | |
600 Tile* tile = find->second.get(); | |
601 | |
602 tile->SetPriority(tree, now_priority); | |
603 | |
604 // Set whether tile is occluded or not. | |
605 gfx::Rect tile_query_rect = ScaleToEnclosingRect( | |
606 IntersectRects(tile->content_rect(), visible_rect_in_content_space), | |
607 1.0f / contents_scale_); | |
608 bool is_occluded = occlusion_in_layer_space.IsOccluded(tile_query_rect); | |
609 tile->set_is_occluded(tree, is_occluded); | |
610 } | |
611 | |
612 // Assign soon priority to skewport tiles. | |
613 has_skewport_rect_tiles_ = false; | |
614 for (TilingData::DifferenceIterator iter( | |
615 &tiling_data_, skewport, visible_rect_in_content_space); | |
616 iter; | |
617 ++iter) { | |
618 TileMap::iterator find = tiles_.find(iter.index()); | |
619 if (find == tiles_.end()) | |
620 continue; | |
621 has_skewport_rect_tiles_ = true; | |
622 Tile* tile = find->second.get(); | |
623 | |
624 gfx::Rect tile_bounds = | |
625 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); | |
626 | |
627 float distance_to_visible = | |
628 visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * | |
629 content_to_screen_scale; | |
630 | |
631 TilePriority priority(resolution_, TilePriority::SOON, distance_to_visible); | |
632 tile->SetPriority(tree, priority); | |
633 } | |
634 | |
635 // Assign eventually priority to interest rect tiles. | |
636 has_eventually_rect_tiles_ = false; | |
637 for (TilingData::DifferenceIterator iter( | |
638 &tiling_data_, eventually_rect, skewport); | |
639 iter; | |
640 ++iter) { | |
641 TileMap::iterator find = tiles_.find(iter.index()); | |
642 if (find == tiles_.end()) | |
643 continue; | |
644 has_eventually_rect_tiles_ = true; | |
645 Tile* tile = find->second.get(); | |
646 | |
647 gfx::Rect tile_bounds = | |
648 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); | |
649 | |
650 float distance_to_visible = | |
651 visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * | |
652 content_to_screen_scale; | |
653 TilePriority priority( | |
654 resolution_, TilePriority::EVENTUALLY, distance_to_visible); | |
655 tile->SetPriority(tree, priority); | |
656 } | |
657 | |
658 // Upgrade the priority on border tiles to be SOON. | |
659 gfx::Rect soon_border_rect = visible_rect_in_content_space; | |
660 float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale; | |
661 soon_border_rect.Inset(-border, -border, -border, -border); | |
662 has_soon_border_rect_tiles_ = false; | |
663 for (TilingData::DifferenceIterator iter( | |
664 &tiling_data_, soon_border_rect, skewport); | |
665 iter; | |
666 ++iter) { | |
667 TileMap::iterator find = tiles_.find(iter.index()); | |
668 if (find == tiles_.end()) | |
669 continue; | |
670 has_soon_border_rect_tiles_ = true; | |
671 Tile* tile = find->second.get(); | |
672 | |
673 TilePriority priority(resolution_, | |
674 TilePriority::SOON, | |
675 tile->priority(tree).distance_to_visible); | |
676 tile->SetPriority(tree, priority); | |
677 } | |
678 | |
679 // Update iteration rects. | |
680 current_visible_rect_ = visible_rect_in_content_space; | 593 current_visible_rect_ = visible_rect_in_content_space; |
681 current_skewport_rect_ = skewport; | 594 current_skewport_rect_ = skewport; |
682 current_soon_border_rect_ = soon_border_rect; | 595 current_soon_border_rect_ = soon_border_rect; |
683 current_eventually_rect_ = eventually_rect; | 596 current_eventually_rect_ = eventually_rect; |
| 597 current_occlusion_in_layer_space_ = occlusion_in_layer_space; |
| 598 |
| 599 // Update has_*_tiles state. |
| 600 gfx::Rect tiling_rect(tiling_size()); |
| 601 |
| 602 has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); |
| 603 has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_); |
| 604 has_soon_border_rect_tiles_ = |
| 605 tiling_rect.Intersects(current_soon_border_rect_); |
| 606 has_eventually_rect_tiles_ = tiling_rect.Intersects(current_eventually_rect_); |
684 } | 607 } |
685 | 608 |
686 void PictureLayerTiling::SetLiveTilesRect( | 609 void PictureLayerTiling::SetLiveTilesRect( |
687 const gfx::Rect& new_live_tiles_rect) { | 610 const gfx::Rect& new_live_tiles_rect) { |
688 DCHECK(new_live_tiles_rect.IsEmpty() || | 611 DCHECK(new_live_tiles_rect.IsEmpty() || |
689 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) | 612 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) |
690 << "tiling_size: " << tiling_size().ToString() | 613 << "tiling_size: " << tiling_size().ToString() |
691 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); | 614 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); |
692 if (live_tiles_rect_ == new_live_tiles_rect) | 615 if (live_tiles_rect_ == new_live_tiles_rect) |
693 return; | 616 return; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 DCHECK(tiling_data_.TileBounds(it->first.first, it->first.second) | 657 DCHECK(tiling_data_.TileBounds(it->first.first, it->first.second) |
735 .Intersects(live_tiles_rect_)) | 658 .Intersects(live_tiles_rect_)) |
736 << this << " " << it->first.first << "," << it->first.second | 659 << this << " " << it->first.first << "," << it->first.second |
737 << " tile bounds " | 660 << " tile bounds " |
738 << tiling_data_.TileBounds(it->first.first, it->first.second).ToString() | 661 << tiling_data_.TileBounds(it->first.first, it->first.second).ToString() |
739 << " live_tiles_rect " << live_tiles_rect_.ToString(); | 662 << " live_tiles_rect " << live_tiles_rect_.ToString(); |
740 } | 663 } |
741 #endif | 664 #endif |
742 } | 665 } |
743 | 666 |
744 void PictureLayerTiling::DidBecomeRecycled() { | 667 bool PictureLayerTiling::IsTileOccluded(const Tile* tile) const { |
745 // DidBecomeActive below will set the active priority for tiles that are | 668 DCHECK(tile); |
746 // still in the tree. Calling this first on an active tiling that is becoming | 669 |
747 // recycled takes care of tiles that are no longer in the active tree (eg. | 670 if (!current_occlusion_in_layer_space_.HasOcclusion()) |
748 // due to a pending invalidation). | 671 return false; |
749 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 672 |
750 it->second->SetPriority(ACTIVE_TREE, TilePriority()); | 673 gfx::Rect tile_query_rect = |
| 674 gfx::IntersectRects(tile->content_rect(), current_visible_rect_); |
| 675 |
| 676 // Explicitly check if the tile is outside the viewport. If so, we need to |
| 677 // return false, since occlusion for this tile is unknown. |
| 678 // TODO(vmpstr): Since the current visible rect is really a viewport in |
| 679 // layer space, we should probably clip tile query rect to tiling bounds |
| 680 // or live tiles rect. |
| 681 if (tile_query_rect.IsEmpty()) |
| 682 return false; |
| 683 |
| 684 if (contents_scale_ != 1.f) { |
| 685 tile_query_rect = |
| 686 gfx::ScaleToEnclosingRect(tile_query_rect, 1.0f / contents_scale_); |
751 } | 687 } |
| 688 |
| 689 return current_occlusion_in_layer_space_.IsOccluded(tile_query_rect); |
752 } | 690 } |
753 | 691 |
754 void PictureLayerTiling::DidBecomeActive() { | 692 bool PictureLayerTiling::IsTileRequiredForActivation(const Tile* tile) const { |
755 PicturePileImpl* active_pile = client_->GetPile(); | 693 DCHECK_EQ(PENDING_TREE, client_->GetTree()); |
756 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | |
757 it->second->SetPriority(ACTIVE_TREE, it->second->priority(PENDING_TREE)); | |
758 it->second->SetPriority(PENDING_TREE, TilePriority()); | |
759 | 694 |
760 // Tile holds a ref onto a picture pile. If the tile never gets invalidated | 695 // Note that although this function will determine whether tile is required |
761 // and recreated, then that picture pile ref could exist indefinitely. To | 696 // for activation assuming that it is in visible (ie in the viewport). That is |
762 // prevent this, ask the client to update the pile to its own ref. This | 697 // to say, even if the tile is outside of the viewport, it will be treated as |
763 // will cause PicturePileImpls to get deleted once the corresponding | 698 // if it was inside (there are no explicit checks for this). Hence, this |
764 // PictureLayerImpl and any in flight raster jobs go out of scope. | 699 // function is only called for visible tiles to ensure we don't block |
765 it->second->set_picture_pile(active_pile); | 700 // activation on tiles outside of the viewport. |
| 701 |
| 702 // If we are not allowed to mark tiles as required for activation, then don't |
| 703 // do it. |
| 704 if (!can_require_tiles_for_activation_) |
| 705 return false; |
| 706 |
| 707 if (resolution_ != HIGH_RESOLUTION) |
| 708 return false; |
| 709 |
| 710 if (IsTileOccluded(tile)) |
| 711 return false; |
| 712 |
| 713 if (client_->RequiresHighResToDraw()) |
| 714 return true; |
| 715 |
| 716 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
| 717 if (!twin_tiling) |
| 718 return true; |
| 719 |
| 720 if (twin_tiling->layer_bounds() != layer_bounds()) |
| 721 return true; |
| 722 |
| 723 if (twin_tiling->current_visible_rect_ != current_visible_rect_) |
| 724 return true; |
| 725 |
| 726 Tile* twin_tile = |
| 727 twin_tiling->TileAt(tile->tiling_i_index(), tile->tiling_j_index()); |
| 728 // If twin tile is missing, it might not have a recording, so we don't need |
| 729 // this tile to be required for activation. |
| 730 if (!twin_tile) |
| 731 return false; |
| 732 |
| 733 return true; |
| 734 } |
| 735 |
| 736 void PictureLayerTiling::UpdateTileAndTwinPriority(Tile* tile) const { |
| 737 UpdateTilePriority(tile); |
| 738 |
| 739 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
| 740 if (!tile->is_shared() || !twin_tiling) { |
| 741 WhichTree tree = client_->GetTree(); |
| 742 WhichTree twin_tree = tree == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE; |
| 743 tile->SetPriority(twin_tree, TilePriority()); |
| 744 tile->set_is_occluded(twin_tree, false); |
| 745 if (twin_tree == PENDING_TREE) |
| 746 tile->set_required_for_activation(false); |
| 747 return; |
766 } | 748 } |
| 749 |
| 750 twin_tiling->UpdateTilePriority(tile); |
| 751 } |
| 752 |
| 753 void PictureLayerTiling::UpdateTilePriority(Tile* tile) const { |
| 754 // TODO(vmpstr): This code should return the priority instead of setting it on |
| 755 // the tile. This should be a part of the change to move tile priority from |
| 756 // tiles into iterators. |
| 757 WhichTree tree = client_->GetTree(); |
| 758 |
| 759 DCHECK_EQ(TileAt(tile->tiling_i_index(), tile->tiling_j_index()), tile); |
| 760 gfx::Rect tile_bounds = |
| 761 tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index()); |
| 762 |
| 763 if (current_visible_rect_.Intersects(tile_bounds)) { |
| 764 tile->SetPriority(tree, TilePriority(resolution_, TilePriority::NOW, 0)); |
| 765 if (tree == PENDING_TREE) |
| 766 tile->set_required_for_activation(IsTileRequiredForActivation(tile)); |
| 767 tile->set_is_occluded(tree, IsTileOccluded(tile)); |
| 768 return; |
| 769 } |
| 770 |
| 771 if (tree == PENDING_TREE) |
| 772 tile->set_required_for_activation(false); |
| 773 tile->set_is_occluded(tree, false); |
| 774 |
| 775 DCHECK_GT(content_to_screen_scale_, 0.f); |
| 776 float distance_to_visible = |
| 777 current_visible_rect_.ManhattanInternalDistance(tile_bounds) * |
| 778 content_to_screen_scale_; |
| 779 |
| 780 if (current_soon_border_rect_.Intersects(tile_bounds) || |
| 781 current_skewport_rect_.Intersects(tile_bounds)) { |
| 782 tile->SetPriority( |
| 783 tree, |
| 784 TilePriority(resolution_, TilePriority::SOON, distance_to_visible)); |
| 785 return; |
| 786 } |
| 787 |
| 788 tile->SetPriority( |
| 789 tree, |
| 790 TilePriority(resolution_, TilePriority::EVENTUALLY, distance_to_visible)); |
767 } | 791 } |
768 | 792 |
769 void PictureLayerTiling::GetAllTilesForTracing( | 793 void PictureLayerTiling::GetAllTilesForTracing( |
770 std::set<const Tile*>* tiles) const { | 794 std::set<const Tile*>* tiles) const { |
771 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) | 795 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) |
772 tiles->insert(it->second.get()); | 796 tiles->insert(it->second.get()); |
773 } | 797 } |
774 | 798 |
775 void PictureLayerTiling::AsValueInto(base::debug::TracedValue* state) const { | 799 void PictureLayerTiling::AsValueInto(base::debug::TracedValue* state) const { |
776 state->SetInteger("num_tiles", tiles_.size()); | 800 state->SetInteger("num_tiles", tiles_.size()); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 return; | 971 return; |
948 | 972 |
949 eviction_tiles_now_.clear(); | 973 eviction_tiles_now_.clear(); |
950 eviction_tiles_now_and_required_for_activation_.clear(); | 974 eviction_tiles_now_and_required_for_activation_.clear(); |
951 eviction_tiles_soon_.clear(); | 975 eviction_tiles_soon_.clear(); |
952 eviction_tiles_soon_and_required_for_activation_.clear(); | 976 eviction_tiles_soon_and_required_for_activation_.clear(); |
953 eviction_tiles_eventually_.clear(); | 977 eviction_tiles_eventually_.clear(); |
954 eviction_tiles_eventually_and_required_for_activation_.clear(); | 978 eviction_tiles_eventually_and_required_for_activation_.clear(); |
955 | 979 |
956 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 980 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
957 // TODO(vmpstr): This should update the priority if UpdateTilePriorities | |
958 // changes not to do this. | |
959 Tile* tile = it->second.get(); | 981 Tile* tile = it->second.get(); |
| 982 UpdateTileAndTwinPriority(tile); |
960 const TilePriority& priority = | 983 const TilePriority& priority = |
961 tile->priority_for_tree_priority(tree_priority); | 984 tile->priority_for_tree_priority(tree_priority); |
962 switch (priority.priority_bin) { | 985 switch (priority.priority_bin) { |
963 case TilePriority::EVENTUALLY: | 986 case TilePriority::EVENTUALLY: |
964 if (tile->required_for_activation()) | 987 if (tile->required_for_activation()) |
965 eviction_tiles_eventually_and_required_for_activation_.push_back( | 988 eviction_tiles_eventually_and_required_for_activation_.push_back( |
966 tile); | 989 tile); |
967 else | 990 else |
968 eviction_tiles_eventually_.push_back(tile); | 991 eviction_tiles_eventually_.push_back(tile); |
969 break; | 992 break; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 return &eviction_tiles_now_and_required_for_activation_; | 1047 return &eviction_tiles_now_and_required_for_activation_; |
1025 } | 1048 } |
1026 NOTREACHED(); | 1049 NOTREACHED(); |
1027 return &eviction_tiles_eventually_; | 1050 return &eviction_tiles_eventually_; |
1028 } | 1051 } |
1029 | 1052 |
1030 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() | 1053 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() |
1031 : tiling_(NULL), current_tile_(NULL) {} | 1054 : tiling_(NULL), current_tile_(NULL) {} |
1032 | 1055 |
1033 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( | 1056 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( |
1034 PictureLayerTiling* tiling, | 1057 PictureLayerTiling* tiling) |
1035 WhichTree tree) | 1058 : tiling_(tiling), phase_(VISIBLE_RECT), current_tile_(NULL) { |
1036 : tiling_(tiling), phase_(VISIBLE_RECT), tree_(tree), current_tile_(NULL) { | |
1037 if (!tiling_->has_visible_rect_tiles_) { | 1059 if (!tiling_->has_visible_rect_tiles_) { |
1038 AdvancePhase(); | 1060 AdvancePhase(); |
1039 return; | 1061 return; |
1040 } | 1062 } |
1041 | 1063 |
1042 visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_, | 1064 visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_, |
1043 tiling_->current_visible_rect_, | 1065 tiling_->current_visible_rect_, |
1044 false /* include_borders */); | 1066 false /* include_borders */); |
1045 if (!visible_iterator_) { | 1067 if (!visible_iterator_) { |
1046 AdvancePhase(); | 1068 AdvancePhase(); |
1047 return; | 1069 return; |
1048 } | 1070 } |
1049 | 1071 |
1050 current_tile_ = | 1072 current_tile_ = |
1051 tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); | 1073 tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); |
1052 if (!current_tile_ || !TileNeedsRaster(current_tile_)) | 1074 if (!current_tile_ || !TileNeedsRaster(current_tile_)) { |
1053 ++(*this); | 1075 ++(*this); |
| 1076 return; |
| 1077 } |
| 1078 tiling_->UpdateTileAndTwinPriority(current_tile_); |
1054 } | 1079 } |
1055 | 1080 |
1056 PictureLayerTiling::TilingRasterTileIterator::~TilingRasterTileIterator() {} | 1081 PictureLayerTiling::TilingRasterTileIterator::~TilingRasterTileIterator() {} |
1057 | 1082 |
1058 void PictureLayerTiling::TilingRasterTileIterator::AdvancePhase() { | 1083 void PictureLayerTiling::TilingRasterTileIterator::AdvancePhase() { |
1059 DCHECK_LT(phase_, EVENTUALLY_RECT); | 1084 DCHECK_LT(phase_, EVENTUALLY_RECT); |
1060 | 1085 |
1061 do { | 1086 do { |
1062 phase_ = static_cast<Phase>(phase_ + 1); | 1087 phase_ = static_cast<Phase>(phase_ + 1); |
1063 switch (phase_) { | 1088 switch (phase_) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 if (current_tile_ && TileNeedsRaster(current_tile_)) | 1129 if (current_tile_ && TileNeedsRaster(current_tile_)) |
1105 break; | 1130 break; |
1106 ++spiral_iterator_; | 1131 ++spiral_iterator_; |
1107 } | 1132 } |
1108 | 1133 |
1109 if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) { | 1134 if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) { |
1110 current_tile_ = NULL; | 1135 current_tile_ = NULL; |
1111 break; | 1136 break; |
1112 } | 1137 } |
1113 } while (!spiral_iterator_); | 1138 } while (!spiral_iterator_); |
| 1139 |
| 1140 if (current_tile_) |
| 1141 tiling_->UpdateTileAndTwinPriority(current_tile_); |
1114 } | 1142 } |
1115 | 1143 |
1116 PictureLayerTiling::TilingRasterTileIterator& | 1144 PictureLayerTiling::TilingRasterTileIterator& |
1117 PictureLayerTiling::TilingRasterTileIterator:: | 1145 PictureLayerTiling::TilingRasterTileIterator:: |
1118 operator++() { | 1146 operator++() { |
1119 current_tile_ = NULL; | 1147 current_tile_ = NULL; |
1120 while (!current_tile_ || !TileNeedsRaster(current_tile_)) { | 1148 while (!current_tile_ || !TileNeedsRaster(current_tile_)) { |
1121 std::pair<int, int> next_index; | 1149 std::pair<int, int> next_index; |
1122 switch (phase_) { | 1150 switch (phase_) { |
1123 case VISIBLE_RECT: | 1151 case VISIBLE_RECT: |
(...skipping 17 matching lines...) Expand all Loading... |
1141 ++spiral_iterator_; | 1169 ++spiral_iterator_; |
1142 if (!spiral_iterator_) { | 1170 if (!spiral_iterator_) { |
1143 current_tile_ = NULL; | 1171 current_tile_ = NULL; |
1144 return *this; | 1172 return *this; |
1145 } | 1173 } |
1146 next_index = spiral_iterator_.index(); | 1174 next_index = spiral_iterator_.index(); |
1147 break; | 1175 break; |
1148 } | 1176 } |
1149 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); | 1177 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); |
1150 } | 1178 } |
| 1179 |
| 1180 if (current_tile_) |
| 1181 tiling_->UpdateTileAndTwinPriority(current_tile_); |
1151 return *this; | 1182 return *this; |
1152 } | 1183 } |
1153 | 1184 |
1154 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator() | 1185 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator() |
1155 : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) { | 1186 : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) { |
1156 } | 1187 } |
1157 | 1188 |
1158 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator( | 1189 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator( |
1159 PictureLayerTiling* tiling, | 1190 PictureLayerTiling* tiling, |
1160 TreePriority tree_priority, | 1191 TreePriority tree_priority, |
(...skipping 30 matching lines...) Expand all Loading... |
1191 DCHECK(*this); | 1222 DCHECK(*this); |
1192 do { | 1223 do { |
1193 ++current_eviction_tiles_index_; | 1224 ++current_eviction_tiles_index_; |
1194 } while (current_eviction_tiles_index_ != eviction_tiles_->size() && | 1225 } while (current_eviction_tiles_index_ != eviction_tiles_->size() && |
1195 !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources()); | 1226 !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources()); |
1196 | 1227 |
1197 return *this; | 1228 return *this; |
1198 } | 1229 } |
1199 | 1230 |
1200 } // namespace cc | 1231 } // namespace cc |
OLD | NEW |