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