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/resources/picture_pile.h"
6#include "cc/test/fake_content_layer_client.h"
7#include "cc/test/fake_rendering_stats_instrumentation.h"
8#include "testing/gtest/include/gtest/gtest.h"
9#include "ui/gfx/rect_conversions.h"
10#include "ui/gfx/size_conversions.h"
11
12namespace cc {
13namespace {
14
15class TestPicturePile : public PicturePile {
16 public:
17  using PicturePile::buffer_pixels;
18
19  PictureListMap& picture_list_map() { return picture_list_map_; }
20
21  typedef PicturePile::PictureList PictureList;
22  typedef PicturePile::PictureListMapKey PictureListMapKey;
23  typedef PicturePile::PictureListMap PictureListMap;
24
25 protected:
26    virtual ~TestPicturePile() {}
27};
28
29TEST(PicturePileTest, SmallInvalidateInflated) {
30  FakeContentLayerClient client;
31  FakeRenderingStatsInstrumentation stats_instrumentation;
32  scoped_refptr<TestPicturePile> pile = new TestPicturePile;
33  SkColor background_color = SK_ColorBLUE;
34
35  float min_scale = 0.125;
36  gfx::Size base_picture_size = pile->tiling().max_texture_size();
37
38  gfx::Size layer_size = base_picture_size;
39  pile->Resize(layer_size);
40  pile->SetTileGridSize(gfx::Size(1000, 1000));
41  pile->SetMinContentsScale(min_scale);
42
43  // Update the whole layer.
44  pile->Update(&client,
45               background_color,
46               false,
47               gfx::Rect(layer_size),
48               gfx::Rect(layer_size),
49               &stats_instrumentation);
50
51  // Invalidate something inside a tile.
52  gfx::Rect invalidate_rect(50, 50, 1, 1);
53  pile->Update(&client,
54               background_color,
55               false,
56               invalidate_rect,
57               gfx::Rect(layer_size),
58               &stats_instrumentation);
59
60  EXPECT_EQ(1, pile->tiling().num_tiles_x());
61  EXPECT_EQ(1, pile->tiling().num_tiles_y());
62
63  TestPicturePile::PictureList& picture_list =
64      pile->picture_list_map().find(
65          TestPicturePile::PictureListMapKey(0, 0))->second;
66  EXPECT_EQ(2u, picture_list.size());
67  for (TestPicturePile::PictureList::iterator it = picture_list.begin();
68       it != picture_list.end();
69       ++it) {
70    scoped_refptr<Picture> picture = *it;
71    gfx::Rect picture_rect =
72        gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale);
73
74    // The invalidation in each tile should have been made large enough
75    // that scaling it never makes a rect smaller than 1 px wide or tall.
76    EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " <<
77        picture_rect.ToString();
78  }
79}
80
81TEST(PicturePileTest, LargeInvalidateInflated) {
82  FakeContentLayerClient client;
83  FakeRenderingStatsInstrumentation stats_instrumentation;
84  scoped_refptr<TestPicturePile> pile = new TestPicturePile;
85  SkColor background_color = SK_ColorBLUE;
86
87  float min_scale = 0.125;
88  gfx::Size base_picture_size = pile->tiling().max_texture_size();
89
90  gfx::Size layer_size = base_picture_size;
91  pile->Resize(layer_size);
92  pile->SetTileGridSize(gfx::Size(1000, 1000));
93  pile->SetMinContentsScale(min_scale);
94
95  // Update the whole layer.
96  pile->Update(&client,
97               background_color,
98               false,
99               gfx::Rect(layer_size),
100               gfx::Rect(layer_size),
101               &stats_instrumentation);
102
103  // Invalidate something inside a tile.
104  gfx::Rect invalidate_rect(50, 50, 100, 100);
105  pile->Update(&client,
106               background_color,
107               false,
108               invalidate_rect,
109               gfx::Rect(layer_size),
110               &stats_instrumentation);
111
112  EXPECT_EQ(1, pile->tiling().num_tiles_x());
113  EXPECT_EQ(1, pile->tiling().num_tiles_y());
114
115  TestPicturePile::PictureList& picture_list =
116      pile->picture_list_map().find(
117          TestPicturePile::PictureListMapKey(0, 0))->second;
118  EXPECT_EQ(2u, picture_list.size());
119
120  int expected_inflation = pile->buffer_pixels();
121
122  scoped_refptr<Picture> base_picture = *picture_list.begin();
123  gfx::Rect base_picture_rect(layer_size);
124  base_picture_rect.Inset(-expected_inflation, -expected_inflation);
125  EXPECT_EQ(base_picture_rect.ToString(),
126            base_picture->LayerRect().ToString());
127
128  scoped_refptr<Picture> picture = *(++picture_list.begin());
129  gfx::Rect picture_rect(invalidate_rect);
130  picture_rect.Inset(-expected_inflation, -expected_inflation);
131  EXPECT_EQ(picture_rect.ToString(),
132            picture->LayerRect().ToString());
133}
134
135TEST(PicturePileTest, InvalidateOnTileBoundaryInflated) {
136  FakeContentLayerClient client;
137  FakeRenderingStatsInstrumentation stats_instrumentation;
138  scoped_refptr<TestPicturePile> pile = new TestPicturePile;
139  SkColor background_color = SK_ColorBLUE;
140
141  float min_scale = 0.125;
142  gfx::Size base_picture_size = pile->tiling().max_texture_size();
143
144  gfx::Size layer_size =
145      gfx::ToFlooredSize(gfx::ScaleSize(base_picture_size, 2.f));
146  pile->Resize(layer_size);
147  pile->SetTileGridSize(gfx::Size(1000, 1000));
148  pile->SetMinContentsScale(min_scale);
149
150  // Due to border pixels, we should have 3 tiles.
151  EXPECT_EQ(3, pile->tiling().num_tiles_x());
152  EXPECT_EQ(3, pile->tiling().num_tiles_y());
153
154  // We should have 1/.125 - 1 = 7 border pixels.
155  EXPECT_EQ(7, pile->buffer_pixels());
156  EXPECT_EQ(7, pile->tiling().border_texels());
157
158  // Update the whole layer.
159  pile->Update(&client,
160               background_color,
161               false,
162               gfx::Rect(layer_size),
163               gfx::Rect(layer_size),
164               &stats_instrumentation);
165
166  // Invalidate something just over a tile boundary by a single pixel.
167  // This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
168  gfx::Rect invalidate_rect(
169      pile->tiling().TileBoundsWithBorder(0, 0).right(),
170      pile->tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
171      50,
172      50);
173  pile->Update(&client,
174               background_color,
175               false,
176               invalidate_rect,
177               gfx::Rect(layer_size),
178               &stats_instrumentation);
179
180  for (int i = 0; i < pile->tiling().num_tiles_x(); ++i) {
181    for (int j = 0; j < pile->tiling().num_tiles_y(); ++j) {
182      // (1, 0) and (1, 1) should be invalidated partially.
183      bool expect_invalidated = i == 1 && (j == 0 || j == 1);
184
185      TestPicturePile::PictureList& picture_list =
186          pile->picture_list_map().find(
187              TestPicturePile::PictureListMapKey(i, j))->second;
188      if (!expect_invalidated) {
189        EXPECT_EQ(1u, picture_list.size()) << "For i,j " << i << "," << j;
190        continue;
191      }
192
193      EXPECT_EQ(2u, picture_list.size()) << "For i,j " << i << "," << j;
194      for (TestPicturePile::PictureList::iterator it = picture_list.begin();
195           it != picture_list.end();
196           ++it) {
197        scoped_refptr<Picture> picture = *it;
198        gfx::Rect picture_rect =
199            gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale);
200
201        // The invalidation in each tile should have been made large enough
202        // that scaling it never makes a rect smaller than 1 px wide or tall.
203        EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " <<
204            picture_rect.ToString();
205      }
206    }
207  }
208}
209
210}  // namespace
211}  // namespace cc
212