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