Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / cc / resources / picture_pile_unittest.cc
blob04b4c3383f463b4024abf16b4a5f589a3b8a8ef9
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.
5 #include <map>
6 #include <utility>
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"
15 namespace cc {
16 namespace {
18 class TestPicturePile : public PicturePile {
19 public:
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;
35 protected:
36 virtual ~TestPicturePile() {}
39 class PicturePileTest : public testing::Test {
40 public:
41 PicturePileTest()
42 : pile_(new TestPicturePile()),
43 background_color_(SK_ColorBLUE),
44 min_scale_(0.125),
45 frame_number_(0),
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) {
55 frame_number_++;
56 return pile_->Update(&client_,
57 background_color_,
58 contents_opaque_,
59 false,
60 invalidation,
61 visible_layer_rect,
62 frame_number_,
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_;
72 float min_scale_;
73 int frame_number_;
74 bool contents_opaque_;
77 TEST_F(PicturePileTest, SmallInvalidateInflated) {
78 UpdateWholePile();
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) {
101 UpdateWholePile();
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.
137 UpdateWholePile();
139 // Invalidate everything again to have a non zero invalidation
140 // frequency.
141 UpdateWholePile();
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,
149 50);
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 =
155 pile_->picture_map()
156 .find(TestPicturePile::PictureMapKey(i, j))
157 ->second;
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)) {
162 EXPECT_FLOAT_EQ(
163 2.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
164 picture_info.GetInvalidationFrequencyForTesting());
165 } else {
166 EXPECT_FLOAT_EQ(
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);
179 gfx::Rect viewport(
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) {
184 UpdateWholePile();
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 =
191 pile_->picture_map()
192 .find(TestPicturePile::PictureMapKey(i, j))
193 ->second;
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 =
206 pile_->picture_map()
207 .find(TestPicturePile::PictureMapKey(i, j))
208 ->second;
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.
213 if (j >= 2)
214 EXPECT_FALSE(picture_info.GetPicture()) << "i " << i << " j " << j;
215 else
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 =
226 pile_->picture_map()
227 .find(TestPicturePile::PictureMapKey(i, j))
228 ->second;
229 // Expect the invalidation frequency to be less than 1, since we just
230 // updated with no invalidations.
231 float expected_frequency =
232 1.0f -
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) {
245 UpdateWholePile();
247 gfx::Rect rect(0, 0, 5, 5);
248 EXPECT_TRUE(pile_->CanRasterLayerRect(rect));
249 EXPECT_TRUE(pile_->CanRasterSlowTileCheck(rect));
251 pile_->Clear();
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));
277 UpdateWholePile();
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) {
288 UpdateWholePile();
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.
313 UpdateWholePile();
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());
329 } // namespace
330 } // namespace cc