Invalidate scans when the host volume is unmounted.
[chromium-blink-merge.git] / cc / resources / picture_pile_unittest.cc
blob98ce3b18a07f40afabd326db98d466123fdf514f
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_picture_pile.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/geometry/rect_conversions.h"
13 #include "ui/gfx/geometry/size_conversions.h"
15 namespace cc {
16 namespace {
18 class PicturePileTestBase {
19 public:
20 PicturePileTestBase() : min_scale_(0.125), frame_number_(0) {}
22 void InitializeData() {
23 pile_.SetTileGridSize(gfx::Size(1000, 1000));
24 pile_.SetMinContentsScale(min_scale_);
25 client_ = FakeContentLayerClient();
26 SetTilingSize(pile_.tiling().max_texture_size());
29 void SetTilingSize(const gfx::Size& tiling_size) {
30 Region invalidation;
31 gfx::Rect viewport_rect(tiling_size);
32 UpdateAndExpandInvalidation(&invalidation, tiling_size, viewport_rect);
35 gfx::Size tiling_size() const { return pile_.GetSize(); }
36 gfx::Rect tiling_rect() const { return gfx::Rect(pile_.GetSize()); }
38 bool UpdateAndExpandInvalidation(Region* invalidation,
39 const gfx::Size& layer_size,
40 const gfx::Rect& visible_layer_rect) {
41 frame_number_++;
42 return pile_.UpdateAndExpandInvalidation(
43 &client_, invalidation, false, layer_size, visible_layer_rect,
44 frame_number_, Picture::RECORD_NORMALLY);
47 bool UpdateWholePile() {
48 Region invalidation = tiling_rect();
49 bool result = UpdateAndExpandInvalidation(&invalidation, tiling_size(),
50 tiling_rect());
51 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
52 return result;
55 FakeContentLayerClient client_;
56 FakePicturePile pile_;
57 float min_scale_;
58 int frame_number_;
61 class PicturePileTest : public PicturePileTestBase, public testing::Test {
62 public:
63 void SetUp() override { InitializeData(); }
66 TEST_F(PicturePileTest, InvalidationOnTileBorderOutsideInterestRect) {
67 // Don't expand the interest rect past what we invalidate.
68 pile_.SetPixelRecordDistance(0);
70 gfx::Size tile_size(100, 100);
71 pile_.tiling().SetMaxTextureSize(tile_size);
73 gfx::Size pile_size(400, 400);
74 SetTilingSize(pile_size);
76 // We have multiple tiles.
77 EXPECT_GT(pile_.tiling().num_tiles_x(), 2);
78 EXPECT_GT(pile_.tiling().num_tiles_y(), 2);
80 // Record everything.
81 Region invalidation(tiling_rect());
82 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
84 // +----------+-----------------+-----------+
85 // | | VVVV 1,0| |
86 // | | VVVV | |
87 // | | VVVV | |
88 // | ...|.................|... |
89 // | ...|.................|... |
90 // +----------+-----------------+-----------+
91 // | ...| |... |
92 // | ...| |... |
93 // | ...| |... |
94 // | ...| |... |
95 // | ...| 1,1|... |
96 // +----------+-----------------+-----------+
97 // | ...|.................|... |
98 // | ...|.................|... |
99 // +----------+-----------------+-----------+
101 // .. = border pixels for tile 1,1
102 // VV = interest rect (what we will record)
104 // The first invalidation is inside VV, so it does not touch border pixels of
105 // tile 1,1.
107 // The second invalidation goes below VV into the .. border pixels of 1,1.
109 // This is the VV interest rect which will be entirely inside 1,0 and not
110 // touch the border of 1,1.
111 gfx::Rect interest_rect(
112 pile_.tiling().TilePositionX(1) + pile_.tiling().border_texels(),
115 pile_.tiling().TileSizeY(0) - pile_.tiling().border_texels());
117 // Invalidate tile 1,0 only. This is a rect that avoids the borders of any
118 // other tiles.
119 gfx::Rect invalidate_tile = interest_rect;
120 // This should cause the tile 1,0 to be invalidated and re-recorded. The
121 // invalidation did not need to be expanded.
122 invalidation = invalidate_tile;
123 UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
124 EXPECT_EQ(invalidate_tile, invalidation);
126 // Invalidate tile 1,0 and 1,1 by invalidating something that only touches the
127 // border of 1,1 (and is inside the tile bounds of 1,0). This is a 10px wide
128 // strip from the top of the tiling onto the border pixels of tile 1,1 that
129 // avoids border pixels of any other tiles.
130 gfx::Rect invalidate_border = interest_rect;
131 invalidate_border.Inset(0, 0, 0, -1);
132 // This should cause the tile 1,0 and 1,1 to be invalidated. The 1,1 tile will
133 // not be re-recorded since it does not touch the interest rect, so the
134 // invalidation should be expanded to cover all of 1,1.
135 invalidation = invalidate_border;
136 UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
137 Region expected_invalidation = invalidate_border;
138 expected_invalidation.Union(pile_.tiling().TileBounds(1, 1));
139 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
142 TEST_F(PicturePileTest, SmallInvalidateInflated) {
143 // Invalidate something inside a tile.
144 Region invalidate_rect(gfx::Rect(50, 50, 1, 1));
145 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
146 EXPECT_EQ(gfx::Rect(50, 50, 1, 1).ToString(), invalidate_rect.ToString());
148 EXPECT_EQ(1, pile_.tiling().num_tiles_x());
149 EXPECT_EQ(1, pile_.tiling().num_tiles_y());
151 FakePicturePile::PictureInfo& picture_info =
152 pile_.picture_map().find(FakePicturePile::PictureMapKey(0, 0))->second;
153 // We should have a picture.
154 EXPECT_TRUE(!!picture_info.GetPicture());
155 gfx::Rect picture_rect = gfx::ScaleToEnclosedRect(
156 picture_info.GetPicture()->LayerRect(), min_scale_);
158 // The the picture should be large enough that scaling it never makes a rect
159 // smaller than 1 px wide or tall.
160 EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " <<
161 picture_rect.ToString();
164 TEST_F(PicturePileTest, LargeInvalidateInflated) {
165 // Invalidate something inside a tile.
166 Region invalidate_rect(gfx::Rect(50, 50, 100, 100));
167 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
168 EXPECT_EQ(gfx::Rect(50, 50, 100, 100).ToString(), invalidate_rect.ToString());
170 EXPECT_EQ(1, pile_.tiling().num_tiles_x());
171 EXPECT_EQ(1, pile_.tiling().num_tiles_y());
173 FakePicturePile::PictureInfo& picture_info =
174 pile_.picture_map().find(FakePicturePile::PictureMapKey(0, 0))->second;
175 EXPECT_TRUE(!!picture_info.GetPicture());
177 int expected_inflation = pile_.buffer_pixels();
179 const Picture* base_picture = picture_info.GetPicture();
180 gfx::Rect base_picture_rect(tiling_size());
181 base_picture_rect.Inset(-expected_inflation, -expected_inflation);
182 EXPECT_EQ(base_picture_rect.ToString(),
183 base_picture->LayerRect().ToString());
186 TEST_F(PicturePileTest, InvalidateOnTileBoundaryInflated) {
187 gfx::Size new_tiling_size =
188 gfx::ToCeiledSize(gfx::ScaleSize(tiling_size(), 2.f));
189 // This creates initial pictures.
190 SetTilingSize(new_tiling_size);
192 // Due to border pixels, we should have 3 tiles.
193 EXPECT_EQ(3, pile_.tiling().num_tiles_x());
194 EXPECT_EQ(3, pile_.tiling().num_tiles_y());
196 // We should have 1/.125 - 1 = 7 border pixels.
197 EXPECT_EQ(7, pile_.buffer_pixels());
198 EXPECT_EQ(7, pile_.tiling().border_texels());
200 // Invalidate everything to have a non zero invalidation frequency.
201 UpdateWholePile();
203 // Invalidate something just over a tile boundary by a single pixel.
204 // This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
205 Region invalidate_rect(
206 gfx::Rect(pile_.tiling().TileBoundsWithBorder(0, 0).right(),
207 pile_.tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
209 50));
210 Region expected_invalidation = invalidate_rect;
211 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
212 EXPECT_EQ(expected_invalidation.ToString(), invalidate_rect.ToString());
214 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
215 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
216 FakePicturePile::PictureInfo& picture_info =
217 pile_.picture_map()
218 .find(FakePicturePile::PictureMapKey(i, j))
219 ->second;
221 // Expect (1, 1) and (1, 0) to be invalidated once more
222 // than the rest of the tiles.
223 if (i == 1 && (j == 0 || j == 1)) {
224 EXPECT_FLOAT_EQ(
225 2.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
226 picture_info.GetInvalidationFrequencyForTesting());
227 } else {
228 EXPECT_FLOAT_EQ(
229 1.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
230 picture_info.GetInvalidationFrequencyForTesting());
236 TEST_F(PicturePileTest, InvalidateOnFullLayer) {
237 UpdateWholePile();
239 // Everything was invalidated once so far.
240 for (auto& it : pile_.picture_map()) {
241 EXPECT_FLOAT_EQ(
242 1.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
243 it.second.GetInvalidationFrequencyForTesting());
246 // Invalidate everything,
247 Region invalidation = tiling_rect();
248 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
250 // Everything was invalidated again.
251 for (auto& it : pile_.picture_map()) {
252 EXPECT_FLOAT_EQ(
253 2.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
254 it.second.GetInvalidationFrequencyForTesting());
258 TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
259 gfx::Size new_tiling_size =
260 gfx::ToCeiledSize(gfx::ScaleSize(tiling_size(), 4.f));
261 SetTilingSize(new_tiling_size);
263 gfx::Rect viewport(tiling_size().width(), 1);
265 // Update the whole pile until the invalidation frequency is high.
266 for (int frame = 0; frame < 33; ++frame) {
267 UpdateWholePile();
270 // Make sure we have a high invalidation frequency.
271 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
272 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
273 FakePicturePile::PictureInfo& picture_info =
274 pile_.picture_map()
275 .find(FakePicturePile::PictureMapKey(i, j))
276 ->second;
277 EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting())
278 << "i " << i << " j " << j;
282 // Update once more with a small viewport.
283 Region invalidation(tiling_rect());
284 UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
285 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
287 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
288 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
289 FakePicturePile::PictureInfo& picture_info =
290 pile_.picture_map()
291 .find(FakePicturePile::PictureMapKey(i, j))
292 ->second;
293 EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting());
295 // If the y far enough away we expect to find no picture (no re-recording
296 // happened). For close y, the picture should change.
297 if (j >= 2)
298 EXPECT_FALSE(picture_info.GetPicture()) << "i " << i << " j " << j;
299 else
300 EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
304 // Update a partial tile that doesn't get recorded. We should expand the
305 // invalidation to the entire tiles that overlap it.
306 Region small_invalidation =
307 gfx::Rect(pile_.tiling().TileBounds(3, 4).x(),
308 pile_.tiling().TileBounds(3, 4).y() + 10,
311 UpdateAndExpandInvalidation(&small_invalidation, tiling_size(), viewport);
312 EXPECT_TRUE(small_invalidation.Contains(gfx::UnionRects(
313 pile_.tiling().TileBounds(2, 4), pile_.tiling().TileBounds(3, 4))))
314 << small_invalidation.ToString();
316 // Now update with no invalidation and full viewport
317 Region empty_invalidation;
318 UpdateAndExpandInvalidation(&empty_invalidation, tiling_size(),
319 tiling_rect());
320 EXPECT_EQ(Region().ToString(), empty_invalidation.ToString());
322 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
323 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
324 FakePicturePile::PictureInfo& picture_info =
325 pile_.picture_map()
326 .find(FakePicturePile::PictureMapKey(i, j))
327 ->second;
328 // Expect the invalidation frequency to be less than 1, since we just
329 // updated with no invalidations.
330 EXPECT_LT(picture_info.GetInvalidationFrequencyForTesting(), 1.f);
332 // We expect that there are pictures everywhere now.
333 EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
338 TEST_F(PicturePileTest, ClearingInvalidatesRecordedRect) {
339 gfx::Rect rect(0, 0, 5, 5);
340 EXPECT_TRUE(pile_.CanRasterLayerRect(rect));
341 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(rect));
343 pile_.Clear();
345 // Make sure both the cache-aware check (using recorded region) and the normal
346 // check are both false after clearing.
347 EXPECT_FALSE(pile_.CanRasterLayerRect(rect));
348 EXPECT_FALSE(pile_.CanRasterSlowTileCheck(rect));
351 TEST_F(PicturePileTest, FrequentInvalidationCanRaster) {
352 // This test makes sure that if part of the page is frequently invalidated
353 // and doesn't get re-recorded, then CanRaster is not true for any
354 // tiles touching it, but is true for adjacent tiles, even if it
355 // overlaps on borders (edge case).
356 gfx::Size new_tiling_size =
357 gfx::ToCeiledSize(gfx::ScaleSize(tiling_size(), 4.f));
358 SetTilingSize(new_tiling_size);
360 gfx::Rect tile01_borders = pile_.tiling().TileBoundsWithBorder(0, 1);
361 gfx::Rect tile02_borders = pile_.tiling().TileBoundsWithBorder(0, 2);
362 gfx::Rect tile01_noborders = pile_.tiling().TileBounds(0, 1);
363 gfx::Rect tile02_noborders = pile_.tiling().TileBounds(0, 2);
365 // Sanity check these two tiles are overlapping with borders, since this is
366 // what the test is trying to repro.
367 EXPECT_TRUE(tile01_borders.Intersects(tile02_borders));
368 EXPECT_FALSE(tile01_noborders.Intersects(tile02_noborders));
369 UpdateWholePile();
370 EXPECT_TRUE(pile_.CanRasterLayerRect(tile01_noborders));
371 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile01_noborders));
372 EXPECT_TRUE(pile_.CanRasterLayerRect(tile02_noborders));
373 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile02_noborders));
374 // Sanity check that an initial paint goes down the fast path of having
375 // a valid recorded viewport.
376 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
378 // Update the whole layer until the invalidation frequency is high.
379 for (int frame = 0; frame < 33; ++frame) {
380 UpdateWholePile();
383 // Update once more with a small viewport.
384 gfx::Rect viewport(tiling_size().width(), 1);
385 Region invalidation(tiling_rect());
386 UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
387 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
389 // Sanity check some pictures exist and others don't.
390 EXPECT_TRUE(pile_.picture_map()
391 .find(FakePicturePile::PictureMapKey(0, 1))
392 ->second.GetPicture());
393 EXPECT_FALSE(pile_.picture_map()
394 .find(FakePicturePile::PictureMapKey(0, 2))
395 ->second.GetPicture());
397 EXPECT_TRUE(pile_.CanRasterLayerRect(tile01_noborders));
398 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile01_noborders));
399 EXPECT_FALSE(pile_.CanRasterLayerRect(tile02_noborders));
400 EXPECT_FALSE(pile_.CanRasterSlowTileCheck(tile02_noborders));
403 TEST_F(PicturePileTest, NoInvalidationValidViewport) {
404 // This test validates that the recorded_viewport cache of full tiles
405 // is still valid for some use cases. If it's not, it's a performance
406 // issue because CanRaster checks will go down the slow path.
407 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
409 // No invalidation, same viewport.
410 Region invalidation;
411 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
412 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
413 EXPECT_EQ(Region().ToString(), invalidation.ToString());
415 // Partial invalidation, same viewport.
416 invalidation = gfx::Rect(0, 0, 1, 1);
417 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
418 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
419 EXPECT_EQ(gfx::Rect(0, 0, 1, 1).ToString(), invalidation.ToString());
421 // No invalidation, changing viewport.
422 invalidation = Region();
423 UpdateAndExpandInvalidation(&invalidation, tiling_size(),
424 gfx::Rect(5, 5, 5, 5));
425 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
426 EXPECT_EQ(Region().ToString(), invalidation.ToString());
429 TEST_F(PicturePileTest, BigFullLayerInvalidation) {
430 gfx::Size huge_layer_size(100000000, 100000000);
431 gfx::Rect viewport(300000, 400000, 5000, 6000);
433 // Resize the pile.
434 Region invalidation;
435 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
437 // Invalidating a huge layer should be fast.
438 base::TimeTicks start = base::TimeTicks::Now();
439 invalidation = gfx::Rect(huge_layer_size);
440 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
441 base::TimeTicks end = base::TimeTicks::Now();
442 base::TimeDelta length = end - start;
443 // This is verrrry generous to avoid flake.
444 EXPECT_LT(length.InSeconds(), 5);
447 TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeGrow) {
448 gfx::Size huge_layer_size(100000000, 100000000);
449 gfx::Rect viewport(300000, 400000, 5000, 6000);
451 // Resize the pile.
452 Region invalidation;
453 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
455 // Resize the pile even larger, while invalidating everything in the old size.
456 // Invalidating the whole thing should be fast.
457 base::TimeTicks start = base::TimeTicks::Now();
458 gfx::Size bigger_layer_size(huge_layer_size.width() * 2,
459 huge_layer_size.height() * 2);
460 invalidation = gfx::Rect(huge_layer_size);
461 UpdateAndExpandInvalidation(&invalidation, bigger_layer_size, viewport);
462 base::TimeTicks end = base::TimeTicks::Now();
463 base::TimeDelta length = end - start;
464 // This is verrrry generous to avoid flake.
465 EXPECT_LT(length.InSeconds(), 5);
468 TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeShrink) {
469 gfx::Size huge_layer_size(100000000, 100000000);
470 gfx::Rect viewport(300000, 400000, 5000, 6000);
472 // Resize the pile.
473 Region invalidation;
474 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
476 // Resize the pile smaller, while invalidating everything in the new size.
477 // Invalidating the whole thing should be fast.
478 base::TimeTicks start = base::TimeTicks::Now();
479 gfx::Size smaller_layer_size(huge_layer_size.width() - 1000,
480 huge_layer_size.height() - 1000);
481 invalidation = gfx::Rect(smaller_layer_size);
482 UpdateAndExpandInvalidation(&invalidation, smaller_layer_size, viewport);
483 base::TimeTicks end = base::TimeTicks::Now();
484 base::TimeDelta length = end - start;
485 // This is verrrry generous to avoid flake.
486 EXPECT_LT(length.InSeconds(), 5);
489 TEST_F(PicturePileTest, InvalidationOutsideRecordingRect) {
490 gfx::Size huge_layer_size(10000000, 20000000);
491 gfx::Rect viewport(300000, 400000, 5000, 6000);
493 // Resize the pile and set up the interest rect.
494 Region invalidation;
495 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
497 // Invalidation inside the recording rect does not need to be expanded.
498 invalidation = viewport;
499 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
500 EXPECT_EQ(viewport.ToString(), invalidation.ToString());
502 // Invalidation outside the recording rect should expand to the tiles it
503 // covers.
504 gfx::Rect recorded_over_tiles =
505 pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
506 gfx::Rect invalidation_outside(
507 recorded_over_tiles.right(), recorded_over_tiles.y(), 30, 30);
508 invalidation = invalidation_outside;
509 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
510 gfx::Rect expanded_recorded_viewport =
511 pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
512 Region expected_invalidation =
513 pile_.tiling().ExpandRectToTileBounds(invalidation_outside);
514 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
517 enum Corner {
518 TOP_LEFT,
519 TOP_RIGHT,
520 BOTTOM_LEFT,
521 BOTTOM_RIGHT,
524 class PicturePileResizeCornerTest : public PicturePileTestBase,
525 public testing::TestWithParam<Corner> {
526 protected:
527 void SetUp() override { InitializeData(); }
529 static gfx::Rect CornerSinglePixelRect(Corner corner, const gfx::Size& s) {
530 switch (corner) {
531 case TOP_LEFT:
532 return gfx::Rect(0, 0, 1, 1);
533 case TOP_RIGHT:
534 return gfx::Rect(s.width() - 1, 0, 1, 1);
535 case BOTTOM_LEFT:
536 return gfx::Rect(0, s.height() - 1, 1, 1);
537 case BOTTOM_RIGHT:
538 return gfx::Rect(s.width() - 1, s.height() - 1, 1, 1);
540 NOTREACHED();
541 return gfx::Rect();
545 TEST_P(PicturePileResizeCornerTest, ResizePileOutsideInterestRect) {
546 Corner corner = GetParam();
548 // This size chosen to be larger than the interest rect size, which is
549 // at least kPixelDistanceToRecord * 2 in each dimension.
550 int tile_size = 100000;
551 // The small number subtracted keeps the last tile in each axis larger than
552 // the interest rect also.
553 int offset = -100;
554 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
555 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
556 8 * tile_size + offset);
557 gfx::Size grow_right_tiling_size(8 * tile_size + offset,
558 6 * tile_size + offset);
559 gfx::Size grow_both_tiling_size(8 * tile_size + offset,
560 8 * tile_size + offset);
562 Region invalidation;
563 Region expected_invalidation;
565 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
566 SetTilingSize(base_tiling_size);
568 // We should have a recording for every tile.
569 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
570 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
571 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
572 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
573 FakePicturePile::PictureMapKey key(i, j);
574 FakePicturePile::PictureMap& map = pile_.picture_map();
575 FakePicturePile::PictureMap::iterator it = map.find(key);
576 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
580 UpdateAndExpandInvalidation(
581 &invalidation,
582 grow_down_tiling_size,
583 CornerSinglePixelRect(corner, grow_down_tiling_size));
585 // We should have lost all of the recordings in the bottom row as none of them
586 // are in the current interest rect (which is either the above or below it).
587 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
588 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
589 for (int i = 0; i < 6; ++i) {
590 for (int j = 0; j < 6; ++j) {
591 FakePicturePile::PictureMapKey key(i, j);
592 FakePicturePile::PictureMap& map = pile_.picture_map();
593 FakePicturePile::PictureMap::iterator it = map.find(key);
594 EXPECT_EQ(j < 5, it != map.end() && it->second.GetPicture());
598 // We invalidated all new pixels in the recording.
599 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
600 gfx::Rect(base_tiling_size));
601 // But the new pixels don't cover the whole bottom row.
602 gfx::Rect bottom_row = gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
603 pile_.tiling().TileBounds(5, 5));
604 EXPECT_FALSE(expected_invalidation.Contains(bottom_row));
605 // We invalidated the entire old bottom row.
606 expected_invalidation.Union(bottom_row);
607 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
608 invalidation.Clear();
610 UpdateWholePile();
611 UpdateAndExpandInvalidation(&invalidation,
612 base_tiling_size,
613 CornerSinglePixelRect(corner, base_tiling_size));
615 // When shrinking, we should have lost all the recordings in the bottom row
616 // not touching the interest rect.
617 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
618 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
619 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
620 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
621 FakePicturePile::PictureMapKey key(i, j);
622 FakePicturePile::PictureMap& map = pile_.picture_map();
623 FakePicturePile::PictureMap::iterator it = map.find(key);
624 bool expect_tile;
625 switch (corner) {
626 case TOP_LEFT:
627 case TOP_RIGHT:
628 expect_tile = j < 5;
629 break;
630 case BOTTOM_LEFT:
631 // The interest rect in the bottom left tile means we'll record it.
632 expect_tile = j < 5 || (j == 5 && i == 0);
633 break;
634 case BOTTOM_RIGHT:
635 // The interest rect in the bottom right tile means we'll record it.
636 expect_tile = j < 5 || (j == 5 && i == 5);
637 break;
639 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
643 // When shrinking, the previously exposed region is invalidated.
644 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
645 gfx::Rect(base_tiling_size));
646 // The whole bottom row of tiles (except any with the interest rect) are
647 // dropped.
648 gfx::Rect bottom_row_minus_existing_corner = gfx::UnionRects(
649 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
650 switch (corner) {
651 case TOP_LEFT:
652 case TOP_RIGHT:
653 // No tiles are kept in the changed region because it doesn't
654 // intersect with the interest rect.
655 break;
656 case BOTTOM_LEFT:
657 bottom_row_minus_existing_corner.Subtract(
658 pile_.tiling().TileBounds(0, 5));
659 break;
660 case BOTTOM_RIGHT:
661 bottom_row_minus_existing_corner.Subtract(
662 pile_.tiling().TileBounds(5, 5));
663 break;
666 expected_invalidation.Union(bottom_row_minus_existing_corner);
667 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
668 invalidation.Clear();
670 UpdateWholePile();
671 UpdateAndExpandInvalidation(
672 &invalidation,
673 grow_right_tiling_size,
674 CornerSinglePixelRect(corner, grow_right_tiling_size));
676 // We should have lost all of the recordings in the right column as none of
677 // them are in the current interest rect (which is either entirely left or
678 // right of it).
679 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
680 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
681 for (int i = 0; i < 6; ++i) {
682 for (int j = 0; j < 6; ++j) {
683 FakePicturePile::PictureMapKey key(i, j);
684 FakePicturePile::PictureMap& map = pile_.picture_map();
685 FakePicturePile::PictureMap::iterator it = map.find(key);
686 EXPECT_EQ(i < 5, it != map.end() && it->second.GetPicture());
690 // We invalidated all new pixels in the recording.
691 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
692 gfx::Rect(base_tiling_size));
693 // But the new pixels don't cover the whole right_column.
694 gfx::Rect right_column = gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
695 pile_.tiling().TileBounds(5, 5));
696 EXPECT_FALSE(expected_invalidation.Contains(right_column));
697 // We invalidated the entire old right column.
698 expected_invalidation.Union(right_column);
699 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
700 invalidation.Clear();
702 UpdateWholePile();
703 UpdateAndExpandInvalidation(&invalidation,
704 base_tiling_size,
705 CornerSinglePixelRect(corner, base_tiling_size));
707 // When shrinking, we should have lost all the recordings in the right column
708 // not touching the interest rect.
709 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
710 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
711 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
712 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
713 FakePicturePile::PictureMapKey key(i, j);
714 FakePicturePile::PictureMap& map = pile_.picture_map();
715 FakePicturePile::PictureMap::iterator it = map.find(key);
716 bool expect_tile;
717 switch (corner) {
718 case TOP_LEFT:
719 case BOTTOM_LEFT:
720 // No tiles are kept in the changed region because it doesn't
721 // intersect with the interest rect.
722 expect_tile = i < 5;
723 break;
724 case TOP_RIGHT:
725 // The interest rect in the top right tile means we'll record it.
726 expect_tile = i < 5 || (j == 0 && i == 5);
727 break;
728 case BOTTOM_RIGHT:
729 // The interest rect in the bottom right tile means we'll record it.
730 expect_tile = i < 5 || (j == 5 && i == 5);
731 break;
733 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
737 // When shrinking, the previously exposed region is invalidated.
738 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
739 gfx::Rect(base_tiling_size));
740 // The whole right column of tiles (except for ones with the interest rect)
741 // are dropped.
742 gfx::Rect right_column_minus_existing_corner = gfx::UnionRects(
743 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
744 switch (corner) {
745 case TOP_LEFT:
746 case BOTTOM_LEFT:
747 break;
748 case TOP_RIGHT:
749 right_column_minus_existing_corner.Subtract(
750 pile_.tiling().TileBounds(5, 0));
751 break;
752 case BOTTOM_RIGHT:
753 right_column_minus_existing_corner.Subtract(
754 pile_.tiling().TileBounds(5, 5));
755 break;
757 expected_invalidation.Union(right_column_minus_existing_corner);
758 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
759 invalidation.Clear();
761 UpdateWholePile();
762 UpdateAndExpandInvalidation(
763 &invalidation,
764 grow_both_tiling_size,
765 CornerSinglePixelRect(corner, grow_both_tiling_size));
767 // We should have lost the recordings in the right column and bottom row.
768 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
769 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
770 for (int i = 0; i < 6; ++i) {
771 for (int j = 0; j < 6; ++j) {
772 FakePicturePile::PictureMapKey key(i, j);
773 FakePicturePile::PictureMap& map = pile_.picture_map();
774 FakePicturePile::PictureMap::iterator it = map.find(key);
775 EXPECT_EQ(i < 5 && j < 5, it != map.end() && it->second.GetPicture());
779 // We invalidated all new pixels in the recording.
780 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
781 gfx::Rect(base_tiling_size));
782 // But the new pixels don't cover the whole right column or bottom row.
783 Region right_column_and_bottom_row =
784 UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
785 pile_.tiling().TileBounds(5, 5)),
786 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
787 pile_.tiling().TileBounds(5, 5)));
788 EXPECT_FALSE(expected_invalidation.Contains(right_column_and_bottom_row));
789 // We invalidated the entire old right column and the old bottom row.
790 expected_invalidation.Union(right_column_and_bottom_row);
791 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
792 invalidation.Clear();
794 UpdateWholePile();
795 UpdateAndExpandInvalidation(&invalidation, base_tiling_size,
796 CornerSinglePixelRect(corner, base_tiling_size));
798 // We should have lost the recordings in the right column and bottom row,
799 // except where it intersects the interest rect.
800 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
801 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
802 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
803 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
804 FakePicturePile::PictureMapKey key(i, j);
805 FakePicturePile::PictureMap& map = pile_.picture_map();
806 FakePicturePile::PictureMap::iterator it = map.find(key);
807 bool expect_tile;
808 switch (corner) {
809 case TOP_LEFT:
810 expect_tile = i < 5 && j < 5;
811 break;
812 case TOP_RIGHT:
813 // The interest rect in the top right tile means we'll record it.
814 expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
815 break;
816 case BOTTOM_LEFT:
817 // The interest rect in the bottom left tile means we'll record it.
818 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
819 break;
820 case BOTTOM_RIGHT:
821 // The interest rect in the bottom right tile means we'll record it.
822 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
823 break;
825 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture())
826 << i << "," << j;
830 // We invalidated all previous pixels in the recording.
831 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
832 gfx::Rect(base_tiling_size));
833 // The whole right column and bottom row of tiles (except for ones with the
834 // interest rect) are dropped.
835 Region right_column_and_bottom_row_minus_existing_corner =
836 right_column_and_bottom_row;
837 switch (corner) {
838 case TOP_LEFT:
839 break;
840 case BOTTOM_LEFT:
841 right_column_and_bottom_row_minus_existing_corner.Subtract(
842 pile_.tiling().TileBounds(0, 5));
843 break;
844 case TOP_RIGHT:
845 right_column_and_bottom_row_minus_existing_corner.Subtract(
846 pile_.tiling().TileBounds(5, 0));
847 break;
848 case BOTTOM_RIGHT:
849 right_column_and_bottom_row_minus_existing_corner.Subtract(
850 pile_.tiling().TileBounds(5, 5));
851 break;
853 expected_invalidation.Union(
854 right_column_and_bottom_row_minus_existing_corner);
855 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
856 invalidation.Clear();
859 TEST_P(PicturePileResizeCornerTest, SmallResizePileOutsideInterestRect) {
860 Corner corner = GetParam();
862 // This size chosen to be larger than the interest rect size, which is
863 // at least kPixelDistanceToRecord * 2 in each dimension.
864 int tile_size = 100000;
865 // The small number subtracted keeps the last tile in each axis larger than
866 // the interest rect also.
867 int offset = -100;
868 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
869 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
870 6 * tile_size + offset + 5);
871 gfx::Size grow_right_tiling_size(6 * tile_size + offset + 5,
872 6 * tile_size + offset);
873 gfx::Size grow_both_tiling_size(6 * tile_size + offset + 5,
874 6 * tile_size + offset + 5);
876 Region invalidation;
877 Region expected_invalidation;
879 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
880 SetTilingSize(base_tiling_size);
882 // We should have a recording for every tile.
883 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
884 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
885 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
886 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
887 FakePicturePile::PictureMapKey key(i, j);
888 FakePicturePile::PictureMap& map = pile_.picture_map();
889 FakePicturePile::PictureMap::iterator it = map.find(key);
890 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
894 // In this test (unlike the large resize test), as all growing and shrinking
895 // happens within tiles, the resulting invalidation is symmetrical, so use
896 // this enum to repeat the test both ways.
897 enum ChangeDirection { GROW, SHRINK, LAST_DIRECTION = SHRINK };
899 // Grow downward.
900 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
901 gfx::Size new_tiling_size =
902 dir == GROW ? grow_down_tiling_size : base_tiling_size;
903 UpdateWholePile();
904 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
905 CornerSinglePixelRect(corner, new_tiling_size));
907 // We should have lost the recordings in the bottom row that do not
908 // intersect the interest rect.
909 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
910 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
911 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
912 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
913 FakePicturePile::PictureMapKey key(i, j);
914 FakePicturePile::PictureMap& map = pile_.picture_map();
915 FakePicturePile::PictureMap::iterator it = map.find(key);
916 bool expect_tile;
917 switch (corner) {
918 case TOP_LEFT:
919 case TOP_RIGHT:
920 expect_tile = j < 5;
921 break;
922 case BOTTOM_LEFT:
923 // The interest rect in the bottom left tile means we'll record it.
924 expect_tile = j < 5 || (j == 5 && i == 0);
925 break;
926 case BOTTOM_RIGHT:
927 // The interest rect in the bottom right tile means we'll record it.
928 expect_tile = j < 5 || (j == 5 && i == 5);
929 break;
931 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
935 // We invalidated the bottom row outside the new interest rect. The tile
936 // that insects the interest rect in invalidated only on its newly
937 // exposed or previously exposed pixels.
938 if (dir == GROW) {
939 // Only calculate the expected invalidation while growing, as the tile
940 // bounds post-growing is the newly exposed / previously exposed sizes.
941 // Post-shrinking, the tile bounds are smaller, so can't be used.
942 switch (corner) {
943 case TOP_LEFT:
944 case TOP_RIGHT:
945 expected_invalidation = gfx::UnionRects(
946 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
947 break;
948 case BOTTOM_LEFT:
949 expected_invalidation = gfx::UnionRects(
950 pile_.tiling().TileBounds(1, 5), pile_.tiling().TileBounds(5, 5));
951 expected_invalidation.Union(SubtractRects(
952 pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
953 break;
954 case BOTTOM_RIGHT:
955 expected_invalidation = gfx::UnionRects(
956 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(4, 5));
957 expected_invalidation.Union(SubtractRects(
958 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
959 break;
962 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
963 invalidation.Clear();
966 // Grow right.
967 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
968 gfx::Size new_tiling_size =
969 dir == GROW ? grow_right_tiling_size : base_tiling_size;
970 UpdateWholePile();
971 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
972 CornerSinglePixelRect(corner, new_tiling_size));
974 // We should have lost the recordings in the right column.
975 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
976 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
977 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
978 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
979 FakePicturePile::PictureMapKey key(i, j);
980 FakePicturePile::PictureMap& map = pile_.picture_map();
981 FakePicturePile::PictureMap::iterator it = map.find(key);
982 bool expect_tile;
983 switch (corner) {
984 case TOP_LEFT:
985 case BOTTOM_LEFT:
986 expect_tile = i < 5;
987 break;
988 case TOP_RIGHT:
989 // The interest rect in the top right tile means we'll record it.
990 expect_tile = i < 5 || (j == 0 && i == 5);
991 break;
992 case BOTTOM_RIGHT:
993 // The interest rect in the bottom right tile means we'll record it.
994 expect_tile = i < 5 || (j == 5 && i == 5);
995 break;
997 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
1001 // We invalidated the right column outside the new interest rect. The tile
1002 // that insects the interest rect in invalidated only on its new or
1003 // previously exposed pixels.
1004 if (dir == GROW) {
1005 // Calculate the expected invalidation the first time through the loop.
1006 switch (corner) {
1007 case TOP_LEFT:
1008 case BOTTOM_LEFT:
1009 expected_invalidation = gfx::UnionRects(
1010 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
1011 break;
1012 case TOP_RIGHT:
1013 expected_invalidation = gfx::UnionRects(
1014 pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
1015 expected_invalidation.Union(SubtractRects(
1016 pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
1017 break;
1018 case BOTTOM_RIGHT:
1019 expected_invalidation = gfx::UnionRects(
1020 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
1021 expected_invalidation.Union(SubtractRects(
1022 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
1023 break;
1026 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1027 invalidation.Clear();
1030 // Grow both.
1031 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
1032 gfx::Size new_tiling_size =
1033 dir == GROW ? grow_both_tiling_size : base_tiling_size;
1034 UpdateWholePile();
1035 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
1036 CornerSinglePixelRect(corner, new_tiling_size));
1038 // We should have lost the recordings in the right column and bottom row.
1039 // The tile that insects the interest rect in invalidated only on its new
1040 // or previously exposed pixels.
1041 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1042 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1043 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1044 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1045 FakePicturePile::PictureMapKey key(i, j);
1046 FakePicturePile::PictureMap& map = pile_.picture_map();
1047 FakePicturePile::PictureMap::iterator it = map.find(key);
1048 bool expect_tile;
1049 switch (corner) {
1050 case TOP_LEFT:
1051 expect_tile = i < 5 && j < 5;
1052 break;
1053 case TOP_RIGHT:
1054 // The interest rect in the top right tile means we'll record it.
1055 expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
1056 break;
1057 case BOTTOM_LEFT:
1058 // The interest rect in the bottom left tile means we'll record it.
1059 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
1060 break;
1061 case BOTTOM_RIGHT:
1062 // The interest rect in the bottom right tile means we'll record it.
1063 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
1064 break;
1066 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture())
1067 << i << "," << j;
1071 // We invalidated the right column and the bottom row outside the new
1072 // interest rect. The tile that insects the interest rect in invalidated
1073 // only on its new or previous exposed pixels.
1074 if (dir == GROW) {
1075 // Calculate the expected invalidation the first time through the loop.
1076 switch (corner) {
1077 case TOP_LEFT:
1078 expected_invalidation = gfx::UnionRects(
1079 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
1080 expected_invalidation.Union(
1081 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1082 pile_.tiling().TileBounds(5, 5)));
1083 break;
1084 case TOP_RIGHT:
1085 expected_invalidation = gfx::UnionRects(
1086 pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
1087 expected_invalidation.Union(
1088 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1089 pile_.tiling().TileBounds(5, 5)));
1090 expected_invalidation.Union(SubtractRects(
1091 pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
1092 break;
1093 case BOTTOM_LEFT:
1094 expected_invalidation = gfx::UnionRects(
1095 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
1096 expected_invalidation.Union(
1097 gfx::UnionRects(pile_.tiling().TileBounds(1, 5),
1098 pile_.tiling().TileBounds(5, 5)));
1099 expected_invalidation.Union(SubtractRects(
1100 pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
1101 break;
1102 case BOTTOM_RIGHT:
1103 expected_invalidation = gfx::UnionRects(
1104 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
1105 expected_invalidation.Union(
1106 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1107 pile_.tiling().TileBounds(4, 5)));
1108 expected_invalidation.Union(SubtractRegions(
1109 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
1110 break;
1113 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1114 invalidation.Clear();
1118 INSTANTIATE_TEST_CASE_P(
1119 PicturePileResizeCornerTests,
1120 PicturePileResizeCornerTest,
1121 ::testing::Values(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT));
1123 TEST_F(PicturePileTest, ResizePileInsideInterestRect) {
1124 // This size chosen to be small enough that all the rects below fit inside the
1125 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
1126 // dimension.
1127 int tile_size = 100;
1128 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
1129 gfx::Size grow_down_tiling_size(5 * tile_size, 7 * tile_size);
1130 gfx::Size grow_right_tiling_size(7 * tile_size, 5 * tile_size);
1131 gfx::Size grow_both_tiling_size(7 * tile_size, 7 * tile_size);
1133 Region invalidation;
1134 Region expected_invalidation;
1136 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
1137 SetTilingSize(base_tiling_size);
1139 // We should have a recording for every tile.
1140 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1141 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1142 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1143 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1144 FakePicturePile::PictureMapKey key(i, j);
1145 FakePicturePile::PictureMap& map = pile_.picture_map();
1146 FakePicturePile::PictureMap::iterator it = map.find(key);
1147 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1151 UpdateAndExpandInvalidation(
1152 &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
1154 // We should have a recording for every tile.
1155 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1156 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
1157 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1158 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1159 FakePicturePile::PictureMapKey key(i, j);
1160 FakePicturePile::PictureMap& map = pile_.picture_map();
1161 FakePicturePile::PictureMap::iterator it = map.find(key);
1162 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1166 // We invalidated the newly exposed pixels on the bottom row of tiles.
1167 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1168 gfx::Rect(base_tiling_size));
1169 Region bottom_row_new_pixels =
1170 SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1171 pile_.tiling().TileBounds(5, 5)),
1172 gfx::Rect(base_tiling_size));
1173 EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
1174 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1175 invalidation.Clear();
1177 UpdateWholePile();
1178 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1180 // We should have a recording for every tile.
1181 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1182 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1183 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1184 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1185 FakePicturePile::PictureMapKey key(i, j);
1186 FakePicturePile::PictureMap& map = pile_.picture_map();
1187 FakePicturePile::PictureMap::iterator it = map.find(key);
1188 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1192 // We invalidated the previously exposed pixels on the bottom row of tiles.
1193 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1194 gfx::Rect(base_tiling_size));
1195 EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
1196 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1197 invalidation.Clear();
1199 UpdateWholePile();
1200 UpdateAndExpandInvalidation(
1201 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1203 // We should have a recording for every tile.
1204 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
1205 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1206 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1207 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1208 FakePicturePile::PictureMapKey key(i, j);
1209 FakePicturePile::PictureMap& map = pile_.picture_map();
1210 FakePicturePile::PictureMap::iterator it = map.find(key);
1211 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1215 // We invalidated the newly exposed pixels on the right column of tiles.
1216 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1217 gfx::Rect(base_tiling_size));
1218 Region right_column_new_pixels =
1219 SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
1220 pile_.tiling().TileBounds(5, 5)),
1221 gfx::Rect(base_tiling_size));
1222 EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
1223 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1224 invalidation.Clear();
1226 UpdateWholePile();
1227 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1229 // We should have lost the recordings that are now outside the tiling only.
1230 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1231 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1232 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1233 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1234 FakePicturePile::PictureMapKey key(i, j);
1235 FakePicturePile::PictureMap& map = pile_.picture_map();
1236 FakePicturePile::PictureMap::iterator it = map.find(key);
1237 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1241 // We invalidated the previously exposed pixels on the right column of tiles.
1242 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1243 gfx::Rect(base_tiling_size));
1244 EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
1245 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1246 invalidation.Clear();
1248 UpdateWholePile();
1249 UpdateAndExpandInvalidation(
1250 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1252 // We should have a recording for every tile.
1253 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
1254 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
1255 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1256 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1257 FakePicturePile::PictureMapKey key(i, j);
1258 FakePicturePile::PictureMap& map = pile_.picture_map();
1259 FakePicturePile::PictureMap::iterator it = map.find(key);
1260 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1264 // We invalidated the newly exposed pixels on the bottom row and right column
1265 // of tiles.
1266 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1267 gfx::Rect(base_tiling_size));
1268 Region bottom_row_and_right_column_new_pixels = SubtractRegions(
1269 UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1270 pile_.tiling().TileBounds(5, 5)),
1271 gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
1272 pile_.tiling().TileBounds(5, 5))),
1273 gfx::Rect(base_tiling_size));
1274 EXPECT_TRUE(
1275 expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
1276 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1277 invalidation.Clear();
1279 UpdateWholePile();
1280 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1282 // We should have lost the recordings that are now outside the tiling only.
1283 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1284 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1285 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1286 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1287 FakePicturePile::PictureMapKey key(i, j);
1288 FakePicturePile::PictureMap& map = pile_.picture_map();
1289 FakePicturePile::PictureMap::iterator it = map.find(key);
1290 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1294 // We invalidated the previously exposed pixels on the bottom row and right
1295 // column of tiles.
1296 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1297 gfx::Rect(base_tiling_size));
1298 EXPECT_TRUE(
1299 expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
1300 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1301 invalidation.Clear();
1304 TEST_F(PicturePileTest, SmallResizePileInsideInterestRect) {
1305 // This size chosen to be small enough that all the rects below fit inside the
1306 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
1307 // dimension.
1308 int tile_size = 100;
1309 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
1310 gfx::Size grow_down_tiling_size(5 * tile_size, 5 * tile_size + 5);
1311 gfx::Size grow_right_tiling_size(5 * tile_size + 5, 5 * tile_size);
1312 gfx::Size grow_both_tiling_size(5 * tile_size + 5, 5 * tile_size + 5);
1314 Region invalidation;
1315 Region expected_invalidation;
1317 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
1318 SetTilingSize(base_tiling_size);
1320 // We should have a recording for every tile.
1321 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1322 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1323 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1324 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1325 FakePicturePile::PictureMapKey key(i, j);
1326 FakePicturePile::PictureMap& map = pile_.picture_map();
1327 FakePicturePile::PictureMap::iterator it = map.find(key);
1328 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1332 UpdateAndExpandInvalidation(
1333 &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
1335 // We should have a recording for every tile.
1336 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1337 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1338 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1339 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1340 FakePicturePile::PictureMapKey key(i, j);
1341 FakePicturePile::PictureMap& map = pile_.picture_map();
1342 FakePicturePile::PictureMap::iterator it = map.find(key);
1343 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1347 // We invalidated the newly exposed pixels.
1348 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1349 gfx::Rect(base_tiling_size));
1350 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1351 invalidation.Clear();
1353 UpdateWholePile();
1354 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1356 // We should have a recording for every tile.
1357 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1358 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1359 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1360 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1361 FakePicturePile::PictureMapKey key(i, j);
1362 FakePicturePile::PictureMap& map = pile_.picture_map();
1363 FakePicturePile::PictureMap::iterator it = map.find(key);
1364 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1368 // We invalidated the previously exposed pixels.
1369 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1370 gfx::Rect(base_tiling_size));
1371 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1372 invalidation.Clear();
1374 UpdateWholePile();
1375 UpdateAndExpandInvalidation(
1376 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1378 // We should have a recording for every tile.
1379 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1380 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1381 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1382 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1383 FakePicturePile::PictureMapKey key(i, j);
1384 FakePicturePile::PictureMap& map = pile_.picture_map();
1385 FakePicturePile::PictureMap::iterator it = map.find(key);
1386 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1390 // We invalidated the newly exposed pixels.
1391 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1392 gfx::Rect(base_tiling_size));
1393 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1394 invalidation.Clear();
1396 UpdateWholePile();
1397 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1399 // We should have lost the recordings that are now outside the tiling only.
1400 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1401 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1402 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1403 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1404 FakePicturePile::PictureMapKey key(i, j);
1405 FakePicturePile::PictureMap& map = pile_.picture_map();
1406 FakePicturePile::PictureMap::iterator it = map.find(key);
1407 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1411 // We invalidated the previously exposed pixels.
1412 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1413 gfx::Rect(base_tiling_size));
1414 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1415 invalidation.Clear();
1417 UpdateWholePile();
1418 UpdateAndExpandInvalidation(
1419 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1421 // We should have a recording for every tile.
1422 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1423 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1424 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1425 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1426 FakePicturePile::PictureMapKey key(i, j);
1427 FakePicturePile::PictureMap& map = pile_.picture_map();
1428 FakePicturePile::PictureMap::iterator it = map.find(key);
1429 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1433 // We invalidated the newly exposed pixels.
1434 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1435 gfx::Rect(base_tiling_size));
1436 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1437 invalidation.Clear();
1439 UpdateWholePile();
1440 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1442 // We should have lost the recordings that are now outside the tiling only.
1443 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1444 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1445 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1446 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1447 FakePicturePile::PictureMapKey key(i, j);
1448 FakePicturePile::PictureMap& map = pile_.picture_map();
1449 FakePicturePile::PictureMap::iterator it = map.find(key);
1450 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1454 // We invalidated the previously exposed pixels.
1455 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1456 gfx::Rect(base_tiling_size));
1457 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1458 invalidation.Clear();
1461 TEST_F(PicturePileTest, SolidRectangleIsSolid) {
1462 // If the client has no contents, the solid state will be true.
1463 Region invalidation1(tiling_rect());
1464 UpdateAndExpandInvalidation(&invalidation1, tiling_size(), tiling_rect());
1465 EXPECT_TRUE(pile_.is_solid_color());
1466 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), pile_.solid_color());
1468 // If there is a single rect that covers the view, the solid
1469 // state will be true.
1470 SkPaint paint;
1471 paint.setColor(SK_ColorCYAN);
1472 client_.add_draw_rect(tiling_rect(), paint);
1473 Region invalidation2(tiling_rect());
1474 UpdateAndExpandInvalidation(&invalidation2, tiling_size(), tiling_rect());
1475 EXPECT_TRUE(pile_.is_solid_color());
1476 EXPECT_EQ(SK_ColorCYAN, pile_.solid_color());
1478 // If a second smaller rect is draw that doesn't cover the viewport
1479 // completely, the solid state will be false.
1480 gfx::Rect smallRect = tiling_rect();
1481 smallRect.Inset(10, 10, 10, 10);
1482 client_.add_draw_rect(smallRect, paint);
1483 Region invalidation3(tiling_rect());
1484 UpdateAndExpandInvalidation(&invalidation3, tiling_size(), tiling_rect());
1485 EXPECT_FALSE(pile_.is_solid_color());
1487 // If a third rect is drawn over everything, we should be solid again.
1488 paint.setColor(SK_ColorRED);
1489 client_.add_draw_rect(tiling_rect(), paint);
1490 Region invalidation4(tiling_rect());
1491 UpdateAndExpandInvalidation(&invalidation4, tiling_size(), tiling_rect());
1492 EXPECT_TRUE(pile_.is_solid_color());
1493 EXPECT_EQ(SK_ColorRED, pile_.solid_color());
1495 // If we draw too many, we don't bother doing the analysis and we should no
1496 // longer be in a solid state. There are 8 rects, two clips and a translate.
1497 client_.add_draw_rect(tiling_rect(), paint);
1498 client_.add_draw_rect(tiling_rect(), paint);
1499 client_.add_draw_rect(tiling_rect(), paint);
1500 client_.add_draw_rect(tiling_rect(), paint);
1501 client_.add_draw_rect(tiling_rect(), paint);
1502 Region invalidation5(tiling_rect());
1503 UpdateAndExpandInvalidation(&invalidation5, tiling_size(), tiling_rect());
1504 EXPECT_FALSE(pile_.is_solid_color());
1507 TEST_F(PicturePileTest, NonSolidRectangleOnOffsettedLayerIsNonSolid) {
1508 gfx::Rect visible_rect(tiling_rect());
1509 visible_rect.Offset(gfx::Vector2d(1000, 1000));
1510 // The picture pile requires that the tiling completely encompass the viewport
1511 // to make this test work correctly since the recorded viewport is an
1512 // intersection of the tile size and viewport rect. This is possibly a flaw
1513 // in |PicturePile|.
1514 gfx::Size tiling_size(visible_rect.right(), visible_rect.bottom());
1515 // |Setup()| will create pictures here that mess with the test, clear it!
1516 pile_.Clear();
1518 SkPaint paint;
1519 paint.setColor(SK_ColorCYAN);
1521 // Add a rect that doesn't cover the viewport completely, the solid state
1522 // will be false.
1523 gfx::Rect smallRect = visible_rect;
1524 smallRect.Inset(10, 10, 10, 10);
1525 client_.add_draw_rect(smallRect, paint);
1526 Region invalidation(visible_rect);
1527 UpdateAndExpandInvalidation(&invalidation, tiling_size, visible_rect);
1528 EXPECT_FALSE(pile_.is_solid_color());
1531 TEST_F(PicturePileTest, SetEmptyBounds) {
1532 EXPECT_TRUE(pile_.is_solid_color());
1533 EXPECT_FALSE(pile_.GetSize().IsEmpty());
1534 EXPECT_FALSE(pile_.picture_map().empty());
1535 EXPECT_TRUE(pile_.HasRecordings());
1536 pile_.SetEmptyBounds();
1537 EXPECT_FALSE(pile_.is_solid_color());
1538 EXPECT_TRUE(pile_.GetSize().IsEmpty());
1539 EXPECT_TRUE(pile_.picture_map().empty());
1540 EXPECT_FALSE(pile_.HasRecordings());
1543 } // namespace
1544 } // namespace cc