Add iOS bots to 10% CQ experiment
[chromium-blink-merge.git] / cc / resources / picture_pile_unittest.cc
blob91ad7ce5d11b10625f3196c1437ff1f90463d90f
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()
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 FakePicturePile::PictureInfo& picture_info =
155 pile_.picture_map().find(FakePicturePile::PictureMapKey(0, 0))->second;
156 // We should have a picture.
157 EXPECT_TRUE(!!picture_info.GetPicture());
158 gfx::Rect picture_rect = gfx::ScaleToEnclosedRect(
159 picture_info.GetPicture()->LayerRect(), min_scale_);
161 // The the picture should be large enough that scaling it never makes a rect
162 // smaller than 1 px wide or tall.
163 EXPECT_FALSE(picture_rect.IsEmpty()) << "Picture rect " <<
164 picture_rect.ToString();
167 TEST_F(PicturePileTest, LargeInvalidateInflated) {
168 // Invalidate something inside a tile.
169 Region invalidate_rect(gfx::Rect(50, 50, 100, 100));
170 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
171 EXPECT_EQ(gfx::Rect(50, 50, 100, 100).ToString(), invalidate_rect.ToString());
173 EXPECT_EQ(1, pile_.tiling().num_tiles_x());
174 EXPECT_EQ(1, pile_.tiling().num_tiles_y());
176 FakePicturePile::PictureInfo& picture_info =
177 pile_.picture_map().find(FakePicturePile::PictureMapKey(0, 0))->second;
178 EXPECT_TRUE(!!picture_info.GetPicture());
180 int expected_inflation = pile_.buffer_pixels();
182 const Picture* base_picture = picture_info.GetPicture();
183 gfx::Rect base_picture_rect(tiling_size());
184 base_picture_rect.Inset(-expected_inflation, -expected_inflation);
185 EXPECT_EQ(base_picture_rect.ToString(),
186 base_picture->LayerRect().ToString());
189 TEST_F(PicturePileTest, InvalidateOnTileBoundaryInflated) {
190 gfx::Size new_tiling_size =
191 gfx::ToCeiledSize(gfx::ScaleSize(tiling_size(), 2.f));
192 // This creates initial pictures.
193 SetTilingSize(new_tiling_size);
195 // Due to border pixels, we should have 3 tiles.
196 EXPECT_EQ(3, pile_.tiling().num_tiles_x());
197 EXPECT_EQ(3, pile_.tiling().num_tiles_y());
199 // We should have 1/.125 - 1 = 7 border pixels.
200 EXPECT_EQ(7, pile_.buffer_pixels());
201 EXPECT_EQ(7, pile_.tiling().border_texels());
203 // Invalidate everything to have a non zero invalidation frequency.
204 UpdateWholePile();
206 // Invalidate something just over a tile boundary by a single pixel.
207 // This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
208 Region invalidate_rect(
209 gfx::Rect(pile_.tiling().TileBoundsWithBorder(0, 0).right(),
210 pile_.tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
212 50));
213 Region expected_invalidation = invalidate_rect;
214 UpdateAndExpandInvalidation(&invalidate_rect, tiling_size(), tiling_rect());
215 EXPECT_EQ(expected_invalidation.ToString(), invalidate_rect.ToString());
217 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
218 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
219 FakePicturePile::PictureInfo& picture_info =
220 pile_.picture_map()
221 .find(FakePicturePile::PictureMapKey(i, j))
222 ->second;
224 // Expect (1, 1) and (1, 0) to be invalidated once more
225 // than the rest of the tiles.
226 if (i == 1 && (j == 0 || j == 1)) {
227 EXPECT_FLOAT_EQ(
228 2.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
229 picture_info.GetInvalidationFrequencyForTesting());
230 } else {
231 EXPECT_FLOAT_EQ(
232 1.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
233 picture_info.GetInvalidationFrequencyForTesting());
239 TEST_F(PicturePileTest, InvalidateOnFullLayer) {
240 UpdateWholePile();
242 // Everything was invalidated once so far.
243 for (auto& it : pile_.picture_map()) {
244 EXPECT_FLOAT_EQ(
245 1.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
246 it.second.GetInvalidationFrequencyForTesting());
249 // Invalidate everything,
250 Region invalidation = tiling_rect();
251 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
253 // Everything was invalidated again.
254 for (auto& it : pile_.picture_map()) {
255 EXPECT_FLOAT_EQ(
256 2.0f / FakePicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED,
257 it.second.GetInvalidationFrequencyForTesting());
261 TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
262 gfx::Size new_tiling_size =
263 gfx::ToCeiledSize(gfx::ScaleSize(tiling_size(), 4.f));
264 SetTilingSize(new_tiling_size);
266 gfx::Rect viewport(tiling_size().width(), 1);
268 // Update the whole pile until the invalidation frequency is high.
269 for (int frame = 0; frame < 33; ++frame) {
270 UpdateWholePile();
273 // Make sure we have a high invalidation frequency.
274 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
275 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
276 FakePicturePile::PictureInfo& picture_info =
277 pile_.picture_map()
278 .find(FakePicturePile::PictureMapKey(i, j))
279 ->second;
280 EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting())
281 << "i " << i << " j " << j;
285 // Update once more with a small viewport.
286 Region invalidation(tiling_rect());
287 UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
288 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
290 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
291 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
292 FakePicturePile::PictureInfo& picture_info =
293 pile_.picture_map()
294 .find(FakePicturePile::PictureMapKey(i, j))
295 ->second;
296 EXPECT_FLOAT_EQ(1.0f, picture_info.GetInvalidationFrequencyForTesting());
298 // If the y far enough away we expect to find no picture (no re-recording
299 // happened). For close y, the picture should change.
300 if (j >= 2)
301 EXPECT_FALSE(picture_info.GetPicture()) << "i " << i << " j " << j;
302 else
303 EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
307 // Update a partial tile that doesn't get recorded. We should expand the
308 // invalidation to the entire tiles that overlap it.
309 Region small_invalidation =
310 gfx::Rect(pile_.tiling().TileBounds(3, 4).x(),
311 pile_.tiling().TileBounds(3, 4).y() + 10,
314 UpdateAndExpandInvalidation(&small_invalidation, tiling_size(), viewport);
315 EXPECT_TRUE(small_invalidation.Contains(gfx::UnionRects(
316 pile_.tiling().TileBounds(2, 4), pile_.tiling().TileBounds(3, 4))))
317 << small_invalidation.ToString();
319 // Now update with no invalidation and full viewport
320 Region empty_invalidation;
321 UpdateAndExpandInvalidation(&empty_invalidation, tiling_size(),
322 tiling_rect());
323 EXPECT_EQ(Region().ToString(), empty_invalidation.ToString());
325 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
326 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
327 FakePicturePile::PictureInfo& picture_info =
328 pile_.picture_map()
329 .find(FakePicturePile::PictureMapKey(i, j))
330 ->second;
331 // Expect the invalidation frequency to be less than 1, since we just
332 // updated with no invalidations.
333 EXPECT_LT(picture_info.GetInvalidationFrequencyForTesting(), 1.f);
335 // We expect that there are pictures everywhere now.
336 EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
341 TEST_F(PicturePileTest, ClearingInvalidatesRecordedRect) {
342 gfx::Rect rect(0, 0, 5, 5);
343 EXPECT_TRUE(pile_.CanRasterLayerRect(rect));
344 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(rect));
346 pile_.Clear();
348 // Make sure both the cache-aware check (using recorded region) and the normal
349 // check are both false after clearing.
350 EXPECT_FALSE(pile_.CanRasterLayerRect(rect));
351 EXPECT_FALSE(pile_.CanRasterSlowTileCheck(rect));
354 TEST_F(PicturePileTest, FrequentInvalidationCanRaster) {
355 // This test makes sure that if part of the page is frequently invalidated
356 // and doesn't get re-recorded, then CanRaster is not true for any
357 // tiles touching it, but is true for adjacent tiles, even if it
358 // overlaps on borders (edge case).
359 gfx::Size new_tiling_size =
360 gfx::ToCeiledSize(gfx::ScaleSize(tiling_size(), 4.f));
361 SetTilingSize(new_tiling_size);
363 gfx::Rect tile01_borders = pile_.tiling().TileBoundsWithBorder(0, 1);
364 gfx::Rect tile02_borders = pile_.tiling().TileBoundsWithBorder(0, 2);
365 gfx::Rect tile01_noborders = pile_.tiling().TileBounds(0, 1);
366 gfx::Rect tile02_noborders = pile_.tiling().TileBounds(0, 2);
368 // Sanity check these two tiles are overlapping with borders, since this is
369 // what the test is trying to repro.
370 EXPECT_TRUE(tile01_borders.Intersects(tile02_borders));
371 EXPECT_FALSE(tile01_noborders.Intersects(tile02_noborders));
372 UpdateWholePile();
373 EXPECT_TRUE(pile_.CanRasterLayerRect(tile01_noborders));
374 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile01_noborders));
375 EXPECT_TRUE(pile_.CanRasterLayerRect(tile02_noborders));
376 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile02_noborders));
377 // Sanity check that an initial paint goes down the fast path of having
378 // a valid recorded viewport.
379 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
381 // Update the whole layer until the invalidation frequency is high.
382 for (int frame = 0; frame < 33; ++frame) {
383 UpdateWholePile();
386 // Update once more with a small viewport.
387 gfx::Rect viewport(tiling_size().width(), 1);
388 Region invalidation(tiling_rect());
389 UpdateAndExpandInvalidation(&invalidation, tiling_size(), viewport);
390 EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
392 // Sanity check some pictures exist and others don't.
393 EXPECT_TRUE(pile_.picture_map()
394 .find(FakePicturePile::PictureMapKey(0, 1))
395 ->second.GetPicture());
396 EXPECT_FALSE(pile_.picture_map()
397 .find(FakePicturePile::PictureMapKey(0, 2))
398 ->second.GetPicture());
400 EXPECT_TRUE(pile_.CanRasterLayerRect(tile01_noborders));
401 EXPECT_TRUE(pile_.CanRasterSlowTileCheck(tile01_noborders));
402 EXPECT_FALSE(pile_.CanRasterLayerRect(tile02_noborders));
403 EXPECT_FALSE(pile_.CanRasterSlowTileCheck(tile02_noborders));
406 TEST_F(PicturePileTest, NoInvalidationValidViewport) {
407 // This test validates that the recorded_viewport cache of full tiles
408 // is still valid for some use cases. If it's not, it's a performance
409 // issue because CanRaster checks will go down the slow path.
410 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
412 // No invalidation, same viewport.
413 Region invalidation;
414 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
415 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
416 EXPECT_EQ(Region().ToString(), invalidation.ToString());
418 // Partial invalidation, same viewport.
419 invalidation = gfx::Rect(0, 0, 1, 1);
420 UpdateAndExpandInvalidation(&invalidation, tiling_size(), tiling_rect());
421 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
422 EXPECT_EQ(gfx::Rect(0, 0, 1, 1).ToString(), invalidation.ToString());
424 // No invalidation, changing viewport.
425 invalidation = Region();
426 UpdateAndExpandInvalidation(&invalidation, tiling_size(),
427 gfx::Rect(5, 5, 5, 5));
428 EXPECT_TRUE(!pile_.recorded_viewport().IsEmpty());
429 EXPECT_EQ(Region().ToString(), invalidation.ToString());
432 TEST_F(PicturePileTest, BigFullLayerInvalidation) {
433 gfx::Size huge_layer_size(100000000, 100000000);
434 gfx::Rect viewport(300000, 400000, 5000, 6000);
436 // Resize the pile.
437 Region invalidation;
438 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
440 // Invalidating a huge layer should be fast.
441 base::TimeTicks start = base::TimeTicks::Now();
442 invalidation = gfx::Rect(huge_layer_size);
443 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
444 base::TimeTicks end = base::TimeTicks::Now();
445 base::TimeDelta length = end - start;
446 // This is verrrry generous to avoid flake.
447 EXPECT_LT(length.InSeconds(), 5);
450 TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeGrow) {
451 gfx::Size huge_layer_size(100000000, 100000000);
452 gfx::Rect viewport(300000, 400000, 5000, 6000);
454 // Resize the pile.
455 Region invalidation;
456 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
458 // Resize the pile even larger, while invalidating everything in the old size.
459 // Invalidating the whole thing should be fast.
460 base::TimeTicks start = base::TimeTicks::Now();
461 gfx::Size bigger_layer_size(huge_layer_size.width() * 2,
462 huge_layer_size.height() * 2);
463 invalidation = gfx::Rect(huge_layer_size);
464 UpdateAndExpandInvalidation(&invalidation, bigger_layer_size, viewport);
465 base::TimeTicks end = base::TimeTicks::Now();
466 base::TimeDelta length = end - start;
467 // This is verrrry generous to avoid flake.
468 EXPECT_LT(length.InSeconds(), 5);
471 TEST_F(PicturePileTest, BigFullLayerInvalidationWithResizeShrink) {
472 gfx::Size huge_layer_size(100000000, 100000000);
473 gfx::Rect viewport(300000, 400000, 5000, 6000);
475 // Resize the pile.
476 Region invalidation;
477 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
479 // Resize the pile smaller, while invalidating everything in the new size.
480 // Invalidating the whole thing should be fast.
481 base::TimeTicks start = base::TimeTicks::Now();
482 gfx::Size smaller_layer_size(huge_layer_size.width() - 1000,
483 huge_layer_size.height() - 1000);
484 invalidation = gfx::Rect(smaller_layer_size);
485 UpdateAndExpandInvalidation(&invalidation, smaller_layer_size, viewport);
486 base::TimeTicks end = base::TimeTicks::Now();
487 base::TimeDelta length = end - start;
488 // This is verrrry generous to avoid flake.
489 EXPECT_LT(length.InSeconds(), 5);
492 TEST_F(PicturePileTest, InvalidationOutsideRecordingRect) {
493 gfx::Size huge_layer_size(10000000, 20000000);
494 gfx::Rect viewport(300000, 400000, 5000, 6000);
496 // Resize the pile and set up the interest rect.
497 Region invalidation;
498 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
500 // Invalidation inside the recording rect does not need to be expanded.
501 invalidation = viewport;
502 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
503 EXPECT_EQ(viewport.ToString(), invalidation.ToString());
505 // Invalidation outside the recording rect should expand to the tiles it
506 // covers.
507 gfx::Rect recorded_over_tiles =
508 pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
509 gfx::Rect invalidation_outside(
510 recorded_over_tiles.right(), recorded_over_tiles.y(), 30, 30);
511 invalidation = invalidation_outside;
512 UpdateAndExpandInvalidation(&invalidation, huge_layer_size, viewport);
513 gfx::Rect expanded_recorded_viewport =
514 pile_.tiling().ExpandRectToTileBounds(pile_.recorded_viewport());
515 Region expected_invalidation =
516 pile_.tiling().ExpandRectToTileBounds(invalidation_outside);
517 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
520 enum Corner {
521 TOP_LEFT,
522 TOP_RIGHT,
523 BOTTOM_LEFT,
524 BOTTOM_RIGHT,
527 class PicturePileResizeCornerTest : public PicturePileTestBase,
528 public testing::TestWithParam<Corner> {
529 protected:
530 void SetUp() override { InitializeData(); }
532 static gfx::Rect CornerSinglePixelRect(Corner corner, const gfx::Size& s) {
533 switch (corner) {
534 case TOP_LEFT:
535 return gfx::Rect(0, 0, 1, 1);
536 case TOP_RIGHT:
537 return gfx::Rect(s.width() - 1, 0, 1, 1);
538 case BOTTOM_LEFT:
539 return gfx::Rect(0, s.height() - 1, 1, 1);
540 case BOTTOM_RIGHT:
541 return gfx::Rect(s.width() - 1, s.height() - 1, 1, 1);
543 NOTREACHED();
544 return gfx::Rect();
548 TEST_P(PicturePileResizeCornerTest, ResizePileOutsideInterestRect) {
549 Corner corner = GetParam();
551 // This size chosen to be larger than the interest rect size, which is
552 // at least kPixelDistanceToRecord * 2 in each dimension.
553 int tile_size = 100000;
554 // The small number subtracted keeps the last tile in each axis larger than
555 // the interest rect also.
556 int offset = -100;
557 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
558 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
559 8 * tile_size + offset);
560 gfx::Size grow_right_tiling_size(8 * tile_size + offset,
561 6 * tile_size + offset);
562 gfx::Size grow_both_tiling_size(8 * tile_size + offset,
563 8 * tile_size + offset);
565 Region invalidation;
566 Region expected_invalidation;
568 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
569 SetTilingSize(base_tiling_size);
571 // We should have a recording for every tile.
572 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
573 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
574 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
575 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
576 FakePicturePile::PictureMapKey key(i, j);
577 FakePicturePile::PictureMap& map = pile_.picture_map();
578 FakePicturePile::PictureMap::iterator it = map.find(key);
579 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
583 UpdateAndExpandInvalidation(
584 &invalidation,
585 grow_down_tiling_size,
586 CornerSinglePixelRect(corner, grow_down_tiling_size));
588 // We should have lost all of the recordings in the bottom row as none of them
589 // are in the current interest rect (which is either the above or below it).
590 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
591 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
592 for (int i = 0; i < 6; ++i) {
593 for (int j = 0; j < 6; ++j) {
594 FakePicturePile::PictureMapKey key(i, j);
595 FakePicturePile::PictureMap& map = pile_.picture_map();
596 FakePicturePile::PictureMap::iterator it = map.find(key);
597 EXPECT_EQ(j < 5, it != map.end() && it->second.GetPicture());
601 // We invalidated all new pixels in the recording.
602 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
603 gfx::Rect(base_tiling_size));
604 // But the new pixels don't cover the whole bottom row.
605 gfx::Rect bottom_row = gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
606 pile_.tiling().TileBounds(5, 5));
607 EXPECT_FALSE(expected_invalidation.Contains(bottom_row));
608 // We invalidated the entire old bottom row.
609 expected_invalidation.Union(bottom_row);
610 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
611 invalidation.Clear();
613 UpdateWholePile();
614 UpdateAndExpandInvalidation(&invalidation,
615 base_tiling_size,
616 CornerSinglePixelRect(corner, base_tiling_size));
618 // When shrinking, we should have lost all the recordings in the bottom row
619 // not touching the interest rect.
620 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
621 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
622 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
623 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
624 FakePicturePile::PictureMapKey key(i, j);
625 FakePicturePile::PictureMap& map = pile_.picture_map();
626 FakePicturePile::PictureMap::iterator it = map.find(key);
627 bool expect_tile;
628 switch (corner) {
629 case TOP_LEFT:
630 case TOP_RIGHT:
631 expect_tile = j < 5;
632 break;
633 case BOTTOM_LEFT:
634 // The interest rect in the bottom left tile means we'll record it.
635 expect_tile = j < 5 || (j == 5 && i == 0);
636 break;
637 case BOTTOM_RIGHT:
638 // The interest rect in the bottom right tile means we'll record it.
639 expect_tile = j < 5 || (j == 5 && i == 5);
640 break;
642 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
646 // When shrinking, the previously exposed region is invalidated.
647 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
648 gfx::Rect(base_tiling_size));
649 // The whole bottom row of tiles (except any with the interest rect) are
650 // dropped.
651 gfx::Rect bottom_row_minus_existing_corner = gfx::UnionRects(
652 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
653 switch (corner) {
654 case TOP_LEFT:
655 case TOP_RIGHT:
656 // No tiles are kept in the changed region because it doesn't
657 // intersect with the interest rect.
658 break;
659 case BOTTOM_LEFT:
660 bottom_row_minus_existing_corner.Subtract(
661 pile_.tiling().TileBounds(0, 5));
662 break;
663 case BOTTOM_RIGHT:
664 bottom_row_minus_existing_corner.Subtract(
665 pile_.tiling().TileBounds(5, 5));
666 break;
669 expected_invalidation.Union(bottom_row_minus_existing_corner);
670 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
671 invalidation.Clear();
673 UpdateWholePile();
674 UpdateAndExpandInvalidation(
675 &invalidation,
676 grow_right_tiling_size,
677 CornerSinglePixelRect(corner, grow_right_tiling_size));
679 // We should have lost all of the recordings in the right column as none of
680 // them are in the current interest rect (which is either entirely left or
681 // right of it).
682 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
683 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
684 for (int i = 0; i < 6; ++i) {
685 for (int j = 0; j < 6; ++j) {
686 FakePicturePile::PictureMapKey key(i, j);
687 FakePicturePile::PictureMap& map = pile_.picture_map();
688 FakePicturePile::PictureMap::iterator it = map.find(key);
689 EXPECT_EQ(i < 5, it != map.end() && it->second.GetPicture());
693 // We invalidated all new pixels in the recording.
694 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
695 gfx::Rect(base_tiling_size));
696 // But the new pixels don't cover the whole right_column.
697 gfx::Rect right_column = gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
698 pile_.tiling().TileBounds(5, 5));
699 EXPECT_FALSE(expected_invalidation.Contains(right_column));
700 // We invalidated the entire old right column.
701 expected_invalidation.Union(right_column);
702 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
703 invalidation.Clear();
705 UpdateWholePile();
706 UpdateAndExpandInvalidation(&invalidation,
707 base_tiling_size,
708 CornerSinglePixelRect(corner, base_tiling_size));
710 // When shrinking, we should have lost all the recordings in the right column
711 // not touching the interest rect.
712 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
713 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
714 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
715 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
716 FakePicturePile::PictureMapKey key(i, j);
717 FakePicturePile::PictureMap& map = pile_.picture_map();
718 FakePicturePile::PictureMap::iterator it = map.find(key);
719 bool expect_tile;
720 switch (corner) {
721 case TOP_LEFT:
722 case BOTTOM_LEFT:
723 // No tiles are kept in the changed region because it doesn't
724 // intersect with the interest rect.
725 expect_tile = i < 5;
726 break;
727 case TOP_RIGHT:
728 // The interest rect in the top right tile means we'll record it.
729 expect_tile = i < 5 || (j == 0 && i == 5);
730 break;
731 case BOTTOM_RIGHT:
732 // The interest rect in the bottom right tile means we'll record it.
733 expect_tile = i < 5 || (j == 5 && i == 5);
734 break;
736 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
740 // When shrinking, the previously exposed region is invalidated.
741 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
742 gfx::Rect(base_tiling_size));
743 // The whole right column of tiles (except for ones with the interest rect)
744 // are dropped.
745 gfx::Rect right_column_minus_existing_corner = gfx::UnionRects(
746 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
747 switch (corner) {
748 case TOP_LEFT:
749 case BOTTOM_LEFT:
750 break;
751 case TOP_RIGHT:
752 right_column_minus_existing_corner.Subtract(
753 pile_.tiling().TileBounds(5, 0));
754 break;
755 case BOTTOM_RIGHT:
756 right_column_minus_existing_corner.Subtract(
757 pile_.tiling().TileBounds(5, 5));
758 break;
760 expected_invalidation.Union(right_column_minus_existing_corner);
761 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
762 invalidation.Clear();
764 UpdateWholePile();
765 UpdateAndExpandInvalidation(
766 &invalidation,
767 grow_both_tiling_size,
768 CornerSinglePixelRect(corner, grow_both_tiling_size));
770 // We should have lost the recordings in the right column and bottom row.
771 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
772 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
773 for (int i = 0; i < 6; ++i) {
774 for (int j = 0; j < 6; ++j) {
775 FakePicturePile::PictureMapKey key(i, j);
776 FakePicturePile::PictureMap& map = pile_.picture_map();
777 FakePicturePile::PictureMap::iterator it = map.find(key);
778 EXPECT_EQ(i < 5 && j < 5, it != map.end() && it->second.GetPicture());
782 // We invalidated all new pixels in the recording.
783 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
784 gfx::Rect(base_tiling_size));
785 // But the new pixels don't cover the whole right column or bottom row.
786 Region right_column_and_bottom_row =
787 UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
788 pile_.tiling().TileBounds(5, 5)),
789 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
790 pile_.tiling().TileBounds(5, 5)));
791 EXPECT_FALSE(expected_invalidation.Contains(right_column_and_bottom_row));
792 // We invalidated the entire old right column and the old bottom row.
793 expected_invalidation.Union(right_column_and_bottom_row);
794 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
795 invalidation.Clear();
797 UpdateWholePile();
798 UpdateAndExpandInvalidation(&invalidation, base_tiling_size,
799 CornerSinglePixelRect(corner, base_tiling_size));
801 // We should have lost the recordings in the right column and bottom row,
802 // except where it intersects the interest rect.
803 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
804 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
805 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
806 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
807 FakePicturePile::PictureMapKey key(i, j);
808 FakePicturePile::PictureMap& map = pile_.picture_map();
809 FakePicturePile::PictureMap::iterator it = map.find(key);
810 bool expect_tile;
811 switch (corner) {
812 case TOP_LEFT:
813 expect_tile = i < 5 && j < 5;
814 break;
815 case TOP_RIGHT:
816 // The interest rect in the top right tile means we'll record it.
817 expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
818 break;
819 case BOTTOM_LEFT:
820 // The interest rect in the bottom left tile means we'll record it.
821 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
822 break;
823 case BOTTOM_RIGHT:
824 // The interest rect in the bottom right tile means we'll record it.
825 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
826 break;
828 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture())
829 << i << "," << j;
833 // We invalidated all previous pixels in the recording.
834 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
835 gfx::Rect(base_tiling_size));
836 // The whole right column and bottom row of tiles (except for ones with the
837 // interest rect) are dropped.
838 Region right_column_and_bottom_row_minus_existing_corner =
839 right_column_and_bottom_row;
840 switch (corner) {
841 case TOP_LEFT:
842 break;
843 case BOTTOM_LEFT:
844 right_column_and_bottom_row_minus_existing_corner.Subtract(
845 pile_.tiling().TileBounds(0, 5));
846 break;
847 case TOP_RIGHT:
848 right_column_and_bottom_row_minus_existing_corner.Subtract(
849 pile_.tiling().TileBounds(5, 0));
850 break;
851 case BOTTOM_RIGHT:
852 right_column_and_bottom_row_minus_existing_corner.Subtract(
853 pile_.tiling().TileBounds(5, 5));
854 break;
856 expected_invalidation.Union(
857 right_column_and_bottom_row_minus_existing_corner);
858 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
859 invalidation.Clear();
862 TEST_P(PicturePileResizeCornerTest, SmallResizePileOutsideInterestRect) {
863 Corner corner = GetParam();
865 // This size chosen to be larger than the interest rect size, which is
866 // at least kPixelDistanceToRecord * 2 in each dimension.
867 int tile_size = 100000;
868 // The small number subtracted keeps the last tile in each axis larger than
869 // the interest rect also.
870 int offset = -100;
871 gfx::Size base_tiling_size(6 * tile_size + offset, 6 * tile_size + offset);
872 gfx::Size grow_down_tiling_size(6 * tile_size + offset,
873 6 * tile_size + offset + 5);
874 gfx::Size grow_right_tiling_size(6 * tile_size + offset + 5,
875 6 * tile_size + offset);
876 gfx::Size grow_both_tiling_size(6 * tile_size + offset + 5,
877 6 * tile_size + offset + 5);
879 Region invalidation;
880 Region expected_invalidation;
882 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
883 SetTilingSize(base_tiling_size);
885 // We should have a recording for every tile.
886 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
887 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
888 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
889 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
890 FakePicturePile::PictureMapKey key(i, j);
891 FakePicturePile::PictureMap& map = pile_.picture_map();
892 FakePicturePile::PictureMap::iterator it = map.find(key);
893 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
897 // In this test (unlike the large resize test), as all growing and shrinking
898 // happens within tiles, the resulting invalidation is symmetrical, so use
899 // this enum to repeat the test both ways.
900 enum ChangeDirection { GROW, SHRINK, LAST_DIRECTION = SHRINK };
902 // Grow downward.
903 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
904 gfx::Size new_tiling_size =
905 dir == GROW ? grow_down_tiling_size : base_tiling_size;
906 UpdateWholePile();
907 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
908 CornerSinglePixelRect(corner, new_tiling_size));
910 // We should have lost the recordings in the bottom row that do not
911 // intersect the interest rect.
912 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
913 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
914 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
915 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
916 FakePicturePile::PictureMapKey key(i, j);
917 FakePicturePile::PictureMap& map = pile_.picture_map();
918 FakePicturePile::PictureMap::iterator it = map.find(key);
919 bool expect_tile;
920 switch (corner) {
921 case TOP_LEFT:
922 case TOP_RIGHT:
923 expect_tile = j < 5;
924 break;
925 case BOTTOM_LEFT:
926 // The interest rect in the bottom left tile means we'll record it.
927 expect_tile = j < 5 || (j == 5 && i == 0);
928 break;
929 case BOTTOM_RIGHT:
930 // The interest rect in the bottom right tile means we'll record it.
931 expect_tile = j < 5 || (j == 5 && i == 5);
932 break;
934 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
938 // We invalidated the bottom row outside the new interest rect. The tile
939 // that insects the interest rect in invalidated only on its newly
940 // exposed or previously exposed pixels.
941 if (dir == GROW) {
942 // Only calculate the expected invalidation while growing, as the tile
943 // bounds post-growing is the newly exposed / previously exposed sizes.
944 // Post-shrinking, the tile bounds are smaller, so can't be used.
945 switch (corner) {
946 case TOP_LEFT:
947 case TOP_RIGHT:
948 expected_invalidation = gfx::UnionRects(
949 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(5, 5));
950 break;
951 case BOTTOM_LEFT:
952 expected_invalidation = gfx::UnionRects(
953 pile_.tiling().TileBounds(1, 5), pile_.tiling().TileBounds(5, 5));
954 expected_invalidation.Union(SubtractRects(
955 pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
956 break;
957 case BOTTOM_RIGHT:
958 expected_invalidation = gfx::UnionRects(
959 pile_.tiling().TileBounds(0, 5), pile_.tiling().TileBounds(4, 5));
960 expected_invalidation.Union(SubtractRects(
961 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
962 break;
965 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
966 invalidation.Clear();
969 // Grow right.
970 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
971 gfx::Size new_tiling_size =
972 dir == GROW ? grow_right_tiling_size : base_tiling_size;
973 UpdateWholePile();
974 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
975 CornerSinglePixelRect(corner, new_tiling_size));
977 // We should have lost the recordings in the right column.
978 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
979 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
980 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
981 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
982 FakePicturePile::PictureMapKey key(i, j);
983 FakePicturePile::PictureMap& map = pile_.picture_map();
984 FakePicturePile::PictureMap::iterator it = map.find(key);
985 bool expect_tile;
986 switch (corner) {
987 case TOP_LEFT:
988 case BOTTOM_LEFT:
989 expect_tile = i < 5;
990 break;
991 case TOP_RIGHT:
992 // The interest rect in the top right tile means we'll record it.
993 expect_tile = i < 5 || (j == 0 && i == 5);
994 break;
995 case BOTTOM_RIGHT:
996 // The interest rect in the bottom right tile means we'll record it.
997 expect_tile = i < 5 || (j == 5 && i == 5);
998 break;
1000 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture());
1004 // We invalidated the right column outside the new interest rect. The tile
1005 // that insects the interest rect in invalidated only on its new or
1006 // previously exposed pixels.
1007 if (dir == GROW) {
1008 // Calculate the expected invalidation the first time through the loop.
1009 switch (corner) {
1010 case TOP_LEFT:
1011 case BOTTOM_LEFT:
1012 expected_invalidation = gfx::UnionRects(
1013 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
1014 break;
1015 case TOP_RIGHT:
1016 expected_invalidation = gfx::UnionRects(
1017 pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
1018 expected_invalidation.Union(SubtractRects(
1019 pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
1020 break;
1021 case BOTTOM_RIGHT:
1022 expected_invalidation = gfx::UnionRects(
1023 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
1024 expected_invalidation.Union(SubtractRects(
1025 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
1026 break;
1029 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1030 invalidation.Clear();
1033 // Grow both.
1034 for (int dir = 0; dir <= LAST_DIRECTION; ++dir) {
1035 gfx::Size new_tiling_size =
1036 dir == GROW ? grow_both_tiling_size : base_tiling_size;
1037 UpdateWholePile();
1038 UpdateAndExpandInvalidation(&invalidation, new_tiling_size,
1039 CornerSinglePixelRect(corner, new_tiling_size));
1041 // We should have lost the recordings in the right column and bottom row.
1042 // The tile that insects the interest rect in invalidated only on its new
1043 // or previously exposed pixels.
1044 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1045 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1046 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1047 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1048 FakePicturePile::PictureMapKey key(i, j);
1049 FakePicturePile::PictureMap& map = pile_.picture_map();
1050 FakePicturePile::PictureMap::iterator it = map.find(key);
1051 bool expect_tile;
1052 switch (corner) {
1053 case TOP_LEFT:
1054 expect_tile = i < 5 && j < 5;
1055 break;
1056 case TOP_RIGHT:
1057 // The interest rect in the top right tile means we'll record it.
1058 expect_tile = (i < 5 && j < 5) || (j == 0 && i == 5);
1059 break;
1060 case BOTTOM_LEFT:
1061 // The interest rect in the bottom left tile means we'll record it.
1062 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 0);
1063 break;
1064 case BOTTOM_RIGHT:
1065 // The interest rect in the bottom right tile means we'll record it.
1066 expect_tile = (i < 5 && j < 5) || (j == 5 && i == 5);
1067 break;
1069 EXPECT_EQ(expect_tile, it != map.end() && it->second.GetPicture())
1070 << i << "," << j;
1074 // We invalidated the right column and the bottom row outside the new
1075 // interest rect. The tile that insects the interest rect in invalidated
1076 // only on its new or previous exposed pixels.
1077 if (dir == GROW) {
1078 // Calculate the expected invalidation the first time through the loop.
1079 switch (corner) {
1080 case TOP_LEFT:
1081 expected_invalidation = gfx::UnionRects(
1082 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
1083 expected_invalidation.Union(
1084 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1085 pile_.tiling().TileBounds(5, 5)));
1086 break;
1087 case TOP_RIGHT:
1088 expected_invalidation = gfx::UnionRects(
1089 pile_.tiling().TileBounds(5, 1), pile_.tiling().TileBounds(5, 5));
1090 expected_invalidation.Union(
1091 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1092 pile_.tiling().TileBounds(5, 5)));
1093 expected_invalidation.Union(SubtractRects(
1094 pile_.tiling().TileBounds(5, 0), gfx::Rect(base_tiling_size)));
1095 break;
1096 case BOTTOM_LEFT:
1097 expected_invalidation = gfx::UnionRects(
1098 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 5));
1099 expected_invalidation.Union(
1100 gfx::UnionRects(pile_.tiling().TileBounds(1, 5),
1101 pile_.tiling().TileBounds(5, 5)));
1102 expected_invalidation.Union(SubtractRects(
1103 pile_.tiling().TileBounds(0, 5), gfx::Rect(base_tiling_size)));
1104 break;
1105 case BOTTOM_RIGHT:
1106 expected_invalidation = gfx::UnionRects(
1107 pile_.tiling().TileBounds(5, 0), pile_.tiling().TileBounds(5, 4));
1108 expected_invalidation.Union(
1109 gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1110 pile_.tiling().TileBounds(4, 5)));
1111 expected_invalidation.Union(SubtractRegions(
1112 pile_.tiling().TileBounds(5, 5), gfx::Rect(base_tiling_size)));
1113 break;
1116 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1117 invalidation.Clear();
1121 INSTANTIATE_TEST_CASE_P(
1122 PicturePileResizeCornerTests,
1123 PicturePileResizeCornerTest,
1124 ::testing::Values(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT));
1126 TEST_F(PicturePileTest, ResizePileInsideInterestRect) {
1127 // This size chosen to be small enough that all the rects below fit inside the
1128 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
1129 // dimension.
1130 int tile_size = 100;
1131 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
1132 gfx::Size grow_down_tiling_size(5 * tile_size, 7 * tile_size);
1133 gfx::Size grow_right_tiling_size(7 * tile_size, 5 * tile_size);
1134 gfx::Size grow_both_tiling_size(7 * tile_size, 7 * tile_size);
1136 Region invalidation;
1137 Region expected_invalidation;
1139 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
1140 SetTilingSize(base_tiling_size);
1142 // We should have a recording for every tile.
1143 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1144 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1145 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1146 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1147 FakePicturePile::PictureMapKey key(i, j);
1148 FakePicturePile::PictureMap& map = pile_.picture_map();
1149 FakePicturePile::PictureMap::iterator it = map.find(key);
1150 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1154 UpdateAndExpandInvalidation(
1155 &invalidation, grow_down_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(8, 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.GetPicture());
1169 // We invalidated the newly exposed pixels on the bottom row of tiles.
1170 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1171 gfx::Rect(base_tiling_size));
1172 Region bottom_row_new_pixels =
1173 SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1174 pile_.tiling().TileBounds(5, 5)),
1175 gfx::Rect(base_tiling_size));
1176 EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
1177 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1178 invalidation.Clear();
1180 UpdateWholePile();
1181 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1183 // We should have a recording for every tile.
1184 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1185 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1186 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1187 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1188 FakePicturePile::PictureMapKey key(i, j);
1189 FakePicturePile::PictureMap& map = pile_.picture_map();
1190 FakePicturePile::PictureMap::iterator it = map.find(key);
1191 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1195 // We invalidated the previously exposed pixels on the bottom row of tiles.
1196 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1197 gfx::Rect(base_tiling_size));
1198 EXPECT_TRUE(expected_invalidation.Contains(bottom_row_new_pixels));
1199 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1200 invalidation.Clear();
1202 UpdateWholePile();
1203 UpdateAndExpandInvalidation(
1204 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1206 // We should have a recording for every tile.
1207 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
1208 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1209 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1210 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1211 FakePicturePile::PictureMapKey key(i, j);
1212 FakePicturePile::PictureMap& map = pile_.picture_map();
1213 FakePicturePile::PictureMap::iterator it = map.find(key);
1214 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1218 // We invalidated the newly exposed pixels on the right column of tiles.
1219 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1220 gfx::Rect(base_tiling_size));
1221 Region right_column_new_pixels =
1222 SubtractRegions(gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
1223 pile_.tiling().TileBounds(5, 5)),
1224 gfx::Rect(base_tiling_size));
1225 EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
1226 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1227 invalidation.Clear();
1229 UpdateWholePile();
1230 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1232 // We should have lost the recordings that are now outside the tiling only.
1233 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1234 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1235 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1236 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1237 FakePicturePile::PictureMapKey key(i, j);
1238 FakePicturePile::PictureMap& map = pile_.picture_map();
1239 FakePicturePile::PictureMap::iterator it = map.find(key);
1240 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1244 // We invalidated the previously exposed pixels on the right column of tiles.
1245 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1246 gfx::Rect(base_tiling_size));
1247 EXPECT_TRUE(expected_invalidation.Contains(right_column_new_pixels));
1248 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1249 invalidation.Clear();
1251 UpdateWholePile();
1252 UpdateAndExpandInvalidation(
1253 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1255 // We should have a recording for every tile.
1256 EXPECT_EQ(8, pile_.tiling().num_tiles_x());
1257 EXPECT_EQ(8, pile_.tiling().num_tiles_y());
1258 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1259 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1260 FakePicturePile::PictureMapKey key(i, j);
1261 FakePicturePile::PictureMap& map = pile_.picture_map();
1262 FakePicturePile::PictureMap::iterator it = map.find(key);
1263 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1267 // We invalidated the newly exposed pixels on the bottom row and right column
1268 // of tiles.
1269 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1270 gfx::Rect(base_tiling_size));
1271 Region bottom_row_and_right_column_new_pixels = SubtractRegions(
1272 UnionRegions(gfx::UnionRects(pile_.tiling().TileBounds(0, 5),
1273 pile_.tiling().TileBounds(5, 5)),
1274 gfx::UnionRects(pile_.tiling().TileBounds(5, 0),
1275 pile_.tiling().TileBounds(5, 5))),
1276 gfx::Rect(base_tiling_size));
1277 EXPECT_TRUE(
1278 expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
1279 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1280 invalidation.Clear();
1282 UpdateWholePile();
1283 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1285 // We should have lost the recordings that are now outside the tiling only.
1286 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1287 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1288 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1289 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1290 FakePicturePile::PictureMapKey key(i, j);
1291 FakePicturePile::PictureMap& map = pile_.picture_map();
1292 FakePicturePile::PictureMap::iterator it = map.find(key);
1293 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1297 // We invalidated the previously exposed pixels on the bottom row and right
1298 // column of tiles.
1299 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1300 gfx::Rect(base_tiling_size));
1301 EXPECT_TRUE(
1302 expected_invalidation.Contains(bottom_row_and_right_column_new_pixels));
1303 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1304 invalidation.Clear();
1307 TEST_F(PicturePileTest, SmallResizePileInsideInterestRect) {
1308 // This size chosen to be small enough that all the rects below fit inside the
1309 // the interest rect, so they are smaller than kPixelDistanceToRecord in each
1310 // dimension.
1311 int tile_size = 100;
1312 gfx::Size base_tiling_size(5 * tile_size, 5 * tile_size);
1313 gfx::Size grow_down_tiling_size(5 * tile_size, 5 * tile_size + 5);
1314 gfx::Size grow_right_tiling_size(5 * tile_size + 5, 5 * tile_size);
1315 gfx::Size grow_both_tiling_size(5 * tile_size + 5, 5 * tile_size + 5);
1317 Region invalidation;
1318 Region expected_invalidation;
1320 pile_.tiling().SetMaxTextureSize(gfx::Size(tile_size, tile_size));
1321 SetTilingSize(base_tiling_size);
1323 // We should have a recording for every tile.
1324 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1325 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1326 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1327 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1328 FakePicturePile::PictureMapKey key(i, j);
1329 FakePicturePile::PictureMap& map = pile_.picture_map();
1330 FakePicturePile::PictureMap::iterator it = map.find(key);
1331 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1335 UpdateAndExpandInvalidation(
1336 &invalidation, grow_down_tiling_size, gfx::Rect(1, 1));
1338 // We should have a recording for every tile.
1339 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1340 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1341 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1342 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1343 FakePicturePile::PictureMapKey key(i, j);
1344 FakePicturePile::PictureMap& map = pile_.picture_map();
1345 FakePicturePile::PictureMap::iterator it = map.find(key);
1346 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1350 // We invalidated the newly exposed pixels.
1351 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1352 gfx::Rect(base_tiling_size));
1353 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1354 invalidation.Clear();
1356 UpdateWholePile();
1357 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1359 // We should have a recording for every tile.
1360 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1361 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1362 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1363 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1364 FakePicturePile::PictureMapKey key(i, j);
1365 FakePicturePile::PictureMap& map = pile_.picture_map();
1366 FakePicturePile::PictureMap::iterator it = map.find(key);
1367 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1371 // We invalidated the previously exposed pixels.
1372 expected_invalidation = SubtractRegions(gfx::Rect(grow_down_tiling_size),
1373 gfx::Rect(base_tiling_size));
1374 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1375 invalidation.Clear();
1377 UpdateWholePile();
1378 UpdateAndExpandInvalidation(
1379 &invalidation, grow_right_tiling_size, gfx::Rect(1, 1));
1381 // We should have a recording for every tile.
1382 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1383 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1384 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1385 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1386 FakePicturePile::PictureMapKey key(i, j);
1387 FakePicturePile::PictureMap& map = pile_.picture_map();
1388 FakePicturePile::PictureMap::iterator it = map.find(key);
1389 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1393 // We invalidated the newly exposed pixels.
1394 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1395 gfx::Rect(base_tiling_size));
1396 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1397 invalidation.Clear();
1399 UpdateWholePile();
1400 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect(1, 1));
1402 // We should have lost the recordings that are now outside the tiling only.
1403 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1404 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1405 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1406 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1407 FakePicturePile::PictureMapKey key(i, j);
1408 FakePicturePile::PictureMap& map = pile_.picture_map();
1409 FakePicturePile::PictureMap::iterator it = map.find(key);
1410 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1414 // We invalidated the previously exposed pixels.
1415 expected_invalidation = SubtractRegions(gfx::Rect(grow_right_tiling_size),
1416 gfx::Rect(base_tiling_size));
1417 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1418 invalidation.Clear();
1420 UpdateWholePile();
1421 UpdateAndExpandInvalidation(
1422 &invalidation, grow_both_tiling_size, gfx::Rect(1, 1));
1424 // We should have a recording for every tile.
1425 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1426 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1427 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1428 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1429 FakePicturePile::PictureMapKey key(i, j);
1430 FakePicturePile::PictureMap& map = pile_.picture_map();
1431 FakePicturePile::PictureMap::iterator it = map.find(key);
1432 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1436 // We invalidated the newly exposed pixels.
1437 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1438 gfx::Rect(base_tiling_size));
1439 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1440 invalidation.Clear();
1442 UpdateWholePile();
1443 UpdateAndExpandInvalidation(&invalidation, base_tiling_size, gfx::Rect());
1445 // We should have lost the recordings that are now outside the tiling only.
1446 EXPECT_EQ(6, pile_.tiling().num_tiles_x());
1447 EXPECT_EQ(6, pile_.tiling().num_tiles_y());
1448 for (int i = 0; i < pile_.tiling().num_tiles_x(); ++i) {
1449 for (int j = 0; j < pile_.tiling().num_tiles_y(); ++j) {
1450 FakePicturePile::PictureMapKey key(i, j);
1451 FakePicturePile::PictureMap& map = pile_.picture_map();
1452 FakePicturePile::PictureMap::iterator it = map.find(key);
1453 EXPECT_TRUE(it != map.end() && it->second.GetPicture());
1457 // We invalidated the previously exposed pixels.
1458 expected_invalidation = SubtractRegions(gfx::Rect(grow_both_tiling_size),
1459 gfx::Rect(base_tiling_size));
1460 EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
1461 invalidation.Clear();
1464 TEST_F(PicturePileTest, SolidRectangleIsSolid) {
1465 // If the client has no contents, the solid state will be true.
1466 Region invalidation1(tiling_rect());
1467 UpdateAndExpandInvalidation(&invalidation1, tiling_size(), tiling_rect());
1468 EXPECT_TRUE(pile_.is_solid_color());
1469 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), pile_.solid_color());
1471 // If there is a single rect that covers the view, the solid
1472 // state will be true.
1473 SkPaint paint;
1474 paint.setColor(SK_ColorCYAN);
1475 client_.add_draw_rect(tiling_rect(), paint);
1476 Region invalidation2(tiling_rect());
1477 UpdateAndExpandInvalidation(&invalidation2, tiling_size(), tiling_rect());
1478 EXPECT_TRUE(pile_.is_solid_color());
1479 EXPECT_EQ(SK_ColorCYAN, pile_.solid_color());
1481 // If a second smaller rect is draw that doesn't cover the viewport
1482 // completely, the solid state will be false.
1483 gfx::Rect smallRect = tiling_rect();
1484 smallRect.Inset(10, 10, 10, 10);
1485 client_.add_draw_rect(smallRect, paint);
1486 Region invalidation3(tiling_rect());
1487 UpdateAndExpandInvalidation(&invalidation3, tiling_size(), tiling_rect());
1488 EXPECT_FALSE(pile_.is_solid_color());
1490 // If a third rect is drawn over everything, we should be solid again.
1491 paint.setColor(SK_ColorRED);
1492 client_.add_draw_rect(tiling_rect(), paint);
1493 Region invalidation4(tiling_rect());
1494 UpdateAndExpandInvalidation(&invalidation4, tiling_size(), tiling_rect());
1495 EXPECT_TRUE(pile_.is_solid_color());
1496 EXPECT_EQ(SK_ColorRED, pile_.solid_color());
1498 // If we draw too many, we don't bother doing the analysis and we should no
1499 // longer be in a solid state. There are 8 rects, two clips and a translate.
1500 client_.add_draw_rect(tiling_rect(), paint);
1501 client_.add_draw_rect(tiling_rect(), paint);
1502 client_.add_draw_rect(tiling_rect(), paint);
1503 client_.add_draw_rect(tiling_rect(), paint);
1504 client_.add_draw_rect(tiling_rect(), paint);
1505 Region invalidation5(tiling_rect());
1506 UpdateAndExpandInvalidation(&invalidation5, tiling_size(), tiling_rect());
1507 EXPECT_FALSE(pile_.is_solid_color());
1510 TEST_F(PicturePileTest, NonSolidRectangleOnOffsettedLayerIsNonSolid) {
1511 gfx::Rect visible_rect(tiling_rect());
1512 visible_rect.Offset(gfx::Vector2d(1000, 1000));
1513 // The picture pile requires that the tiling completely encompass the viewport
1514 // to make this test work correctly since the recorded viewport is an
1515 // intersection of the tile size and viewport rect. This is possibly a flaw
1516 // in |PicturePile|.
1517 gfx::Size tiling_size(visible_rect.right(), visible_rect.bottom());
1518 // |Setup()| will create pictures here that mess with the test, clear it!
1519 pile_.Clear();
1521 SkPaint paint;
1522 paint.setColor(SK_ColorCYAN);
1524 // Add a rect that doesn't cover the viewport completely, the solid state
1525 // will be false.
1526 gfx::Rect smallRect = visible_rect;
1527 smallRect.Inset(10, 10, 10, 10);
1528 client_.add_draw_rect(smallRect, paint);
1529 Region invalidation(visible_rect);
1530 UpdateAndExpandInvalidation(&invalidation, tiling_size, visible_rect);
1531 EXPECT_FALSE(pile_.is_solid_color());
1534 TEST_F(PicturePileTest, SetEmptyBounds) {
1535 EXPECT_TRUE(pile_.is_solid_color());
1536 EXPECT_FALSE(pile_.GetSize().IsEmpty());
1537 EXPECT_FALSE(pile_.picture_map().empty());
1538 EXPECT_TRUE(pile_.HasRecordings());
1539 pile_.SetEmptyBounds();
1540 EXPECT_FALSE(pile_.is_solid_color());
1541 EXPECT_TRUE(pile_.GetSize().IsEmpty());
1542 EXPECT_TRUE(pile_.picture_map().empty());
1543 EXPECT_FALSE(pile_.HasRecordings());
1546 } // namespace
1547 } // namespace cc