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_(1.0f), | |
danakj
2014/10/08 18:46:25
can this be 0 to indicate it is set before we use
vmpstr
2014/10/08 22:38:34
Done.
| |
78 can_require_tiles_for_activation_(true), | |
danakj
2014/10/08 18:46:26
can this be false? we should set it before we use
vmpstr
2014/10/08 22:38:34
Done.
| |
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 // TODO(vmpstr): Skip this work if occlusion is empty (this needs a bool |
danakj
2014/10/08 18:46:25
This bool function exists now right?
vmpstr
2014/10/08 22:38:34
Done.
| |
747 // recycled takes care of tiles that are no longer in the active tree (eg. | 670 // function on occlusion). |
748 // due to a pending invalidation). | 671 gfx::Rect tile_query_rect = |
749 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 672 IntersectRects(tile->content_rect(), current_visible_rect_); |
danakj
2014/10/08 18:46:25
nit: gfx::IntersectRects
vmpstr
2014/10/08 22:38:34
Done.
| |
750 it->second->SetPriority(ACTIVE_TREE, TilePriority()); | 673 |
674 if (contents_scale_ != 1.f) { | |
675 tile_query_rect = | |
676 ScaleToEnclosingRect(tile_query_rect, 1.0f / contents_scale_); | |
danakj
2014/10/08 18:46:26
nit: gfx::ScaleToE..
vmpstr
2014/10/08 22:38:34
Done.
| |
751 } | 677 } |
678 | |
679 // Explicitly check if the tile is outside the viewport. If so, we need to | |
680 // return false, since occlusion for this tile is unknown. | |
681 // TODO(vmpstr): Since the current visible rect is really a viewport in | |
682 // layer space, we should probably clip tile query rect to tiling bounds | |
683 // or live tiles rect. | |
684 if (tile_query_rect.IsEmpty()) | |
danakj
2014/10/08 18:46:25
nit: do this before scaling, scaling shouldn't mak
vmpstr
2014/10/08 22:38:34
Done.
| |
685 return false; | |
686 return current_occlusion_in_layer_space_.IsOccluded(tile_query_rect); | |
752 } | 687 } |
753 | 688 |
754 void PictureLayerTiling::DidBecomeActive() { | 689 bool PictureLayerTiling::IsTileRequiredForActivation(const Tile* tile) const { |
danakj
2014/10/08 18:46:25
can you add a comment somewhere here saying this i
vmpstr
2014/10/08 22:38:34
Done.
| |
755 PicturePileImpl* active_pile = client_->GetPile(); | 690 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 | 691 |
760 // Tile holds a ref onto a picture pile. If the tile never gets invalidated | 692 // If we are not allowed to mark tiles as required for activation, then don't |
761 // and recreated, then that picture pile ref could exist indefinitely. To | 693 // do it. |
762 // prevent this, ask the client to update the pile to its own ref. This | 694 if (!can_require_tiles_for_activation_) |
763 // will cause PicturePileImpls to get deleted once the corresponding | 695 return false; |
764 // PictureLayerImpl and any in flight raster jobs go out of scope. | 696 |
765 it->second->set_picture_pile(active_pile); | 697 if (resolution_ != HIGH_RESOLUTION) |
698 return false; | |
699 | |
700 if (IsTileOccluded(tile)) | |
701 return false; | |
702 | |
703 if (client_->RequiresHighResToDraw()) | |
704 return true; | |
705 | |
706 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); | |
707 if (!twin_tiling) | |
708 return true; | |
709 | |
710 if (twin_tiling->layer_bounds() != layer_bounds()) | |
711 return true; | |
712 | |
713 if (twin_tiling->current_visible_rect_ != current_visible_rect_) | |
714 return true; | |
715 | |
716 Tile* twin_tile = | |
717 twin_tiling->TileAt(tile->tiling_i_index(), tile->tiling_j_index()); | |
718 // If twin tile is missing, it might not have a recording, so we don't need | |
719 // this tile to be required for activation. | |
720 if (!twin_tile) | |
721 return false; | |
722 | |
723 return true; | |
724 } | |
725 | |
726 void PictureLayerTiling::UpdateTileAndTwinPriority(Tile* tile) const { | |
727 UpdateTilePriority(tile); | |
728 | |
729 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); | |
730 if (!tile->is_shared() || !twin_tiling) { | |
731 WhichTree tree = client_->GetTree(); | |
732 WhichTree twin_tree = tree == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE; | |
733 tile->SetPriority(twin_tree, TilePriority()); | |
734 tile->set_is_occluded(twin_tree, false); | |
735 if (twin_tree == PENDING_TREE) | |
danakj
2014/10/08 18:46:25
nit: it's probly cheaper to just set_required all
vmpstr
2014/10/08 22:38:34
Not really harmless in general, since we have to e
| |
736 tile->set_required_for_activation(false); | |
737 return; | |
766 } | 738 } |
739 | |
740 twin_tiling->UpdateTilePriority(tile); | |
741 } | |
742 | |
743 void PictureLayerTiling::UpdateTilePriority(Tile* tile) const { | |
744 // TODO(vmpstr): This code should return the priority instead of setting it on | |
745 // the tile. This should be a part of the change to move tile priority from | |
746 // tiles into iterators. | |
747 WhichTree tree = client_->GetTree(); | |
748 | |
749 if (tree == PENDING_TREE) | |
danakj
2014/10/08 18:46:26
same here, can just set false always?
vmpstr
2014/10/08 22:38:34
We have ensure that we don't set that from the act
| |
750 tile->set_required_for_activation(false); | |
751 tile->set_is_occluded(tree, false); | |
danakj
2014/10/08 18:46:26
move these below the early out so we don't set the
vmpstr
2014/10/08 22:38:34
Done.
| |
752 | |
753 DCHECK_EQ(TileAt(tile->tiling_i_index(), tile->tiling_j_index()), tile); | |
754 gfx::Rect tile_bounds = | |
755 tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index()); | |
756 | |
757 if (current_visible_rect_.Intersects(tile_bounds)) { | |
758 tile->SetPriority(tree, TilePriority(resolution_, TilePriority::NOW, 0)); | |
759 if (tree == PENDING_TREE) | |
760 tile->set_required_for_activation(IsTileRequiredForActivation(tile)); | |
761 tile->set_is_occluded(tree, IsTileOccluded(tile)); | |
762 return; | |
763 } | |
764 | |
765 float distance_to_visible = | |
766 current_visible_rect_.ManhattanInternalDistance(tile_bounds) * | |
767 content_to_screen_scale_; | |
768 | |
769 if (current_soon_border_rect_.Intersects(tile_bounds) || | |
770 current_skewport_rect_.Intersects(tile_bounds)) { | |
771 tile->SetPriority( | |
772 tree, | |
773 TilePriority(resolution_, TilePriority::SOON, distance_to_visible)); | |
774 return; | |
775 } | |
776 | |
777 tile->SetPriority( | |
778 tree, | |
779 TilePriority(resolution_, TilePriority::EVENTUALLY, distance_to_visible)); | |
767 } | 780 } |
768 | 781 |
769 void PictureLayerTiling::GetAllTilesForTracing( | 782 void PictureLayerTiling::GetAllTilesForTracing( |
770 std::set<const Tile*>* tiles) const { | 783 std::set<const Tile*>* tiles) const { |
771 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) | 784 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) |
772 tiles->insert(it->second.get()); | 785 tiles->insert(it->second.get()); |
773 } | 786 } |
774 | 787 |
775 void PictureLayerTiling::AsValueInto(base::debug::TracedValue* state) const { | 788 void PictureLayerTiling::AsValueInto(base::debug::TracedValue* state) const { |
776 state->SetInteger("num_tiles", tiles_.size()); | 789 state->SetInteger("num_tiles", tiles_.size()); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
947 return; | 960 return; |
948 | 961 |
949 eviction_tiles_now_.clear(); | 962 eviction_tiles_now_.clear(); |
950 eviction_tiles_now_and_required_for_activation_.clear(); | 963 eviction_tiles_now_and_required_for_activation_.clear(); |
951 eviction_tiles_soon_.clear(); | 964 eviction_tiles_soon_.clear(); |
952 eviction_tiles_soon_and_required_for_activation_.clear(); | 965 eviction_tiles_soon_and_required_for_activation_.clear(); |
953 eviction_tiles_eventually_.clear(); | 966 eviction_tiles_eventually_.clear(); |
954 eviction_tiles_eventually_and_required_for_activation_.clear(); | 967 eviction_tiles_eventually_and_required_for_activation_.clear(); |
955 | 968 |
956 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 969 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(); | 970 Tile* tile = it->second.get(); |
971 UpdateTileAndTwinPriority(tile); | |
960 const TilePriority& priority = | 972 const TilePriority& priority = |
961 tile->priority_for_tree_priority(tree_priority); | 973 tile->priority_for_tree_priority(tree_priority); |
962 switch (priority.priority_bin) { | 974 switch (priority.priority_bin) { |
963 case TilePriority::EVENTUALLY: | 975 case TilePriority::EVENTUALLY: |
964 if (tile->required_for_activation()) | 976 if (tile->required_for_activation()) |
965 eviction_tiles_eventually_and_required_for_activation_.push_back( | 977 eviction_tiles_eventually_and_required_for_activation_.push_back( |
966 tile); | 978 tile); |
967 else | 979 else |
968 eviction_tiles_eventually_.push_back(tile); | 980 eviction_tiles_eventually_.push_back(tile); |
969 break; | 981 break; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1024 return &eviction_tiles_now_and_required_for_activation_; | 1036 return &eviction_tiles_now_and_required_for_activation_; |
1025 } | 1037 } |
1026 NOTREACHED(); | 1038 NOTREACHED(); |
1027 return &eviction_tiles_eventually_; | 1039 return &eviction_tiles_eventually_; |
1028 } | 1040 } |
1029 | 1041 |
1030 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() | 1042 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() |
1031 : tiling_(NULL), current_tile_(NULL) {} | 1043 : tiling_(NULL), current_tile_(NULL) {} |
1032 | 1044 |
1033 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( | 1045 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( |
1034 PictureLayerTiling* tiling, | 1046 PictureLayerTiling* tiling) |
1035 WhichTree tree) | 1047 : 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_) { | 1048 if (!tiling_->has_visible_rect_tiles_) { |
1038 AdvancePhase(); | 1049 AdvancePhase(); |
1039 return; | 1050 return; |
1040 } | 1051 } |
1041 | 1052 |
1042 visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_, | 1053 visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_, |
1043 tiling_->current_visible_rect_, | 1054 tiling_->current_visible_rect_, |
1044 false /* include_borders */); | 1055 false /* include_borders */); |
1045 if (!visible_iterator_) { | 1056 if (!visible_iterator_) { |
1046 AdvancePhase(); | 1057 AdvancePhase(); |
1047 return; | 1058 return; |
1048 } | 1059 } |
1049 | 1060 |
1050 current_tile_ = | 1061 current_tile_ = |
1051 tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); | 1062 tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); |
1052 if (!current_tile_ || !TileNeedsRaster(current_tile_)) | 1063 if (!current_tile_ || !TileNeedsRaster(current_tile_)) { |
1053 ++(*this); | 1064 ++(*this); |
1065 return; | |
1066 } | |
1067 tiling_->UpdateTileAndTwinPriority(current_tile_); | |
danakj
2014/10/08 18:46:26
while iterating you always update the priority of
vmpstr
2014/10/08 22:38:34
The priority is only updated for returned values.
danakj
2014/10/08 23:38:01
Right, but if the first tile in the iterator didn'
danakj
2014/10/08 23:39:27
Or would operator bool be false? I'm not sure why
vmpstr
2014/10/09 00:01:42
operator* can only return a tile that needs raster
danakj
2014/10/09 00:03:26
Oh, ok ++ above would end up with a NULL tile in t
| |
1054 } | 1068 } |
1055 | 1069 |
1056 PictureLayerTiling::TilingRasterTileIterator::~TilingRasterTileIterator() {} | 1070 PictureLayerTiling::TilingRasterTileIterator::~TilingRasterTileIterator() {} |
1057 | 1071 |
1058 void PictureLayerTiling::TilingRasterTileIterator::AdvancePhase() { | 1072 void PictureLayerTiling::TilingRasterTileIterator::AdvancePhase() { |
1059 DCHECK_LT(phase_, EVENTUALLY_RECT); | 1073 DCHECK_LT(phase_, EVENTUALLY_RECT); |
1060 | 1074 |
1061 do { | 1075 do { |
1062 phase_ = static_cast<Phase>(phase_ + 1); | 1076 phase_ = static_cast<Phase>(phase_ + 1); |
1063 switch (phase_) { | 1077 switch (phase_) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1104 if (current_tile_ && TileNeedsRaster(current_tile_)) | 1118 if (current_tile_ && TileNeedsRaster(current_tile_)) |
1105 break; | 1119 break; |
1106 ++spiral_iterator_; | 1120 ++spiral_iterator_; |
1107 } | 1121 } |
1108 | 1122 |
1109 if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) { | 1123 if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) { |
1110 current_tile_ = NULL; | 1124 current_tile_ = NULL; |
1111 break; | 1125 break; |
1112 } | 1126 } |
1113 } while (!spiral_iterator_); | 1127 } while (!spiral_iterator_); |
1128 | |
1129 if (current_tile_) | |
1130 tiling_->UpdateTileAndTwinPriority(current_tile_); | |
1114 } | 1131 } |
1115 | 1132 |
1116 PictureLayerTiling::TilingRasterTileIterator& | 1133 PictureLayerTiling::TilingRasterTileIterator& |
1117 PictureLayerTiling::TilingRasterTileIterator:: | 1134 PictureLayerTiling::TilingRasterTileIterator:: |
1118 operator++() { | 1135 operator++() { |
1119 current_tile_ = NULL; | 1136 current_tile_ = NULL; |
1120 while (!current_tile_ || !TileNeedsRaster(current_tile_)) { | 1137 while (!current_tile_ || !TileNeedsRaster(current_tile_)) { |
1121 std::pair<int, int> next_index; | 1138 std::pair<int, int> next_index; |
1122 switch (phase_) { | 1139 switch (phase_) { |
1123 case VISIBLE_RECT: | 1140 case VISIBLE_RECT: |
(...skipping 17 matching lines...) Expand all Loading... | |
1141 ++spiral_iterator_; | 1158 ++spiral_iterator_; |
1142 if (!spiral_iterator_) { | 1159 if (!spiral_iterator_) { |
1143 current_tile_ = NULL; | 1160 current_tile_ = NULL; |
1144 return *this; | 1161 return *this; |
1145 } | 1162 } |
1146 next_index = spiral_iterator_.index(); | 1163 next_index = spiral_iterator_.index(); |
1147 break; | 1164 break; |
1148 } | 1165 } |
1149 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); | 1166 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); |
1150 } | 1167 } |
1168 | |
1169 if (current_tile_) | |
1170 tiling_->UpdateTileAndTwinPriority(current_tile_); | |
1151 return *this; | 1171 return *this; |
1152 } | 1172 } |
1153 | 1173 |
1154 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator() | 1174 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator() |
1155 : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) { | 1175 : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) { |
1156 } | 1176 } |
1157 | 1177 |
1158 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator( | 1178 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator( |
1159 PictureLayerTiling* tiling, | 1179 PictureLayerTiling* tiling, |
1160 TreePriority tree_priority, | 1180 TreePriority tree_priority, |
(...skipping 30 matching lines...) Expand all Loading... | |
1191 DCHECK(*this); | 1211 DCHECK(*this); |
1192 do { | 1212 do { |
1193 ++current_eviction_tiles_index_; | 1213 ++current_eviction_tiles_index_; |
1194 } while (current_eviction_tiles_index_ != eviction_tiles_->size() && | 1214 } while (current_eviction_tiles_index_ != eviction_tiles_->size() && |
1195 !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources()); | 1215 !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources()); |
1196 | 1216 |
1197 return *this; | 1217 return *this; |
1198 } | 1218 } |
1199 | 1219 |
1200 } // namespace cc | 1220 } // namespace cc |
OLD | NEW |