[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 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 | |
[email protected] | 556fd29 | 2013-03-18 08:03:04 | [diff] [blame] | 5 | #include "cc/trees/layer_tree_host.h" |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 6 | |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 7 | #include "base/file_util.h" |
[email protected] | 5799981 | 2013-02-24 05:40:52 | [diff] [blame] | 8 | #include "base/files/file_path.h" |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 9 | #include "base/path_service.h" |
[email protected] | daf079a | 2013-04-17 21:42:40 | [diff] [blame] | 10 | #include "base/strings/string_piece.h" |
[email protected] | cc3cfaa | 2013-03-18 09:05:52 | [diff] [blame] | 11 | #include "cc/layers/content_layer.h" |
| 12 | #include "cc/layers/nine_patch_layer.h" |
| 13 | #include "cc/layers/solid_color_layer.h" |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 14 | #include "cc/test/fake_content_layer_client.h" |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 15 | #include "cc/test/layer_tree_json_parser.h" |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 16 | #include "cc/test/layer_tree_test.h" |
[email protected] | 1b901a3 | 2012-12-07 08:52:03 | [diff] [blame] | 17 | #include "cc/test/paths.h" |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 18 | #include "cc/trees/layer_tree_impl.h" |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 19 | |
| 20 | namespace cc { |
| 21 | namespace { |
| 22 | |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 23 | static const int kTimeLimitMillis = 2000; |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 24 | static const int kWarmupRuns = 5; |
| 25 | static const int kTimeCheckInterval = 10; |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 26 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 27 | class LayerTreeHostPerfTest : public LayerTreeTest { |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 28 | public: |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 29 | LayerTreeHostPerfTest() |
[email protected] | e034135 | 2013-04-06 05:01:20 | [diff] [blame] | 30 | : num_draws_(0), |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 31 | num_commits_(0), |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 32 | full_damage_each_frame_(false), |
| 33 | animation_driven_drawing_(false), |
| 34 | measure_commit_cost_(false) { |
[email protected] | 2384c8a | 2013-03-21 08:35:04 | [diff] [blame] | 35 | fake_content_layer_client_.set_paint_all_opaque(true); |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 36 | } |
| 37 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 38 | virtual void BeginTest() OVERRIDE { |
| 39 | BuildTree(); |
| 40 | PostSetNeedsCommitToMainThread(); |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 41 | } |
| 42 | |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 43 | 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] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 54 | if (measure_commit_cost_ && num_draws_ >= kWarmupRuns) { |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 55 | total_commit_time_ += base::TimeTicks::HighResNow() - commit_start_time_; |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 56 | ++num_commits_; |
| 57 | } |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 58 | } |
| 59 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 60 | virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE { |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 61 | ++num_draws_; |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 62 | 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] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 69 | EndTest(); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 70 | return; |
| 71 | } |
| 72 | } |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 73 | if (!animation_driven_drawing_) |
| 74 | impl->SetNeedsRedraw(); |
[email protected] | e034135 | 2013-04-06 05:01:20 | [diff] [blame] | 75 | if (full_damage_each_frame_) |
| 76 | impl->SetFullRootLayerDamage(); |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 77 | } |
| 78 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 79 | virtual void BuildTree() {} |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 80 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 81 | virtual void AfterTest() OVERRIDE { |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 82 | num_draws_ -= kWarmupRuns; |
| 83 | |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 84 | // Format matches chrome/test/perf/perf_test.h:PrintResult |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 85 | printf("*RESULT %s: frames: %d, %.2f ms/frame\n", |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 86 | test_name_.c_str(), |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 87 | num_draws_, |
| 88 | elapsed_.InMillisecondsF() / num_draws_); |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 89 | if (measure_commit_cost_) { |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 90 | printf("*RESULT %s: commits: %d, %.2f ms/commit\n", |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 91 | test_name_.c_str(), |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 92 | num_commits_, |
| 93 | total_commit_time_.InMillisecondsF() / num_commits_); |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 94 | } |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 95 | } |
| 96 | |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 97 | protected: |
| 98 | base::TimeTicks start_time_; |
| 99 | int num_draws_; |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 100 | int num_commits_; |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 101 | std::string test_name_; |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 102 | base::TimeDelta elapsed_; |
| 103 | FakeContentLayerClient fake_content_layer_client_; |
[email protected] | e034135 | 2013-04-06 05:01:20 | [diff] [blame] | 104 | bool full_damage_each_frame_; |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 105 | bool animation_driven_drawing_; |
| 106 | |
| 107 | bool measure_commit_cost_; |
| 108 | base::TimeTicks commit_start_time_; |
| 109 | base::TimeDelta total_commit_time_; |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 110 | }; |
| 111 | |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 112 | |
| 113 | class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest { |
| 114 | public: |
| 115 | LayerTreeHostPerfTestJsonReader() |
| 116 | : LayerTreeHostPerfTest() { |
| 117 | } |
| 118 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 119 | void ReadTestFile(std::string name) { |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 120 | test_name_ = name; |
[email protected] | 6d4b67a | 2013-02-10 04:49:30 | [diff] [blame] | 121 | base::FilePath test_data_dir; |
[email protected] | 009dc07 | 2012-12-16 20:32:13 | [diff] [blame] | 122 | ASSERT_TRUE(PathService::Get(cc::DIR_TEST_DATA, &test_data_dir)); |
[email protected] | 6d4b67a | 2013-02-10 04:49:30 | [diff] [blame] | 123 | base::FilePath json_file = test_data_dir.AppendASCII(name + ".json"); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 124 | ASSERT_TRUE(file_util::ReadFileToString(json_file, &json_)); |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 125 | } |
| 126 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 127 | virtual void BuildTree() OVERRIDE { |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 128 | gfx::Size viewport = gfx::Size(720, 1038); |
[email protected] | 18ce5970 | 2013-04-09 04:58:40 | [diff] [blame] | 129 | layer_tree_host()->SetViewportSize(viewport); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 130 | scoped_refptr<Layer> root = ParseTreeFromJson(json_, |
| 131 | &fake_content_layer_client_); |
| 132 | ASSERT_TRUE(root.get()); |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 133 | layer_tree_host()->SetRootLayer(root); |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 134 | } |
| 135 | |
| 136 | private: |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 137 | std::string json_; |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 138 | }; |
| 139 | |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 140 | // Simulates a tab switcher scene with two stacks of 10 tabs each. |
| 141 | TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) { |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 142 | ReadTestFile("10_10_layer_tree"); |
[email protected] | 2a61ad5 | 2013-05-13 14:01:29 | [diff] [blame] | 143 | RunTest(false, false, false); |
[email protected] | 91cd748 | 2012-11-30 05:51:45 | [diff] [blame] | 144 | } |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 145 | |
[email protected] | e034135 | 2013-04-06 05:01:20 | [diff] [blame] | 146 | // Simulates a tab switcher scene with two stacks of 10 tabs each. |
| 147 | TEST_F(LayerTreeHostPerfTestJsonReader, |
| 148 | TenTenSingleThread_FullDamageEachFrame) { |
| 149 | full_damage_each_frame_ = true; |
| 150 | ReadTestFile("10_10_layer_tree"); |
[email protected] | 2a61ad5 | 2013-05-13 14:01:29 | [diff] [blame] | 151 | RunTest(false, false, false); |
[email protected] | e034135 | 2013-04-06 05:01:20 | [diff] [blame] | 152 | } |
| 153 | |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 154 | // Simulates main-thread scrolling on each frame. |
| 155 | class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader { |
| 156 | public: |
| 157 | ScrollingLayerTreePerfTest() |
| 158 | : LayerTreeHostPerfTestJsonReader() { |
| 159 | } |
| 160 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 161 | virtual void BuildTree() OVERRIDE { |
| 162 | LayerTreeHostPerfTestJsonReader::BuildTree(); |
| 163 | scrollable_ = layer_tree_host()->root_layer()->children()[1]; |
[email protected] | 22898ed | 2013-06-01 04:52:30 | [diff] [blame] | 164 | ASSERT_TRUE(scrollable_.get()); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 165 | } |
| 166 | |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 167 | virtual void Layout() OVERRIDE { |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 168 | static const gfx::Vector2d delta = gfx::Vector2d(0, 10); |
[email protected] | 7aba666 | 2013-03-12 10:17:34 | [diff] [blame] | 169 | scrollable_->SetScrollOffset(scrollable_->scroll_offset() + delta); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | private: |
[email protected] | 7aba666 | 2013-03-12 10:17:34 | [diff] [blame] | 173 | scoped_refptr<Layer> scrollable_; |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 174 | }; |
| 175 | |
| 176 | TEST_F(ScrollingLayerTreePerfTest, LongScrollablePage) { |
[email protected] | e216fef0 | 2013-03-20 22:56:10 | [diff] [blame] | 177 | ReadTestFile("long_scrollable_page"); |
[email protected] | 2a61ad5 | 2013-05-13 14:01:29 | [diff] [blame] | 178 | RunTest(false, false, false); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 179 | } |
| 180 | |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 181 | class ImplSidePaintingPerfTest : public LayerTreeHostPerfTestJsonReader { |
[email protected] | 2a61ad5 | 2013-05-13 14:01:29 | [diff] [blame] | 182 | protected: |
| 183 | // Run test with impl-side painting. |
| 184 | void RunTestWithImplSidePainting() { RunTest(true, false, true); } |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 185 | }; |
| 186 | |
| 187 | // Simulates a page with several large, transformed and animated layers. |
| 188 | TEST_F(ImplSidePaintingPerfTest, HeavyPage) { |
| 189 | animation_driven_drawing_ = true; |
| 190 | measure_commit_cost_ = true; |
| 191 | ReadTestFile("heavy_layer_tree"); |
[email protected] | 2a61ad5 | 2013-05-13 14:01:29 | [diff] [blame] | 192 | RunTestWithImplSidePainting(); |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 193 | } |
| 194 | |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame^] | 195 | class 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 | |
| 252 | TEST_F(PageScaleImplSidePaintingPerfTest, HeavyPage) { |
| 253 | measure_commit_cost_ = true; |
| 254 | ReadTestFile("heavy_layer_tree"); |
| 255 | RunTestWithImplSidePainting(); |
| 256 | } |
| 257 | |
[email protected] | ed9b489a | 2012-11-28 22:01:40 | [diff] [blame] | 258 | } // namespace |
| 259 | } // namespace cc |