blob: 79ee46be8142bd84eef6e8b2eb0434e626242d4e [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]3393fa92013-10-18 03:37:527#include <sstream>
8
[email protected]91cd7482012-11-30 05:51:459#include "base/file_util.h"
[email protected]57999812013-02-24 05:40:5210#include "base/files/file_path.h"
[email protected]91cd7482012-11-30 05:51:4511#include "base/path_service.h"
[email protected]daf079a2013-04-17 21:42:4012#include "base/strings/string_piece.h"
[email protected]542ce1a2013-08-29 14:25:4413#include "base/time/time.h"
[email protected]cc3cfaa2013-03-18 09:05:5214#include "cc/layers/content_layer.h"
15#include "cc/layers/nine_patch_layer.h"
16#include "cc/layers/solid_color_layer.h"
[email protected]3393fa92013-10-18 03:37:5217#include "cc/layers/texture_layer.h"
18#include "cc/resources/texture_mailbox.h"
[email protected]ed9b489a2012-11-28 22:01:4019#include "cc/test/fake_content_layer_client.h"
[email protected]542ce1a2013-08-29 14:25:4420#include "cc/test/lap_timer.h"
[email protected]f8fef2bd2013-02-04 23:39:2221#include "cc/test/layer_tree_json_parser.h"
[email protected]e216fef02013-03-20 22:56:1022#include "cc/test/layer_tree_test.h"
[email protected]1b901a32012-12-07 08:52:0323#include "cc/test/paths.h"
[email protected]d993e032013-06-07 00:16:1624#include "cc/trees/layer_tree_impl.h"
[email protected]ab1555a2013-09-04 02:16:1625#include "testing/perf/perf_test.h"
[email protected]ed9b489a2012-11-28 22:01:4026
27namespace cc {
28namespace {
29
[email protected]91cd7482012-11-30 05:51:4530static const int kTimeLimitMillis = 2000;
[email protected]f8fef2bd2013-02-04 23:39:2231static const int kWarmupRuns = 5;
32static const int kTimeCheckInterval = 10;
[email protected]ed9b489a2012-11-28 22:01:4033
[email protected]e216fef02013-03-20 22:56:1034class LayerTreeHostPerfTest : public LayerTreeTest {
[email protected]ed9b489a2012-11-28 22:01:4035 public:
[email protected]91cd7482012-11-30 05:51:4536 LayerTreeHostPerfTest()
[email protected]542ce1a2013-08-29 14:25:4437 : draw_timer_(kWarmupRuns,
38 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
39 kTimeCheckInterval),
40 commit_timer_(0, base::TimeDelta(), 1),
[email protected]a49d0f8a2013-05-09 23:26:1941 full_damage_each_frame_(false),
42 animation_driven_drawing_(false),
43 measure_commit_cost_(false) {
[email protected]2384c8a2013-03-21 08:35:0444 fake_content_layer_client_.set_paint_all_opaque(true);
[email protected]ed9b489a2012-11-28 22:01:4045 }
46
[email protected]1673d6e2013-10-28 21:51:1747 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
48 settings->throttle_frame_production = false;
49 }
50
[email protected]e216fef02013-03-20 22:56:1051 virtual void BeginTest() OVERRIDE {
52 BuildTree();
53 PostSetNeedsCommitToMainThread();
[email protected]91cd7482012-11-30 05:51:4554 }
55
[email protected]a49d0f8a2013-05-09 23:26:1956 virtual void Animate(base::TimeTicks monotonic_time) OVERRIDE {
57 if (animation_driven_drawing_ && !TestEnded())
58 layer_tree_host()->SetNeedsAnimate();
59 }
60
61 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
62 if (measure_commit_cost_)
[email protected]542ce1a2013-08-29 14:25:4463 commit_timer_.Start();
[email protected]a49d0f8a2013-05-09 23:26:1964 }
65
66 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
[email protected]542ce1a2013-08-29 14:25:4467 if (measure_commit_cost_ && draw_timer_.IsWarmedUp()) {
68 commit_timer_.NextLap();
[email protected]d993e032013-06-07 00:16:1669 }
[email protected]a49d0f8a2013-05-09 23:26:1970 }
71
[email protected]e216fef02013-03-20 22:56:1072 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
[email protected]542ce1a2013-08-29 14:25:4473 if (TestEnded()) {
74 return;
75 }
76 draw_timer_.NextLap();
77 if (draw_timer_.HasTimeLimitExpired()) {
78 EndTest();
79 return;
[email protected]f8fef2bd2013-02-04 23:39:2280 }
[email protected]a49d0f8a2013-05-09 23:26:1981 if (!animation_driven_drawing_)
82 impl->SetNeedsRedraw();
[email protected]e0341352013-04-06 05:01:2083 if (full_damage_each_frame_)
84 impl->SetFullRootLayerDamage();
[email protected]91cd7482012-11-30 05:51:4585 }
86
[email protected]e216fef02013-03-20 22:56:1087 virtual void BuildTree() {}
[email protected]91cd7482012-11-30 05:51:4588
[email protected]e216fef02013-03-20 22:56:1089 virtual void AfterTest() OVERRIDE {
[email protected]ab1555a2013-09-04 02:16:1690 CHECK(!test_name_.empty()) << "Must SetTestName() before AfterTest().";
91 perf_test::PrintResult("layer_tree_host_frame_count", "", test_name_,
[email protected]01aba0d2013-09-14 05:04:1892 draw_timer_.NumLaps(), "frame_count", true);
[email protected]ab1555a2013-09-04 02:16:1693 perf_test::PrintResult("layer_tree_host_frame_time", "", test_name_,
94 1000 * draw_timer_.MsPerLap(), "us", true);
[email protected]a49d0f8a2013-05-09 23:26:1995 if (measure_commit_cost_) {
[email protected]ab1555a2013-09-04 02:16:1696 perf_test::PrintResult("layer_tree_host_commit_count", "", test_name_,
[email protected]01aba0d2013-09-14 05:04:1897 commit_timer_.NumLaps(), "commit_count", true);
[email protected]ab1555a2013-09-04 02:16:1698 perf_test::PrintResult("layer_tree_host_commit_time", "", test_name_,
99 1000 * commit_timer_.MsPerLap(), "us", true);
[email protected]a49d0f8a2013-05-09 23:26:19100 }
[email protected]ed9b489a2012-11-28 22:01:40101 }
102
[email protected]91cd7482012-11-30 05:51:45103 protected:
[email protected]542ce1a2013-08-29 14:25:44104 LapTimer draw_timer_;
105 LapTimer commit_timer_;
106
[email protected]91cd7482012-11-30 05:51:45107 std::string test_name_;
[email protected]f8fef2bd2013-02-04 23:39:22108 FakeContentLayerClient fake_content_layer_client_;
[email protected]e0341352013-04-06 05:01:20109 bool full_damage_each_frame_;
[email protected]a49d0f8a2013-05-09 23:26:19110 bool animation_driven_drawing_;
111
112 bool measure_commit_cost_;
[email protected]91cd7482012-11-30 05:51:45113};
114
[email protected]91cd7482012-11-30 05:51:45115
116class LayerTreeHostPerfTestJsonReader : public LayerTreeHostPerfTest {
117 public:
118 LayerTreeHostPerfTestJsonReader()
119 : LayerTreeHostPerfTest() {
120 }
121
[email protected]ab1555a2013-09-04 02:16:16122 void SetTestName(const std::string& name) {
[email protected]91cd7482012-11-30 05:51:45123 test_name_ = name;
[email protected]ab1555a2013-09-04 02:16:16124 }
125
126 void ReadTestFile(const std::string& name) {
[email protected]6d4b67a2013-02-10 04:49:30127 base::FilePath test_data_dir;
[email protected]009dc072012-12-16 20:32:13128 ASSERT_TRUE(PathService::Get(cc::DIR_TEST_DATA, &test_data_dir));
[email protected]6d4b67a2013-02-10 04:49:30129 base::FilePath json_file = test_data_dir.AppendASCII(name + ".json");
[email protected]82f84b92013-08-30 18:23:50130 ASSERT_TRUE(base::ReadFileToString(json_file, &json_));
[email protected]91cd7482012-11-30 05:51:45131 }
132
[email protected]e216fef02013-03-20 22:56:10133 virtual void BuildTree() OVERRIDE {
[email protected]91cd7482012-11-30 05:51:45134 gfx::Size viewport = gfx::Size(720, 1038);
[email protected]18ce59702013-04-09 04:58:40135 layer_tree_host()->SetViewportSize(viewport);
[email protected]f8fef2bd2013-02-04 23:39:22136 scoped_refptr<Layer> root = ParseTreeFromJson(json_,
137 &fake_content_layer_client_);
138 ASSERT_TRUE(root.get());
[email protected]e216fef02013-03-20 22:56:10139 layer_tree_host()->SetRootLayer(root);
[email protected]91cd7482012-11-30 05:51:45140 }
141
142 private:
[email protected]f8fef2bd2013-02-04 23:39:22143 std::string json_;
[email protected]91cd7482012-11-30 05:51:45144};
145
[email protected]f8fef2bd2013-02-04 23:39:22146// Simulates a tab switcher scene with two stacks of 10 tabs each.
147TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) {
[email protected]ab1555a2013-09-04 02:16:16148 SetTestName("10_10_single_thread");
[email protected]e216fef02013-03-20 22:56:10149 ReadTestFile("10_10_layer_tree");
[email protected]2a61ad52013-05-13 14:01:29150 RunTest(false, false, false);
[email protected]91cd7482012-11-30 05:51:45151}
[email protected]ed9b489a2012-11-28 22:01:40152
[email protected]c0f7a7f2013-10-15 21:33:56153TEST_F(LayerTreeHostPerfTestJsonReader, TenTenThreadedImplSide) {
154 SetTestName("10_10_threaded_impl_side");
155 ReadTestFile("10_10_layer_tree");
156 RunTestWithImplSidePainting();
157}
158
[email protected]e0341352013-04-06 05:01:20159// Simulates a tab switcher scene with two stacks of 10 tabs each.
160TEST_F(LayerTreeHostPerfTestJsonReader,
161 TenTenSingleThread_FullDamageEachFrame) {
162 full_damage_each_frame_ = true;
[email protected]ab1555a2013-09-04 02:16:16163 SetTestName("10_10_single_thread_full_damage_each_frame");
[email protected]e0341352013-04-06 05:01:20164 ReadTestFile("10_10_layer_tree");
[email protected]2a61ad52013-05-13 14:01:29165 RunTest(false, false, false);
[email protected]e0341352013-04-06 05:01:20166}
167
[email protected]c0f7a7f2013-10-15 21:33:56168TEST_F(LayerTreeHostPerfTestJsonReader,
169 TenTenThreadedImplSide_FullDamageEachFrame) {
170 full_damage_each_frame_ = true;
171 SetTestName("10_10_threaded_impl_side_full_damage_each_frame");
172 ReadTestFile("10_10_layer_tree");
173 RunTestWithImplSidePainting();
174}
175
[email protected]f4e25f92013-07-13 20:54:53176// Invalidates a leaf layer in the tree on the main thread after every commit.
177class LayerTreeHostPerfTestLeafInvalidates
178 : public LayerTreeHostPerfTestJsonReader {
179 public:
180 virtual void BuildTree() OVERRIDE {
181 LayerTreeHostPerfTestJsonReader::BuildTree();
182
183 // Find a leaf layer.
184 for (layer_to_invalidate_ = layer_tree_host()->root_layer();
185 layer_to_invalidate_->children().size();
186 layer_to_invalidate_ = layer_to_invalidate_->children()[0]) {}
187 }
188
189 virtual void DidCommitAndDrawFrame() OVERRIDE {
190 if (TestEnded())
191 return;
192
193 static bool flip = true;
194 layer_to_invalidate_->SetOpacity(flip ? 1.f : 0.5f);
195 flip = !flip;
196 }
197
198 protected:
199 Layer* layer_to_invalidate_;
200};
201
202// Simulates a tab switcher scene with two stacks of 10 tabs each. Invalidate a
203// property on a leaf layer in the tree every commit.
204TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenSingleThread) {
[email protected]ab1555a2013-09-04 02:16:16205 SetTestName("10_10_single_thread_leaf_invalidates");
[email protected]f4e25f92013-07-13 20:54:53206 ReadTestFile("10_10_layer_tree");
207 RunTest(false, false, false);
208}
209
[email protected]c0f7a7f2013-10-15 21:33:56210TEST_F(LayerTreeHostPerfTestLeafInvalidates, TenTenThreadedImplSide) {
211 SetTestName("10_10_threaded_impl_side_leaf_invalidates");
212 ReadTestFile("10_10_layer_tree");
213 RunTestWithImplSidePainting();
214}
215
[email protected]f8fef2bd2013-02-04 23:39:22216// Simulates main-thread scrolling on each frame.
217class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader {
218 public:
219 ScrollingLayerTreePerfTest()
220 : LayerTreeHostPerfTestJsonReader() {
221 }
222
[email protected]e216fef02013-03-20 22:56:10223 virtual void BuildTree() OVERRIDE {
224 LayerTreeHostPerfTestJsonReader::BuildTree();
225 scrollable_ = layer_tree_host()->root_layer()->children()[1];
[email protected]22898ed2013-06-01 04:52:30226 ASSERT_TRUE(scrollable_.get());
[email protected]f8fef2bd2013-02-04 23:39:22227 }
228
[email protected]e216fef02013-03-20 22:56:10229 virtual void Layout() OVERRIDE {
[email protected]f8fef2bd2013-02-04 23:39:22230 static const gfx::Vector2d delta = gfx::Vector2d(0, 10);
[email protected]7aba6662013-03-12 10:17:34231 scrollable_->SetScrollOffset(scrollable_->scroll_offset() + delta);
[email protected]f8fef2bd2013-02-04 23:39:22232 }
233
234 private:
[email protected]7aba6662013-03-12 10:17:34235 scoped_refptr<Layer> scrollable_;
[email protected]f8fef2bd2013-02-04 23:39:22236};
237
[email protected]c0f7a7f2013-10-15 21:33:56238TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageSingleThread) {
[email protected]ab1555a2013-09-04 02:16:16239 SetTestName("long_scrollable_page");
[email protected]e216fef02013-03-20 22:56:10240 ReadTestFile("long_scrollable_page");
[email protected]2a61ad52013-05-13 14:01:29241 RunTest(false, false, false);
[email protected]f8fef2bd2013-02-04 23:39:22242}
243
[email protected]c0f7a7f2013-10-15 21:33:56244TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageThreadedImplSide) {
245 SetTestName("long_scrollable_page_threaded_impl_side");
246 ReadTestFile("long_scrollable_page");
247 RunTestWithImplSidePainting();
248}
[email protected]a49d0f8a2013-05-09 23:26:19249
[email protected]3393fa92013-10-18 03:37:52250static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
251
252// Simulates main-thread scrolling on each frame.
253class BrowserCompositorInvalidateLayerTreePerfTest
254 : public LayerTreeHostPerfTestJsonReader {
255 public:
256 BrowserCompositorInvalidateLayerTreePerfTest()
257 : next_sync_point_(1) {
258 }
259
260 virtual void BuildTree() OVERRIDE {
261 LayerTreeHostPerfTestJsonReader::BuildTree();
262 tab_contents_ =
263 static_cast<TextureLayer*>(
264 layer_tree_host()->root_layer()->children()[0]->
265 children()[0]->
266 children()[0]->
267 children()[0].get());
268 ASSERT_TRUE(tab_contents_.get());
269 }
270
271 virtual void Layout() OVERRIDE {
272 gpu::Mailbox gpu_mailbox;
273 std::ostringstream name_stream;
274 name_stream << "name" << next_sync_point_;
275 const char* name = name_stream.str().c_str();
276 memcpy(gpu_mailbox.name, name, strlen(name) + 1);
277 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
278 base::Bind(&EmptyReleaseCallback));
279 TextureMailbox mailbox(gpu_mailbox, next_sync_point_);
280 next_sync_point_++;
281
282 tab_contents_->SetTextureMailbox(mailbox, callback.Pass());
283 }
284
285 private:
286 scoped_refptr<TextureLayer> tab_contents_;
287 unsigned next_sync_point_;
288};
289
290TEST_F(BrowserCompositorInvalidateLayerTreePerfTest, DenseBrowserUI) {
291 SetTestName("dense_layer_tree");
292 ReadTestFile("dense_layer_tree");
293 RunTestWithImplSidePainting();
294}
295
[email protected]a49d0f8a2013-05-09 23:26:19296// Simulates a page with several large, transformed and animated layers.
[email protected]c0f7a7f2013-10-15 21:33:56297TEST_F(LayerTreeHostPerfTestJsonReader, HeavyPageThreadedImplSide) {
[email protected]a49d0f8a2013-05-09 23:26:19298 animation_driven_drawing_ = true;
299 measure_commit_cost_ = true;
[email protected]ab1555a2013-09-04 02:16:16300 SetTestName("heavy_page");
[email protected]a49d0f8a2013-05-09 23:26:19301 ReadTestFile("heavy_layer_tree");
[email protected]2a61ad52013-05-13 14:01:29302 RunTestWithImplSidePainting();
[email protected]a49d0f8a2013-05-09 23:26:19303}
304
[email protected]c0f7a7f2013-10-15 21:33:56305class PageScaleImplSidePaintingPerfTest
306 : public LayerTreeHostPerfTestJsonReader {
[email protected]d993e032013-06-07 00:16:16307 public:
308 PageScaleImplSidePaintingPerfTest()
309 : max_scale_(16.f), min_scale_(1.f / max_scale_) {}
310
311 virtual void SetupTree() OVERRIDE {
312 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, min_scale_, max_scale_);
313 }
314
315 virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
316 float scale_delta) OVERRIDE {
317 float page_scale_factor = layer_tree_host()->page_scale_factor();
318 page_scale_factor *= scale_delta;
319 layer_tree_host()->SetPageScaleFactorAndLimits(
320 page_scale_factor, min_scale_, max_scale_);
321 }
322
323 virtual void AnimateLayers(LayerTreeHostImpl* host_impl,
324 base::TimeTicks monotonic_time) OVERRIDE {
325 if (!host_impl->pinch_gesture_active()) {
326 host_impl->PinchGestureBegin();
327 start_time_ = monotonic_time;
328 }
329 gfx::Point anchor(200, 200);
330
331 float seconds = (monotonic_time - start_time_).InSecondsF();
332
333 // Every half second, zoom from min scale to max scale.
334 float interval = 0.5f;
335
336 // Start time in the middle of the interval when zoom = 1.
337 seconds += interval / 2.f;
338
339 // Stack two ranges together to go up from min to max and down from
340 // max to min in the next so as not to have a zoom discrepancy.
341 float time_in_two_intervals = fmod(seconds, 2.f * interval) / interval;
342
343 // Map everything to go from min to max between 0 and 1.
344 float time_in_one_interval =
345 time_in_two_intervals > 1.f ? 2.f - time_in_two_intervals
346 : time_in_two_intervals;
347 // Normalize time to -1..1.
348 float normalized = 2.f * time_in_one_interval - 1.f;
[email protected]81d205442013-07-29 21:42:03349 float scale_factor = std::abs(normalized) * (max_scale_ - 1.f) + 1.f;
[email protected]d993e032013-06-07 00:16:16350 float total_scale = normalized < 0.f ? 1.f / scale_factor : scale_factor;
351
352 float desired_delta =
353 total_scale / host_impl->active_tree()->total_page_scale_factor();
354 host_impl->PinchGestureUpdate(desired_delta, anchor);
355 }
356
357 private:
358 float max_scale_;
359 float min_scale_;
360 base::TimeTicks start_time_;
361};
362
[email protected]0983f0652013-10-14 20:25:19363TEST_F(PageScaleImplSidePaintingPerfTest, HeavyPage) {
[email protected]d993e032013-06-07 00:16:16364 measure_commit_cost_ = true;
[email protected]ab1555a2013-09-04 02:16:16365 SetTestName("heavy_page_page_scale");
[email protected]d993e032013-06-07 00:16:16366 ReadTestFile("heavy_layer_tree");
367 RunTestWithImplSidePainting();
368}
369
[email protected]ed9b489a2012-11-28 22:01:40370} // namespace
371} // namespace cc