| // 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/debug/lap_timer.h" |
| #include "cc/resources/picture_layer_tiling.h" |
| #include "cc/resources/resource_provider.h" |
| #include "cc/resources/scoped_resource.h" |
| #include "cc/test/fake_output_surface.h" |
| #include "cc/test/fake_output_surface_client.h" |
| #include "cc/test/fake_picture_layer_tiling_client.h" |
| #include "cc/test/test_context_provider.h" |
| #include "cc/test/test_shared_bitmap_manager.h" |
| |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/perf/perf_test.h" |
| |
| namespace cc { |
| |
| namespace { |
| |
| static const int kTimeLimitMillis = 2000; |
| static const int kWarmupRuns = 5; |
| static const int kTimeCheckInterval = 10; |
| |
| class PictureLayerTilingPerfTest : public testing::Test { |
| public: |
| PictureLayerTilingPerfTest() |
| : timer_(kWarmupRuns, |
| base::TimeDelta::FromMilliseconds(kTimeLimitMillis), |
| kTimeCheckInterval), |
| context_provider_(TestContextProvider::Create()) { |
| output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass(); |
| CHECK(output_surface_->BindToClient(&output_surface_client_)); |
| |
| shared_bitmap_manager_.reset(new TestSharedBitmapManager()); |
| resource_provider_ = ResourceProvider::Create(output_surface_.get(), |
| shared_bitmap_manager_.get(), |
| NULL, |
| NULL, |
| 0, |
| false, |
| 1).Pass(); |
| } |
| |
| virtual void SetUp() override { |
| picture_layer_tiling_client_.SetTileSize(gfx::Size(256, 256)); |
| picture_layer_tiling_client_.set_max_tiles_for_interest_area(250); |
| picture_layer_tiling_client_.set_tree(PENDING_TREE); |
| picture_layer_tiling_ = PictureLayerTiling::Create( |
| 1, gfx::Size(256 * 50, 256 * 50), &picture_layer_tiling_client_); |
| picture_layer_tiling_->CreateAllTilesForTesting(); |
| } |
| |
| virtual void TearDown() override { |
| picture_layer_tiling_.reset(NULL); |
| } |
| |
| void RunInvalidateTest(const std::string& test_name, const Region& region) { |
| timer_.Reset(); |
| do { |
| picture_layer_tiling_->UpdateTilesToCurrentRasterSource( |
| region, picture_layer_tiling_->tiling_size()); |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| perf_test::PrintResult( |
| "invalidation", "", test_name, timer_.LapsPerSecond(), "runs/s", true); |
| } |
| |
| void RunComputeTilePriorityRectsStationaryTest( |
| const std::string& test_name, |
| const gfx::Transform& transform) { |
| gfx::Rect viewport_rect(0, 0, 1024, 768); |
| |
| timer_.Reset(); |
| do { |
| picture_layer_tiling_->ComputeTilePriorityRects( |
| PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion()); |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| perf_test::PrintResult("compute_tile_priority_rects_stationary", |
| "", |
| test_name, |
| timer_.LapsPerSecond(), |
| "runs/s", |
| true); |
| } |
| |
| void RunComputeTilePriorityRectsScrollingTest( |
| const std::string& test_name, |
| const gfx::Transform& transform) { |
| gfx::Size viewport_size(1024, 768); |
| gfx::Rect viewport_rect(viewport_size); |
| int xoffsets[] = {10, 0, -10, 0}; |
| int yoffsets[] = {0, 10, 0, -10}; |
| int offsetIndex = 0; |
| int offsetCount = 0; |
| const int maxOffsetCount = 1000; |
| |
| timer_.Reset(); |
| do { |
| picture_layer_tiling_->ComputeTilePriorityRects( |
| PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion()); |
| |
| viewport_rect = gfx::Rect(viewport_rect.x() + xoffsets[offsetIndex], |
| viewport_rect.y() + yoffsets[offsetIndex], |
| viewport_rect.width(), |
| viewport_rect.height()); |
| |
| if (++offsetCount > maxOffsetCount) { |
| offsetCount = 0; |
| offsetIndex = (offsetIndex + 1) % 4; |
| } |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| perf_test::PrintResult("compute_tile_priority_rects_scrolling", |
| "", |
| test_name, |
| timer_.LapsPerSecond(), |
| "runs/s", |
| true); |
| } |
| |
| void RunRasterIteratorConstructTest(const std::string& test_name, |
| const gfx::Rect& viewport) { |
| gfx::Size bounds(viewport.size()); |
| picture_layer_tiling_ = |
| PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_); |
| picture_layer_tiling_client_.set_tree(ACTIVE_TREE); |
| picture_layer_tiling_->ComputeTilePriorityRects( |
| ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion()); |
| |
| timer_.Reset(); |
| do { |
| PictureLayerTiling::TilingRasterTileIterator it( |
| picture_layer_tiling_.get()); |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| perf_test::PrintResult("tiling_raster_tile_iterator_construct", |
| "", |
| test_name, |
| timer_.LapsPerSecond(), |
| "runs/s", |
| true); |
| } |
| |
| void RunRasterIteratorConstructAndIterateTest(const std::string& test_name, |
| int num_tiles, |
| const gfx::Rect& viewport) { |
| gfx::Size bounds(10000, 10000); |
| picture_layer_tiling_ = |
| PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_); |
| picture_layer_tiling_client_.set_tree(ACTIVE_TREE); |
| picture_layer_tiling_->ComputeTilePriorityRects( |
| ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion()); |
| |
| timer_.Reset(); |
| do { |
| int count = num_tiles; |
| PictureLayerTiling::TilingRasterTileIterator it( |
| picture_layer_tiling_.get()); |
| while (count--) { |
| ASSERT_TRUE(it) << "count: " << count; |
| ASSERT_TRUE(*it != NULL) << "count: " << count; |
| ++it; |
| } |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| perf_test::PrintResult("tiling_raster_tile_iterator_construct_and_iterate", |
| "", |
| test_name, |
| timer_.LapsPerSecond(), |
| "runs/s", |
| true); |
| } |
| |
| void RunEvictionIteratorConstructTest(const std::string& test_name, |
| const gfx::Rect& viewport) { |
| gfx::Size bounds(viewport.size()); |
| picture_layer_tiling_ = |
| PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_); |
| picture_layer_tiling_client_.set_tree(ACTIVE_TREE); |
| picture_layer_tiling_->ComputeTilePriorityRects( |
| ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion()); |
| |
| timer_.Reset(); |
| TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES, |
| SMOOTHNESS_TAKES_PRIORITY, |
| NEW_CONTENT_TAKES_PRIORITY}; |
| int priority_count = 0; |
| do { |
| PictureLayerTiling::TilingEvictionTileIterator it( |
| picture_layer_tiling_.get(), |
| priorities[priority_count], |
| PictureLayerTiling::NOW); |
| priority_count = (priority_count + 1) % arraysize(priorities); |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| perf_test::PrintResult("tiling_eviction_tile_iterator_construct", |
| "", |
| test_name, |
| timer_.LapsPerSecond(), |
| "runs/s", |
| true); |
| } |
| |
| void RunEvictionIteratorConstructAndIterateTest(const std::string& test_name, |
| int num_tiles, |
| const gfx::Rect& viewport) { |
| gfx::Size bounds(10000, 10000); |
| picture_layer_tiling_ = |
| PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_); |
| picture_layer_tiling_client_.set_tree(ACTIVE_TREE); |
| picture_layer_tiling_->ComputeTilePriorityRects( |
| ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion()); |
| |
| TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES, |
| SMOOTHNESS_TAKES_PRIORITY, |
| NEW_CONTENT_TAKES_PRIORITY}; |
| |
| // Ensure all tiles have resources. |
| std::vector<Tile*> all_tiles = picture_layer_tiling_->AllTilesForTesting(); |
| for (std::vector<Tile*>::iterator tile_it = all_tiles.begin(); |
| tile_it != all_tiles.end(); |
| ++tile_it) { |
| Tile* tile = *tile_it; |
| ManagedTileState::DrawInfo& draw_info = tile->draw_info(); |
| draw_info.SetResourceForTesting( |
| ScopedResource::Create(resource_provider_.get()).Pass()); |
| } |
| |
| int priority_count = 0; |
| timer_.Reset(); |
| do { |
| int count = num_tiles; |
| PictureLayerTiling::TilingEvictionTileIterator it( |
| picture_layer_tiling_.get(), |
| priorities[priority_count], |
| PictureLayerTiling::EVENTUALLY); |
| while (count--) { |
| ASSERT_TRUE(it) << "count: " << count; |
| ASSERT_TRUE(*it != NULL) << "count: " << count; |
| ++it; |
| } |
| priority_count = (priority_count + 1) % arraysize(priorities); |
| timer_.NextLap(); |
| } while (!timer_.HasTimeLimitExpired()); |
| |
| // Remove all resources from tiles to make sure the tile version destructor |
| // doesn't complain. |
| for (std::vector<Tile*>::iterator tile_it = all_tiles.begin(); |
| tile_it != all_tiles.end(); |
| ++tile_it) { |
| Tile* tile = *tile_it; |
| ManagedTileState::DrawInfo& draw_info = tile->draw_info(); |
| draw_info.SetResourceForTesting(nullptr); |
| } |
| |
| perf_test::PrintResult( |
| "tiling_eviction_tile_iterator_construct_and_iterate", |
| "", |
| test_name, |
| timer_.LapsPerSecond(), |
| "runs/s", |
| true); |
| } |
| |
| private: |
| FakePictureLayerTilingClient picture_layer_tiling_client_; |
| scoped_ptr<PictureLayerTiling> picture_layer_tiling_; |
| |
| LapTimer timer_; |
| |
| scoped_refptr<ContextProvider> context_provider_; |
| FakeOutputSurfaceClient output_surface_client_; |
| scoped_ptr<FakeOutputSurface> output_surface_; |
| scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; |
| scoped_ptr<ResourceProvider> resource_provider_; |
| }; |
| |
| TEST_F(PictureLayerTilingPerfTest, Invalidate) { |
| Region one_tile(gfx::Rect(256, 256)); |
| RunInvalidateTest("1x1", one_tile); |
| |
| Region half_region(gfx::Rect(25 * 256, 50 * 256)); |
| RunInvalidateTest("25x50", half_region); |
| |
| Region full_region(gfx::Rect(50 * 256, 50 * 256)); |
| RunInvalidateTest("50x50", full_region); |
| } |
| |
| #if defined(OS_ANDROID) |
| // TODO(vmpstr): Investigate why this is noisy (crbug.com/310220). |
| TEST_F(PictureLayerTilingPerfTest, DISABLED_ComputeTilePriorityRects) { |
| #else |
| TEST_F(PictureLayerTilingPerfTest, ComputeTilePriorityRects) { |
| #endif // defined(OS_ANDROID) |
| gfx::Transform transform; |
| |
| RunComputeTilePriorityRectsStationaryTest("no_transform", transform); |
| RunComputeTilePriorityRectsScrollingTest("no_transform", transform); |
| |
| transform.Rotate(10); |
| RunComputeTilePriorityRectsStationaryTest("rotation", transform); |
| RunComputeTilePriorityRectsScrollingTest("rotation", transform); |
| |
| transform.ApplyPerspectiveDepth(10); |
| RunComputeTilePriorityRectsStationaryTest("perspective", transform); |
| RunComputeTilePriorityRectsScrollingTest("perspective", transform); |
| } |
| |
| TEST_F(PictureLayerTilingPerfTest, TilingRasterTileIteratorConstruct) { |
| RunRasterIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100)); |
| RunRasterIteratorConstructTest("50_0_100x100", gfx::Rect(50, 0, 100, 100)); |
| RunRasterIteratorConstructTest("100_0_100x100", gfx::Rect(100, 0, 100, 100)); |
| RunRasterIteratorConstructTest("150_0_100x100", gfx::Rect(150, 0, 100, 100)); |
| } |
| |
| TEST_F(PictureLayerTilingPerfTest, |
| TilingRasterTileIteratorConstructAndIterate) { |
| RunRasterIteratorConstructAndIterateTest( |
| "32_100x100", 32, gfx::Rect(0, 0, 100, 100)); |
| RunRasterIteratorConstructAndIterateTest( |
| "32_500x500", 32, gfx::Rect(0, 0, 500, 500)); |
| RunRasterIteratorConstructAndIterateTest( |
| "64_100x100", 64, gfx::Rect(0, 0, 100, 100)); |
| RunRasterIteratorConstructAndIterateTest( |
| "64_500x500", 64, gfx::Rect(0, 0, 500, 500)); |
| } |
| |
| TEST_F(PictureLayerTilingPerfTest, TilingEvictionTileIteratorConstruct) { |
| RunEvictionIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100)); |
| RunEvictionIteratorConstructTest("50_0_100x100", gfx::Rect(50, 0, 100, 100)); |
| RunEvictionIteratorConstructTest("100_0_100x100", |
| gfx::Rect(100, 0, 100, 100)); |
| RunEvictionIteratorConstructTest("150_0_100x100", |
| gfx::Rect(150, 0, 100, 100)); |
| } |
| |
| TEST_F(PictureLayerTilingPerfTest, |
| TilingEvictionTileIteratorConstructAndIterate) { |
| RunEvictionIteratorConstructAndIterateTest( |
| "32_100x100", 32, gfx::Rect(0, 0, 100, 100)); |
| RunEvictionIteratorConstructAndIterateTest( |
| "32_500x500", 32, gfx::Rect(0, 0, 500, 500)); |
| RunEvictionIteratorConstructAndIterateTest( |
| "64_100x100", 64, gfx::Rect(0, 0, 100, 100)); |
| RunEvictionIteratorConstructAndIterateTest( |
| "64_500x500", 64, gfx::Rect(0, 0, 500, 500)); |
| } |
| |
| } // namespace |
| |
| } // namespace cc |