OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/trees/layer_tree_host.h" | |
6 | |
7 #include <sstream> | |
8 | |
9 #include "base/files/file_path.h" | |
10 #include "base/files/file_util.h" | |
11 #include "base/path_service.h" | |
12 #include "base/strings/string_piece.h" | |
13 #include "base/time/time.h" | |
14 #include "cc/debug/lap_timer.h" | |
15 #include "cc/layers/content_layer.h" | |
16 #include "cc/layers/nine_patch_layer.h" | |
17 #include "cc/layers/solid_color_layer.h" | |
18 #include "cc/layers/texture_layer.h" | |
19 #include "cc/resources/single_release_callback.h" | |
20 #include "cc/resources/texture_mailbox.h" | |
21 #include "cc/test/fake_content_layer_client.h" | |
22 #include "cc/test/layer_tree_json_parser.h" | |
23 #include "cc/test/layer_tree_test.h" | |
24 #include "cc/test/paths.h" | |
25 #include "cc/trees/layer_tree_impl.h" | |
26 #include "testing/perf/perf_test.h" | |
27 | |
28 namespace cc { | |
29 namespace { | |
30 | |
31 static const int kTimeLimitMillis = 2000; | |
32 static const int kWarmupRuns = 5; | |
33 static const int kTimeCheckInterval = 10; | |
34 | |
35 class LayerTreeHostPerfTest : public LayerTreeTest { | |
36 public: | |
37 LayerTreeHostPerfTest() | |
38 : draw_timer_(kWarmupRuns, | |
39 base::TimeDelta::FromMilliseconds(kTimeLimitMillis), | |
40 kTimeCheckInterval), | |
41 commit_timer_(0, base::TimeDelta(), 1), | |
42 full_damage_each_frame_(false), | |
43 begin_frame_driven_drawing_(false), | |
44 measure_commit_cost_(false) { | |
45 } | |
46 | |
47 void InitializeSettings(LayerTreeSettings* settings) override { | |
48 settings->throttle_frame_production = false; | |
49 } | |
50 | |
51 void BeginTest() override { | |
52 BuildTree(); | |
53 PostSetNeedsCommitToMainThread(); | |
54 } | |
55 | |
56 void BeginMainFrame(const BeginFrameArgs& args) override { | |
57 if (begin_frame_driven_drawing_ && !TestEnded()) { | |
58 layer_tree_host()->SetNeedsAnimate(); | |
59 layer_tree_host()->SetNextCommitForcesRedraw(); | |
60 } | |
61 } | |
62 | |
63 void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { | |
64 if (measure_commit_cost_) | |
65 commit_timer_.Start(); | |
66 } | |
67 | |
68 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { | |
69 if (measure_commit_cost_ && draw_timer_.IsWarmedUp()) { | |
70 commit_timer_.NextLap(); | |
71 } | |
72 } | |
73 | |
74 void DrawLayersOnThread(LayerTreeHostImpl* impl) override { | |
75 if (TestEnded() || CleanUpStarted()) | |
76 return; | |
77 draw_timer_.NextLap(); | |
78 if (draw_timer_.HasTimeLimitExpired()) { | |
79 CleanUpAndEndTest(impl); | |
80 return; | |
81 } | |
82 if (!begin_frame_driven_drawing_) | |
83 impl->SetNeedsRedraw(); | |
84 if (full_damage_each_frame_) | |
85 impl->SetFullRootLayerDamage(); | |
86 } | |
87 | |
88 virtual void CleanUpAndEndTest(LayerTreeHostImpl* host_impl) { EndTest(); } | |
89 | |
90 virtual bool CleanUpStarted() { return false; } | |
91 | |
92 virtual void BuildTree() {} | |
93 | |
94 void AfterTest() override { | |
95 CHECK(!test_name_.empty()) << "Must SetTestName() before AfterTest()."; | |
96 perf_test::PrintResult("layer_tree_host_frame_time", "", test_name_, | |
97 1000 * draw_timer_.MsPerLap(), "us", true); | |
98 if (measure_commit_cost_) { | |
99 perf_test::PrintResult("layer_tree_host_commit_time", "", test_name_, | |
100 1000 * commit_timer_.MsPerLap(), "us", true); | |
101 } | |
102 } | |
103 | |
104 protected: | |
105 LapTimer draw_timer_; | |
106 LapTimer commit_timer_; | |
107 | |
108 std::string test_name_; | |
109 FakeContentLayerClient fake_content_layer_client_; | |
110 bool full_damage_each_frame_; | |
111 bool begin_frame_driven_drawing_; | |
112 | |
113 bool measure_commit_cost_; | |
114 }; | |
115 | |
116 | |
117 class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest { | |
118 public: | |
119 LayerTreeHostPerfTestJsonReader() | |
120 : LayerTreeHostPerfTest() { | |
121 } | |
122 | |
123 void SetTestName(const std::string& name) { | |
124 test_name_ = name; | |
125 } | |
126 | |
127 void ReadTestFile(const std::string& name) { | |
128 base::FilePath test_data_dir; | |
129 ASSERT_TRUE(PathService::Get(CCPaths::DIR_TEST_DATA, &test_data_dir)); | |
130 base::FilePath json_file = test_data_dir.AppendASCII(name + ".json"); | |
131 ASSERT_TRUE(base::ReadFileToString(json_file, &json_)); | |
132 } | |
133 | |
134 void BuildTree() override { | |
135 gfx::Size viewport = gfx::Size(720, 1038); | |
136 layer_tree_host()->SetViewportSize(viewport); | |
137 scoped_refptr<Layer> root = ParseTreeFromJson(json_, | |
138 &fake_content_layer_client_); | |
139 ASSERT_TRUE(root.get()); | |
140 layer_tree_host()->SetRootLayer(root); | |
141 } | |
142 | |
143 private: | |
144 std::string json_; | |
145 }; | |
146 | |
147 // Simulates a tab switcher scene with two stacks of 10 tabs each. | |
148 TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) { | |
149 SetTestName("10_10_single_thread"); | |
150 ReadTestFile("10_10_layer_tree"); | |
151 RunTest(false, false, false); | |
152 } | |
153 | |
154 TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreadedImplSide) { | |
155 SetTestName("10_10_threaded_impl_side"); | |
156 ReadTestFile("10_10_layer_tree"); | |
157 RunTestWithImplSidePainting(); | |
158 } | |
159 | |
160 // Simulates a tab switcher scene with two stacks of 10 tabs each. | |
161 TEST_F(LayerTreeHostPerfTestJsonReader, | |
162 TenTenSingleThread_FullDamageEachFrame) { | |
163 full_damage_each_frame_ = true; | |
164 SetTestName("10_10_single_thread_full_damage_each_frame"); | |
165 ReadTestFile("10_10_layer_tree"); | |
166 RunTest(false, false, false); | |
167 } | |
168 | |
169 TEST_F(LayerTreeHostPerfTestJsonReader, | |
170 TenTenThreadedImplSide_FullDamageEachFrame) { | |
171 full_damage_each_frame_ = true; | |
172 SetTestName("10_10_threaded_impl_side_full_damage_each_frame"); | |
173 ReadTestFile("10_10_layer_tree"); | |
174 RunTestWithImplSidePainting(); | |
175 } | |
176 | |
177 // Invalidates a leaf layer in the tree on the main thread after every commit. | |
178 class LayerTreeHostPerfTestLeafInvalidates | |
179 : public LayerTreeHostPerfTestJsonReader { | |
180 public: | |
181 void BuildTree() override { | |
182 LayerTreeHostPerfTestJsonReader::BuildTree(); | |
183 | |
184 // Find a leaf layer. | |
185 for (layer_to_invalidate_ = layer_tree_host()->root_layer(); | |
186 layer_to_invalidate_->children().size(); | |
187 layer_to_invalidate_ = layer_to_invalidate_->children()[0].get()) { | |
188 } | |
189 } | |
190 | |
191 void DidCommitAndDrawFrame() override { | |
192 if (TestEnded()) | |
193 return; | |
194 | |
195 layer_to_invalidate_->SetOpacity( | |
196 layer_to_invalidate_->opacity() != 1.f ? 1.f : 0.5f); | |
197 } | |
198 | |
199 protected: | |
200 Layer* layer_to_invalidate_; | |
201 }; | |
202 | |
203 // Simulates a tab switcher scene with two stacks of 10 tabs each. Invalidate a | |
204 // property on a leaf layer in the tree every commit. | |
205 TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenSingleThread) { | |
206 SetTestName("10_10_single_thread_leaf_invalidates"); | |
207 ReadTestFile("10_10_layer_tree"); | |
208 RunTest(false, false, false); | |
209 } | |
210 | |
211 TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenThreadedImplSide) { | |
212 SetTestName("10_10_threaded_impl_side_leaf_invalidates"); | |
213 ReadTestFile("10_10_layer_tree"); | |
214 RunTestWithImplSidePainting(); | |
215 } | |
216 | |
217 // Simulates main-thread scrolling on each frame. | |
218 class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader { | |
219 public: | |
220 ScrollingLayerTreePerfTest() | |
221 : LayerTreeHostPerfTestJsonReader() { | |
222 } | |
223 | |
224 void BuildTree() override { | |
225 LayerTreeHostPerfTestJsonReader::BuildTree(); | |
226 scrollable_ = layer_tree_host()->root_layer()->children()[1]; | |
227 ASSERT_TRUE(scrollable_.get()); | |
228 } | |
229 | |
230 void Layout() override { | |
231 if (TestEnded()) | |
232 return; | |
233 static const gfx::Vector2d delta = gfx::Vector2d(0, 10); | |
234 scrollable_->SetScrollOffset( | |
235 gfx::ScrollOffsetWithDelta(scrollable_->scroll_offset(), delta)); | |
236 } | |
237 | |
238 private: | |
239 scoped_refptr<Layer> scrollable_; | |
240 }; | |
241 | |
242 TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageSingleThread) { | |
243 SetTestName("long_scrollable_page"); | |
244 ReadTestFile("long_scrollable_page"); | |
245 // TODO(vollick): Remove verify_property_trees setting after | |
246 // crbug.com/444219 is fixed. | |
247 bool old_verify_property_trees = verify_property_trees(); | |
248 set_verify_property_trees(false); | |
249 RunTest(false, false, false); | |
250 set_verify_property_trees(old_verify_property_trees); | |
251 } | |
252 | |
253 TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageThreadedImplSide) { | |
254 SetTestName("long_scrollable_page_threaded_impl_side"); | |
255 ReadTestFile("long_scrollable_page"); | |
256 // TODO(vollick): Remove verify_property_trees setting after | |
257 // crbug.com/444219 is fixed. | |
258 bool old_verify_property_trees = verify_property_trees(); | |
259 set_verify_property_trees(false); | |
260 RunTestWithImplSidePainting(); | |
261 set_verify_property_trees(old_verify_property_trees); | |
262 } | |
263 | |
264 static void EmptyReleaseCallback(uint32 sync_point, bool lost_resource) {} | |
265 | |
266 // Simulates main-thread scrolling on each frame. | |
267 class BrowserCompositorInvalidateLayerTreePerfTest | |
268 : public LayerTreeHostPerfTestJsonReader { | |
269 public: | |
270 BrowserCompositorInvalidateLayerTreePerfTest() | |
271 : LayerTreeHostPerfTestJsonReader(), | |
272 next_sync_point_(1), | |
273 clean_up_started_(false) {} | |
274 | |
275 void BuildTree() override { | |
276 LayerTreeHostPerfTestJsonReader::BuildTree(); | |
277 tab_contents_ = | |
278 static_cast<TextureLayer*>( | |
279 layer_tree_host()->root_layer()->children()[0]-> | |
280 children()[0]-> | |
281 children()[0]-> | |
282 children()[0].get()); | |
283 ASSERT_TRUE(tab_contents_.get()); | |
284 } | |
285 | |
286 void WillCommit() override { | |
287 if (CleanUpStarted()) | |
288 return; | |
289 gpu::Mailbox gpu_mailbox; | |
290 std::ostringstream name_stream; | |
291 name_stream << "name" << next_sync_point_; | |
292 gpu_mailbox.SetName( | |
293 reinterpret_cast<const int8*>(name_stream.str().c_str())); | |
294 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( | |
295 base::Bind(&EmptyReleaseCallback)); | |
296 TextureMailbox mailbox(gpu_mailbox, GL_TEXTURE_2D, next_sync_point_); | |
297 next_sync_point_++; | |
298 | |
299 tab_contents_->SetTextureMailbox(mailbox, callback.Pass()); | |
300 } | |
301 | |
302 void DidCommit() override { | |
303 if (CleanUpStarted()) | |
304 return; | |
305 layer_tree_host()->SetNeedsCommit(); | |
306 } | |
307 | |
308 void CleanUpAndEndTest(LayerTreeHostImpl* host_impl) override { | |
309 clean_up_started_ = true; | |
310 MainThreadTaskRunner()->PostTask( | |
311 FROM_HERE, | |
312 base::Bind(&BrowserCompositorInvalidateLayerTreePerfTest:: | |
313 CleanUpAndEndTestOnMainThread, | |
314 base::Unretained(this))); | |
315 } | |
316 | |
317 void CleanUpAndEndTestOnMainThread() { | |
318 tab_contents_->SetTextureMailbox(TextureMailbox(), nullptr); | |
319 EndTest(); | |
320 } | |
321 | |
322 bool CleanUpStarted() override { return clean_up_started_; } | |
323 | |
324 private: | |
325 scoped_refptr<TextureLayer> tab_contents_; | |
326 unsigned next_sync_point_; | |
327 bool clean_up_started_; | |
328 }; | |
329 | |
330 TEST_F(BrowserCompositorInvalidateLayerTreePerfTest, DenseBrowserUI) { | |
331 measure_commit_cost_ = true; | |
332 SetTestName("dense_layer_tree"); | |
333 ReadTestFile("dense_layer_tree"); | |
334 RunTestWithImplSidePainting(); | |
335 } | |
336 | |
337 // Simulates a page with several large, transformed and animated layers. | |
338 TEST_F(LayerTreeHostPerfTestJsonReader, HeavyPageThreadedImplSide) { | |
339 begin_frame_driven_drawing_ = true; | |
340 measure_commit_cost_ = true; | |
341 SetTestName("heavy_page"); | |
342 ReadTestFile("heavy_layer_tree"); | |
343 RunTestWithImplSidePainting(); | |
344 } | |
345 | |
346 } // namespace | |
347 } // namespace cc | |
OLD | NEW |