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/resources/picture_layer_tiling_set.h"
6
7#include <map>
8#include <vector>
9
10#include "cc/resources/resource_pool.h"
11#include "cc/resources/resource_provider.h"
12#include "cc/test/fake_output_surface.h"
13#include "cc/test/fake_output_surface_client.h"
14#include "cc/test/fake_picture_layer_tiling_client.h"
15#include "cc/test/fake_tile_manager_client.h"
16#include "cc/test/test_shared_bitmap_manager.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "ui/gfx/size_conversions.h"
19
20namespace cc {
21namespace {
22
23TEST(PictureLayerTilingSetTest, NoResources) {
24  FakePictureLayerTilingClient client;
25  gfx::Size layer_bounds(1000, 800);
26  PictureLayerTilingSet set(&client, layer_bounds);
27  client.SetTileSize(gfx::Size(256, 256));
28
29  set.AddTiling(1.0);
30  set.AddTiling(1.5);
31  set.AddTiling(2.0);
32
33  float contents_scale = 2.0;
34  gfx::Size content_bounds(
35      gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
36  gfx::Rect content_rect(content_bounds);
37
38  Region remaining(content_rect);
39  PictureLayerTilingSet::CoverageIterator iter(
40      &set,
41      contents_scale,
42      content_rect,
43      contents_scale);
44  for (; iter; ++iter) {
45    gfx::Rect geometry_rect = iter.geometry_rect();
46    EXPECT_TRUE(content_rect.Contains(geometry_rect));
47    ASSERT_TRUE(remaining.Contains(geometry_rect));
48    remaining.Subtract(geometry_rect);
49
50    // No tiles have resources, so no iter represents a real tile.
51    EXPECT_FALSE(*iter);
52  }
53  EXPECT_TRUE(remaining.IsEmpty());
54}
55
56class PictureLayerTilingSetTestWithResources : public testing::Test {
57 public:
58  void runTest(
59      int num_tilings,
60      float min_scale,
61      float scale_increment,
62      float ideal_contents_scale,
63      float expected_scale) {
64    FakeOutputSurfaceClient output_surface_client;
65    scoped_ptr<FakeOutputSurface> output_surface =
66        FakeOutputSurface::Create3d();
67    CHECK(output_surface->BindToClient(&output_surface_client));
68
69    scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
70        new TestSharedBitmapManager());
71    scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
72        output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false);
73
74    FakePictureLayerTilingClient client(resource_provider.get());
75    client.SetTileSize(gfx::Size(256, 256));
76    gfx::Size layer_bounds(1000, 800);
77    PictureLayerTilingSet set(&client, layer_bounds);
78
79    float scale = min_scale;
80    for (int i = 0; i < num_tilings; ++i, scale += scale_increment) {
81      PictureLayerTiling* tiling = set.AddTiling(scale);
82      tiling->CreateAllTilesForTesting();
83      std::vector<Tile*> tiles = tiling->AllTilesForTesting();
84      client.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
85    }
86
87    float max_contents_scale = scale;
88    gfx::Size content_bounds(
89        gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, max_contents_scale)));
90    gfx::Rect content_rect(content_bounds);
91
92    Region remaining(content_rect);
93    PictureLayerTilingSet::CoverageIterator iter(
94        &set,
95        max_contents_scale,
96        content_rect,
97        ideal_contents_scale);
98    for (; iter; ++iter) {
99      gfx::Rect geometry_rect = iter.geometry_rect();
100      EXPECT_TRUE(content_rect.Contains(geometry_rect));
101      ASSERT_TRUE(remaining.Contains(geometry_rect));
102      remaining.Subtract(geometry_rect);
103
104      float scale = iter.CurrentTiling()->contents_scale();
105      EXPECT_EQ(expected_scale, scale);
106
107      if (num_tilings)
108        EXPECT_TRUE(*iter);
109      else
110        EXPECT_FALSE(*iter);
111    }
112    EXPECT_TRUE(remaining.IsEmpty());
113  }
114};
115
116TEST_F(PictureLayerTilingSetTestWithResources, NoTilings) {
117  runTest(0, 0.f, 0.f, 2.f, 0.f);
118}
119TEST_F(PictureLayerTilingSetTestWithResources, OneTiling_Smaller) {
120  runTest(1, 1.f, 0.f, 2.f, 1.f);
121}
122TEST_F(PictureLayerTilingSetTestWithResources, OneTiling_Larger) {
123  runTest(1, 3.f, 0.f, 2.f, 3.f);
124}
125TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_Smaller) {
126  runTest(2, 1.f, 1.f, 3.f, 2.f);
127}
128
129TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_SmallerEqual) {
130  runTest(2, 1.f, 1.f, 2.f, 2.f);
131}
132
133TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_LargerEqual) {
134  runTest(2, 1.f, 1.f, 1.f, 1.f);
135}
136
137TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_Larger) {
138  runTest(2, 2.f, 8.f, 1.f, 2.f);
139}
140
141TEST_F(PictureLayerTilingSetTestWithResources, ManyTilings_Equal) {
142  runTest(10, 1.f, 1.f, 5.f, 5.f);
143}
144
145TEST_F(PictureLayerTilingSetTestWithResources, ManyTilings_NotEqual) {
146  runTest(10, 1.f, 1.f, 4.5f, 5.f);
147}
148
149class PictureLayerTilingSetSyncTest : public testing::Test {
150 public:
151  PictureLayerTilingSetSyncTest()
152      : tile_size_(gfx::Size(10, 10)),
153        source_bounds_(gfx::Size(30, 20)),
154        target_bounds_(gfx::Size(30, 30)) {
155    source_client_.SetTileSize(tile_size_);
156    target_client_.SetTileSize(tile_size_);
157    source_.reset(new PictureLayerTilingSet(&source_client_, source_bounds_));
158    target_.reset(new PictureLayerTilingSet(&target_client_, target_bounds_));
159  }
160
161  // Sync from source to target.
162  void SyncTilings(const gfx::Size& new_bounds,
163                   const Region& invalidation,
164                   float minimum_scale) {
165    for (size_t i = 0; i < source_->num_tilings(); ++i)
166      source_->tiling_at(i)->CreateAllTilesForTesting();
167    for (size_t i = 0; i < target_->num_tilings(); ++i)
168      target_->tiling_at(i)->CreateAllTilesForTesting();
169
170    target_->SyncTilings(
171        *source_.get(), new_bounds, invalidation, minimum_scale);
172  }
173  void SyncTilings(const gfx::Size& new_bounds) {
174    Region invalidation;
175    SyncTilings(new_bounds, invalidation, 0.f);
176  }
177  void SyncTilings(const gfx::Size& new_bounds, const Region& invalidation) {
178    SyncTilings(new_bounds, invalidation, 0.f);
179  }
180  void SyncTilings(const gfx::Size& new_bounds, float minimum_scale) {
181    Region invalidation;
182    SyncTilings(new_bounds, invalidation, minimum_scale);
183  }
184
185  void VerifyTargetEqualsSource(const gfx::Size& new_bounds) const {
186    ASSERT_FALSE(new_bounds.IsEmpty());
187    EXPECT_EQ(target_->num_tilings(), source_->num_tilings());
188    EXPECT_EQ(target_->layer_bounds().ToString(), new_bounds.ToString());
189
190    for (size_t i = 0; i < target_->num_tilings(); ++i) {
191      ASSERT_GT(source_->num_tilings(), i);
192      const PictureLayerTiling* source_tiling = source_->tiling_at(i);
193      const PictureLayerTiling* target_tiling = target_->tiling_at(i);
194      EXPECT_EQ(target_tiling->layer_bounds().ToString(),
195                new_bounds.ToString());
196      EXPECT_EQ(source_tiling->contents_scale(),
197                target_tiling->contents_scale());
198    }
199
200    EXPECT_EQ(source_->client(), &source_client_);
201    EXPECT_EQ(target_->client(), &target_client_);
202    ValidateTargetTilingSet();
203  }
204
205  void ValidateTargetTilingSet() const {
206    // Tilings should be sorted largest to smallest.
207    if (target_->num_tilings() > 0) {
208      float last_scale = target_->tiling_at(0)->contents_scale();
209      for (size_t i = 1; i < target_->num_tilings(); ++i) {
210        const PictureLayerTiling* target_tiling = target_->tiling_at(i);
211        EXPECT_LT(target_tiling->contents_scale(), last_scale);
212        last_scale = target_tiling->contents_scale();
213      }
214    }
215
216    for (size_t i = 0; i < target_->num_tilings(); ++i)
217      ValidateTiling(target_->tiling_at(i), target_client_.pile());
218  }
219
220  void ValidateTiling(const PictureLayerTiling* tiling,
221                      const PicturePileImpl* pile) const {
222    if (tiling->TilingRect().IsEmpty())
223      EXPECT_TRUE(tiling->live_tiles_rect().IsEmpty());
224    else if (!tiling->live_tiles_rect().IsEmpty())
225      EXPECT_TRUE(tiling->TilingRect().Contains(tiling->live_tiles_rect()));
226
227    std::vector<Tile*> tiles = tiling->AllTilesForTesting();
228    for (size_t i = 0; i < tiles.size(); ++i) {
229      const Tile* tile = tiles[i];
230      ASSERT_TRUE(!!tile);
231      EXPECT_EQ(tile->picture_pile(), pile);
232      EXPECT_TRUE(tile->content_rect().Intersects(tiling->live_tiles_rect()))
233          << "All tiles must be inside the live tiles rect.";
234    }
235
236    for (PictureLayerTiling::CoverageIterator iter(
237             tiling, tiling->contents_scale(), tiling->live_tiles_rect());
238         iter;
239         ++iter) {
240      EXPECT_TRUE(*iter) << "The live tiles rect must be full.";
241    }
242  }
243
244  gfx::Size tile_size_;
245
246  FakePictureLayerTilingClient source_client_;
247  gfx::Size source_bounds_;
248  scoped_ptr<PictureLayerTilingSet> source_;
249
250  FakePictureLayerTilingClient target_client_;
251  gfx::Size target_bounds_;
252  scoped_ptr<PictureLayerTilingSet> target_;
253};
254
255TEST_F(PictureLayerTilingSetSyncTest, EmptyBounds) {
256  float source_scales[] = {1.f, 1.2f};
257  for (size_t i = 0; i < arraysize(source_scales); ++i)
258    source_->AddTiling(source_scales[i]);
259
260  gfx::Size new_bounds;
261  SyncTilings(new_bounds);
262  EXPECT_EQ(target_->num_tilings(), 0u);
263  EXPECT_EQ(target_->layer_bounds().ToString(), new_bounds.ToString());
264}
265
266TEST_F(PictureLayerTilingSetSyncTest, AllNew) {
267  float source_scales[] = {0.5f, 1.f, 1.2f};
268  for (size_t i = 0; i < arraysize(source_scales); ++i)
269    source_->AddTiling(source_scales[i]);
270  float target_scales[] = {0.75f, 1.4f, 3.f};
271  for (size_t i = 0; i < arraysize(target_scales); ++i)
272    target_->AddTiling(target_scales[i]);
273
274  gfx::Size new_bounds(15, 40);
275  SyncTilings(new_bounds);
276  VerifyTargetEqualsSource(new_bounds);
277}
278
279Tile* FindTileAtOrigin(PictureLayerTiling* tiling) {
280  std::vector<Tile*> tiles = tiling->AllTilesForTesting();
281  for (size_t i = 0; i < tiles.size(); ++i) {
282    if (tiles[i]->content_rect().origin() == gfx::Point())
283      return tiles[i];
284  }
285  return NULL;
286}
287
288TEST_F(PictureLayerTilingSetSyncTest, KeepExisting) {
289  float source_scales[] = {0.7f, 1.f, 1.1f, 2.f};
290  for (size_t i = 0; i < arraysize(source_scales); ++i)
291    source_->AddTiling(source_scales[i]);
292  float target_scales[] = {0.5f, 1.f, 2.f};
293  for (size_t i = 0; i < arraysize(target_scales); ++i)
294    target_->AddTiling(target_scales[i]);
295
296  PictureLayerTiling* tiling1 = source_->TilingAtScale(1.f);
297  ASSERT_TRUE(tiling1);
298  tiling1->CreateAllTilesForTesting();
299  EXPECT_EQ(tiling1->contents_scale(), 1.f);
300  Tile* tile1 = FindTileAtOrigin(tiling1);
301  ASSERT_TRUE(tile1);
302
303  PictureLayerTiling* tiling2 = source_->TilingAtScale(2.f);
304  tiling2->CreateAllTilesForTesting();
305  ASSERT_TRUE(tiling2);
306  EXPECT_EQ(tiling2->contents_scale(), 2.f);
307  Tile* tile2 = FindTileAtOrigin(tiling2);
308  ASSERT_TRUE(tile2);
309
310  gfx::Size new_bounds(15, 40);
311  SyncTilings(new_bounds);
312  VerifyTargetEqualsSource(new_bounds);
313
314  EXPECT_EQ(tiling1, source_->TilingAtScale(1.f));
315  EXPECT_EQ(tile1, FindTileAtOrigin(tiling1));
316  EXPECT_FALSE(tiling1->live_tiles_rect().IsEmpty());
317
318  EXPECT_EQ(tiling2, source_->TilingAtScale(2.f));
319  EXPECT_EQ(tile2, FindTileAtOrigin(tiling2));
320  EXPECT_FALSE(tiling2->live_tiles_rect().IsEmpty());
321}
322
323TEST_F(PictureLayerTilingSetSyncTest, EmptySet) {
324  float target_scales[] = {0.2f, 1.f};
325  for (size_t i = 0; i < arraysize(target_scales); ++i)
326    target_->AddTiling(target_scales[i]);
327
328  gfx::Size new_bounds(15, 40);
329  SyncTilings(new_bounds);
330  VerifyTargetEqualsSource(new_bounds);
331}
332
333TEST_F(PictureLayerTilingSetSyncTest, MinimumScale) {
334  float source_scales[] = {0.7f, 1.f, 1.1f, 2.f};
335  for (size_t i = 0; i < arraysize(source_scales); ++i)
336    source_->AddTiling(source_scales[i]);
337  float target_scales[] = {0.5f, 0.7f, 1.f, 1.1f, 2.f};
338  for (size_t i = 0; i < arraysize(target_scales); ++i)
339    target_->AddTiling(target_scales[i]);
340
341  gfx::Size new_bounds(15, 40);
342  float minimum_scale = 1.5f;
343  SyncTilings(new_bounds, minimum_scale);
344
345  EXPECT_EQ(target_->num_tilings(), 1u);
346  EXPECT_EQ(target_->tiling_at(0)->contents_scale(), 2.f);
347  ValidateTargetTilingSet();
348}
349
350TEST_F(PictureLayerTilingSetSyncTest, Invalidation) {
351  source_->AddTiling(2.f);
352  target_->AddTiling(2.f);
353  target_->tiling_at(0)->CreateAllTilesForTesting();
354
355  Region layer_invalidation;
356  layer_invalidation.Union(gfx::Rect(0, 0, 1, 1));
357  layer_invalidation.Union(gfx::Rect(0, 15, 1, 1));
358  // Out of bounds layer_invalidation.
359  layer_invalidation.Union(gfx::Rect(100, 100, 1, 1));
360
361  Region content_invalidation;
362  for (Region::Iterator iter(layer_invalidation); iter.has_rect();
363       iter.next()) {
364    gfx::Rect content_rect = gfx::ScaleToEnclosingRect(iter.rect(), 2.f);
365    content_invalidation.Union(content_rect);
366  }
367
368  std::vector<Tile*> old_tiles = target_->tiling_at(0)->AllTilesForTesting();
369  std::map<gfx::Point, scoped_refptr<Tile> > old_tile_map;
370  for (size_t i = 0; i < old_tiles.size(); ++i)
371    old_tile_map[old_tiles[i]->content_rect().origin()] = old_tiles[i];
372
373  SyncTilings(target_bounds_, layer_invalidation);
374  VerifyTargetEqualsSource(target_bounds_);
375
376  std::vector<Tile*> new_tiles = target_->tiling_at(0)->AllTilesForTesting();
377  for (size_t i = 0; i < new_tiles.size(); ++i) {
378    const Tile* tile = new_tiles[i];
379    std::map<gfx::Point, scoped_refptr<Tile> >::iterator find =
380        old_tile_map.find(tile->content_rect().origin());
381    if (content_invalidation.Intersects(tile->content_rect()))
382      EXPECT_NE(tile, find->second.get());
383    else
384      EXPECT_EQ(tile, find->second.get());
385  }
386}
387
388TEST_F(PictureLayerTilingSetSyncTest, TileSizeChange) {
389  source_->AddTiling(1.f);
390  target_->AddTiling(1.f);
391
392  target_->tiling_at(0)->CreateAllTilesForTesting();
393  std::vector<Tile*> original_tiles =
394      target_->tiling_at(0)->AllTilesForTesting();
395  EXPECT_GT(original_tiles.size(), 0u);
396  gfx::Size new_tile_size(100, 100);
397  target_client_.SetTileSize(new_tile_size);
398  EXPECT_NE(target_->tiling_at(0)->tile_size().ToString(),
399            new_tile_size.ToString());
400
401  gfx::Size new_bounds(15, 40);
402  SyncTilings(new_bounds);
403  VerifyTargetEqualsSource(new_bounds);
404
405  EXPECT_EQ(target_->tiling_at(0)->tile_size().ToString(),
406            new_tile_size.ToString());
407
408  // All old tiles should not be present in new tiles.
409  std::vector<Tile*> new_tiles = target_->tiling_at(0)->AllTilesForTesting();
410  for (size_t i = 0; i < original_tiles.size(); ++i) {
411    std::vector<Tile*>::iterator find =
412        std::find(new_tiles.begin(), new_tiles.end(), original_tiles[i]);
413    EXPECT_TRUE(find == new_tiles.end());
414  }
415}
416
417}  // namespace
418}  // namespace cc
419