Chromium Code Reviews| 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 |