blob: 1f761262a673002bda7c2475ad3b3f796d7018c2 [file] [log] [blame]
[email protected]ed9b489a2012-11-28 22:01:401// 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
[email protected]556fd292013-03-18 08:03:045#include "cc/trees/layer_tree_host.h"
[email protected]ed9b489a2012-11-28 22:01:406
[email protected]91cd7482012-11-30 05:51:457#include "base/file_util.h"
[email protected]57999812013-02-24 05:40:528#include "base/files/file_path.h"
[email protected]91cd7482012-11-30 05:51:459#include "base/path_service.h"
[email protected]daf079a2013-04-17 21:42:4010#include "base/strings/string_piece.h"
[email protected]cc3cfaa2013-03-18 09:05:5211#include "cc/layers/content_layer.h"
12#include "cc/layers/nine_patch_layer.h"
13#include "cc/layers/solid_color_layer.h"
[email protected]ed9b489a2012-11-28 22:01:4014#include "cc/test/fake_content_layer_client.h"
[email protected]f8fef2bd2013-02-04 23:39:2215#include "cc/test/layer_tree_json_parser.h"
[email protected]e216fef02013-03-20 22:56:1016#include "cc/test/layer_tree_test.h"
[email protected]1b901a32012-12-07 08:52:0317#include "cc/test/paths.h"
[email protected]d993e032013-06-07 00:16:1618#include "cc/trees/layer_tree_impl.h"
[email protected]ed9b489a2012-11-28 22:01:4019
20namespace cc {
21namespace {
22
[email protected]91cd7482012-11-30 05:51:4523static const int kTimeLimitMillis = 2000;
[email protected]f8fef2bd2013-02-04 23:39:2224static const int kWarmupRuns = 5;
25static const int kTimeCheckInterval = 10;
[email protected]ed9b489a2012-11-28 22:01:4026
[email protected]e216fef02013-03-20 22:56:1027class LayerTreeHostPerfTest : public LayerTreeTest {
[email protected]ed9b489a2012-11-28 22:01:4028 public:
[email protected]91cd7482012-11-30 05:51:4529 LayerTreeHostPerfTest()
[email protected]e0341352013-04-06 05:01:2030 : num_draws_(0),
[email protected]d993e032013-06-07 00:16:1631 num_commits_(0),
[email protected]a49d0f8a2013-05-09 23:26:1932 full_damage_each_frame_(false),
33 animation_driven_drawing_(false),
34 measure_commit_cost_(false) {
[email protected]2384c8a2013-03-21 08:35:0435 fake_content_layer_client_.set_paint_all_opaque(true);
[email protected]ed9b489a2012-11-28 22:01:4036 }
37
[email protected]e216fef02013-03-20 22:56:1038 virtual void BeginTest() OVERRIDE {
39 BuildTree();
40 PostSetNeedsCommitToMainThread();
[email protected]91cd7482012-11-30 05:51:4541 }
42
[email protected]a49d0f8a2013-05-09 23:26:1943 virtual void Animate(base::TimeTicks monotonic_time) OVERRIDE {
44 if (animation_driven_drawing_ && !TestEnded())
45 layer_tree_host()->SetNeedsAnimate();
46 }
47
48 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
49 if (measure_commit_cost_)
50 commit_start_time_ = base::TimeTicks::HighResNow();
51 }
52
53 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
[email protected]d993e032013-06-07 00:16:1654 if (measure_commit_cost_ && num_draws_ >= kWarmupRuns) {
[email protected]a49d0f8a2013-05-09 23:26:1955 total_commit_time_ += base::TimeTicks::HighResNow() - commit_start_time_;
[email protected]d993e032013-06-07 00:16:1656 ++num_commits_;
57 }
[email protected]a49d0f8a2013-05-09 23:26:1958 }
59
[email protected]e216fef02013-03-20 22:56:1060 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
[email protected]91cd7482012-11-30 05:51:4561 ++num_draws_;
[email protected]f8fef2bd2013-02-04 23:39:2262 if (num_draws_ == kWarmupRuns)
63 start_time_ = base::TimeTicks::HighResNow();
64
65 if (!start_time_.is_null() && (num_draws_ % kTimeCheckInterval) == 0) {
66 base::TimeDelta elapsed = base::TimeTicks::HighResNow() - start_time_;
67 if (elapsed >= base::TimeDelta::FromMilliseconds(kTimeLimitMillis)) {
68 elapsed_ = elapsed;
[email protected]e216fef02013-03-20 22:56:1069 EndTest();
[email protected]f8fef2bd2013-02-04 23:39:2270 return;
71 }
72 }
[email protected]a49d0f8a2013-05-09 23:26:1973 if (!animation_driven_drawing_)
74 impl->SetNeedsRedraw();
[email protected]e0341352013-04-06 05:01:2075 if (full_damage_each_frame_)
76 impl->SetFullRootLayerDamage();
[email protected]91cd7482012-11-30 05:51:4577 }
78
[email protected]e216fef02013-03-20 22:56:1079 virtual void BuildTree() {}
[email protected]91cd7482012-11-30 05:51:4580
[email protected]e216fef02013-03-20 22:56:1081 virtual void AfterTest() OVERRIDE {
[email protected]d993e032013-06-07 00:16:1682 num_draws_ -= kWarmupRuns;
83
[email protected]91cd7482012-11-30 05:51:4584 // Format matches chrome/test/perf/perf_test.h:PrintResult
[email protected]d993e032013-06-07 00:16:1685 printf("*RESULT %s: frames: %d, %.2f ms/frame\n",
[email protected]91cd7482012-11-30 05:51:4586 test_name_.c_str(),
[email protected]d993e032013-06-07 00:16:1687 num_draws_,
88 elapsed_.InMillisecondsF() / num_draws_);
[email protected]a49d0f8a2013-05-09 23:26:1989 if (measure_commit_cost_) {
[email protected]d993e032013-06-07 00:16:1690 printf("*RESULT %s: commits: %d, %.2f ms/commit\n",
[email protected]a49d0f8a2013-05-09 23:26:1991 test_name_.c_str(),
[email protected]d993e032013-06-07 00:16:1692 num_commits_,
93 total_commit_time_.InMillisecondsF() / num_commits_);
[email protected]a49d0f8a2013-05-09 23:26:1994 }
[email protected]ed9b489a2012-11-28 22:01:4095 }
96
[email protected]91cd7482012-11-30 05:51:4597 protected:
98 base::TimeTicks start_time_;
99 int num_draws_;
[email protected]d993e032013-06-07 00:16:16100 int num_commits_;
[email protected]91cd7482012-11-30 05:51:45101 std::string test_name_;
[email protected]f8fef2bd2013-02-04 23:39:22102 base::TimeDelta elapsed_;
103 FakeContentLayerClient fake_content_layer_client_;
[email protected]e0341352013-04-06 05:01:20104 bool full_damage_each_frame_;
[email protected]a49d0f8a2013-05-09 23:26:19105 bool animation_driven_drawing_;
106
107 bool measure_commit_cost_;
108 base::TimeTicks commit_start_time_;
109 base::TimeDelta total_commit_time_;
[email protected]91cd7482012-11-30 05:51:45110};
111
[email protected]91cd7482012-11-30 05:51:45112
113class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest {
114 public:
115 LayerTreeHostPerfTestJsonReader()
116 : LayerTreeHostPerfTest() {
117 }
118
[email protected]e216fef02013-03-20 22:56:10119 void ReadTestFile(std::string name) {
[email protected]91cd7482012-11-30 05:51:45120 test_name_ = name;
[email protected]6d4b67a2013-02-10 04:49:30121 base::FilePath test_data_dir;
[email protected]009dc072012-12-16 20:32:13122 ASSERT_TRUE(PathService::Get(cc::DIR_TEST_DATA, &test_data_dir));
[email protected]6d4b67a2013-02-10 04:49:30123 base::FilePath json_file = test_data_dir.AppendASCII(name + ".json");
[email protected]f8fef2bd2013-02-04 23:39:22124 ASSERT_TRUE(file_util::ReadFileToString(json_file, &json_));
[email protected]91cd7482012-11-30 05:51:45125 }
126
[email protected]e216fef02013-03-20 22:56:10127 virtual void BuildTree() OVERRIDE {
[email protected]91cd7482012-11-30 05:51:45128 gfx::Size viewport = gfx::Size(720, 1038);
[email protected]18ce59702013-04-09 04:58:40129 layer_tree_host()->SetViewportSize(viewport);
[email protected]f8fef2bd2013-02-04 23:39:22130 scoped_refptr<Layer> root = ParseTreeFromJson(json_,
131 &fake_content_layer_client_);
132 ASSERT_TRUE(root.get());
[email protected]e216fef02013-03-20 22:56:10133 layer_tree_host()->SetRootLayer(root);
[email protected]91cd7482012-11-30 05:51:45134 }
135
136 private:
[email protected]f8fef2bd2013-02-04 23:39:22137 std::string json_;
[email protected]91cd7482012-11-30 05:51:45138};
139
[email protected]f8fef2bd2013-02-04 23:39:22140// Simulates a tab switcher scene with two stacks of 10 tabs each.
141TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) {
[email protected]e216fef02013-03-20 22:56:10142 ReadTestFile("10_10_layer_tree");
[email protected]2a61ad52013-05-13 14:01:29143 RunTest(false, false, false);
[email protected]91cd7482012-11-30 05:51:45144}
[email protected]ed9b489a2012-11-28 22:01:40145
[email protected]e0341352013-04-06 05:01:20146// Simulates a tab switcher scene with two stacks of 10 tabs each.
147TEST_F(LayerTreeHostPerfTestJsonReader,
148 TenTenSingleThread_FullDamageEachFrame) {
149 full_damage_each_frame_ = true;
150 ReadTestFile("10_10_layer_tree");
[email protected]2a61ad52013-05-13 14:01:29151 RunTest(false, false, false);
[email protected]e0341352013-04-06 05:01:20152}
153
[email protected]f8fef2bd2013-02-04 23:39:22154// Simulates main-thread scrolling on each frame.
155class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader {
156 public:
157 ScrollingLayerTreePerfTest()
158 : LayerTreeHostPerfTestJsonReader() {
159 }
160
[email protected]e216fef02013-03-20 22:56:10161 virtual void BuildTree() OVERRIDE {
162 LayerTreeHostPerfTestJsonReader::BuildTree();
163 scrollable_ = layer_tree_host()->root_layer()->children()[1];
[email protected]22898ed2013-06-01 04:52:30164 ASSERT_TRUE(scrollable_.get());
[email protected]f8fef2bd2013-02-04 23:39:22165 }
166
[email protected]e216fef02013-03-20 22:56:10167 virtual void Layout() OVERRIDE {
[email protected]f8fef2bd2013-02-04 23:39:22168 static const gfx::Vector2d delta = gfx::Vector2d(0, 10);
[email protected]7aba6662013-03-12 10:17:34169 scrollable_->SetScrollOffset(scrollable_->scroll_offset() + delta);
[email protected]f8fef2bd2013-02-04 23:39:22170 }
171
172 private:
[email protected]7aba6662013-03-12 10:17:34173 scoped_refptr<Layer> scrollable_;
[email protected]f8fef2bd2013-02-04 23:39:22174};
175
176TEST_F(ScrollingLayerTreePerfTest, LongScrollablePage) {
[email protected]e216fef02013-03-20 22:56:10177 ReadTestFile("long_scrollable_page");
[email protected]2a61ad52013-05-13 14:01:29178 RunTest(false, false, false);
[email protected]f8fef2bd2013-02-04 23:39:22179}
180
[email protected]a49d0f8a2013-05-09 23:26:19181class ImplSidePaintingPerfTest : public LayerTreeHostPerfTestJsonReader {
[email protected]2a61ad52013-05-13 14:01:29182 protected:
183 // Run test with impl-side painting.
184 void RunTestWithImplSidePainting() { RunTest(true, false, true); }
[email protected]a49d0f8a2013-05-09 23:26:19185};
186
187// Simulates a page with several large, transformed and animated layers.
188TEST_F(ImplSidePaintingPerfTest, HeavyPage) {
189 animation_driven_drawing_ = true;
190 measure_commit_cost_ = true;
191 ReadTestFile("heavy_layer_tree");
[email protected]2a61ad52013-05-13 14:01:29192 RunTestWithImplSidePainting();
[email protected]a49d0f8a2013-05-09 23:26:19193}
194
[email protected]d993e032013-06-07 00:16:16195class PageScaleImplSidePaintingPerfTest : public ImplSidePaintingPerfTest {
196 public:
197 PageScaleImplSidePaintingPerfTest()
198 : max_scale_(16.f), min_scale_(1.f / max_scale_) {}
199
200 virtual void SetupTree() OVERRIDE {
201 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, min_scale_, max_scale_);
202 }
203
204 virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
205 float scale_delta) OVERRIDE {
206 float page_scale_factor = layer_tree_host()->page_scale_factor();
207 page_scale_factor *= scale_delta;
208 layer_tree_host()->SetPageScaleFactorAndLimits(
209 page_scale_factor, min_scale_, max_scale_);
210 }
211
212 virtual void AnimateLayers(LayerTreeHostImpl* host_impl,
213 base::TimeTicks monotonic_time) OVERRIDE {
214 if (!host_impl->pinch_gesture_active()) {
215 host_impl->PinchGestureBegin();
216 start_time_ = monotonic_time;
217 }
218 gfx::Point anchor(200, 200);
219
220 float seconds = (monotonic_time - start_time_).InSecondsF();
221
222 // Every half second, zoom from min scale to max scale.
223 float interval = 0.5f;
224
225 // Start time in the middle of the interval when zoom = 1.
226 seconds += interval / 2.f;
227
228 // Stack two ranges together to go up from min to max and down from
229 // max to min in the next so as not to have a zoom discrepancy.
230 float time_in_two_intervals = fmod(seconds, 2.f * interval) / interval;
231
232 // Map everything to go from min to max between 0 and 1.
233 float time_in_one_interval =
234 time_in_two_intervals > 1.f ? 2.f - time_in_two_intervals
235 : time_in_two_intervals;
236 // Normalize time to -1..1.
237 float normalized = 2.f * time_in_one_interval - 1.f;
238 float scale_factor = std::fabs(normalized) * (max_scale_ - 1.f) + 1.f;
239 float total_scale = normalized < 0.f ? 1.f / scale_factor : scale_factor;
240
241 float desired_delta =
242 total_scale / host_impl->active_tree()->total_page_scale_factor();
243 host_impl->PinchGestureUpdate(desired_delta, anchor);
244 }
245
246 private:
247 float max_scale_;
248 float min_scale_;
249 base::TimeTicks start_time_;
250};
251
252TEST_F(PageScaleImplSidePaintingPerfTest, HeavyPage) {
253 measure_commit_cost_ = true;
254 ReadTestFile("heavy_layer_tree");
255 RunTestWithImplSidePainting();
256}
257
[email protected]ed9b489a2012-11-28 22:01:40258} // namespace
259} // namespace cc