cc: Fix post-commit property tree update for animations
[chromium-blink-merge.git] / cc / trees / layer_tree_host_perftest.cc
blobeb8183fadf2ef861a64e8d5da563f70a9e95d6c6
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.
5 #include "cc/trees/layer_tree_host.h"
7 #include <sstream>
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/nine_patch_layer.h"
16 #include "cc/layers/solid_color_layer.h"
17 #include "cc/layers/texture_layer.h"
18 #include "cc/resources/single_release_callback.h"
19 #include "cc/resources/texture_mailbox.h"
20 #include "cc/test/fake_content_layer_client.h"
21 #include "cc/test/layer_tree_json_parser.h"
22 #include "cc/test/layer_tree_test.h"
23 #include "cc/test/paths.h"
24 #include "cc/trees/layer_tree_impl.h"
25 #include "testing/perf/perf_test.h"
27 namespace cc {
28 namespace {
30 static const int kTimeLimitMillis = 2000;
31 static const int kWarmupRuns = 5;
32 static const int kTimeCheckInterval = 10;
34 class LayerTreeHostPerfTest : public LayerTreeTest {
35 public:
36 LayerTreeHostPerfTest()
37 : draw_timer_(kWarmupRuns,
38 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
39 kTimeCheckInterval),
40 commit_timer_(0, base::TimeDelta(), 1),
41 full_damage_each_frame_(false),
42 begin_frame_driven_drawing_(false),
43 measure_commit_cost_(false) {
46 void InitializeSettings(LayerTreeSettings* settings) override {
47 settings->renderer_settings.disable_gpu_vsync = true;
50 void BeginTest() override {
51 BuildTree();
52 PostSetNeedsCommitToMainThread();
55 void BeginMainFrame(const BeginFrameArgs& args) override {
56 if (begin_frame_driven_drawing_ && !TestEnded()) {
57 layer_tree_host()->SetNeedsAnimate();
58 layer_tree_host()->SetNextCommitForcesRedraw();
62 void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
63 if (measure_commit_cost_)
64 commit_timer_.Start();
67 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
68 if (measure_commit_cost_ && draw_timer_.IsWarmedUp()) {
69 commit_timer_.NextLap();
73 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
74 if (TestEnded() || CleanUpStarted())
75 return;
76 draw_timer_.NextLap();
77 if (draw_timer_.HasTimeLimitExpired()) {
78 CleanUpAndEndTest(impl);
79 return;
81 if (!begin_frame_driven_drawing_)
82 impl->SetNeedsRedraw();
83 if (full_damage_each_frame_)
84 impl->SetFullRootLayerDamage();
87 virtual void CleanUpAndEndTest(LayerTreeHostImpl* host_impl) { EndTest(); }
89 virtual bool CleanUpStarted() { return false; }
91 virtual void BuildTree() {}
93 void AfterTest() override {
94 CHECK(!test_name_.empty()) << "Must SetTestName() before AfterTest().";
95 perf_test::PrintResult("layer_tree_host_frame_time", "", test_name_,
96 1000 * draw_timer_.MsPerLap(), "us", true);
97 if (measure_commit_cost_) {
98 perf_test::PrintResult("layer_tree_host_commit_time", "", test_name_,
99 1000 * commit_timer_.MsPerLap(), "us", true);
103 protected:
104 LapTimer draw_timer_;
105 LapTimer commit_timer_;
107 std::string test_name_;
108 FakeContentLayerClient fake_content_layer_client_;
109 bool full_damage_each_frame_;
110 bool begin_frame_driven_drawing_;
112 bool measure_commit_cost_;
116 class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest {
117 public:
118 LayerTreeHostPerfTestJsonReader()
119 : LayerTreeHostPerfTest() {
122 void SetTestName(const std::string& name) {
123 test_name_ = name;
126 void ReadTestFile(const std::string& name) {
127 base::FilePath test_data_dir;
128 ASSERT_TRUE(PathService::Get(CCPaths::DIR_TEST_DATA, &test_data_dir));
129 base::FilePath json_file = test_data_dir.AppendASCII(name + ".json");
130 ASSERT_TRUE(base::ReadFileToString(json_file, &json_));
133 void BuildTree() override {
134 gfx::Size viewport = gfx::Size(720, 1038);
135 layer_tree_host()->SetViewportSize(viewport);
136 scoped_refptr<Layer> root = ParseTreeFromJson(json_,
137 &fake_content_layer_client_);
138 ASSERT_TRUE(root.get());
139 layer_tree_host()->SetRootLayer(root);
142 private:
143 std::string json_;
146 // Simulates a tab switcher scene with two stacks of 10 tabs each.
147 TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) {
148 SetTestName("10_10_single_thread");
149 ReadTestFile("10_10_layer_tree");
150 RunTest(false, false);
153 TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreaded) {
154 SetTestName("10_10_threaded_impl_side");
155 ReadTestFile("10_10_layer_tree");
156 RunTest(true, false);
159 // Simulates a tab switcher scene with two stacks of 10 tabs each.
160 TEST_F(LayerTreeHostPerfTestJsonReader,
161 TenTenSingleThread_FullDamageEachFrame) {
162 full_damage_each_frame_ = true;
163 SetTestName("10_10_single_thread_full_damage_each_frame");
164 ReadTestFile("10_10_layer_tree");
165 RunTest(false, false);
168 TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreaded_FullDamageEachFrame) {
169 full_damage_each_frame_ = true;
170 SetTestName("10_10_threaded_impl_side_full_damage_each_frame");
171 ReadTestFile("10_10_layer_tree");
172 RunTest(true, false);
175 // Invalidates a leaf layer in the tree on the main thread after every commit.
176 class LayerTreeHostPerfTestLeafInvalidates
177 : public LayerTreeHostPerfTestJsonReader {
178 public:
179 void BuildTree() override {
180 LayerTreeHostPerfTestJsonReader::BuildTree();
182 // Find a leaf layer.
183 for (layer_to_invalidate_ = layer_tree_host()->root_layer();
184 layer_to_invalidate_->children().size();
185 layer_to_invalidate_ = layer_to_invalidate_->children()[0].get()) {
189 void DidCommitAndDrawFrame() override {
190 if (TestEnded())
191 return;
193 layer_to_invalidate_->SetOpacity(
194 layer_to_invalidate_->opacity() != 1.f ? 1.f : 0.5f);
197 protected:
198 Layer* layer_to_invalidate_;
201 // Simulates a tab switcher scene with two stacks of 10 tabs each. Invalidate a
202 // property on a leaf layer in the tree every commit.
203 TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenSingleThread) {
204 SetTestName("10_10_single_thread_leaf_invalidates");
205 ReadTestFile("10_10_layer_tree");
206 RunTest(false, false);
209 TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenThreaded) {
210 SetTestName("10_10_threaded_impl_side_leaf_invalidates");
211 ReadTestFile("10_10_layer_tree");
212 RunTest(true, false);
215 // Simulates main-thread scrolling on each frame.
216 class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader {
217 public:
218 ScrollingLayerTreePerfTest()
219 : LayerTreeHostPerfTestJsonReader() {
222 void BuildTree() override {
223 LayerTreeHostPerfTestJsonReader::BuildTree();
224 scrollable_ = layer_tree_host()->root_layer()->children()[1];
225 ASSERT_TRUE(scrollable_.get());
228 void Layout() override {
229 if (TestEnded())
230 return;
231 static const gfx::Vector2d delta = gfx::Vector2d(0, 10);
232 scrollable_->SetScrollOffset(
233 gfx::ScrollOffsetWithDelta(scrollable_->scroll_offset(), delta));
236 private:
237 scoped_refptr<Layer> scrollable_;
240 TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageSingleThread) {
241 SetTestName("long_scrollable_page");
242 ReadTestFile("long_scrollable_page");
243 // TODO(vollick): Remove verify_property_trees setting after
244 // crbug.com/444219 is fixed.
245 bool old_verify_property_trees = verify_property_trees();
246 set_verify_property_trees(false);
247 RunTest(false, false);
248 set_verify_property_trees(old_verify_property_trees);
251 TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageThreaded) {
252 SetTestName("long_scrollable_page_threaded_impl_side");
253 ReadTestFile("long_scrollable_page");
254 // TODO(vollick): Remove verify_property_trees setting after
255 // crbug.com/444219 is fixed.
256 bool old_verify_property_trees = verify_property_trees();
257 set_verify_property_trees(false);
258 RunTest(true, false);
259 set_verify_property_trees(old_verify_property_trees);
262 static void EmptyReleaseCallback(uint32 sync_point, bool lost_resource) {}
264 // Simulates main-thread scrolling on each frame.
265 class BrowserCompositorInvalidateLayerTreePerfTest
266 : public LayerTreeHostPerfTestJsonReader {
267 public:
268 BrowserCompositorInvalidateLayerTreePerfTest()
269 : LayerTreeHostPerfTestJsonReader(),
270 next_sync_point_(1),
271 clean_up_started_(false) {}
273 void BuildTree() override {
274 LayerTreeHostPerfTestJsonReader::BuildTree();
275 tab_contents_ =
276 static_cast<TextureLayer*>(
277 layer_tree_host()->root_layer()->children()[0]->
278 children()[0]->
279 children()[0]->
280 children()[0].get());
281 ASSERT_TRUE(tab_contents_.get());
284 void WillCommit() override {
285 if (CleanUpStarted())
286 return;
287 gpu::Mailbox gpu_mailbox;
288 std::ostringstream name_stream;
289 name_stream << "name" << next_sync_point_;
290 gpu_mailbox.SetName(
291 reinterpret_cast<const int8*>(name_stream.str().c_str()));
292 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
293 base::Bind(&EmptyReleaseCallback));
294 TextureMailbox mailbox(gpu_mailbox, GL_TEXTURE_2D, next_sync_point_);
295 next_sync_point_++;
297 tab_contents_->SetTextureMailbox(mailbox, callback.Pass());
300 void DidCommit() override {
301 if (CleanUpStarted())
302 return;
303 layer_tree_host()->SetNeedsCommit();
306 void CleanUpAndEndTest(LayerTreeHostImpl* host_impl) override {
307 clean_up_started_ = true;
308 MainThreadTaskRunner()->PostTask(
309 FROM_HERE,
310 base::Bind(&BrowserCompositorInvalidateLayerTreePerfTest::
311 CleanUpAndEndTestOnMainThread,
312 base::Unretained(this)));
315 void CleanUpAndEndTestOnMainThread() {
316 tab_contents_->SetTextureMailbox(TextureMailbox(), nullptr);
317 EndTest();
320 bool CleanUpStarted() override { return clean_up_started_; }
322 private:
323 scoped_refptr<TextureLayer> tab_contents_;
324 unsigned next_sync_point_;
325 bool clean_up_started_;
328 TEST_F(BrowserCompositorInvalidateLayerTreePerfTest, DenseBrowserUIThreaded) {
329 measure_commit_cost_ = true;
330 SetTestName("dense_layer_tree");
331 ReadTestFile("dense_layer_tree");
332 RunTest(true, false);
335 // Simulates a page with several large, transformed and animated layers.
336 TEST_F(LayerTreeHostPerfTestJsonReader, HeavyPageThreaded) {
337 begin_frame_driven_drawing_ = true;
338 measure_commit_cost_ = true;
339 SetTestName("heavy_page");
340 ReadTestFile("heavy_layer_tree");
341 RunTest(true, false);
344 } // namespace
345 } // namespace cc