1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6
7 #include <memory>
8 #include <sstream>
9
10 #include "base/containers/circular_deque.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_piece.h"
15 #include "base/threading/thread.h"
16 #include "base/time/time.h"
17 #include "base/timer/lap_timer.h"
18 #include "cc/layers/layer.h"
19 #include "cc/test/fake_content_layer_client.h"
20 #include "cc/test/fake_layer_tree_host_client.h"
21 #include "cc/test/layer_tree_json_parser.h"
22 #include "cc/test/layer_tree_test.h"
23 #include "cc/trees/layer_tree_impl.h"
24 #include "cc/trees/transform_node.h"
25 #include "components/viz/service/display/bsp_tree.h"
26 #include "components/viz/service/display/draw_polygon.h"
27 #include "components/viz/test/paths.h"
28 #include "testing/perf/perf_result_reporter.h"
29
30 namespace viz {
31 namespace {
32
33 static const int kTimeLimitMillis = 2000;
34 static const int kWarmupRuns = 5;
35 static const int kTimeCheckInterval = 10;
36
37 const char kMetricPrefixBspTree[] = "BspTree.";
38 const char kMetricCalcDrawPropsTimeUs[] = "calc_draw_props_time";
39
SetUpBspTreeReporter(const std::string & story)40 perf_test::PerfResultReporter SetUpBspTreeReporter(const std::string& story) {
41 perf_test::PerfResultReporter reporter(kMetricPrefixBspTree, story);
42 reporter.RegisterImportantMetric(kMetricCalcDrawPropsTimeUs, "us");
43 return reporter;
44 }
45
46 class BspTreePerfTest : public cc::LayerTreeTest {
47 public:
BspTreePerfTest()48 BspTreePerfTest()
49 : timer_(kWarmupRuns,
50 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
51 kTimeCheckInterval) {}
52
SetupTree()53 void SetupTree() override {
54 gfx::Size viewport = gfx::Size(720, 1038);
55 layer_tree_host()->SetViewportRectAndScale(gfx::Rect(viewport), 1.f,
56 LocalSurfaceId());
57 scoped_refptr<cc::Layer> root =
58 ParseTreeFromJson(json_, &content_layer_client_);
59 ASSERT_TRUE(root.get());
60 layer_tree_host()->SetRootLayer(root);
61 content_layer_client_.set_bounds(viewport);
62 }
63
SetStory(const std::string & story)64 void SetStory(const std::string& story) { story_ = story; }
65
SetNumberOfDuplicates(int num_duplicates)66 void SetNumberOfDuplicates(int num_duplicates) {
67 num_duplicates_ = num_duplicates;
68 }
69
ReadTestFile(const std::string & name)70 void ReadTestFile(const std::string& name) {
71 base::FilePath test_data_dir;
72 ASSERT_TRUE(base::PathService::Get(Paths::DIR_TEST_DATA, &test_data_dir));
73 base::FilePath json_file = test_data_dir.AppendASCII(name + ".json");
74 ASSERT_TRUE(base::ReadFileToString(json_file, &json_));
75 }
76
BeginTest()77 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
78
DrawLayersOnThread(cc::LayerTreeHostImpl * host_impl)79 void DrawLayersOnThread(cc::LayerTreeHostImpl* host_impl) override {
80 cc::LayerTreeImpl* active_tree = host_impl->active_tree();
81 // First build the tree and then we'll start running tests on layersorter
82 // itself
83 host_impl->active_tree()->UpdateDrawProperties();
84
85 cc::LayerImplList base_list;
86 BuildLayerImplList(active_tree->root_layer(), &base_list);
87
88 int polygon_counter = 0;
89 std::vector<std::unique_ptr<DrawPolygon>> polygon_list;
90 for (auto it = base_list.begin(); it != base_list.end(); ++it) {
91 DrawPolygon* draw_polygon = new DrawPolygon(
92 nullptr, gfx::RectF(gfx::SizeF((*it)->bounds())),
93 (*it)->draw_properties().target_space_transform, polygon_counter++);
94 polygon_list.push_back(std::unique_ptr<DrawPolygon>(draw_polygon));
95 }
96
97 timer_.Reset();
98 do {
99 base::circular_deque<std::unique_ptr<DrawPolygon>> test_list;
100 for (int i = 0; i < num_duplicates_; i++) {
101 for (size_t i = 0; i < polygon_list.size(); i++) {
102 test_list.push_back(polygon_list[i]->CreateCopy());
103 }
104 }
105 BspTree bsp_tree(&test_list);
106 timer_.NextLap();
107 } while (!timer_.HasTimeLimitExpired());
108
109 EndTest();
110 }
111
BuildLayerImplList(cc::LayerImpl * layer,cc::LayerImplList * list)112 void BuildLayerImplList(cc::LayerImpl* layer, cc::LayerImplList* list) {
113 for (auto* layer_impl : *layer->layer_tree_impl()) {
114 if (layer_impl->Is3dSorted() && !layer_impl->bounds().IsEmpty()) {
115 list->push_back(layer_impl);
116 }
117 }
118 }
119
AfterTest()120 void AfterTest() override {
121 CHECK(!story_.empty()) << "Must SetStory() before TearDown().";
122 auto reporter = SetUpBspTreeReporter(story_);
123 reporter.AddResult(kMetricCalcDrawPropsTimeUs,
124 timer_.TimePerLap().InMicrosecondsF());
125 }
126
127 private:
128 cc::FakeContentLayerClient content_layer_client_;
129 base::LapTimer timer_;
130 std::string story_;
131 std::string json_;
132 cc::LayerImplList base_list_;
133 int num_duplicates_ = 1;
134 };
135
TEST_F(BspTreePerfTest,LayerSorterCubes)136 TEST_F(BspTreePerfTest, LayerSorterCubes) {
137 SetStory("layer_sort_cubes");
138 ReadTestFile("layer_sort_cubes");
139 RunTest(cc::CompositorMode::SINGLE_THREADED);
140 }
141
TEST_F(BspTreePerfTest,LayerSorterRubik)142 TEST_F(BspTreePerfTest, LayerSorterRubik) {
143 SetStory("layer_sort_rubik");
144 ReadTestFile("layer_sort_rubik");
145 RunTest(cc::CompositorMode::SINGLE_THREADED);
146 }
147
TEST_F(BspTreePerfTest,BspTreeCubes)148 TEST_F(BspTreePerfTest, BspTreeCubes) {
149 SetStory("bsp_tree_cubes");
150 SetNumberOfDuplicates(1);
151 ReadTestFile("layer_sort_cubes");
152 RunTest(cc::CompositorMode::SINGLE_THREADED);
153 }
154
TEST_F(BspTreePerfTest,BspTreeRubik)155 TEST_F(BspTreePerfTest, BspTreeRubik) {
156 SetStory("bsp_tree_rubik");
157 SetNumberOfDuplicates(1);
158 ReadTestFile("layer_sort_rubik");
159 RunTest(cc::CompositorMode::SINGLE_THREADED);
160 }
161
TEST_F(BspTreePerfTest,BspTreeCubes_2)162 TEST_F(BspTreePerfTest, BspTreeCubes_2) {
163 SetStory("bsp_tree_cubes_2");
164 SetNumberOfDuplicates(2);
165 ReadTestFile("layer_sort_cubes");
166 RunTest(cc::CompositorMode::SINGLE_THREADED);
167 }
168
TEST_F(BspTreePerfTest,BspTreeCubes_4)169 TEST_F(BspTreePerfTest, BspTreeCubes_4) {
170 SetStory("bsp_tree_cubes_4");
171 SetNumberOfDuplicates(4);
172 ReadTestFile("layer_sort_cubes");
173 RunTest(cc::CompositorMode::SINGLE_THREADED);
174 }
175
176 } // namespace
177 } // namespace viz
178