Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / cc / trees / layer_tree_host_perftest.cc
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   RunTest(false, false, false);
246 }
247
248 TEST_F(ScrollingLayerTreePerfTest, LongScrollablePageThreadedImplSide) {
249   SetTestName("long_scrollable_page_threaded_impl_side");
250   ReadTestFile("long_scrollable_page");
251   RunTestWithImplSidePainting();
252 }
253
254 static void EmptyReleaseCallback(uint32 sync_point, bool lost_resource) {}
255
256 // Simulates main-thread scrolling on each frame.
257 class BrowserCompositorInvalidateLayerTreePerfTest
258     : public LayerTreeHostPerfTestJsonReader {
259  public:
260   BrowserCompositorInvalidateLayerTreePerfTest()
261       : LayerTreeHostPerfTestJsonReader(),
262         next_sync_point_(1),
263         clean_up_started_(false) {}
264
265   void BuildTree() override {
266     LayerTreeHostPerfTestJsonReader::BuildTree();
267     tab_contents_ =
268         static_cast<TextureLayer*>(
269             layer_tree_host()->root_layer()->children()[0]->
270                                              children()[0]->
271                                              children()[0]->
272                                              children()[0].get());
273     ASSERT_TRUE(tab_contents_.get());
274   }
275
276   void WillCommit() override {
277     if (CleanUpStarted())
278       return;
279     gpu::Mailbox gpu_mailbox;
280     std::ostringstream name_stream;
281     name_stream << "name" << next_sync_point_;
282     gpu_mailbox.SetName(
283         reinterpret_cast<const int8*>(name_stream.str().c_str()));
284     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
285         base::Bind(&EmptyReleaseCallback));
286     TextureMailbox mailbox(gpu_mailbox, GL_TEXTURE_2D, next_sync_point_);
287     next_sync_point_++;
288
289     tab_contents_->SetTextureMailbox(mailbox, callback.Pass());
290   }
291
292   void DidCommit() override {
293     if (CleanUpStarted())
294       return;
295     layer_tree_host()->SetNeedsCommit();
296   }
297
298   void CleanUpAndEndTest(LayerTreeHostImpl* host_impl) override {
299     clean_up_started_ = true;
300     MainThreadTaskRunner()->PostTask(
301         FROM_HERE,
302         base::Bind(&BrowserCompositorInvalidateLayerTreePerfTest::
303                         CleanUpAndEndTestOnMainThread,
304                    base::Unretained(this)));
305   }
306
307   void CleanUpAndEndTestOnMainThread() {
308     tab_contents_->SetTextureMailbox(TextureMailbox(), nullptr);
309     EndTest();
310   }
311
312   bool CleanUpStarted() override { return clean_up_started_; }
313
314  private:
315   scoped_refptr<TextureLayer> tab_contents_;
316   unsigned next_sync_point_;
317   bool clean_up_started_;
318 };
319
320 TEST_F(BrowserCompositorInvalidateLayerTreePerfTest, DenseBrowserUI) {
321   measure_commit_cost_ = true;
322   SetTestName("dense_layer_tree");
323   ReadTestFile("dense_layer_tree");
324   RunTestWithImplSidePainting();
325 }
326
327 // Simulates a page with several large, transformed and animated layers.
328 TEST_F(LayerTreeHostPerfTestJsonReader, HeavyPageThreadedImplSide) {
329   begin_frame_driven_drawing_ = true;
330   measure_commit_cost_ = true;
331   SetTestName("heavy_page");
332   ReadTestFile("heavy_layer_tree");
333   RunTestWithImplSidePainting();
334 }
335
336 }  // namespace
337 }  // namespace cc