| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/resources/tile.h" |
| #include "cc/resources/tile_priority.h" |
| #include "cc/test/fake_impl_proxy.h" |
| #include "cc/test/fake_layer_tree_host_impl.h" |
| #include "cc/test/fake_output_surface.h" |
| #include "cc/test/fake_output_surface_client.h" |
| #include "cc/test/fake_picture_layer_impl.h" |
| #include "cc/test/fake_picture_pile_impl.h" |
| #include "cc/test/fake_tile_manager.h" |
| #include "cc/test/impl_side_painting_settings.h" |
| #include "cc/test/test_shared_bitmap_manager.h" |
| #include "cc/test/test_tile_priorities.h" |
| #include "cc/trees/layer_tree_impl.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace cc { |
| namespace { |
| |
| class TileManagerTest : public testing::TestWithParam<bool>, |
| public TileManagerClient { |
| public: |
| typedef std::vector<scoped_refptr<Tile> > TileVector; |
| |
| TileManagerTest() |
| : memory_limit_policy_(ALLOW_ANYTHING), |
| max_tiles_(0), |
| ready_to_activate_(false) {} |
| |
| void Initialize(int max_tiles, |
| TileMemoryLimitPolicy memory_limit_policy, |
| TreePriority tree_priority) { |
| output_surface_ = FakeOutputSurface::Create3d(); |
| CHECK(output_surface_->BindToClient(&output_surface_client_)); |
| |
| shared_bitmap_manager_.reset(new TestSharedBitmapManager()); |
| resource_provider_ = ResourceProvider::Create( |
| output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1, |
| false); |
| resource_pool_ = ResourcePool::Create( |
| resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888); |
| tile_manager_ = |
| make_scoped_ptr(new FakeTileManager(this, resource_pool_.get())); |
| |
| memory_limit_policy_ = memory_limit_policy; |
| max_tiles_ = max_tiles; |
| picture_pile_ = FakePicturePileImpl::CreateInfiniteFilledPile(); |
| |
| SetTreePriority(tree_priority); |
| } |
| |
| void SetTreePriority(TreePriority tree_priority) { |
| GlobalStateThatImpactsTilePriority state; |
| gfx::Size tile_size = settings_.default_tile_size; |
| |
| if (UsingMemoryLimit()) { |
| state.soft_memory_limit_in_bytes = |
| max_tiles_ * 4 * tile_size.width() * tile_size.height(); |
| state.num_resources_limit = 100; |
| } else { |
| state.soft_memory_limit_in_bytes = 100 * 1000 * 1000; |
| state.num_resources_limit = max_tiles_; |
| } |
| state.hard_memory_limit_in_bytes = state.soft_memory_limit_in_bytes * 2; |
| state.memory_limit_policy = memory_limit_policy_; |
| state.tree_priority = tree_priority; |
| |
| global_state_ = state; |
| resource_pool_->SetResourceUsageLimits(state.soft_memory_limit_in_bytes, |
| state.soft_memory_limit_in_bytes, |
| state.num_resources_limit); |
| tile_manager_->SetGlobalStateForTesting(state); |
| } |
| |
| virtual void TearDown() OVERRIDE { |
| tile_manager_.reset(NULL); |
| picture_pile_ = NULL; |
| |
| testing::Test::TearDown(); |
| } |
| |
| // TileManagerClient implementation. |
| virtual const std::vector<PictureLayerImpl*>& GetPictureLayers() OVERRIDE { |
| return picture_layers_; |
| } |
| virtual void NotifyReadyToActivate() OVERRIDE { ready_to_activate_ = true; } |
| virtual void NotifyTileStateChanged(const Tile* tile) OVERRIDE {} |
| |
| TileVector CreateTilesWithSize(int count, |
| TilePriority active_priority, |
| TilePriority pending_priority, |
| const gfx::Size& tile_size) { |
| TileVector tiles; |
| for (int i = 0; i < count; ++i) { |
| scoped_refptr<Tile> tile = tile_manager_->CreateTile(picture_pile_.get(), |
| tile_size, |
| gfx::Rect(), |
| gfx::Rect(), |
| 1.0, |
| 0, |
| 0, |
| 0); |
| tile->SetPriority(ACTIVE_TREE, active_priority); |
| tile->SetPriority(PENDING_TREE, pending_priority); |
| tiles.push_back(tile); |
| } |
| return tiles; |
| } |
| |
| TileVector CreateTiles(int count, |
| TilePriority active_priority, |
| TilePriority pending_priority) { |
| return CreateTilesWithSize( |
| count, active_priority, pending_priority, settings_.default_tile_size); |
| } |
| |
| FakeTileManager* tile_manager() { return tile_manager_.get(); } |
| |
| int AssignedMemoryCount(const TileVector& tiles) { |
| int has_memory_count = 0; |
| for (TileVector::const_iterator it = tiles.begin(); it != tiles.end(); |
| ++it) { |
| if (tile_manager_->HasBeenAssignedMemory(*it)) |
| ++has_memory_count; |
| } |
| return has_memory_count; |
| } |
| |
| bool ready_to_activate() const { return ready_to_activate_; } |
| |
| // The parametrization specifies whether the max tile limit should |
| // be applied to memory or resources. |
| bool UsingResourceLimit() { return !GetParam(); } |
| bool UsingMemoryLimit() { return GetParam(); } |
| |
| protected: |
| GlobalStateThatImpactsTilePriority global_state_; |
| |
| private: |
| LayerTreeSettings settings_; |
| scoped_ptr<FakeTileManager> tile_manager_; |
| scoped_refptr<FakePicturePileImpl> picture_pile_; |
| FakeOutputSurfaceClient output_surface_client_; |
| scoped_ptr<FakeOutputSurface> output_surface_; |
| scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; |
| scoped_ptr<ResourceProvider> resource_provider_; |
| scoped_ptr<ResourcePool> resource_pool_; |
| TileMemoryLimitPolicy memory_limit_policy_; |
| int max_tiles_; |
| bool ready_to_activate_; |
| std::vector<PictureLayerImpl*> picture_layers_; |
| }; |
| |
| TEST_P(TileManagerTest, EnoughMemoryAllowAnything) { |
| // A few tiles of each type of priority, with enough memory for all tiles. |
| |
| Initialize(10, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_now = |
| CreateTiles(3, TilePriorityForNowBin(), TilePriority()); |
| TileVector pending_now = |
| CreateTiles(3, TilePriority(), TilePriorityForNowBin()); |
| TileVector active_pending_soon = |
| CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin()); |
| TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(3, AssignedMemoryCount(active_now)); |
| EXPECT_EQ(3, AssignedMemoryCount(pending_now)); |
| EXPECT_EQ(3, AssignedMemoryCount(active_pending_soon)); |
| EXPECT_EQ(0, AssignedMemoryCount(never_bin)); |
| } |
| |
| TEST_P(TileManagerTest, EnoughMemoryAllowPrepaintOnly) { |
| // A few tiles of each type of priority, with enough memory for all tiles, |
| // with the exception of never bin. |
| |
| Initialize(10, ALLOW_PREPAINT_ONLY, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_now = |
| CreateTiles(3, TilePriorityForNowBin(), TilePriority()); |
| TileVector pending_now = |
| CreateTiles(3, TilePriority(), TilePriorityForNowBin()); |
| TileVector active_pending_soon = |
| CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin()); |
| TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(3, AssignedMemoryCount(active_now)); |
| EXPECT_EQ(3, AssignedMemoryCount(pending_now)); |
| EXPECT_EQ(3, AssignedMemoryCount(active_pending_soon)); |
| EXPECT_EQ(0, AssignedMemoryCount(never_bin)); |
| } |
| |
| TEST_P(TileManagerTest, EnoughMemoryPendingLowResAllowAbsoluteMinimum) { |
| // A few low-res tiles required for activation, with enough memory for all |
| // tiles. |
| |
| Initialize(5, ALLOW_ABSOLUTE_MINIMUM, SAME_PRIORITY_FOR_BOTH_TREES); |
| TileVector pending_low_res = |
| CreateTiles(5, TilePriority(), TilePriorityLowRes()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(5, AssignedMemoryCount(pending_low_res)); |
| } |
| |
| TEST_P(TileManagerTest, EnoughMemoryAllowAbsoluteMinimum) { |
| // A few tiles of each type of priority, with enough memory for all tiles, |
| // with the exception of never and soon bins. |
| |
| Initialize(10, ALLOW_ABSOLUTE_MINIMUM, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_now = |
| CreateTiles(3, TilePriorityForNowBin(), TilePriority()); |
| TileVector pending_now = |
| CreateTiles(3, TilePriority(), TilePriorityForNowBin()); |
| TileVector active_pending_soon = |
| CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin()); |
| TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(3, AssignedMemoryCount(active_now)); |
| EXPECT_EQ(3, AssignedMemoryCount(pending_now)); |
| EXPECT_EQ(0, AssignedMemoryCount(active_pending_soon)); |
| EXPECT_EQ(0, AssignedMemoryCount(never_bin)); |
| } |
| |
| TEST_P(TileManagerTest, EnoughMemoryAllowNothing) { |
| // A few tiles of each type of priority, with enough memory for all tiles, |
| // but allow nothing should not assign any memory. |
| |
| Initialize(10, ALLOW_NOTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_now = |
| CreateTiles(3, TilePriorityForNowBin(), TilePriority()); |
| TileVector pending_now = |
| CreateTiles(3, TilePriority(), TilePriorityForNowBin()); |
| TileVector active_pending_soon = |
| CreateTiles(3, TilePriorityForSoonBin(), TilePriorityForSoonBin()); |
| TileVector never_bin = CreateTiles(1, TilePriority(), TilePriority()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(0, AssignedMemoryCount(active_now)); |
| EXPECT_EQ(0, AssignedMemoryCount(pending_now)); |
| EXPECT_EQ(0, AssignedMemoryCount(active_pending_soon)); |
| EXPECT_EQ(0, AssignedMemoryCount(never_bin)); |
| } |
| |
| TEST_P(TileManagerTest, PartialOOMMemoryToPending) { |
| // 5 tiles on active tree eventually bin, 5 tiles on pending tree that are |
| // required for activation, but only enough memory for 8 tiles. The result |
| // is all pending tree tiles get memory, and 3 of the active tree tiles |
| // get memory. None of these tiles is needed to avoid calimity (flickering or |
| // raster-on-demand) so the soft memory limit is used. |
| |
| Initialize(8, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_tree_tiles = |
| CreateTiles(5, TilePriorityForEventualBin(), TilePriority()); |
| TileVector pending_tree_tiles = |
| CreateTiles(5, TilePriority(), TilePriorityRequiredForActivation()); |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(5, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(3, AssignedMemoryCount(pending_tree_tiles)); |
| |
| SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES); |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(3, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(5, AssignedMemoryCount(pending_tree_tiles)); |
| } |
| |
| TEST_P(TileManagerTest, PartialOOMMemoryToActive) { |
| // 5 tiles on active tree eventually bin, 5 tiles on pending tree now bin, |
| // but only enough memory for 8 tiles. The result is all active tree tiles |
| // get memory, and 3 of the pending tree tiles get memory. |
| // The pending tiles are not needed to avoid calimity (flickering or |
| // raster-on-demand) and the active tiles fit, so the soft limit is used. |
| |
| Initialize(8, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_tree_tiles = |
| CreateTiles(5, TilePriorityForNowBin(), TilePriority()); |
| TileVector pending_tree_tiles = |
| CreateTiles(5, TilePriority(), TilePriorityForNowBin()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(5, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(3, AssignedMemoryCount(pending_tree_tiles)); |
| } |
| |
| TEST_P(TileManagerTest, TotalOOMMemoryToPending) { |
| // 10 tiles on active tree eventually bin, 10 tiles on pending tree that are |
| // required for activation, but only enough tiles for 4 tiles. The result |
| // is 4 pending tree tiles get memory, and none of the active tree tiles |
| // get memory. |
| |
| Initialize(4, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_tree_tiles = |
| CreateTiles(10, TilePriorityForEventualBin(), TilePriority()); |
| TileVector pending_tree_tiles = |
| CreateTiles(10, TilePriority(), TilePriorityRequiredForActivation()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles)); |
| |
| SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES); |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| if (UsingResourceLimit()) { |
| EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(4, AssignedMemoryCount(pending_tree_tiles)); |
| } else { |
| // Pending tiles are now required to avoid calimity (flickering or |
| // raster-on-demand). Hard-limit is used and double the tiles fit. |
| EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(8, AssignedMemoryCount(pending_tree_tiles)); |
| } |
| } |
| |
| TEST_P(TileManagerTest, TotalOOMActiveSoonMemoryToPending) { |
| // 10 tiles on active tree soon bin, 10 tiles on pending tree that are |
| // required for activation, but only enough tiles for 4 tiles. The result |
| // is 4 pending tree tiles get memory, and none of the active tree tiles |
| // get memory. |
| |
| Initialize(4, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_tree_tiles = |
| CreateTiles(10, TilePriorityForSoonBin(), TilePriority()); |
| TileVector pending_tree_tiles = |
| CreateTiles(10, TilePriority(), TilePriorityRequiredForActivation()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles)); |
| |
| SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES); |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| if (UsingResourceLimit()) { |
| EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(4, AssignedMemoryCount(pending_tree_tiles)); |
| } else { |
| // Pending tiles are now required to avoid calimity (flickering or |
| // raster-on-demand). Hard-limit is used and double the tiles fit. |
| EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(8, AssignedMemoryCount(pending_tree_tiles)); |
| } |
| } |
| |
| TEST_P(TileManagerTest, TotalOOMMemoryToActive) { |
| // 10 tiles on active tree eventually bin, 10 tiles on pending tree now bin, |
| // but only enough memory for 4 tiles. The result is 4 active tree tiles |
| // get memory, and none of the pending tree tiles get memory. |
| |
| Initialize(4, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_tree_tiles = |
| CreateTiles(10, TilePriorityForNowBin(), TilePriority()); |
| TileVector pending_tree_tiles = |
| CreateTiles(10, TilePriority(), TilePriorityForNowBin()); |
| |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| |
| if (UsingResourceLimit()) { |
| EXPECT_EQ(4, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles)); |
| } else { |
| // Active tiles are required to avoid calimity (flickering or |
| // raster-on-demand). Hard-limit is used and double the tiles fit. |
| EXPECT_EQ(8, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles)); |
| } |
| } |
| |
| TEST_P(TileManagerTest, TotalOOMMemoryToNewContent) { |
| // 10 tiles on active tree now bin, 10 tiles on pending tree now bin, |
| // but only enough memory for 8 tiles. Any tile missing would cause |
| // a calamity (flickering or raster-on-demand). Depending on mode, |
| // we should use varying amounts of the higher hard memory limit. |
| if (UsingResourceLimit()) |
| return; |
| |
| Initialize(8, ALLOW_ANYTHING, SMOOTHNESS_TAKES_PRIORITY); |
| TileVector active_tree_tiles = |
| CreateTiles(10, TilePriorityForNowBin(), TilePriority()); |
| TileVector pending_tree_tiles = |
| CreateTiles(10, TilePriority(), TilePriorityForNowBin()); |
| |
| // Active tiles are required to avoid calimity. The hard-limit is used and all |
| // active-tiles fit. No pending tiles are needed to avoid calamity so only 10 |
| // tiles total are used. |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| EXPECT_EQ(10, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(0, AssignedMemoryCount(pending_tree_tiles)); |
| |
| // Even the hard-limit won't save us now. All tiles are required to avoid |
| // a clamity but we only have 16. The tiles will be distribted randomly |
| // given they are identical, in practice depending on their screen location. |
| SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES); |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| EXPECT_EQ(16, |
| AssignedMemoryCount(active_tree_tiles) + |
| AssignedMemoryCount(pending_tree_tiles)); |
| |
| // The pending tree is now more important. Active tiles will take higher |
| // priority if they are ready-to-draw in practice. Importantly though, |
| // pending tiles also utilize the hard-limit. |
| SetTreePriority(NEW_CONTENT_TAKES_PRIORITY); |
| tile_manager()->AssignMemoryToTiles(global_state_); |
| EXPECT_EQ(0, AssignedMemoryCount(active_tree_tiles)); |
| EXPECT_EQ(10, AssignedMemoryCount(pending_tree_tiles)); |
| } |
| |
| // If true, the max tile limit should be applied as bytes; if false, |
| // as num_resources_limit. |
| INSTANTIATE_TEST_CASE_P(TileManagerTests, |
| TileManagerTest, |
| ::testing::Values(true, false)); |
| |
| class TileManagerTileIteratorTest : public testing::Test { |
| public: |
| TileManagerTileIteratorTest() |
| : memory_limit_policy_(ALLOW_ANYTHING), |
| max_tiles_(10000), |
| ready_to_activate_(false), |
| id_(7), |
| proxy_(base::MessageLoopProxy::current()), |
| host_impl_(ImplSidePaintingSettings(), |
| &proxy_, |
| &shared_bitmap_manager_) {} |
| |
| void SetTreePriority(TreePriority tree_priority) { |
| GlobalStateThatImpactsTilePriority state; |
| gfx::Size tile_size(256, 256); |
| |
| state.soft_memory_limit_in_bytes = 100 * 1000 * 1000; |
| state.num_resources_limit = max_tiles_; |
| state.hard_memory_limit_in_bytes = state.soft_memory_limit_in_bytes * 2; |
| state.memory_limit_policy = memory_limit_policy_; |
| state.tree_priority = tree_priority; |
| |
| global_state_ = state; |
| host_impl_.resource_pool()->SetResourceUsageLimits( |
| state.soft_memory_limit_in_bytes, |
| state.soft_memory_limit_in_bytes, |
| state.num_resources_limit); |
| host_impl_.tile_manager()->SetGlobalStateForTesting(state); |
| } |
| |
| virtual void SetUp() OVERRIDE { |
| InitializeRenderer(); |
| SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES); |
| } |
| |
| virtual void InitializeRenderer() { |
| host_impl_.InitializeRenderer( |
| FakeOutputSurface::Create3d().PassAs<OutputSurface>()); |
| } |
| |
| void SetupDefaultTrees(const gfx::Size& layer_bounds) { |
| gfx::Size tile_size(100, 100); |
| |
| scoped_refptr<FakePicturePileImpl> pending_pile = |
| FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); |
| scoped_refptr<FakePicturePileImpl> active_pile = |
| FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); |
| |
| SetupTrees(pending_pile, active_pile); |
| } |
| |
| void ActivateTree() { |
| host_impl_.ActivatePendingTree(); |
| CHECK(!host_impl_.pending_tree()); |
| pending_layer_ = NULL; |
| active_layer_ = static_cast<FakePictureLayerImpl*>( |
| host_impl_.active_tree()->LayerById(id_)); |
| } |
| |
| void SetupDefaultTreesWithFixedTileSize(const gfx::Size& layer_bounds, |
| const gfx::Size& tile_size) { |
| SetupDefaultTrees(layer_bounds); |
| pending_layer_->set_fixed_tile_size(tile_size); |
| active_layer_->set_fixed_tile_size(tile_size); |
| } |
| |
| void SetupTrees(scoped_refptr<PicturePileImpl> pending_pile, |
| scoped_refptr<PicturePileImpl> active_pile) { |
| SetupPendingTree(active_pile); |
| ActivateTree(); |
| SetupPendingTree(pending_pile); |
| } |
| |
| void SetupPendingTree(scoped_refptr<PicturePileImpl> pile) { |
| host_impl_.CreatePendingTree(); |
| LayerTreeImpl* pending_tree = host_impl_.pending_tree(); |
| // Clear recycled tree. |
| pending_tree->DetachLayerTree(); |
| |
| scoped_ptr<FakePictureLayerImpl> pending_layer = |
| FakePictureLayerImpl::CreateWithPile(pending_tree, id_, pile); |
| pending_layer->SetDrawsContent(true); |
| pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>()); |
| |
| pending_layer_ = static_cast<FakePictureLayerImpl*>( |
| host_impl_.pending_tree()->LayerById(id_)); |
| pending_layer_->DoPostCommitInitializationIfNeeded(); |
| } |
| |
| void CreateHighLowResAndSetAllTilesVisible() { |
| // Active layer must get updated first so pending layer can share from it. |
| active_layer_->CreateDefaultTilingsAndTiles(); |
| active_layer_->SetAllTilesVisible(); |
| pending_layer_->CreateDefaultTilingsAndTiles(); |
| pending_layer_->SetAllTilesVisible(); |
| } |
| |
| TileManager* tile_manager() { return host_impl_.tile_manager(); } |
| |
| protected: |
| GlobalStateThatImpactsTilePriority global_state_; |
| |
| TestSharedBitmapManager shared_bitmap_manager_; |
| TileMemoryLimitPolicy memory_limit_policy_; |
| int max_tiles_; |
| bool ready_to_activate_; |
| int id_; |
| FakeImplProxy proxy_; |
| FakeLayerTreeHostImpl host_impl_; |
| FakePictureLayerImpl* pending_layer_; |
| FakePictureLayerImpl* active_layer_; |
| }; |
| |
| TEST_F(TileManagerTileIteratorTest, PairedPictureLayers) { |
| host_impl_.CreatePendingTree(); |
| host_impl_.ActivatePendingTree(); |
| host_impl_.CreatePendingTree(); |
| |
| LayerTreeImpl* active_tree = host_impl_.active_tree(); |
| LayerTreeImpl* pending_tree = host_impl_.pending_tree(); |
| EXPECT_NE(active_tree, pending_tree); |
| |
| scoped_ptr<FakePictureLayerImpl> active_layer = |
| FakePictureLayerImpl::Create(active_tree, 10); |
| scoped_ptr<FakePictureLayerImpl> pending_layer = |
| FakePictureLayerImpl::Create(pending_tree, 10); |
| |
| TileManager* tile_manager = TileManagerTileIteratorTest::tile_manager(); |
| EXPECT_TRUE(tile_manager); |
| |
| std::vector<TileManager::PairedPictureLayer> paired_layers; |
| tile_manager->GetPairedPictureLayers(&paired_layers); |
| |
| EXPECT_EQ(2u, paired_layers.size()); |
| if (paired_layers[0].active_layer) { |
| EXPECT_EQ(active_layer.get(), paired_layers[0].active_layer); |
| EXPECT_EQ(NULL, paired_layers[0].pending_layer); |
| } else { |
| EXPECT_EQ(pending_layer.get(), paired_layers[0].pending_layer); |
| EXPECT_EQ(NULL, paired_layers[0].active_layer); |
| } |
| |
| if (paired_layers[1].active_layer) { |
| EXPECT_EQ(active_layer.get(), paired_layers[1].active_layer); |
| EXPECT_EQ(NULL, paired_layers[1].pending_layer); |
| } else { |
| EXPECT_EQ(pending_layer.get(), paired_layers[1].pending_layer); |
| EXPECT_EQ(NULL, paired_layers[1].active_layer); |
| } |
| |
| active_layer->set_twin_layer(pending_layer.get()); |
| pending_layer->set_twin_layer(active_layer.get()); |
| |
| tile_manager->GetPairedPictureLayers(&paired_layers); |
| EXPECT_EQ(1u, paired_layers.size()); |
| |
| EXPECT_EQ(active_layer.get(), paired_layers[0].active_layer); |
| EXPECT_EQ(pending_layer.get(), paired_layers[0].pending_layer); |
| } |
| |
| TEST_F(TileManagerTileIteratorTest, RasterTileIterator) { |
| SetupDefaultTrees(gfx::Size(1000, 1000)); |
| TileManager* tile_manager = TileManagerTileIteratorTest::tile_manager(); |
| EXPECT_TRUE(tile_manager); |
| |
| active_layer_->CreateDefaultTilingsAndTiles(); |
| pending_layer_->CreateDefaultTilingsAndTiles(); |
| |
| std::vector<TileManager::PairedPictureLayer> paired_layers; |
| tile_manager->GetPairedPictureLayers(&paired_layers); |
| EXPECT_EQ(1u, paired_layers.size()); |
| |
| TileManager::RasterTileIterator it(tile_manager, |
| SAME_PRIORITY_FOR_BOTH_TREES); |
| EXPECT_TRUE(it); |
| |
| size_t tile_count = 0; |
| std::set<Tile*> all_tiles; |
| for (; it; ++it) { |
| EXPECT_TRUE(*it); |
| all_tiles.insert(*it); |
| ++tile_count; |
| } |
| |
| EXPECT_EQ(tile_count, all_tiles.size()); |
| EXPECT_EQ(17u, tile_count); |
| |
| // Sanity check, all tiles should be visible. |
| std::set<Tile*> smoothness_tiles; |
| for (TileManager::RasterTileIterator it(tile_manager, |
| SMOOTHNESS_TAKES_PRIORITY); |
| it; |
| ++it) { |
| Tile* tile = *it; |
| EXPECT_TRUE(tile); |
| EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin); |
| EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin); |
| smoothness_tiles.insert(tile); |
| } |
| EXPECT_EQ(all_tiles, smoothness_tiles); |
| |
| Region invalidation(gfx::Rect(0, 0, 500, 500)); |
| |
| // Invalidate the pending tree. |
| pending_layer_->set_invalidation(invalidation); |
| pending_layer_->HighResTiling()->Invalidate(invalidation); |
| pending_layer_->LowResTiling()->Invalidate(invalidation); |
| |
| active_layer_->ResetAllTilesPriorities(); |
| pending_layer_->ResetAllTilesPriorities(); |
| |
| // Renew all of the tile priorities. |
| gfx::Rect viewport(50, 50, 100, 100); |
| pending_layer_->HighResTiling()->UpdateTilePriorities( |
| PENDING_TREE, viewport, 1.0f, 1.0); |
| pending_layer_->LowResTiling()->UpdateTilePriorities( |
| PENDING_TREE, viewport, 1.0f, 1.0); |
| active_layer_->HighResTiling()->UpdateTilePriorities( |
| ACTIVE_TREE, viewport, 1.0f, 1.0); |
| active_layer_->LowResTiling()->UpdateTilePriorities( |
| ACTIVE_TREE, viewport, 1.0f, 1.0); |
| |
| // Populate all tiles directly from the tilings. |
| all_tiles.clear(); |
| std::vector<Tile*> pending_high_res_tiles = |
| pending_layer_->HighResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < pending_high_res_tiles.size(); ++i) |
| all_tiles.insert(pending_high_res_tiles[i]); |
| |
| std::vector<Tile*> pending_low_res_tiles = |
| pending_layer_->LowResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < pending_low_res_tiles.size(); ++i) |
| all_tiles.insert(pending_low_res_tiles[i]); |
| |
| std::vector<Tile*> active_high_res_tiles = |
| active_layer_->HighResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < active_high_res_tiles.size(); ++i) |
| all_tiles.insert(active_high_res_tiles[i]); |
| |
| std::vector<Tile*> active_low_res_tiles = |
| active_layer_->LowResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < active_low_res_tiles.size(); ++i) |
| all_tiles.insert(active_low_res_tiles[i]); |
| |
| Tile* last_tile = NULL; |
| smoothness_tiles.clear(); |
| tile_count = 0; |
| size_t increasing_distance_tiles = 0u; |
| // Here we expect to get increasing ACTIVE_TREE priority_bin. |
| for (TileManager::RasterTileIterator it(tile_manager, |
| SMOOTHNESS_TAKES_PRIORITY); |
| it; |
| ++it) { |
| Tile* tile = *it; |
| EXPECT_TRUE(tile); |
| |
| if (!last_tile) |
| last_tile = tile; |
| |
| EXPECT_LE(last_tile->priority(ACTIVE_TREE).priority_bin, |
| tile->priority(ACTIVE_TREE).priority_bin); |
| if (last_tile->priority(ACTIVE_TREE).priority_bin == |
| tile->priority(ACTIVE_TREE).priority_bin) { |
| increasing_distance_tiles += |
| last_tile->priority(ACTIVE_TREE).distance_to_visible <= |
| tile->priority(ACTIVE_TREE).distance_to_visible; |
| } |
| |
| if (tile->priority(ACTIVE_TREE).priority_bin == TilePriority::NOW && |
| last_tile->priority(ACTIVE_TREE).resolution != |
| tile->priority(ACTIVE_TREE).resolution) { |
| // Low resolution should come first. |
| EXPECT_EQ(LOW_RESOLUTION, last_tile->priority(ACTIVE_TREE).resolution); |
| } |
| |
| last_tile = tile; |
| ++tile_count; |
| smoothness_tiles.insert(tile); |
| } |
| |
| EXPECT_EQ(tile_count, smoothness_tiles.size()); |
| EXPECT_EQ(all_tiles, smoothness_tiles); |
| // Since we don't guarantee increasing distance due to spiral iterator, we |
| // should check that we're _mostly_ right. |
| EXPECT_GT(increasing_distance_tiles, 3 * tile_count / 4); |
| |
| std::set<Tile*> new_content_tiles; |
| last_tile = NULL; |
| increasing_distance_tiles = 0u; |
| // Here we expect to get increasing PENDING_TREE priority_bin. |
| for (TileManager::RasterTileIterator it(tile_manager, |
| NEW_CONTENT_TAKES_PRIORITY); |
| it; |
| ++it) { |
| Tile* tile = *it; |
| EXPECT_TRUE(tile); |
| |
| if (!last_tile) |
| last_tile = tile; |
| |
| EXPECT_LE(last_tile->priority(PENDING_TREE).priority_bin, |
| tile->priority(PENDING_TREE).priority_bin); |
| if (last_tile->priority(PENDING_TREE).priority_bin == |
| tile->priority(PENDING_TREE).priority_bin) { |
| increasing_distance_tiles += |
| last_tile->priority(PENDING_TREE).distance_to_visible <= |
| tile->priority(PENDING_TREE).distance_to_visible; |
| } |
| |
| if (tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW && |
| last_tile->priority(PENDING_TREE).resolution != |
| tile->priority(PENDING_TREE).resolution) { |
| // High resolution should come first. |
| EXPECT_EQ(HIGH_RESOLUTION, last_tile->priority(PENDING_TREE).resolution); |
| } |
| |
| last_tile = tile; |
| new_content_tiles.insert(tile); |
| } |
| |
| EXPECT_EQ(tile_count, new_content_tiles.size()); |
| EXPECT_EQ(all_tiles, new_content_tiles); |
| // Since we don't guarantee increasing distance due to spiral iterator, we |
| // should check that we're _mostly_ right. |
| EXPECT_GT(increasing_distance_tiles, 3 * tile_count / 4); |
| } |
| |
| TEST_F(TileManagerTileIteratorTest, EvictionTileIterator) { |
| SetupDefaultTrees(gfx::Size(1000, 1000)); |
| TileManager* tile_manager = TileManagerTileIteratorTest::tile_manager(); |
| EXPECT_TRUE(tile_manager); |
| |
| active_layer_->CreateDefaultTilingsAndTiles(); |
| pending_layer_->CreateDefaultTilingsAndTiles(); |
| |
| std::vector<TileManager::PairedPictureLayer> paired_layers; |
| tile_manager->GetPairedPictureLayers(&paired_layers); |
| EXPECT_EQ(1u, paired_layers.size()); |
| |
| TileManager::EvictionTileIterator empty_it(tile_manager, |
| SAME_PRIORITY_FOR_BOTH_TREES); |
| EXPECT_FALSE(empty_it); |
| std::set<Tile*> all_tiles; |
| size_t tile_count = 0; |
| |
| for (TileManager::RasterTileIterator raster_it(tile_manager, |
| SAME_PRIORITY_FOR_BOTH_TREES); |
| raster_it; |
| ++raster_it) { |
| ++tile_count; |
| EXPECT_TRUE(*raster_it); |
| all_tiles.insert(*raster_it); |
| } |
| |
| EXPECT_EQ(tile_count, all_tiles.size()); |
| EXPECT_EQ(17u, tile_count); |
| |
| tile_manager->InitializeTilesWithResourcesForTesting( |
| std::vector<Tile*>(all_tiles.begin(), all_tiles.end())); |
| |
| TileManager::EvictionTileIterator it(tile_manager, SMOOTHNESS_TAKES_PRIORITY); |
| EXPECT_TRUE(it); |
| |
| // Sanity check, all tiles should be visible. |
| std::set<Tile*> smoothness_tiles; |
| for (; it; ++it) { |
| Tile* tile = *it; |
| EXPECT_TRUE(tile); |
| EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin); |
| EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin); |
| EXPECT_TRUE(tile->HasResources()); |
| smoothness_tiles.insert(tile); |
| } |
| EXPECT_EQ(all_tiles, smoothness_tiles); |
| |
| tile_manager->ReleaseTileResourcesForTesting( |
| std::vector<Tile*>(all_tiles.begin(), all_tiles.end())); |
| |
| Region invalidation(gfx::Rect(0, 0, 500, 500)); |
| |
| // Invalidate the pending tree. |
| pending_layer_->set_invalidation(invalidation); |
| pending_layer_->HighResTiling()->Invalidate(invalidation); |
| pending_layer_->LowResTiling()->Invalidate(invalidation); |
| |
| active_layer_->ResetAllTilesPriorities(); |
| pending_layer_->ResetAllTilesPriorities(); |
| |
| // Renew all of the tile priorities. |
| gfx::Rect viewport(50, 50, 100, 100); |
| pending_layer_->HighResTiling()->UpdateTilePriorities( |
| PENDING_TREE, viewport, 1.0f, 1.0); |
| pending_layer_->LowResTiling()->UpdateTilePriorities( |
| PENDING_TREE, viewport, 1.0f, 1.0); |
| active_layer_->HighResTiling()->UpdateTilePriorities( |
| ACTIVE_TREE, viewport, 1.0f, 1.0); |
| active_layer_->LowResTiling()->UpdateTilePriorities( |
| ACTIVE_TREE, viewport, 1.0f, 1.0); |
| |
| // Populate all tiles directly from the tilings. |
| all_tiles.clear(); |
| std::vector<Tile*> pending_high_res_tiles = |
| pending_layer_->HighResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < pending_high_res_tiles.size(); ++i) |
| all_tiles.insert(pending_high_res_tiles[i]); |
| |
| std::vector<Tile*> pending_low_res_tiles = |
| pending_layer_->LowResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < pending_low_res_tiles.size(); ++i) |
| all_tiles.insert(pending_low_res_tiles[i]); |
| |
| std::vector<Tile*> active_high_res_tiles = |
| active_layer_->HighResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < active_high_res_tiles.size(); ++i) |
| all_tiles.insert(active_high_res_tiles[i]); |
| |
| std::vector<Tile*> active_low_res_tiles = |
| active_layer_->LowResTiling()->AllTilesForTesting(); |
| for (size_t i = 0; i < active_low_res_tiles.size(); ++i) |
| all_tiles.insert(active_low_res_tiles[i]); |
| |
| tile_manager->InitializeTilesWithResourcesForTesting( |
| std::vector<Tile*>(all_tiles.begin(), all_tiles.end())); |
| |
| Tile* last_tile = NULL; |
| smoothness_tiles.clear(); |
| tile_count = 0; |
| // Here we expect to get increasing ACTIVE_TREE priority_bin. |
| for (TileManager::EvictionTileIterator it(tile_manager, |
| SMOOTHNESS_TAKES_PRIORITY); |
| it; |
| ++it) { |
| Tile* tile = *it; |
| EXPECT_TRUE(tile); |
| EXPECT_TRUE(tile->HasResources()); |
| |
| if (!last_tile) |
| last_tile = tile; |
| |
| EXPECT_GE(last_tile->priority(ACTIVE_TREE).priority_bin, |
| tile->priority(ACTIVE_TREE).priority_bin); |
| if (last_tile->priority(ACTIVE_TREE).priority_bin == |
| tile->priority(ACTIVE_TREE).priority_bin) { |
| EXPECT_GE(last_tile->priority(ACTIVE_TREE).distance_to_visible, |
| tile->priority(ACTIVE_TREE).distance_to_visible); |
| } |
| |
| last_tile = tile; |
| ++tile_count; |
| smoothness_tiles.insert(tile); |
| } |
| |
| EXPECT_EQ(tile_count, smoothness_tiles.size()); |
| EXPECT_EQ(all_tiles, smoothness_tiles); |
| |
| std::set<Tile*> new_content_tiles; |
| last_tile = NULL; |
| // Here we expect to get increasing PENDING_TREE priority_bin. |
| for (TileManager::EvictionTileIterator it(tile_manager, |
| NEW_CONTENT_TAKES_PRIORITY); |
| it; |
| ++it) { |
| Tile* tile = *it; |
| EXPECT_TRUE(tile); |
| |
| if (!last_tile) |
| last_tile = tile; |
| |
| EXPECT_GE(last_tile->priority(PENDING_TREE).priority_bin, |
| tile->priority(PENDING_TREE).priority_bin); |
| if (last_tile->priority(PENDING_TREE).priority_bin == |
| tile->priority(PENDING_TREE).priority_bin) { |
| EXPECT_GE(last_tile->priority(PENDING_TREE).distance_to_visible, |
| tile->priority(PENDING_TREE).distance_to_visible); |
| } |
| |
| last_tile = tile; |
| new_content_tiles.insert(tile); |
| } |
| |
| EXPECT_EQ(tile_count, new_content_tiles.size()); |
| EXPECT_EQ(all_tiles, new_content_tiles); |
| } |
| } // namespace |
| } // namespace cc |