// 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 #include #include "cc/resources/managed_tile_state.h" #include "cc/resources/prioritized_tile_set.h" #include "cc/resources/tile.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_picture_pile_impl.h" #include "cc/test/fake_tile_manager.h" #include "cc/test/fake_tile_manager_client.h" #include "cc/test/test_tile_priorities.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { class BinComparator { public: bool operator()(const scoped_refptr& a, const scoped_refptr& b) const { const ManagedTileState& ams = a->managed_state(); const ManagedTileState& bms = b->managed_state(); if (ams.required_for_activation != bms.required_for_activation) return ams.required_for_activation; if (ams.resolution != bms.resolution) return ams.resolution < bms.resolution; if (ams.time_to_needed_in_seconds != bms.time_to_needed_in_seconds) return ams.time_to_needed_in_seconds < bms.time_to_needed_in_seconds; if (ams.distance_to_visible_in_pixels != bms.distance_to_visible_in_pixels) { return ams.distance_to_visible_in_pixels < bms.distance_to_visible_in_pixels; } gfx::Rect a_rect = a->content_rect(); gfx::Rect b_rect = b->content_rect(); if (a_rect.y() != b_rect.y()) return a_rect.y() < b_rect.y(); return a_rect.x() < b_rect.x(); } }; namespace { class PrioritizedTileSetTest : public testing::Test { public: PrioritizedTileSetTest() { output_surface_ = FakeOutputSurface::Create3d().Pass(); CHECK(output_surface_->BindToClient(&output_surface_client_)); resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1).Pass(); tile_manager_.reset( new FakeTileManager(&tile_manager_client_, resource_provider_.get())); picture_pile_ = FakePicturePileImpl::CreatePile(); } scoped_refptr CreateTile() { return tile_manager_->CreateTile(picture_pile_.get(), settings_.default_tile_size, gfx::Rect(), gfx::Rect(), 1.0, 0, 0, Tile::USE_LCD_TEXT); } private: LayerTreeSettings settings_; FakeOutputSurfaceClient output_surface_client_; scoped_ptr output_surface_; scoped_ptr resource_provider_; FakeTileManagerClient tile_manager_client_; scoped_ptr tile_manager_; scoped_refptr picture_pile_; }; TEST_F(PrioritizedTileSetTest, EmptyIterator) { // Creating an iterator to an empty set should work (but create iterator that // isn't valid). PrioritizedTileSet set; PrioritizedTileSet::Iterator it(&set, true); EXPECT_FALSE(it); } TEST_F(PrioritizedTileSetTest, NonEmptyIterator) { PrioritizedTileSet set; scoped_refptr tile = CreateTile(); set.InsertTile(tile, NOW_BIN); PrioritizedTileSet::Iterator it(&set, true); EXPECT_TRUE(it); EXPECT_TRUE(*it == tile.get()); ++it; EXPECT_FALSE(it); } TEST_F(PrioritizedTileSetTest, NowAndReadyToDrawBin) { // Ensure that tiles in NOW_AND_READY_TO_DRAW_BIN aren't sorted. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, NOW_AND_READY_TO_DRAW_BIN); } } // Tiles should appear in the same order as inserted. int i = 0; for (PrioritizedTileSet::Iterator it(&set, true); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, NowBin) { // Ensure that tiles in NOW_BIN are sorted according to BinComparator. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, NOW_BIN); } } // Tiles should appear in BinComparator order. std::sort(tiles.begin(), tiles.end(), BinComparator()); int i = 0; for (PrioritizedTileSet::Iterator it(&set, true); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, SoonBin) { // Ensure that tiles in SOON_BIN are sorted according to BinComparator. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, SOON_BIN); } } // Tiles should appear in BinComparator order. std::sort(tiles.begin(), tiles.end(), BinComparator()); int i = 0; for (PrioritizedTileSet::Iterator it(&set, true); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, SoonBinNoPriority) { // Ensure that when not using priority iterator, SOON_BIN tiles // are not sorted. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, SOON_BIN); } } int i = 0; for (PrioritizedTileSet::Iterator it(&set, false); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, EventuallyAndActiveBin) { // Ensure that EVENTUALLY_AND_ACTIVE_BIN tiles are sorted. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, EVENTUALLY_AND_ACTIVE_BIN); } } // Tiles should appear in BinComparator order. std::sort(tiles.begin(), tiles.end(), BinComparator()); int i = 0; for (PrioritizedTileSet::Iterator it(&set, true); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, EventuallyBin) { // Ensure that EVENTUALLY_BIN tiles are sorted. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, EVENTUALLY_BIN); } } // Tiles should appear in BinComparator order. std::sort(tiles.begin(), tiles.end(), BinComparator()); int i = 0; for (PrioritizedTileSet::Iterator it(&set, true); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, AtLastAndActiveBin) { // Ensure that AT_LAST_AND_ACTIVE_BIN tiles are sorted. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, AT_LAST_AND_ACTIVE_BIN); } } // Tiles should appear in BinComparator order. std::sort(tiles.begin(), tiles.end(), BinComparator()); int i = 0; for (PrioritizedTileSet::Iterator it(&set, true); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, AtLastBin) { // Ensure that AT_LAST_BIN tiles are sorted. PrioritizedTileSet set; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; std::vector > tiles; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); tiles.push_back(tile); set.InsertTile(tile, AT_LAST_BIN); } } // Tiles should appear in BinComparator order. std::sort(tiles.begin(), tiles.end(), BinComparator()); int i = 0; for (PrioritizedTileSet::Iterator it(&set, true); it; ++it) { EXPECT_TRUE(*it == tiles[i].get()); ++i; } EXPECT_EQ(20, i); } TEST_F(PrioritizedTileSetTest, TilesForEachBin) { // Aggregate test with one tile for each of the bins, which // should appear in order of the bins. scoped_refptr now_and_ready_to_draw_bin = CreateTile(); scoped_refptr now_bin = CreateTile(); scoped_refptr soon_bin = CreateTile(); scoped_refptr eventually_and_active_bin = CreateTile(); scoped_refptr eventually_bin = CreateTile(); scoped_refptr at_last_bin = CreateTile(); scoped_refptr at_last_and_active_bin = CreateTile(); PrioritizedTileSet set; set.InsertTile(soon_bin, SOON_BIN); set.InsertTile(at_last_and_active_bin, AT_LAST_AND_ACTIVE_BIN); set.InsertTile(eventually_bin, EVENTUALLY_BIN); set.InsertTile(now_bin, NOW_BIN); set.InsertTile(eventually_and_active_bin, EVENTUALLY_AND_ACTIVE_BIN); set.InsertTile(at_last_bin, AT_LAST_BIN); set.InsertTile(now_and_ready_to_draw_bin, NOW_AND_READY_TO_DRAW_BIN); // Tiles should appear in order. PrioritizedTileSet::Iterator it(&set, true); EXPECT_TRUE(*it == now_and_ready_to_draw_bin.get()); ++it; EXPECT_TRUE(*it == now_bin.get()); ++it; EXPECT_TRUE(*it == soon_bin.get()); ++it; EXPECT_TRUE(*it == eventually_and_active_bin.get()); ++it; EXPECT_TRUE(*it == eventually_bin.get()); ++it; EXPECT_TRUE(*it == at_last_and_active_bin.get()); ++it; EXPECT_TRUE(*it == at_last_bin.get()); ++it; EXPECT_FALSE(it); } TEST_F(PrioritizedTileSetTest, ManyTilesForEachBin) { // Aggregate test with many tiles in each of the bins of various // priorities. Ensure that they are all returned in a sorted order. std::vector > now_and_ready_to_draw_bins; std::vector > now_bins; std::vector > soon_bins; std::vector > eventually_and_active_bins; std::vector > eventually_bins; std::vector > at_last_bins; std::vector > at_last_and_active_bins; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; PrioritizedTileSet set; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); now_and_ready_to_draw_bins.push_back(tile); now_bins.push_back(tile); soon_bins.push_back(tile); eventually_and_active_bins.push_back(tile); eventually_bins.push_back(tile); at_last_bins.push_back(tile); at_last_and_active_bins.push_back(tile); set.InsertTile(tile, NOW_AND_READY_TO_DRAW_BIN); set.InsertTile(tile, NOW_BIN); set.InsertTile(tile, SOON_BIN); set.InsertTile(tile, EVENTUALLY_AND_ACTIVE_BIN); set.InsertTile(tile, EVENTUALLY_BIN); set.InsertTile(tile, AT_LAST_BIN); set.InsertTile(tile, AT_LAST_AND_ACTIVE_BIN); } } PrioritizedTileSet::Iterator it(&set, true); std::vector >::iterator vector_it; // Now and ready are not sorted. for (vector_it = now_and_ready_to_draw_bins.begin(); vector_it != now_and_ready_to_draw_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // Now bins are sorted. std::sort(now_bins.begin(), now_bins.end(), BinComparator()); for (vector_it = now_bins.begin(); vector_it != now_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // Soon bins are sorted. std::sort(soon_bins.begin(), soon_bins.end(), BinComparator()); for (vector_it = soon_bins.begin(); vector_it != soon_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // Eventually and active bins are sorted. std::sort(eventually_and_active_bins.begin(), eventually_and_active_bins.end(), BinComparator()); for (vector_it = eventually_and_active_bins.begin(); vector_it != eventually_and_active_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // Eventually bins are sorted. std::sort(eventually_bins.begin(), eventually_bins.end(), BinComparator()); for (vector_it = eventually_bins.begin(); vector_it != eventually_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // At last and active bins are sorted. std::sort(at_last_and_active_bins.begin(), at_last_and_active_bins.end(), BinComparator()); for (vector_it = at_last_and_active_bins.begin(); vector_it != at_last_and_active_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // At last bins are sorted. std::sort(at_last_bins.begin(), at_last_bins.end(), BinComparator()); for (vector_it = at_last_bins.begin(); vector_it != at_last_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } EXPECT_FALSE(it); } TEST_F(PrioritizedTileSetTest, ManyTilesForEachBinDisablePriority) { // Aggregate test with many tiles for each of the bins. Tiles should // appear in order, until DisablePriorityOrdering is called. After that // tiles should appear in the order they were inserted. std::vector > now_and_ready_to_draw_bins; std::vector > now_bins; std::vector > soon_bins; std::vector > eventually_and_active_bins; std::vector > eventually_bins; std::vector > at_last_bins; std::vector > at_last_and_active_bins; TilePriority priorities[4] = { TilePriorityForEventualBin(), TilePriorityForNowBin(), TilePriority(), TilePriorityForSoonBin()}; PrioritizedTileSet set; for (int priority = 0; priority < 4; ++priority) { for (int i = 0; i < 5; ++i) { scoped_refptr tile = CreateTile(); tile->SetPriority(ACTIVE_TREE, priorities[priority]); tile->SetPriority(PENDING_TREE, priorities[priority]); now_and_ready_to_draw_bins.push_back(tile); now_bins.push_back(tile); soon_bins.push_back(tile); eventually_and_active_bins.push_back(tile); eventually_bins.push_back(tile); at_last_bins.push_back(tile); at_last_and_active_bins.push_back(tile); set.InsertTile(tile, NOW_AND_READY_TO_DRAW_BIN); set.InsertTile(tile, NOW_BIN); set.InsertTile(tile, SOON_BIN); set.InsertTile(tile, EVENTUALLY_AND_ACTIVE_BIN); set.InsertTile(tile, EVENTUALLY_BIN); set.InsertTile(tile, AT_LAST_BIN); set.InsertTile(tile, AT_LAST_AND_ACTIVE_BIN); } } PrioritizedTileSet::Iterator it(&set, true); std::vector >::iterator vector_it; // Now and ready are not sorted. for (vector_it = now_and_ready_to_draw_bins.begin(); vector_it != now_and_ready_to_draw_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // Now bins are sorted. std::sort(now_bins.begin(), now_bins.end(), BinComparator()); for (vector_it = now_bins.begin(); vector_it != now_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // Soon bins are sorted. std::sort(soon_bins.begin(), soon_bins.end(), BinComparator()); for (vector_it = soon_bins.begin(); vector_it != soon_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // After we disable priority ordering, we already have sorted the next vector. it.DisablePriorityOrdering(); // Eventually and active bins are sorted. std::sort(eventually_and_active_bins.begin(), eventually_and_active_bins.end(), BinComparator()); for (vector_it = eventually_and_active_bins.begin(); vector_it != eventually_and_active_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // Eventually bins are not sorted. for (vector_it = eventually_bins.begin(); vector_it != eventually_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // At last and active bins are not sorted. for (vector_it = at_last_and_active_bins.begin(); vector_it != at_last_and_active_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } // At last bins are not sorted. for (vector_it = at_last_bins.begin(); vector_it != at_last_bins.end(); ++vector_it) { EXPECT_TRUE(*vector_it == *it); ++it; } EXPECT_FALSE(it); } TEST_F(PrioritizedTileSetTest, TilesForFirstAndLastBins) { // Make sure that if we have empty lists between two non-empty lists, // we just get two tiles from the iterator. scoped_refptr now_and_ready_to_draw_bin = CreateTile(); scoped_refptr at_last_bin = CreateTile(); PrioritizedTileSet set; set.InsertTile(at_last_bin, AT_LAST_BIN); set.InsertTile(now_and_ready_to_draw_bin, NOW_AND_READY_TO_DRAW_BIN); // Only two tiles should appear and they should appear in order. PrioritizedTileSet::Iterator it(&set, true); EXPECT_TRUE(*it == now_and_ready_to_draw_bin.get()); ++it; EXPECT_TRUE(*it == at_last_bin.get()); ++it; EXPECT_FALSE(it); } TEST_F(PrioritizedTileSetTest, MultipleIterators) { // Ensure that multiple iterators don't interfere with each other. scoped_refptr now_and_ready_to_draw_bin = CreateTile(); scoped_refptr now_bin = CreateTile(); scoped_refptr soon_bin = CreateTile(); scoped_refptr eventually_bin = CreateTile(); scoped_refptr at_last_bin = CreateTile(); PrioritizedTileSet set; set.InsertTile(soon_bin, SOON_BIN); set.InsertTile(eventually_bin, EVENTUALLY_BIN); set.InsertTile(now_bin, NOW_BIN); set.InsertTile(at_last_bin, AT_LAST_BIN); set.InsertTile(now_and_ready_to_draw_bin, NOW_AND_READY_TO_DRAW_BIN); // Tiles should appear in order. PrioritizedTileSet::Iterator it(&set, true); EXPECT_TRUE(*it == now_and_ready_to_draw_bin.get()); ++it; EXPECT_TRUE(*it == now_bin.get()); ++it; EXPECT_TRUE(*it == soon_bin.get()); ++it; EXPECT_TRUE(*it == eventually_bin.get()); ++it; EXPECT_TRUE(*it == at_last_bin.get()); ++it; EXPECT_FALSE(it); // Creating multiple iterators shouldn't affect old iterators. PrioritizedTileSet::Iterator second_it(&set, true); EXPECT_TRUE(second_it); EXPECT_FALSE(it); ++second_it; EXPECT_TRUE(second_it); ++second_it; EXPECT_TRUE(second_it); EXPECT_FALSE(it); PrioritizedTileSet::Iterator third_it(&set, true); EXPECT_TRUE(third_it); ++second_it; ++second_it; EXPECT_TRUE(second_it); EXPECT_TRUE(third_it); EXPECT_FALSE(it); ++third_it; ++third_it; EXPECT_TRUE(third_it); EXPECT_TRUE(*third_it == soon_bin.get()); EXPECT_TRUE(second_it); EXPECT_TRUE(*second_it == at_last_bin.get()); EXPECT_FALSE(it); ++second_it; EXPECT_TRUE(third_it); EXPECT_FALSE(second_it); EXPECT_FALSE(it); set.Clear(); PrioritizedTileSet::Iterator empty_it(&set, true); EXPECT_FALSE(empty_it); } } // namespace } // namespace cc