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 Picture::RECORD_NORMALLY
,
64 &stats_instrumentation_
);
67 bool UpdateWholePile() { return Update(tiling_rect(), tiling_rect()); }
69 FakeContentLayerClient client_
;
70 FakeRenderingStatsInstrumentation stats_instrumentation_
;
71 scoped_refptr
<TestPicturePile
> pile_
;
72 SkColor background_color_
;
75 bool contents_opaque_
;
78 TEST_F(PicturePileTest
, SmallInvalidateInflated
) {
81 // Invalidate something inside a tile.
82 gfx::Rect
invalidate_rect(50, 50, 1, 1);
83 Update(invalidate_rect
, tiling_rect());
85 EXPECT_EQ(1, pile_
->tiling().num_tiles_x());
86 EXPECT_EQ(1, pile_
->tiling().num_tiles_y());
88 TestPicturePile::PictureInfo
& picture_info
=
89 pile_
->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second
;
90 // We should have a picture.
91 EXPECT_TRUE(!!picture_info
.GetPicture());
92 gfx::Rect picture_rect
= gfx::ScaleToEnclosedRect(
93 picture_info
.GetPicture()->LayerRect(), min_scale_
);
95 // The the picture should be large enough that scaling it never makes a rect
96 // smaller than 1 px wide or tall.
97 EXPECT_FALSE(picture_rect
.IsEmpty()) << "Picture rect " <<
98 picture_rect
.ToString();
101 TEST_F(PicturePileTest
, LargeInvalidateInflated
) {
104 // Invalidate something inside a tile.
105 gfx::Rect
invalidate_rect(50, 50, 100, 100);
106 Update(invalidate_rect
, tiling_rect());
108 EXPECT_EQ(1, pile_
->tiling().num_tiles_x());
109 EXPECT_EQ(1, pile_
->tiling().num_tiles_y());
111 TestPicturePile::PictureInfo
& picture_info
=
112 pile_
->picture_map().find(TestPicturePile::PictureMapKey(0, 0))->second
;
113 EXPECT_TRUE(!!picture_info
.GetPicture());
115 int expected_inflation
= pile_
->buffer_pixels();
117 Picture
* base_picture
= picture_info
.GetPicture();
118 gfx::Rect base_picture_rect
= pile_
->tiling_rect();
119 base_picture_rect
.Inset(-expected_inflation
, -expected_inflation
);
120 EXPECT_EQ(base_picture_rect
.ToString(),
121 base_picture
->LayerRect().ToString());
124 TEST_F(PicturePileTest
, InvalidateOnTileBoundaryInflated
) {
125 gfx::Rect new_tiling_rect
=
126 gfx::ToEnclosedRect(gfx::ScaleRect(pile_
->tiling_rect(), 2.f
));
127 pile_
->SetTilingRect(new_tiling_rect
);
129 // Due to border pixels, we should have 3 tiles.
130 EXPECT_EQ(3, pile_
->tiling().num_tiles_x());
131 EXPECT_EQ(3, pile_
->tiling().num_tiles_y());
133 // We should have 1/.125 - 1 = 7 border pixels.
134 EXPECT_EQ(7, pile_
->buffer_pixels());
135 EXPECT_EQ(7, pile_
->tiling().border_texels());
137 // Update the whole layer to create initial pictures.
140 // Invalidate everything again to have a non zero invalidation
144 // Invalidate something just over a tile boundary by a single pixel.
145 // This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
146 gfx::Rect
invalidate_rect(
147 pile_
->tiling().TileBoundsWithBorder(0, 0).right(),
148 pile_
->tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
151 Update(invalidate_rect
, tiling_rect());
153 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
154 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
155 TestPicturePile::PictureInfo
& picture_info
=
157 .find(TestPicturePile::PictureMapKey(i
, j
))
160 // Expect (1, 1) and (1, 0) to be invalidated once more
161 // than the rest of the tiles.
162 if (i
== 1 && (j
== 0 || j
== 1)) {
164 2.0f
/ TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED
,
165 picture_info
.GetInvalidationFrequencyForTesting());
168 1.0f
/ TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED
,
169 picture_info
.GetInvalidationFrequencyForTesting());
175 TEST_F(PicturePileTest
, StopRecordingOffscreenInvalidations
) {
176 gfx::Rect new_tiling_rect
=
177 gfx::ToEnclosedRect(gfx::ScaleRect(pile_
->tiling_rect(), 4.f
));
178 pile_
->SetTilingRect(new_tiling_rect
);
181 tiling_rect().x(), tiling_rect().y(), tiling_rect().width(), 1);
183 // Update the whole pile until the invalidation frequency is high.
184 for (int frame
= 0; frame
< 33; ++frame
) {
188 // Make sure we have a high invalidation frequency.
189 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
190 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
191 TestPicturePile::PictureInfo
& picture_info
=
193 .find(TestPicturePile::PictureMapKey(i
, j
))
195 EXPECT_FLOAT_EQ(1.0f
, picture_info
.GetInvalidationFrequencyForTesting())
196 << "i " << i
<< " j " << j
;
200 // Update once more with a small viewport tiilng_rect.x(), tiilng_rect.y(),
201 // tiling_rect.width() by 1
202 Update(tiling_rect(), viewport
);
204 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
205 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
206 TestPicturePile::PictureInfo
& picture_info
=
208 .find(TestPicturePile::PictureMapKey(i
, j
))
210 EXPECT_FLOAT_EQ(1.0f
, picture_info
.GetInvalidationFrequencyForTesting());
212 // If the y far enough away we expect to find no picture (no re-recording
213 // happened). For close y, the picture should change.
215 EXPECT_FALSE(picture_info
.GetPicture()) << "i " << i
<< " j " << j
;
217 EXPECT_TRUE(picture_info
.GetPicture()) << "i " << i
<< " j " << j
;
221 // Now update with no invalidation and full viewport
222 Update(gfx::Rect(), tiling_rect());
224 for (int i
= 0; i
< pile_
->tiling().num_tiles_x(); ++i
) {
225 for (int j
= 0; j
< pile_
->tiling().num_tiles_y(); ++j
) {
226 TestPicturePile::PictureInfo
& picture_info
=
228 .find(TestPicturePile::PictureMapKey(i
, j
))
230 // Expect the invalidation frequency to be less than 1, since we just
231 // updated with no invalidations.
232 float expected_frequency
=
234 1.0f
/ TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED
;
236 EXPECT_FLOAT_EQ(expected_frequency
,
237 picture_info
.GetInvalidationFrequencyForTesting());
239 // We expect that there are pictures everywhere now.
240 EXPECT_TRUE(picture_info
.GetPicture()) << "i " << i
<< " j " << j
;
245 TEST_F(PicturePileTest
, ClearingInvalidatesRecordedRect
) {
248 gfx::Rect
rect(0, 0, 5, 5);
249 EXPECT_TRUE(pile_
->CanRasterLayerRect(rect
));
250 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(rect
));
254 // Make sure both the cache-aware check (using recorded region) and the normal
255 // check are both false after clearing.
256 EXPECT_FALSE(pile_
->CanRasterLayerRect(rect
));
257 EXPECT_FALSE(pile_
->CanRasterSlowTileCheck(rect
));
260 TEST_F(PicturePileTest
, FrequentInvalidationCanRaster
) {
261 // This test makes sure that if part of the page is frequently invalidated
262 // and doesn't get re-recorded, then CanRaster is not true for any
263 // tiles touching it, but is true for adjacent tiles, even if it
264 // overlaps on borders (edge case).
265 gfx::Rect new_tiling_rect
=
266 gfx::ToEnclosedRect(gfx::ScaleRect(pile_
->tiling_rect(), 4.f
));
267 pile_
->SetTilingRect(new_tiling_rect
);
269 gfx::Rect tile01_borders
= pile_
->tiling().TileBoundsWithBorder(0, 1);
270 gfx::Rect tile02_borders
= pile_
->tiling().TileBoundsWithBorder(0, 2);
271 gfx::Rect tile01_noborders
= pile_
->tiling().TileBounds(0, 1);
272 gfx::Rect tile02_noborders
= pile_
->tiling().TileBounds(0, 2);
274 // Sanity check these two tiles are overlapping with borders, since this is
275 // what the test is trying to repro.
276 EXPECT_TRUE(tile01_borders
.Intersects(tile02_borders
));
277 EXPECT_FALSE(tile01_noborders
.Intersects(tile02_noborders
));
279 EXPECT_TRUE(pile_
->CanRasterLayerRect(tile01_noborders
));
280 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(tile01_noborders
));
281 EXPECT_TRUE(pile_
->CanRasterLayerRect(tile02_noborders
));
282 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(tile02_noborders
));
283 // Sanity check that an initial paint goes down the fast path of having
284 // a valid recorded viewport.
285 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
287 // Update the whole layer until the invalidation frequency is high.
288 for (int frame
= 0; frame
< 33; ++frame
) {
292 // Update once more with a small viewport.
293 gfx::Rect
viewport(0, 0, tiling_rect().width(), 1);
294 Update(tiling_rect(), viewport
);
296 // Sanity check some pictures exist and others don't.
297 EXPECT_TRUE(pile_
->picture_map()
298 .find(TestPicturePile::PictureMapKey(0, 1))
299 ->second
.GetPicture());
300 EXPECT_FALSE(pile_
->picture_map()
301 .find(TestPicturePile::PictureMapKey(0, 2))
302 ->second
.GetPicture());
304 EXPECT_TRUE(pile_
->CanRasterLayerRect(tile01_noborders
));
305 EXPECT_TRUE(pile_
->CanRasterSlowTileCheck(tile01_noborders
));
306 EXPECT_FALSE(pile_
->CanRasterLayerRect(tile02_noborders
));
307 EXPECT_FALSE(pile_
->CanRasterSlowTileCheck(tile02_noborders
));
310 TEST_F(PicturePileTest
, NoInvalidationValidViewport
) {
311 // This test validates that the recorded_viewport cache of full tiles
312 // is still valid for some use cases. If it's not, it's a performance
313 // issue because CanRaster checks will go down the slow path.
315 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
317 // No invalidation, same viewport.
318 Update(gfx::Rect(), tiling_rect());
319 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
321 // Partial invalidation, same viewport.
322 Update(gfx::Rect(gfx::Rect(0, 0, 1, 1)), tiling_rect());
323 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());
325 // No invalidation, changing viewport.
326 Update(gfx::Rect(), gfx::Rect(5, 5, 5, 5));
327 EXPECT_TRUE(!pile_
->recorded_viewport().IsEmpty());