Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / cc / playback / picture_pile_unittest.cc
blobf929aeffb0a4c29a66a1426d5526f9d05c510b26
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/playback/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()
21 : min_scale_(0.125),
22 pile_(min_scale_, gfx::Size(1000, 1000)),
23 frame_number_(0) {}
25 void InitializeData() {
26 pile_.SetTileGridSize(gfx::Size(1000, 1000));
27 pile_.SetMinContentsScale(min_scale_);
28 client_ = FakeContentLayerClient();
29 SetTilingSize(pile_.tiling().max_texture_size());
32 void SetTilingSize(const gfx::Size& tiling_size) {
33 Region invalidation;
34 gfx::Rect viewport_rect(tiling_size);
35 UpdateAndExpandInvalidation(&invalidation, tiling_size, viewport_rect);
38 gfx::Size tiling_size() const { return pile_.GetSize(); }
39 gfx::Rect tiling_rect() const { return gfx::Rect(pile_.GetSize()); }
41 bool UpdateAndExpandInvalidation(Region* invalidation,
42 const gfx::Size& layer_size,
43 const gfx::Rect& visible_layer_rect) {
44 frame_number_++;
45 return pile_.UpdateAndExpandInvalidation(&client_, invalidation, layer_size,
46 visible_layer_rect, frame_number_,
47 RecordingSource::RECORD_NORMALLY);
50 bool UpdateWholePile() {
51 Region invalidation = tiling_rect();
52 bool result = UpdateAndExpandInvalidation(&invalidation, tiling_size(),
53 tiling_rect());
54 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
55 return result;
58 FakeContentLayerClient client_;
59 float min_scale_;
60 FakePicturePile pile_;
61 int frame_number_;
64 class PicturePileTest : public PicturePileTestBase, public testing::Test {
65 public:
66 void SetUp() override { InitializeData(); }
69 TEST_F(PicturePileTest, InvalidationOnTileBorderOutsideInterestRect) {
70 // Don't expand the interest rect past what we invalidate.
71 pile_.SetPixelRecordDistance(0);
73 gfx::Size tile_size(100, 100);
74 pile_.tiling().SetMaxTextureSize(tile_size);
76 gfx::Size pile_size(400, 400);
77 SetTilingSize(pile_size);
79 // We have multiple tiles.
80 EXPECT_GT(pile_.tiling().num_tiles_x(), 2);
81 EXPECT_GT(pile_.tiling().num_tiles_y(), 2);
83 // Record everything.
84 Region invalidation(tiling_rect());
85 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
87 // +----------+-----------------+-----------+
88 // | | VVVV 1,0| |
89 // | | VVVV | |
90 // | | VVVV | |
91 // | ...|.................|... |
92 // | ...|.................|... |
93 // +----------+-----------------+-----------+
94 // | ...| |... |
95 // | ...| |... |
96 // | ...| |... |
97 // | ...| |... |
98 // | ...| 1,1|... |
99 // +----------+-----------------+-----------+
100 // | ...|.................|... |
101 // | ...|.................|... |
102 // +----------+-----------------+-----------+
104 // .. = border pixels for tile 1,1
105 // VV = interest rect (what we will record)
107 // The first invalidation is inside VV, so it does not touch border pixels of
108 // tile 1,1.
110 // The second invalidation goes below VV into the .. border pixels of 1,1.
112 // This is the VV interest rect which will be entirely inside 1,0 and not
113 // touch the border of 1,1.
114 gfx::Rect interest_rect(
115 pile_.tiling().TilePositionX(1) + pile_.tiling().border_texels(),
118 pile_.tiling().TileSizeY(0) - pile_.tiling().border_texels());
120 // Invalidate tile 1,0 only. This is a rect that avoids the borders of any
121 // other tiles.
122 gfx::Rect invalidate_tile = interest_rect;
123 // This should cause the tile 1,0 to be invalidated and re-recorded. The
124 // invalidation did not need to be expanded.
125 invalidation = invalidate_tile;
126 UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
127 EXPECT_EQ(invalidate_tile, invalidation);
129 // Invalidate tile 1,0 and 1,1 by invalidating something that only touches the
130 // border of 1,1 (and is inside the tile bounds of 1,0). This is a 10px wide
131 // strip from the top of the tiling onto the border pixels of tile 1,1 that
132 // avoids border pixels of any other tiles.
133 gfx::Rect invalidate_border = interest_rect;
134 invalidate_border.Inset(0, 0, 0, -1);
135 // This should cause the tile 1,0 and 1,1 to be invalidated. The 1,1 tile will
136 // not be re-recorded since it does not touch the interest rect, so the
137 // invalidation should be expanded to cover all of 1,1.
138 invalidation = invalidate_border;
139 UpdateAndExpandInvalidation(&invalidation, tiling_size(), interest_rect);
140 Region expected_invalidation = invalidate_border;
141 expected_invalidation.Union(pile_.tiling().TileBounds(1, 1));
142 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
145 TEST_F(PicturePileTest, SmallInvalidateInflated) {
146 // Invalidate something inside a tile.
147 Region invalidate_rect(gfx::Rect(50, 50, 1, 1));
148 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
149 EXPECT_EQ(gfx::Rect(50, 50, 1, 1).ToString(), invalidate_rect.ToString());
151 EXPECT_EQ(1, pile_.tiling().num_tiles_x());
152 EXPECT_EQ(1, pile_.tiling().num_tiles_y());
154 PicturePile::PictureMapKey key = FakePicturePile::PictureMapKey(0, 0);
155 PicturePile::PictureMap::iterator it = pile_.picture_map().find(key);
156 EXPECT_TRUE(it != pile_.picture_map().end());
157 const Picture* picture = it->second.get();
158 EXPECT_TRUE(picture);
160 gfx::Rect picture_rect =
161 gfx::ScaleToEnclosedRect(picture->LayerRect(), min_scale_);
163 // The the picture should be large enough that scaling it never makes a rect
164 // smaller than 1 px wide or tall.
165 EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect "
166 << picture_rect.ToString();
169 TEST_F(PicturePileTest, LargeInvalidateInflated) {
170 // Invalidate something inside a tile.
171 Region invalidate_rect(gfx::Rect(50, 50, 100, 100));
172 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
173 EXPECT_EQ(gfx::Rect(50, 50, 100, 100).ToString(), invalidate_rect.ToString());
175 EXPECT_EQ(1, pile_.tiling().num_tiles_x());
176 EXPECT_EQ(1, pile_.tiling().num_tiles_y());
178 PicturePile::PictureMapKey key = FakePicturePile::PictureMapKey(0, 0);
179 PicturePile::PictureMap::iterator it = pile_.picture_map().find(key);
180 EXPECT_TRUE(it != pile_.picture_map().end());
181 const Picture* picture = it->second.get();
182 EXPECT_TRUE(picture);
184 int expected_inflation = pile_.buffer_pixels();
186 gfx::Rect base_picture_rect(tiling_size());
187 base_picture_rect.Inset(-expected_inflation, -expected_inflation);
188 EXPECT_EQ(base_picture_rect.ToString(), picture->LayerRect().ToString());
191 TEST_F(PicturePileTest, ClearingInvalidatesRecordedRect) {
192 gfx::Rect rect(0, 0, 5, 5);
193 EXPECT_TRUE(pile_.CanRasterLayerRect(rect));
194 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(rect));
196 pile_.Clear();
198 // Make sure both the cache-aware check (using recorded region) and the normal
199 // check are both false after clearing.
200 EXPECT_FALSE(pile_.CanRasterLayerRect(rect));
201 EXPECT_FALSE(pile_.CanRasterSlowTileCheck(rect));
204 TEST_F(PicturePileTest, NoInvalidationValidViewport) {
205 // This test validates that the recorded_viewport cache of full tiles
206 // is still valid for some use cases. If it's not, it's a performance
207 // issue because CanRaster checks will go down the slow path.
208 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
210 // No invalidation, same viewport.
211 Region invalidation;
212 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
213 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
214 EXPECT_EQ(Region().ToString(), invalidation.ToString());
216 // Partial invalidation, same viewport.
217 invalidation = gfx::Rect(0, 0, 1, 1);
218 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
219 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
220 EXPECT_EQ(gfx::Rect(0, 0, 1, 1).ToString(), invalidation.ToString());
222 // No invalidation, changing viewport.
223 invalidation = Region();
224 UpdateAndExpandInvalidation(&invalidation, tiling_size(),
225 gfx::Rect(5, 5, 5, 5));
226 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
227 EXPECT_EQ(Region().ToString(), invalidation.ToString());
230 TEST_F(PicturePileTest, BigFullLayerInvalidation) {
231 gfx::Size huge_layer_size(100000000, 100000000);
232 gfx::Rect viewport(300000, 400000, 5000, 6000);
234 // Resize the pile.
235 Region invalidation;
236 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
238 // Invalidating a huge layer should be fast.
239 base::TimeTicks start = base::TimeTicks::Now();
240 invalidation = gfx::Rect(huge_layer_size);
241 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
242 base::TimeTicks end = base::TimeTicks::Now();
243 base::TimeDelta length = end - start;
244 // This is verrrry generous to avoid flake.
245 EXPECT_LT(length.InSeconds(), 5);
248 TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeGrow) {
249 gfx::Size huge_layer_size(100000000, 100000000);
250 gfx::Rect viewport(300000, 400000, 5000, 6000);
252 // Resize the pile.
253 Region invalidation;
254 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
256 // Resize the pile even larger, while invalidating everything in the old size.
257 // Invalidating the whole thing should be fast.
258 base::TimeTicks start = base::TimeTicks::Now();
259 gfx::Size bigger_layer_size(huge_layer_size.width() * 2,
260 huge_layer_size.height() * 2);
261 invalidation = gfx::Rect(huge_layer_size);
262 UpdateAndExpandInvalidation(&invalidation, bigger_layer_size, viewport);
263 base::TimeTicks end = base::TimeTicks::Now();
264 base::TimeDelta length = end - start;
265 // This is verrrry generous to avoid flake.
266 EXPECT_LT(length.InSeconds(), 5);
269 TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeShrink) {
270 gfx::Size huge_layer_size(100000000, 100000000);
271 gfx::Rect viewport(300000, 400000, 5000, 6000);
273 // Resize the pile.
274 Region invalidation;
275 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
277 // Resize the pile smaller, while invalidating everything in the new size.
278 // Invalidating the whole thing should be fast.
279 base::TimeTicks start = base::TimeTicks::Now();
280 gfx::Size smaller_layer_size(huge_layer_size.width() - 1000,
281 huge_layer_size.height() - 1000);
282 invalidation = gfx::Rect(smaller_layer_size);
283 UpdateAndExpandInvalidation(&invalidation, smaller_layer_size, viewport);
284 base::TimeTicks end = base::TimeTicks::Now();
285 base::TimeDelta length = end - start;
286 // This is verrrry generous to avoid flake.
287 EXPECT_LT(length.InSeconds(), 5);
290 TEST_F(PicturePileTest, InvalidationOutsideRecordingRect) {
291 gfx::Size huge_layer_size(10000000, 20000000);
292 gfx::Rect viewport(300000, 400000, 5000, 6000);
294 // Resize the pile and set up the interest rect.
295 Region invalidation;
296 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
298 // Invalidation inside the recording rect does not need to be expanded.
299 invalidation = viewport;
300 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
301 EXPECT_EQ(viewport.ToString(), invalidation.ToString());
303 // Invalidation outside the recording rect should expand to the tiles it
304 // covers.
305 gfx::Rect recorded_over_tiles =
306 pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
307 gfx::Rect invalidation_outside(
308 recorded_over_tiles.right(), recorded_over_tiles.y(), 30, 30);
309 invalidation = invalidation_outside;
310 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
311 gfx::Rect expanded_recorded_viewport =
312 pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
313 Region expected_invalidation =
314 pile_.tiling().ExpandRectToTileBounds(invalidation_outside);
315 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
318 enum Corner {
319 TOP_LEFT,
320 TOP_RIGHT,
321 BOTTOM_LEFT,
322 BOTTOM_RIGHT,
325 class PicturePileResizeCornerTest : public PicturePileTestBase,
326 public testing::TestWithParam<Corner> {
327 protected:
328 void SetUp() override { InitializeData(); }
330 static gfx::Rect CornerSinglePixelRect(Corner corner, const gfx::Size& s) {
331 switch (corner) {
332 case TOP_LEFT:
333 return gfx::Rect(0, 0, 1, 1);
334 case TOP_RIGHT:
335 return gfx::Rect(s.width() - 1, 0, 1, 1);
336 case BOTTOM_LEFT:
337 return gfx::Rect(0, s.height() - 1, 1, 1);
338 case BOTTOM_RIGHT:
339 return gfx::Rect(s.width() - 1, s.height() - 1, 1, 1);
341 NOTREACHED();
342 return gfx::Rect();
346 TEST_P(PicturePileResizeCornerTest, ResizePileOutsideInterestRect) {
347 Corner corner = GetParam();
349 // This size chosen to be larger than the interest rect size, which is
350 // at least kPixelDistanceToRecord * 2 in each dimension.
351 int tile_size = 100000;
352 // The small number subtracted keeps the last tile in each axis larger than
353 // the interest rect also.
354 int offset = -100;
355 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
356 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
357 8 * tile_size + offset);
358 gfx::Size grow_right_tiling_size(8 * tile_size + offset,
359 6 * tile_size + offset);
360 gfx::Size grow_both_tiling_size(8 * tile_size + offset,
361 8 * tile_size + offset);
363 Region invalidation;
364 Region expected_invalidation;
366 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
367 SetTilingSize(base_tiling_size);
369 // We should have a recording for every tile.
370 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
371 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
372 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
373 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
374 FakePicturePile::PictureMapKey key(i, j);
375 FakePicturePile::PictureMap& map = pile_.picture_map();
376 FakePicturePile::PictureMap::iterator it = map.find(key);
377 EXPECT_TRUE(it != map.end() && it->second.get());
381 UpdateAndExpandInvalidation(
382 &invalidation,
383 grow_down_tiling_size,
384 CornerSinglePixelRect(corner, grow_down_tiling_size));
386 // We should have lost all of the recordings in the bottom row as none of them
387 // are in the current interest rect (which is either the above or below it).
388 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
389 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
390 for (int i = 0; i < 6; ++i) {
391 for (int j = 0; j < 6; ++j) {
392 FakePicturePile::PictureMapKey key(i, j);
393 FakePicturePile::PictureMap& map = pile_.picture_map();
394 FakePicturePile::PictureMap::iterator it = map.find(key);
395 EXPECT_EQ(j < 5, it != map.end() && it->second.get());
399 // We invalidated all new pixels in the recording.
400 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
401 gfx::Rect(base_tiling_size));
402 // But the new pixels don't cover the whole bottom row.
403 gfx::Rect bottom_row = gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
404 pile_.tiling().TileBounds(5, 5));
405 EXPECT_FALSE(expected_invalidation.Contains(bottom_row));
406 // We invalidated the entire old bottom row.
407 expected_invalidation.Union(bottom_row);
408 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
409 invalidation.Clear();
411 UpdateWholePile();
412 UpdateAndExpandInvalidation(&invalidation,
413 base_tiling_size,
414 CornerSinglePixelRect(corner, base_tiling_size));
416 // When shrinking, we should have lost all the recordings in the bottom row
417 // not touching the interest rect.
418 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
419 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
420 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
421 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
422 FakePicturePile::PictureMapKey key(i, j);
423 FakePicturePile::PictureMap& map = pile_.picture_map();
424 FakePicturePile::PictureMap::iterator it = map.find(key);
425 bool expect_tile;
426 switch (corner) {
427 case TOP_LEFT:
428 case TOP_RIGHT:
429 expect_tile = j < 5;
430 break;
431 case BOTTOM_LEFT:
432 // The interest rect in the bottom left tile means we'll record it.
433 expect_tile = j < 5 || (j == 5 && i == 0);
434 break;
435 case BOTTOM_RIGHT:
436 // The interest rect in the bottom right tile means we'll record it.
437 expect_tile = j < 5 || (j == 5 && i == 5);
438 break;
440 EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
444 // When shrinking, the previously exposed region is invalidated.
445 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
446 gfx::Rect(base_tiling_size));
447 // The whole bottom row of tiles (except any with the interest rect) are
448 // dropped.
449 gfx::Rect bottom_row_minus_existing_corner = gfx::UnionRects(
450 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
451 switch (corner) {
452 case TOP_LEFT:
453 case TOP_RIGHT:
454 // No tiles are kept in the changed region because it doesn't
455 // intersect with the interest rect.
456 break;
457 case BOTTOM_LEFT:
458 bottom_row_minus_existing_corner.Subtract(
459 pile_.tiling().TileBounds(0, 5));
460 break;
461 case BOTTOM_RIGHT:
462 bottom_row_minus_existing_corner.Subtract(
463 pile_.tiling().TileBounds(5, 5));
464 break;
467 expected_invalidation.Union(bottom_row_minus_existing_corner);
468 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
469 invalidation.Clear();
471 UpdateWholePile();
472 UpdateAndExpandInvalidation(
473 &invalidation,
474 grow_right_tiling_size,
475 CornerSinglePixelRect(corner, grow_right_tiling_size));
477 // We should have lost all of the recordings in the right column as none of
478 // them are in the current interest rect (which is either entirely left or
479 // right of it).
480 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
481 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
482 for (int i = 0; i < 6; ++i) {
483 for (int j = 0; j < 6; ++j) {
484 FakePicturePile::PictureMapKey key(i, j);
485 FakePicturePile::PictureMap& map = pile_.picture_map();
486 FakePicturePile::PictureMap::iterator it = map.find(key);
487 EXPECT_EQ(i < 5, it != map.end() && it->second.get());
491 // We invalidated all new pixels in the recording.
492 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
493 gfx::Rect(base_tiling_size));
494 // But the new pixels don't cover the whole right_column.
495 gfx::Rect right_column = gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
496 pile_.tiling().TileBounds(5, 5));
497 EXPECT_FALSE(expected_invalidation.Contains(right_column));
498 // We invalidated the entire old right column.
499 expected_invalidation.Union(right_column);
500 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
501 invalidation.Clear();
503 UpdateWholePile();
504 UpdateAndExpandInvalidation(&invalidation,
505 base_tiling_size,
506 CornerSinglePixelRect(corner, base_tiling_size));
508 // When shrinking, we should have lost all the recordings in the right column
509 // not touching the interest rect.
510 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
511 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
512 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
513 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
514 FakePicturePile::PictureMapKey key(i, j);
515 FakePicturePile::PictureMap& map = pile_.picture_map();
516 FakePicturePile::PictureMap::iterator it = map.find(key);
517 bool expect_tile;
518 switch (corner) {
519 case TOP_LEFT:
520 case BOTTOM_LEFT:
521 // No tiles are kept in the changed region because it doesn't
522 // intersect with the interest rect.
523 expect_tile = i < 5;
524 break;
525 case TOP_RIGHT:
526 // The interest rect in the top right tile means we'll record it.
527 expect_tile = i < 5 || (j == 0 && i == 5);
528 break;
529 case BOTTOM_RIGHT:
530 // The interest rect in the bottom right tile means we'll record it.
531 expect_tile = i < 5 || (j == 5 && i == 5);
532 break;
534 EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
538 // When shrinking, the previously exposed region is invalidated.
539 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
540 gfx::Rect(base_tiling_size));
541 // The whole right column of tiles (except for ones with the interest rect)
542 // are dropped.
543 gfx::Rect right_column_minus_existing_corner = gfx::UnionRects(
544 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
545 switch (corner) {
546 case TOP_LEFT:
547 case BOTTOM_LEFT:
548 break;
549 case TOP_RIGHT:
550 right_column_minus_existing_corner.Subtract(
551 pile_.tiling().TileBounds(5, 0));
552 break;
553 case BOTTOM_RIGHT:
554 right_column_minus_existing_corner.Subtract(
555 pile_.tiling().TileBounds(5, 5));
556 break;
558 expected_invalidation.Union(right_column_minus_existing_corner);
559 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
560 invalidation.Clear();
562 UpdateWholePile();
563 UpdateAndExpandInvalidation(
564 &invalidation,
565 grow_both_tiling_size,
566 CornerSinglePixelRect(corner, grow_both_tiling_size));
568 // We should have lost the recordings in the right column and bottom row.
569 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
570 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
571 for (int i = 0; i < 6; ++i) {
572 for (int j = 0; j < 6; ++j) {
573 FakePicturePile::PictureMapKey key(i, j);
574 FakePicturePile::PictureMap& map = pile_.picture_map();
575 FakePicturePile::PictureMap::iterator it = map.find(key);
576 EXPECT_EQ(i < 5 && j < 5, it != map.end() && it->second.get());
580 // We invalidated all new pixels in the recording.
581 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
582 gfx::Rect(base_tiling_size));
583 // But the new pixels don't cover the whole right column or bottom row.
584 Region right_column_and_bottom_row =
585 UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
586 pile_.tiling().TileBounds(5, 5)),
587 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
588 pile_.tiling().TileBounds(5, 5)));
589 EXPECT_FALSE(expected_invalidation.Contains(right_column_and_bottom_row));
590 // We invalidated the entire old right column and the old bottom row.
591 expected_invalidation.Union(right_column_and_bottom_row);
592 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
593 invalidation.Clear();
595 UpdateWholePile();
596 UpdateAndExpandInvalidation(&invalidation, base_tiling_size,
597 CornerSinglePixelRect(corner, base_tiling_size));
599 // We should have lost the recordings in the right column and bottom row,
600 // except where it intersects the interest rect.
601 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
602 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
603 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
604 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
605 FakePicturePile::PictureMapKey key(i, j);
606 FakePicturePile::PictureMap& map = pile_.picture_map();
607 FakePicturePile::PictureMap::iterator it = map.find(key);
608 bool expect_tile;
609 switch (corner) {
610 case TOP_LEFT:
611 expect_tile = i < 5 && j < 5;
612 break;
613 case TOP_RIGHT:
614 // The interest rect in the top right tile means we'll record it.
615 expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
616 break;
617 case BOTTOM_LEFT:
618 // The interest rect in the bottom left tile means we'll record it.
619 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
620 break;
621 case BOTTOM_RIGHT:
622 // The interest rect in the bottom right tile means we'll record it.
623 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
624 break;
626 EXPECT_EQ(expect_tile, it != map.end() && it->second.get()) << i << ","
627 << j;
631 // We invalidated all previous pixels in the recording.
632 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
633 gfx::Rect(base_tiling_size));
634 // The whole right column and bottom row of tiles (except for ones with the
635 // interest rect) are dropped.
636 Region right_column_and_bottom_row_minus_existing_corner =
637 right_column_and_bottom_row;
638 switch (corner) {
639 case TOP_LEFT:
640 break;
641 case BOTTOM_LEFT:
642 right_column_and_bottom_row_minus_existing_corner.Subtract(
643 pile_.tiling().TileBounds(0, 5));
644 break;
645 case TOP_RIGHT:
646 right_column_and_bottom_row_minus_existing_corner.Subtract(
647 pile_.tiling().TileBounds(5, 0));
648 break;
649 case BOTTOM_RIGHT:
650 right_column_and_bottom_row_minus_existing_corner.Subtract(
651 pile_.tiling().TileBounds(5, 5));
652 break;
654 expected_invalidation.Union(
655 right_column_and_bottom_row_minus_existing_corner);
656 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
657 invalidation.Clear();
660 TEST_P(PicturePileResizeCornerTest, SmallResizePileOutsideInterestRect) {
661 Corner corner = GetParam();
663 // This size chosen to be larger than the interest rect size, which is
664 // at least kPixelDistanceToRecord * 2 in each dimension.
665 int tile_size = 100000;
666 // The small number subtracted keeps the last tile in each axis larger than
667 // the interest rect also.
668 int offset = -100;
669 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
670 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
671 6 * tile_size + offset + 5);
672 gfx::Size grow_right_tiling_size(6 * tile_size + offset + 5,
673 6 * tile_size + offset);
674 gfx::Size grow_both_tiling_size(6 * tile_size + offset + 5,
675 6 * tile_size + offset + 5);
677 Region invalidation;
678 Region expected_invalidation;
680 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
681 SetTilingSize(base_tiling_size);
683 // We should have a recording for every tile.
684 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
685 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
686 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
687 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
688 FakePicturePile::PictureMapKey key(i, j);
689 FakePicturePile::PictureMap& map = pile_.picture_map();
690 FakePicturePile::PictureMap::iterator it = map.find(key);
691 EXPECT_TRUE(it != map.end() && it->second.get());
695 // In this test (unlike the large resize test), as all growing and shrinking
696 // happens within tiles, the resulting invalidation is symmetrical, so use
697 // this enum to repeat the test both ways.
698 enum ChangeDirection { GROW, SHRINK, LAST_DIRECTION = SHRINK };
700 // Grow downward.
701 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
702 gfx::Size new_tiling_size =
703 dir == GROW ? grow_down_tiling_size : base_tiling_size;
704 UpdateWholePile();
705 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
706 CornerSinglePixelRect(corner, new_tiling_size));
708 // We should have lost the recordings in the bottom row that do not
709 // intersect the interest rect.
710 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
711 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
712 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
713 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
714 FakePicturePile::PictureMapKey key(i, j);
715 FakePicturePile::PictureMap& map = pile_.picture_map();
716 FakePicturePile::PictureMap::iterator it = map.find(key);
717 bool expect_tile;
718 switch (corner) {
719 case TOP_LEFT:
720 case TOP_RIGHT:
721 expect_tile = j < 5;
722 break;
723 case BOTTOM_LEFT:
724 // The interest rect in the bottom left tile means we'll record it.
725 expect_tile = j < 5 || (j == 5 && i == 0);
726 break;
727 case BOTTOM_RIGHT:
728 // The interest rect in the bottom right tile means we'll record it.
729 expect_tile = j < 5 || (j == 5 && i == 5);
730 break;
732 EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
736 // We invalidated the bottom row outside the new interest rect. The tile
737 // that insects the interest rect in invalidated only on its newly
738 // exposed or previously exposed pixels.
739 if (dir == GROW) {
740 // Only calculate the expected invalidation while growing, as the tile
741 // bounds post-growing is the newly exposed / previously exposed sizes.
742 // Post-shrinking, the tile bounds are smaller, so can't be used.
743 switch (corner) {
744 case TOP_LEFT:
745 case TOP_RIGHT:
746 expected_invalidation = gfx::UnionRects(
747 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
748 break;
749 case BOTTOM_LEFT:
750 expected_invalidation = gfx::UnionRects(
751 pile_.tiling().TileBounds(1, 5), pile_.tiling().TileBounds(5, 5));
752 expected_invalidation.Union(SubtractRects(
753 pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
754 break;
755 case BOTTOM_RIGHT:
756 expected_invalidation = gfx::UnionRects(
757 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(4, 5));
758 expected_invalidation.Union(SubtractRects(
759 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
760 break;
763 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
764 invalidation.Clear();
767 // Grow right.
768 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
769 gfx::Size new_tiling_size =
770 dir == GROW ? grow_right_tiling_size : base_tiling_size;
771 UpdateWholePile();
772 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
773 CornerSinglePixelRect(corner, new_tiling_size));
775 // We should have lost the recordings in the right column.
776 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
777 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
778 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
779 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
780 FakePicturePile::PictureMapKey key(i, j);
781 FakePicturePile::PictureMap& map = pile_.picture_map();
782 FakePicturePile::PictureMap::iterator it = map.find(key);
783 bool expect_tile;
784 switch (corner) {
785 case TOP_LEFT:
786 case BOTTOM_LEFT:
787 expect_tile = i < 5;
788 break;
789 case TOP_RIGHT:
790 // The interest rect in the top right tile means we'll record it.
791 expect_tile = i < 5 || (j == 0 && i == 5);
792 break;
793 case BOTTOM_RIGHT:
794 // The interest rect in the bottom right tile means we'll record it.
795 expect_tile = i < 5 || (j == 5 && i == 5);
796 break;
798 EXPECT_EQ(expect_tile, it != map.end() && it->second.get());
802 // We invalidated the right column outside the new interest rect. The tile
803 // that insects the interest rect in invalidated only on its new or
804 // previously exposed pixels.
805 if (dir == GROW) {
806 // Calculate the expected invalidation the first time through the loop.
807 switch (corner) {
808 case TOP_LEFT:
809 case BOTTOM_LEFT:
810 expected_invalidation = gfx::UnionRects(
811 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
812 break;
813 case TOP_RIGHT:
814 expected_invalidation = gfx::UnionRects(
815 pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
816 expected_invalidation.Union(SubtractRects(
817 pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
818 break;
819 case BOTTOM_RIGHT:
820 expected_invalidation = gfx::UnionRects(
821 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
822 expected_invalidation.Union(SubtractRects(
823 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
824 break;
827 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
828 invalidation.Clear();
831 // Grow both.
832 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
833 gfx::Size new_tiling_size =
834 dir == GROW ? grow_both_tiling_size : base_tiling_size;
835 UpdateWholePile();
836 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
837 CornerSinglePixelRect(corner, new_tiling_size));
839 // We should have lost the recordings in the right column and bottom row.
840 // The tile that insects the interest rect in invalidated only on its new
841 // or previously exposed pixels.
842 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
843 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
844 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
845 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
846 FakePicturePile::PictureMapKey key(i, j);
847 FakePicturePile::PictureMap& map = pile_.picture_map();
848 FakePicturePile::PictureMap::iterator it = map.find(key);
849 bool expect_tile;
850 switch (corner) {
851 case TOP_LEFT:
852 expect_tile = i < 5 && j < 5;
853 break;
854 case TOP_RIGHT:
855 // The interest rect in the top right tile means we'll record it.
856 expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
857 break;
858 case BOTTOM_LEFT:
859 // The interest rect in the bottom left tile means we'll record it.
860 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
861 break;
862 case BOTTOM_RIGHT:
863 // The interest rect in the bottom right tile means we'll record it.
864 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
865 break;
867 EXPECT_EQ(expect_tile, it != map.end() && it->second.get()) << i << ","
868 << j;
872 // We invalidated the right column and the bottom row outside the new
873 // interest rect. The tile that insects the interest rect in invalidated
874 // only on its new or previous exposed pixels.
875 if (dir == GROW) {
876 // Calculate the expected invalidation the first time through the loop.
877 switch (corner) {
878 case TOP_LEFT:
879 expected_invalidation = gfx::UnionRects(
880 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
881 expected_invalidation.Union(
882 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
883 pile_.tiling().TileBounds(5, 5)));
884 break;
885 case TOP_RIGHT:
886 expected_invalidation = gfx::UnionRects(
887 pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
888 expected_invalidation.Union(
889 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
890 pile_.tiling().TileBounds(5, 5)));
891 expected_invalidation.Union(SubtractRects(
892 pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
893 break;
894 case BOTTOM_LEFT:
895 expected_invalidation = gfx::UnionRects(
896 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
897 expected_invalidation.Union(
898 gfx::UnionRects(pile_.tiling().TileBounds(1, 5),
899 pile_.tiling().TileBounds(5, 5)));
900 expected_invalidation.Union(SubtractRects(
901 pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
902 break;
903 case BOTTOM_RIGHT:
904 expected_invalidation = gfx::UnionRects(
905 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
906 expected_invalidation.Union(
907 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
908 pile_.tiling().TileBounds(4, 5)));
909 expected_invalidation.Union(SubtractRegions(
910 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
911 break;
914 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
915 invalidation.Clear();
919 INSTANTIATE_TEST_CASE_P(
920 PicturePileResizeCornerTests,
921 PicturePileResizeCornerTest,
922 ::testing::Values(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT));
924 TEST_F(PicturePileTest, ResizePileInsideInterestRect) {
925 // This size chosen to be small enough that all the rects below fit inside the
926 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
927 // dimension.
928 int tile_size = 100;
929 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
930 gfx::Size grow_down_tiling_size(5 * tile_size, 7 * tile_size);
931 gfx::Size grow_right_tiling_size(7 * tile_size, 5 * tile_size);
932 gfx::Size grow_both_tiling_size(7 * tile_size, 7 * tile_size);
934 Region invalidation;
935 Region expected_invalidation;
937 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
938 SetTilingSize(base_tiling_size);
940 // We should have a recording for every tile.
941 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
942 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
943 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
944 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
945 FakePicturePile::PictureMapKey key(i, j);
946 FakePicturePile::PictureMap& map = pile_.picture_map();
947 FakePicturePile::PictureMap::iterator it = map.find(key);
948 EXPECT_TRUE(it != map.end() && it->second.get());
952 UpdateAndExpandInvalidation(
953 &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
955 // We should have a recording for every tile.
956 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
957 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
958 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
959 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
960 FakePicturePile::PictureMapKey key(i, j);
961 FakePicturePile::PictureMap& map = pile_.picture_map();
962 FakePicturePile::PictureMap::iterator it = map.find(key);
963 EXPECT_TRUE(it != map.end() && it->second.get());
967 // We invalidated the newly exposed pixels on the bottom row of tiles.
968 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
969 gfx::Rect(base_tiling_size));
970 Region bottom_row_new_pixels =
971 SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
972 pile_.tiling().TileBounds(5, 5)),
973 gfx::Rect(base_tiling_size));
974 EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
975 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
976 invalidation.Clear();
978 UpdateWholePile();
979 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
981 // We should have a recording for every tile.
982 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
983 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
984 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
985 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
986 FakePicturePile::PictureMapKey key(i, j);
987 FakePicturePile::PictureMap& map = pile_.picture_map();
988 FakePicturePile::PictureMap::iterator it = map.find(key);
989 EXPECT_TRUE(it != map.end() && it->second.get());
993 // We invalidated the previously exposed pixels on the bottom row of tiles.
994 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
995 gfx::Rect(base_tiling_size));
996 EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
997 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
998 invalidation.Clear();
1000 UpdateWholePile();
1001 UpdateAndExpandInvalidation(
1002 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1004 // We should have a recording for every tile.
1005 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
1006 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1007 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1008 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1009 FakePicturePile::PictureMapKey key(i, j);
1010 FakePicturePile::PictureMap& map = pile_.picture_map();
1011 FakePicturePile::PictureMap::iterator it = map.find(key);
1012 EXPECT_TRUE(it != map.end() && it->second.get());
1016 // We invalidated the newly exposed pixels on the right column of tiles.
1017 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1018 gfx::Rect(base_tiling_size));
1019 Region right_column_new_pixels =
1020 SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
1021 pile_.tiling().TileBounds(5, 5)),
1022 gfx::Rect(base_tiling_size));
1023 EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
1024 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1025 invalidation.Clear();
1027 UpdateWholePile();
1028 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1030 // We should have lost the recordings that are now outside the tiling only.
1031 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1032 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1033 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1034 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1035 FakePicturePile::PictureMapKey key(i, j);
1036 FakePicturePile::PictureMap& map = pile_.picture_map();
1037 FakePicturePile::PictureMap::iterator it = map.find(key);
1038 EXPECT_TRUE(it != map.end() && it->second.get());
1042 // We invalidated the previously exposed pixels on the right column of tiles.
1043 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1044 gfx::Rect(base_tiling_size));
1045 EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
1046 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1047 invalidation.Clear();
1049 UpdateWholePile();
1050 UpdateAndExpandInvalidation(
1051 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1053 // We should have a recording for every tile.
1054 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
1055 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
1056 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1057 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1058 FakePicturePile::PictureMapKey key(i, j);
1059 FakePicturePile::PictureMap& map = pile_.picture_map();
1060 FakePicturePile::PictureMap::iterator it = map.find(key);
1061 EXPECT_TRUE(it != map.end() && it->second.get());
1065 // We invalidated the newly exposed pixels on the bottom row and right column
1066 // of tiles.
1067 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1068 gfx::Rect(base_tiling_size));
1069 Region bottom_row_and_right_column_new_pixels = SubtractRegions(
1070 UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1071 pile_.tiling().TileBounds(5, 5)),
1072 gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
1073 pile_.tiling().TileBounds(5, 5))),
1074 gfx::Rect(base_tiling_size));
1075 EXPECT_TRUE(
1076 expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
1077 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1078 invalidation.Clear();
1080 UpdateWholePile();
1081 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1083 // We should have lost the recordings that are now outside the tiling only.
1084 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1085 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1086 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1087 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1088 FakePicturePile::PictureMapKey key(i, j);
1089 FakePicturePile::PictureMap& map = pile_.picture_map();
1090 FakePicturePile::PictureMap::iterator it = map.find(key);
1091 EXPECT_TRUE(it != map.end() && it->second.get());
1095 // We invalidated the previously exposed pixels on the bottom row and right
1096 // column of tiles.
1097 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1098 gfx::Rect(base_tiling_size));
1099 EXPECT_TRUE(
1100 expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
1101 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1102 invalidation.Clear();
1105 TEST_F(PicturePileTest, SmallResizePileInsideInterestRect) {
1106 // This size chosen to be small enough that all the rects below fit inside the
1107 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
1108 // dimension.
1109 int tile_size = 100;
1110 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
1111 gfx::Size grow_down_tiling_size(5 * tile_size, 5 * tile_size + 5);
1112 gfx::Size grow_right_tiling_size(5 * tile_size + 5, 5 * tile_size);
1113 gfx::Size grow_both_tiling_size(5 * tile_size + 5, 5 * tile_size + 5);
1115 Region invalidation;
1116 Region expected_invalidation;
1118 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
1119 SetTilingSize(base_tiling_size);
1121 // We should have a recording for every tile.
1122 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1123 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1124 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1125 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1126 FakePicturePile::PictureMapKey key(i, j);
1127 FakePicturePile::PictureMap& map = pile_.picture_map();
1128 FakePicturePile::PictureMap::iterator it = map.find(key);
1129 EXPECT_TRUE(it != map.end() && it->second.get());
1133 UpdateAndExpandInvalidation(
1134 &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
1136 // We should have a recording for every tile.
1137 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1138 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1139 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1140 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1141 FakePicturePile::PictureMapKey key(i, j);
1142 FakePicturePile::PictureMap& map = pile_.picture_map();
1143 FakePicturePile::PictureMap::iterator it = map.find(key);
1144 EXPECT_TRUE(it != map.end() && it->second.get());
1148 // We invalidated the newly exposed pixels.
1149 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1150 gfx::Rect(base_tiling_size));
1151 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1152 invalidation.Clear();
1154 UpdateWholePile();
1155 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1157 // We should have a recording for every tile.
1158 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1159 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1160 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1161 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1162 FakePicturePile::PictureMapKey key(i, j);
1163 FakePicturePile::PictureMap& map = pile_.picture_map();
1164 FakePicturePile::PictureMap::iterator it = map.find(key);
1165 EXPECT_TRUE(it != map.end() && it->second.get());
1169 // We invalidated the previously exposed pixels.
1170 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1171 gfx::Rect(base_tiling_size));
1172 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1173 invalidation.Clear();
1175 UpdateWholePile();
1176 UpdateAndExpandInvalidation(
1177 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1179 // We should have a recording for every tile.
1180 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1181 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1182 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1183 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1184 FakePicturePile::PictureMapKey key(i, j);
1185 FakePicturePile::PictureMap& map = pile_.picture_map();
1186 FakePicturePile::PictureMap::iterator it = map.find(key);
1187 EXPECT_TRUE(it != map.end() && it->second.get());
1191 // We invalidated the newly exposed pixels.
1192 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1193 gfx::Rect(base_tiling_size));
1194 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1195 invalidation.Clear();
1197 UpdateWholePile();
1198 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1200 // We should have lost the recordings that are now outside the tiling only.
1201 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1202 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1203 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1204 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1205 FakePicturePile::PictureMapKey key(i, j);
1206 FakePicturePile::PictureMap& map = pile_.picture_map();
1207 FakePicturePile::PictureMap::iterator it = map.find(key);
1208 EXPECT_TRUE(it != map.end() && it->second.get());
1212 // We invalidated the previously exposed pixels.
1213 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1214 gfx::Rect(base_tiling_size));
1215 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1216 invalidation.Clear();
1218 UpdateWholePile();
1219 UpdateAndExpandInvalidation(
1220 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1222 // We should have a recording for every tile.
1223 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1224 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1225 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1226 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1227 FakePicturePile::PictureMapKey key(i, j);
1228 FakePicturePile::PictureMap& map = pile_.picture_map();
1229 FakePicturePile::PictureMap::iterator it = map.find(key);
1230 EXPECT_TRUE(it != map.end() && it->second.get());
1234 // We invalidated the newly exposed pixels.
1235 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1236 gfx::Rect(base_tiling_size));
1237 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1238 invalidation.Clear();
1240 UpdateWholePile();
1241 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1243 // We should have lost the recordings that are now outside the tiling only.
1244 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1245 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1246 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1247 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1248 FakePicturePile::PictureMapKey key(i, j);
1249 FakePicturePile::PictureMap& map = pile_.picture_map();
1250 FakePicturePile::PictureMap::iterator it = map.find(key);
1251 EXPECT_TRUE(it != map.end() && it->second.get());
1255 // We invalidated the previously exposed pixels.
1256 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1257 gfx::Rect(base_tiling_size));
1258 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1259 invalidation.Clear();
1262 TEST_F(PicturePileTest, SolidRectangleIsSolid) {
1263 // If the client has no contents, the solid state will be true.
1264 Region invalidation1(tiling_rect());
1265 UpdateAndExpandInvalidation(&invalidation1, tiling_size(), tiling_rect());
1266 EXPECT_TRUE(pile_.is_solid_color());
1267 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), pile_.solid_color());
1269 // If there is a single rect that covers the view, the solid
1270 // state will be true.
1271 SkPaint paint;
1272 paint.setColor(SK_ColorCYAN);
1273 client_.add_draw_rect(tiling_rect(), paint);
1274 Region invalidation2(tiling_rect());
1275 UpdateAndExpandInvalidation(&invalidation2, tiling_size(), tiling_rect());
1276 EXPECT_TRUE(pile_.is_solid_color());
1277 EXPECT_EQ(SK_ColorCYAN, pile_.solid_color());
1279 // If a second smaller rect is draw that doesn't cover the viewport
1280 // completely, the solid state will be false.
1281 gfx::Rect smallRect = tiling_rect();
1282 smallRect.Inset(10, 10, 10, 10);
1283 client_.add_draw_rect(smallRect, paint);
1284 Region invalidation3(tiling_rect());
1285 UpdateAndExpandInvalidation(&invalidation3, tiling_size(), tiling_rect());
1286 EXPECT_FALSE(pile_.is_solid_color());
1288 // If a third rect is drawn over everything, we should be solid again.
1289 paint.setColor(SK_ColorRED);
1290 client_.add_draw_rect(tiling_rect(), paint);
1291 Region invalidation4(tiling_rect());
1292 UpdateAndExpandInvalidation(&invalidation4, tiling_size(), tiling_rect());
1293 EXPECT_TRUE(pile_.is_solid_color());
1294 EXPECT_EQ(SK_ColorRED, pile_.solid_color());
1296 // If we draw too many, we don't bother doing the analysis and we should no
1297 // longer be in a solid state. There are 8 rects, two clips and a translate.
1298 client_.add_draw_rect(tiling_rect(), paint);
1299 client_.add_draw_rect(tiling_rect(), paint);
1300 client_.add_draw_rect(tiling_rect(), paint);
1301 client_.add_draw_rect(tiling_rect(), paint);
1302 client_.add_draw_rect(tiling_rect(), paint);
1303 Region invalidation5(tiling_rect());
1304 UpdateAndExpandInvalidation(&invalidation5, tiling_size(), tiling_rect());
1305 EXPECT_FALSE(pile_.is_solid_color());
1308 TEST_F(PicturePileTest, NonSolidRectangleOnOffsettedLayerIsNonSolid) {
1309 gfx::Rect visible_rect(tiling_rect());
1310 visible_rect.Offset(gfx::Vector2d(1000, 1000));
1311 // The picture pile requires that the tiling completely encompass the viewport
1312 // to make this test work correctly since the recorded viewport is an
1313 // intersection of the tile size and viewport rect. This is possibly a flaw
1314 // in |PicturePile|.
1315 gfx::Size tiling_size(visible_rect.right(), visible_rect.bottom());
1316 // |Setup()| will create pictures here that mess with the test, clear it!
1317 pile_.Clear();
1319 SkPaint paint;
1320 paint.setColor(SK_ColorCYAN);
1322 // Add a rect that doesn't cover the viewport completely, the solid state
1323 // will be false.
1324 gfx::Rect smallRect = visible_rect;
1325 smallRect.Inset(10, 10, 10, 10);
1326 client_.add_draw_rect(smallRect, paint);
1327 Region invalidation(visible_rect);
1328 UpdateAndExpandInvalidation(&invalidation, tiling_size, visible_rect);
1329 EXPECT_FALSE(pile_.is_solid_color());
1332 TEST_F(PicturePileTest, SetEmptyBounds) {
1333 EXPECT_TRUE(pile_.is_solid_color());
1334 EXPECT_FALSE(pile_.GetSize().IsEmpty());
1335 EXPECT_FALSE(pile_.picture_map().empty());
1336 EXPECT_TRUE(pile_.HasRecordings());
1337 pile_.SetEmptyBounds();
1338 EXPECT_FALSE(pile_.is_solid_color());
1339 EXPECT_TRUE(pile_.GetSize().IsEmpty());
1340 EXPECT_TRUE(pile_.picture_map().empty());
1341 EXPECT_FALSE(pile_.HasRecordings());
1344 } // namespace
1345 } // namespace cc