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.
8 #include "cc/resources/picture_pile.h"
9 #include "cc/test/fake_content_layer_client.h"
10 #include "cc/test/fake_rendering_stats_instrumentation.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/rect_conversions.h"
13 #include "ui/gfx/size_conversions.h"
18 class TestPicturePile
: public PicturePile
{
20 using PicturePile::buffer_pixels
;
21 using PicturePile::CanRasterSlowTileCheck
;
22 using PicturePile::Clear
;
24 PictureMap
& picture_map() { return picture_map_
; }
25 const gfx::Rect
& recorded_viewport() const { return recorded_viewport_
; }
27 bool CanRasterLayerRect(const gfx::Rect
& layer_rect
) {
28 return CanRaster(1.f
, layer_rect
);
31 typedef PicturePile::PictureInfo PictureInfo
;
32 typedef PicturePile::PictureMapKey PictureMapKey
;
33 typedef PicturePile::PictureMap PictureMap
;
36 virtual ~TestPicturePile() {}
39 class PicturePileTest
: public testing::Test
{
42 : pile_(new TestPicturePile()),
43 background_color_(SK_ColorBLUE
),
46 contents_opaque_(false) {
47 pile_
->SetTilingRect(gfx::Rect(pile_
->tiling().max_texture_size()));
48 pile_
->SetTileGridSize(gfx::Size(1000, 1000));
49 pile_
->SetMinContentsScale(min_scale_
);
52 gfx::Rect
tiling_rect() const { return pile_
->tiling_rect(); }
54 bool Update(const Region
& invalidation
, const gfx::Rect
& visible_layer_rect
) {
56 return pile_
->Update(&client_
,
63 &stats_instrumentation_
);
66 bool UpdateWholePile() { return Update(tiling_rect(), tiling_rect()); }
68 FakeContentLayerClient client_
;
69 FakeRenderingStatsInstrumentation stats_instrumentation_
;
70 scoped_refptr
<TestPicturePile
> pile_
;
71 SkColor background_color_
;
74 bool contents_opaque_
;
77 TEST_F(PicturePileTest
, SmallInvalidateInflated
) {
80 // Invalidate something inside a tile.
81 gfx::Rect
invalidate_rect(50, 50, 1, 1);
82 Update(invalidate_rect
, tiling_rect());
84 EXPECT_EQ(1, pile_
->tiling().num_tiles_x());
85 EXPECT_EQ(1, pile_
->tiling().num_tiles_y());
87 TestPicturePile::PictureInfo
& picture_info
=
88 pile_
->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second
;
89 // We should have a picture.
90 EXPECT_TRUE(!!picture_info
.GetPicture());
91 gfx::Rect picture_rect
= gfx::ScaleToEnclosedRect(
92 picture_info
.GetPicture()->LayerRect(), min_scale_
);
94 // The the picture should be large enough that scaling it never makes a rect
95 // smaller than 1 px wide or tall.
96 EXPECT_FALSE(picture_rect
.IsEmpty()) << "Picture rect " <<
97 picture_rect
.ToString();
100 TEST_F(PicturePileTest
, LargeInvalidateInflated
) {
103 // Invalidate something inside a tile.
104 gfx::Rect
invalidate_rect(50, 50, 100, 100);
105 Update(invalidate_rect
, tiling_rect());
107 EXPECT_EQ(1, pile_
->tiling().num_tiles_x());
108 EXPECT_EQ(1, pile_
->tiling().num_tiles_y());
110 TestPicturePile::PictureInfo
& picture_info
=
111 pile_
->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second
;
112 EXPECT_TRUE(!!picture_info
.GetPicture());
114 int expected_inflation
= pile_
->buffer_pixels();
116 Picture
* base_picture
= picture_info
.GetPicture();
117 gfx::Rect base_picture_rect
= pile_
->tiling_rect();
118 base_picture_rect
.Inset(-expected_inflation
, -expected_inflation
);
119 EXPECT_EQ(base_picture_rect
.ToString(),
120 base_picture
->LayerRect().ToString());
123 TEST_F(PicturePileTest
, InvalidateOnTileBoundaryInflated
) {
124 gfx::Rect new_tiling_rect
=
125 gfx::ToEnclosedRect(gfx::ScaleRect(pile_
->tiling_rect(), 2.f
));
126 pile_
->SetTilingRect(new_tiling_rect
);
128 // Due to border pixels, we should have 3 tiles.
129 EXPECT_EQ(3, pile_
->tiling().num_tiles_x());
130 EXPECT_EQ(3, pile_
->tiling().num_tiles_y());
132 // We should have 1/.125 - 1 = 7 border pixels.
133 EXPECT_EQ(7, pile_
->buffer_pixels());
134 EXPECT_EQ(7, pile_
->tiling().border_texels());
136 // Update the whole layer to create initial pictures.
139 // Invalidate everything again to have a non zero invalidation
143 // Invalidate something just over a tile boundary by a single pixel.
144 // This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
145 gfx::Rect
invalidate_rect(
146 pile_
->tiling().TileBoundsWithBorder(0, 0).right(),
147 pile_
->tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
150 Update(invalidate_rect
, tiling_rect());
152 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
153 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
154 TestPicturePile::PictureInfo
& picture_info
=
156 .find(TestPicturePile::PictureMapKey(i
, j
))
159 // Expect (1, 1) and (1, 0) to be invalidated once more
160 // than the rest of the tiles.
161 if (i
== 1 && (j
== 0 || j
== 1)) {
163 2.0f
/ TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED
,
164 picture_info
.GetInvalidationFrequencyForTesting());
167 1.0f
/ TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED
,
168 picture_info
.GetInvalidationFrequencyForTesting());
174 TEST_F(PicturePileTest
, StopRecordingOffscreenInvalidations
) {
175 gfx::Rect new_tiling_rect
=
176 gfx::ToEnclosedRect(gfx::ScaleRect(pile_
->tiling_rect(), 4.f
));
177 pile_
->SetTilingRect(new_tiling_rect
);
180 tiling_rect().x(), tiling_rect().y(), tiling_rect().width(), 1);
182 // Update the whole pile until the invalidation frequency is high.
183 for (int frame
= 0; frame
< 33; ++frame
) {
187 // Make sure we have a high invalidation frequency.
188 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
189 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
190 TestPicturePile::PictureInfo
& picture_info
=
192 .find(TestPicturePile::PictureMapKey(i
, j
))
194 EXPECT_FLOAT_EQ(1.0f
, picture_info
.GetInvalidationFrequencyForTesting())
195 << "i " << i
<< " j " << j
;
199 // Update once more with a small viewport tiilng_rect.x(), tiilng_rect.y(),
200 // tiling_rect.width() by 1
201 Update(tiling_rect(), viewport
);
203 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
204 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
205 TestPicturePile::PictureInfo
& picture_info
=
207 .find(TestPicturePile::PictureMapKey(i
, j
))
209 EXPECT_FLOAT_EQ(1.0f
, picture_info
.GetInvalidationFrequencyForTesting());
211 // If the y far enough away we expect to find no picture (no re-recording
212 // happened). For close y, the picture should change.
214 EXPECT_FALSE(picture_info
.GetPicture()) << "i " << i
<< " j " << j
;
216 EXPECT_TRUE(picture_info
.GetPicture()) << "i " << i
<< " j " << j
;
220 // Now update with no invalidation and full viewport
221 Update(gfx::Rect(), tiling_rect());
223 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
224 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
225 TestPicturePile::PictureInfo
& picture_info
=
227 .find(TestPicturePile::PictureMapKey(i
, j
))
229 // Expect the invalidation frequency to be less than 1, since we just
230 // updated with no invalidations.
231 float expected_frequency
=
233 1.0f
/ TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED
;
235 EXPECT_FLOAT_EQ(expected_frequency
,
236 picture_info
.GetInvalidationFrequencyForTesting());
238 // We expect that there are pictures everywhere now.
239 EXPECT_TRUE(picture_info
.GetPicture()) << "i " << i
<< " j " << j
;
244 TEST_F(PicturePileTest
, ClearingInvalidatesRecordedRect
) {
247 gfx::Rect
rect(0, 0, 5, 5);
248 EXPECT_TRUE(pile_
->CanRasterLayerRect(rect
));
249 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(rect
));
253 // Make sure both the cache-aware check (using recorded region) and the normal
254 // check are both false after clearing.
255 EXPECT_FALSE(pile_
->CanRasterLayerRect(rect
));
256 EXPECT_FALSE(pile_
->CanRasterSlowTileCheck(rect
));
259 TEST_F(PicturePileTest
, FrequentInvalidationCanRaster
) {
260 // This test makes sure that if part of the page is frequently invalidated
261 // and doesn't get re-recorded, then CanRaster is not true for any
262 // tiles touching it, but is true for adjacent tiles, even if it
263 // overlaps on borders (edge case).
264 gfx::Rect new_tiling_rect
=
265 gfx::ToEnclosedRect(gfx::ScaleRect(pile_
->tiling_rect(), 4.f
));
266 pile_
->SetTilingRect(new_tiling_rect
);
268 gfx::Rect tile01_borders
= pile_
->tiling().TileBoundsWithBorder(0, 1);
269 gfx::Rect tile02_borders
= pile_
->tiling().TileBoundsWithBorder(0, 2);
270 gfx::Rect tile01_noborders
= pile_
->tiling().TileBounds(0, 1);
271 gfx::Rect tile02_noborders
= pile_
->tiling().TileBounds(0, 2);
273 // Sanity check these two tiles are overlapping with borders, since this is
274 // what the test is trying to repro.
275 EXPECT_TRUE(tile01_borders
.Intersects(tile02_borders
));
276 EXPECT_FALSE(tile01_noborders
.Intersects(tile02_noborders
));
278 EXPECT_TRUE(pile_
->CanRasterLayerRect(tile01_noborders
));
279 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(tile01_noborders
));
280 EXPECT_TRUE(pile_
->CanRasterLayerRect(tile02_noborders
));
281 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(tile02_noborders
));
282 // Sanity check that an initial paint goes down the fast path of having
283 // a valid recorded viewport.
284 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
286 // Update the whole layer until the invalidation frequency is high.
287 for (int frame
= 0; frame
< 33; ++frame
) {
291 // Update once more with a small viewport.
292 gfx::Rect
viewport(0, 0, tiling_rect().width(), 1);
293 Update(tiling_rect(), viewport
);
295 // Sanity check some pictures exist and others don't.
296 EXPECT_TRUE(pile_
->picture_map()
297 .find(TestPicturePile::PictureMapKey(0, 1))
298 ->second
.GetPicture());
299 EXPECT_FALSE(pile_
->picture_map()
300 .find(TestPicturePile::PictureMapKey(0, 2))
301 ->second
.GetPicture());
303 EXPECT_TRUE(pile_
->CanRasterLayerRect(tile01_noborders
));
304 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(tile01_noborders
));
305 EXPECT_FALSE(pile_
->CanRasterLayerRect(tile02_noborders
));
306 EXPECT_FALSE(pile_
->CanRasterSlowTileCheck(tile02_noborders
));
309 TEST_F(PicturePileTest
, NoInvalidationValidViewport
) {
310 // This test validates that the recorded_viewport cache of full tiles
311 // is still valid for some use cases. If it's not, it's a performance
312 // issue because CanRaster checks will go down the slow path.
314 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
316 // No invalidation, same viewport.
317 Update(gfx::Rect(), tiling_rect());
318 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
320 // Partial invalidation, same viewport.
321 Update(gfx::Rect(gfx::Rect(0, 0, 1, 1)), tiling_rect());
322 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
324 // No invalidation, changing viewport.
325 Update(gfx::Rect(), gfx::Rect(5, 5, 5, 5));
326 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());