1// Copyright 2013 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/debug/lap_timer.h"
6#include "cc/resources/picture_layer_tiling.h"
7#include "cc/resources/resource_provider.h"
8#include "cc/resources/scoped_resource.h"
9#include "cc/test/fake_output_surface.h"
10#include "cc/test/fake_output_surface_client.h"
11#include "cc/test/fake_picture_layer_tiling_client.h"
12#include "cc/test/test_context_provider.h"
13#include "cc/test/test_shared_bitmap_manager.h"
14
15#include "testing/gtest/include/gtest/gtest.h"
16#include "testing/perf/perf_test.h"
17
18namespace cc {
19
20namespace {
21
22static const int kTimeLimitMillis = 2000;
23static const int kWarmupRuns = 5;
24static const int kTimeCheckInterval = 10;
25
26class PictureLayerTilingPerfTest : public testing::Test {
27 public:
28  PictureLayerTilingPerfTest()
29      : timer_(kWarmupRuns,
30               base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
31               kTimeCheckInterval),
32        context_provider_(TestContextProvider::Create()) {
33    output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
34    CHECK(output_surface_->BindToClient(&output_surface_client_));
35
36    shared_bitmap_manager_.reset(new TestSharedBitmapManager());
37    resource_provider_ = ResourceProvider::Create(output_surface_.get(),
38                                                  shared_bitmap_manager_.get(),
39                                                  NULL,
40                                                  0,
41                                                  false,
42                                                  1,
43                                                  false).Pass();
44  }
45
46  virtual void SetUp() OVERRIDE {
47    picture_layer_tiling_client_.SetTileSize(gfx::Size(256, 256));
48    picture_layer_tiling_client_.set_max_tiles_for_interest_area(250);
49    picture_layer_tiling_client_.set_tree(PENDING_TREE);
50    picture_layer_tiling_ = PictureLayerTiling::Create(
51        1, gfx::Size(256 * 50, 256 * 50), &picture_layer_tiling_client_);
52    picture_layer_tiling_->CreateAllTilesForTesting();
53  }
54
55  virtual void TearDown() OVERRIDE {
56    picture_layer_tiling_.reset(NULL);
57  }
58
59  void RunInvalidateTest(const std::string& test_name, const Region& region) {
60    timer_.Reset();
61    do {
62      picture_layer_tiling_->UpdateTilesToCurrentPile(
63          region, picture_layer_tiling_->tiling_size());
64      timer_.NextLap();
65    } while (!timer_.HasTimeLimitExpired());
66
67    perf_test::PrintResult(
68        "invalidation", "", test_name, timer_.LapsPerSecond(), "runs/s", true);
69  }
70
71  void RunUpdateTilePrioritiesStationaryTest(const std::string& test_name,
72                                             const gfx::Transform& transform) {
73    gfx::Rect viewport_rect(0, 0, 1024, 768);
74
75    timer_.Reset();
76    do {
77      picture_layer_tiling_->UpdateTilePriorities(
78          PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion());
79      timer_.NextLap();
80    } while (!timer_.HasTimeLimitExpired());
81
82    perf_test::PrintResult("update_tile_priorities_stationary",
83                           "",
84                           test_name,
85                           timer_.LapsPerSecond(),
86                           "runs/s",
87                           true);
88  }
89
90  void RunUpdateTilePrioritiesScrollingTest(const std::string& test_name,
91                                            const gfx::Transform& transform) {
92    gfx::Size viewport_size(1024, 768);
93    gfx::Rect viewport_rect(viewport_size);
94    int xoffsets[] = {10, 0, -10, 0};
95    int yoffsets[] = {0, 10, 0, -10};
96    int offsetIndex = 0;
97    int offsetCount = 0;
98    const int maxOffsetCount = 1000;
99
100    timer_.Reset();
101    do {
102      picture_layer_tiling_->UpdateTilePriorities(
103          PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion());
104
105      viewport_rect = gfx::Rect(viewport_rect.x() + xoffsets[offsetIndex],
106                                viewport_rect.y() + yoffsets[offsetIndex],
107                                viewport_rect.width(),
108                                viewport_rect.height());
109
110      if (++offsetCount > maxOffsetCount) {
111        offsetCount = 0;
112        offsetIndex = (offsetIndex + 1) % 4;
113      }
114      timer_.NextLap();
115    } while (!timer_.HasTimeLimitExpired());
116
117    perf_test::PrintResult("update_tile_priorities_scrolling",
118                           "",
119                           test_name,
120                           timer_.LapsPerSecond(),
121                           "runs/s",
122                           true);
123  }
124
125  void RunRasterIteratorConstructTest(const std::string& test_name,
126                                      const gfx::Rect& viewport) {
127    gfx::Size bounds(viewport.size());
128    picture_layer_tiling_ =
129        PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
130    picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
131    picture_layer_tiling_->UpdateTilePriorities(
132        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
133
134    timer_.Reset();
135    do {
136      PictureLayerTiling::TilingRasterTileIterator it(
137          picture_layer_tiling_.get(), ACTIVE_TREE);
138      timer_.NextLap();
139    } while (!timer_.HasTimeLimitExpired());
140
141    perf_test::PrintResult("tiling_raster_tile_iterator_construct",
142                           "",
143                           test_name,
144                           timer_.LapsPerSecond(),
145                           "runs/s",
146                           true);
147  }
148
149  void RunRasterIteratorConstructAndIterateTest(const std::string& test_name,
150                                                int num_tiles,
151                                                const gfx::Rect& viewport) {
152    gfx::Size bounds(10000, 10000);
153    picture_layer_tiling_ =
154        PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
155    picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
156    picture_layer_tiling_->UpdateTilePriorities(
157        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
158
159    timer_.Reset();
160    do {
161      int count = num_tiles;
162      PictureLayerTiling::TilingRasterTileIterator it(
163          picture_layer_tiling_.get(), ACTIVE_TREE);
164      while (count--) {
165        ASSERT_TRUE(it) << "count: " << count;
166        ASSERT_TRUE(*it != NULL) << "count: " << count;
167        ++it;
168      }
169      timer_.NextLap();
170    } while (!timer_.HasTimeLimitExpired());
171
172    perf_test::PrintResult("tiling_raster_tile_iterator_construct_and_iterate",
173                           "",
174                           test_name,
175                           timer_.LapsPerSecond(),
176                           "runs/s",
177                           true);
178  }
179
180  void RunEvictionIteratorConstructTest(const std::string& test_name,
181                                        const gfx::Rect& viewport) {
182    gfx::Size bounds(viewport.size());
183    picture_layer_tiling_ =
184        PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
185    picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
186    picture_layer_tiling_->UpdateTilePriorities(
187        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
188
189    timer_.Reset();
190    TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
191                                 SMOOTHNESS_TAKES_PRIORITY,
192                                 NEW_CONTENT_TAKES_PRIORITY};
193    int priority_count = 0;
194    do {
195      PictureLayerTiling::TilingEvictionTileIterator it(
196          picture_layer_tiling_.get(),
197          priorities[priority_count],
198          PictureLayerTiling::NOW);
199      priority_count = (priority_count + 1) % arraysize(priorities);
200      timer_.NextLap();
201    } while (!timer_.HasTimeLimitExpired());
202
203    perf_test::PrintResult("tiling_eviction_tile_iterator_construct",
204                           "",
205                           test_name,
206                           timer_.LapsPerSecond(),
207                           "runs/s",
208                           true);
209  }
210
211  void RunEvictionIteratorConstructAndIterateTest(const std::string& test_name,
212                                                  int num_tiles,
213                                                  const gfx::Rect& viewport) {
214    gfx::Size bounds(10000, 10000);
215    picture_layer_tiling_ =
216        PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
217    picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
218    picture_layer_tiling_->UpdateTilePriorities(
219        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
220
221    TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
222                                 SMOOTHNESS_TAKES_PRIORITY,
223                                 NEW_CONTENT_TAKES_PRIORITY};
224
225    // Ensure all tiles have resources.
226    std::vector<Tile*> all_tiles = picture_layer_tiling_->AllTilesForTesting();
227    for (std::vector<Tile*>::iterator tile_it = all_tiles.begin();
228         tile_it != all_tiles.end();
229         ++tile_it) {
230      Tile* tile = *tile_it;
231      ManagedTileState::TileVersion& tile_version =
232          tile->GetTileVersionForTesting(tile->GetRasterModeForTesting());
233      tile_version.SetResourceForTesting(
234          ScopedResource::Create(resource_provider_.get()).Pass());
235    }
236
237    int priority_count = 0;
238    timer_.Reset();
239    do {
240      int count = num_tiles;
241      PictureLayerTiling::TilingEvictionTileIterator it(
242          picture_layer_tiling_.get(),
243          priorities[priority_count],
244          PictureLayerTiling::EVENTUALLY);
245      while (count--) {
246        ASSERT_TRUE(it) << "count: " << count;
247        ASSERT_TRUE(*it != NULL) << "count: " << count;
248        ++it;
249      }
250      priority_count = (priority_count + 1) % arraysize(priorities);
251      timer_.NextLap();
252    } while (!timer_.HasTimeLimitExpired());
253
254    // Remove all resources from tiles to make sure the tile version destructor
255    // doesn't complain.
256    for (std::vector<Tile*>::iterator tile_it = all_tiles.begin();
257         tile_it != all_tiles.end();
258         ++tile_it) {
259      Tile* tile = *tile_it;
260      ManagedTileState::TileVersion& tile_version =
261          tile->GetTileVersionForTesting(tile->GetRasterModeForTesting());
262      tile_version.SetResourceForTesting(scoped_ptr<ScopedResource>());
263    }
264
265    perf_test::PrintResult(
266        "tiling_eviction_tile_iterator_construct_and_iterate",
267        "",
268        test_name,
269        timer_.LapsPerSecond(),
270        "runs/s",
271        true);
272  }
273
274 private:
275  FakePictureLayerTilingClient picture_layer_tiling_client_;
276  scoped_ptr<PictureLayerTiling> picture_layer_tiling_;
277
278  LapTimer timer_;
279
280  scoped_refptr<ContextProvider> context_provider_;
281  FakeOutputSurfaceClient output_surface_client_;
282  scoped_ptr<FakeOutputSurface> output_surface_;
283  scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
284  scoped_ptr<ResourceProvider> resource_provider_;
285};
286
287TEST_F(PictureLayerTilingPerfTest, Invalidate) {
288  Region one_tile(gfx::Rect(256, 256));
289  RunInvalidateTest("1x1", one_tile);
290
291  Region half_region(gfx::Rect(25 * 256, 50 * 256));
292  RunInvalidateTest("25x50", half_region);
293
294  Region full_region(gfx::Rect(50 * 256, 50 * 256));
295  RunInvalidateTest("50x50", full_region);
296}
297
298#if defined(OS_ANDROID)
299// TODO(vmpstr): Investigate why this is noisy (crbug.com/310220).
300TEST_F(PictureLayerTilingPerfTest, DISABLED_UpdateTilePriorities) {
301#else
302TEST_F(PictureLayerTilingPerfTest, UpdateTilePriorities) {
303#endif  // defined(OS_ANDROID)
304  gfx::Transform transform;
305
306  RunUpdateTilePrioritiesStationaryTest("no_transform", transform);
307  RunUpdateTilePrioritiesScrollingTest("no_transform", transform);
308
309  transform.Rotate(10);
310  RunUpdateTilePrioritiesStationaryTest("rotation", transform);
311  RunUpdateTilePrioritiesScrollingTest("rotation", transform);
312
313  transform.ApplyPerspectiveDepth(10);
314  RunUpdateTilePrioritiesStationaryTest("perspective", transform);
315  RunUpdateTilePrioritiesScrollingTest("perspective", transform);
316}
317
318TEST_F(PictureLayerTilingPerfTest, TilingRasterTileIteratorConstruct) {
319  RunRasterIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
320  RunRasterIteratorConstructTest("50_0_100x100", gfx::Rect(50, 0, 100, 100));
321  RunRasterIteratorConstructTest("100_0_100x100", gfx::Rect(100, 0, 100, 100));
322  RunRasterIteratorConstructTest("150_0_100x100", gfx::Rect(150, 0, 100, 100));
323}
324
325TEST_F(PictureLayerTilingPerfTest,
326       TilingRasterTileIteratorConstructAndIterate) {
327  RunRasterIteratorConstructAndIterateTest(
328      "32_100x100", 32, gfx::Rect(0, 0, 100, 100));
329  RunRasterIteratorConstructAndIterateTest(
330      "32_500x500", 32, gfx::Rect(0, 0, 500, 500));
331  RunRasterIteratorConstructAndIterateTest(
332      "64_100x100", 64, gfx::Rect(0, 0, 100, 100));
333  RunRasterIteratorConstructAndIterateTest(
334      "64_500x500", 64, gfx::Rect(0, 0, 500, 500));
335}
336
337TEST_F(PictureLayerTilingPerfTest, TilingEvictionTileIteratorConstruct) {
338  RunEvictionIteratorConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
339  RunEvictionIteratorConstructTest("50_0_100x100", gfx::Rect(50, 0, 100, 100));
340  RunEvictionIteratorConstructTest("100_0_100x100",
341                                   gfx::Rect(100, 0, 100, 100));
342  RunEvictionIteratorConstructTest("150_0_100x100",
343                                   gfx::Rect(150, 0, 100, 100));
344}
345
346TEST_F(PictureLayerTilingPerfTest,
347       TilingEvictionTileIteratorConstructAndIterate) {
348  RunEvictionIteratorConstructAndIterateTest(
349      "32_100x100", 32, gfx::Rect(0, 0, 100, 100));
350  RunEvictionIteratorConstructAndIterateTest(
351      "32_500x500", 32, gfx::Rect(0, 0, 500, 500));
352  RunEvictionIteratorConstructAndIterateTest(
353      "64_100x100", 64, gfx::Rect(0, 0, 100, 100));
354  RunEvictionIteratorConstructAndIterateTest(
355      "64_500x500", 64, gfx::Rect(0, 0, 500, 500));
356}
357
358}  // namespace
359
360}  // namespace cc
361