1 // Copyright (c) 2009 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 "content/renderer/paint_aggregator.h" 6 #include "testing/gtest/include/gtest/gtest.h" 7 8 namespace content { 9 10 TEST(PaintAggregator, InitialState) { 11 PaintAggregator greg; 12 EXPECT_FALSE(greg.HasPendingUpdate()); 13 } 14 15 TEST(PaintAggregator, SingleInvalidation) { 16 PaintAggregator greg; 17 18 gfx::Rect rect(2, 4, 10, 16); 19 greg.InvalidateRect(rect); 20 21 EXPECT_TRUE(greg.HasPendingUpdate()); 22 PaintAggregator::PendingUpdate update; 23 greg.PopPendingUpdate(&update); 24 25 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 26 ASSERT_EQ(1U, update.paint_rects.size()); 27 28 EXPECT_EQ(rect, update.paint_rects[0]); 29 } 30 31 TEST(PaintAggregator, DoubleDisjointInvalidation) { 32 PaintAggregator greg; 33 34 gfx::Rect r1(2, 4, 2, 40); 35 gfx::Rect r2(4, 2, 40, 2); 36 37 greg.InvalidateRect(r1); 38 greg.InvalidateRect(r2); 39 40 gfx::Rect expected_bounds = gfx::UnionRects(r1, r2); 41 42 EXPECT_TRUE(greg.HasPendingUpdate()); 43 PaintAggregator::PendingUpdate update; 44 greg.PopPendingUpdate(&update); 45 46 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 47 EXPECT_EQ(2U, update.paint_rects.size()); 48 49 EXPECT_EQ(expected_bounds, update.GetPaintBounds()); 50 } 51 52 TEST(PaintAggregator, DisjointInvalidationsCombined) { 53 PaintAggregator greg; 54 55 // Make the rectangles such that they don't overlap but cover a very large 56 // percentage of the area of covered by their union. This is so we're not 57 // very sensitive to the combining heuristic in the paint aggregator. 58 gfx::Rect r1(2, 4, 2, 1000); 59 gfx::Rect r2(5, 2, 2, 1000); 60 61 greg.InvalidateRect(r1); 62 greg.InvalidateRect(r2); 63 64 gfx::Rect expected_bounds = gfx::UnionRects(r1, r2); 65 66 EXPECT_TRUE(greg.HasPendingUpdate()); 67 PaintAggregator::PendingUpdate update; 68 greg.PopPendingUpdate(&update); 69 70 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 71 ASSERT_EQ(1U, update.paint_rects.size()); 72 73 EXPECT_EQ(expected_bounds, update.paint_rects[0]); 74 } 75 76 TEST(PaintAggregator, SingleScroll) { 77 PaintAggregator greg; 78 79 gfx::Rect rect(1, 2, 3, 4); 80 gfx::Vector2d delta(1, 0); 81 greg.ScrollRect(delta, rect); 82 83 EXPECT_TRUE(greg.HasPendingUpdate()); 84 PaintAggregator::PendingUpdate update; 85 greg.PopPendingUpdate(&update); 86 87 EXPECT_TRUE(update.paint_rects.empty()); 88 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 89 90 EXPECT_EQ(rect, update.scroll_rect); 91 92 EXPECT_EQ(delta.x(), update.scroll_delta.x()); 93 EXPECT_EQ(delta.y(), update.scroll_delta.y()); 94 95 gfx::Rect resulting_damage = update.GetScrollDamage(); 96 gfx::Rect expected_damage(1, 2, 1, 4); 97 EXPECT_EQ(expected_damage, resulting_damage); 98 } 99 100 TEST(PaintAggregator, DoubleOverlappingScroll) { 101 PaintAggregator greg; 102 103 gfx::Rect rect(1, 2, 3, 4); 104 gfx::Vector2d delta1(1, 0); 105 gfx::Vector2d delta2(1, 0); 106 greg.ScrollRect(delta1, rect); 107 greg.ScrollRect(delta2, rect); 108 109 EXPECT_TRUE(greg.HasPendingUpdate()); 110 PaintAggregator::PendingUpdate update; 111 greg.PopPendingUpdate(&update); 112 113 EXPECT_TRUE(update.paint_rects.empty()); 114 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 115 116 EXPECT_EQ(rect, update.scroll_rect); 117 118 gfx::Vector2d expected_delta = delta1 + delta2; 119 EXPECT_EQ(expected_delta.ToString(), update.scroll_delta.ToString()); 120 121 gfx::Rect resulting_damage = update.GetScrollDamage(); 122 gfx::Rect expected_damage(1, 2, 2, 4); 123 EXPECT_EQ(expected_damage, resulting_damage); 124 } 125 126 TEST(PaintAggregator, NegatingScroll) { 127 PaintAggregator greg; 128 129 // Scroll twice in opposite directions by equal amounts. The result 130 // should be no scrolling. 131 132 gfx::Rect rect(1, 2, 3, 4); 133 gfx::Vector2d delta1(1, 0); 134 gfx::Vector2d delta2(-1, 0); 135 greg.ScrollRect(delta1, rect); 136 greg.ScrollRect(delta2, rect); 137 138 EXPECT_FALSE(greg.HasPendingUpdate()); 139 } 140 141 TEST(PaintAggregator, DiagonalScroll) { 142 PaintAggregator greg; 143 144 // We don't support optimized diagonal scrolling, so this should result in 145 // repainting. 146 147 gfx::Rect rect(1, 2, 3, 4); 148 gfx::Vector2d delta(1, 1); 149 greg.ScrollRect(delta, rect); 150 151 EXPECT_TRUE(greg.HasPendingUpdate()); 152 PaintAggregator::PendingUpdate update; 153 greg.PopPendingUpdate(&update); 154 155 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 156 ASSERT_EQ(1U, update.paint_rects.size()); 157 158 EXPECT_EQ(rect, update.paint_rects[0]); 159 } 160 161 TEST(PaintAggregator, ContainedPaintAfterScroll) { 162 PaintAggregator greg; 163 164 gfx::Rect scroll_rect(0, 0, 10, 10); 165 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 166 167 gfx::Rect paint_rect(4, 4, 2, 2); 168 greg.InvalidateRect(paint_rect); 169 170 EXPECT_TRUE(greg.HasPendingUpdate()); 171 PaintAggregator::PendingUpdate update; 172 greg.PopPendingUpdate(&update); 173 174 // expecting a paint rect inside the scroll rect 175 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 176 EXPECT_EQ(1U, update.paint_rects.size()); 177 178 EXPECT_EQ(scroll_rect, update.scroll_rect); 179 EXPECT_EQ(paint_rect, update.paint_rects[0]); 180 } 181 182 TEST(PaintAggregator, ContainedPaintBeforeScroll) { 183 PaintAggregator greg; 184 185 gfx::Rect paint_rect(4, 4, 2, 2); 186 greg.InvalidateRect(paint_rect); 187 188 gfx::Rect scroll_rect(0, 0, 10, 10); 189 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 190 191 EXPECT_TRUE(greg.HasPendingUpdate()); 192 PaintAggregator::PendingUpdate update; 193 greg.PopPendingUpdate(&update); 194 195 // Expecting a paint rect inside the scroll rect 196 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 197 EXPECT_EQ(1U, update.paint_rects.size()); 198 199 paint_rect.Offset(2, 0); 200 201 EXPECT_EQ(scroll_rect, update.scroll_rect); 202 EXPECT_EQ(paint_rect, update.paint_rects[0]); 203 } 204 205 TEST(PaintAggregator, ContainedPaintsBeforeAndAfterScroll) { 206 PaintAggregator greg; 207 208 gfx::Rect paint_rect1(4, 4, 2, 2); 209 greg.InvalidateRect(paint_rect1); 210 211 gfx::Rect scroll_rect(0, 0, 10, 10); 212 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 213 214 gfx::Rect paint_rect2(6, 4, 2, 2); 215 greg.InvalidateRect(paint_rect2); 216 217 gfx::Rect expected_paint_rect = paint_rect2; 218 219 EXPECT_TRUE(greg.HasPendingUpdate()); 220 PaintAggregator::PendingUpdate update; 221 greg.PopPendingUpdate(&update); 222 223 // Expecting a paint rect inside the scroll rect 224 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 225 EXPECT_EQ(1U, update.paint_rects.size()); 226 227 EXPECT_EQ(scroll_rect, update.scroll_rect); 228 EXPECT_EQ(expected_paint_rect, update.paint_rects[0]); 229 } 230 231 TEST(PaintAggregator, LargeContainedPaintAfterScroll) { 232 PaintAggregator greg; 233 234 gfx::Rect scroll_rect(0, 0, 10, 10); 235 greg.ScrollRect(gfx::Vector2d(0, 1), scroll_rect); 236 237 gfx::Rect paint_rect(0, 0, 10, 9); // Repaint 90% 238 greg.InvalidateRect(paint_rect); 239 240 EXPECT_TRUE(greg.HasPendingUpdate()); 241 PaintAggregator::PendingUpdate update; 242 greg.PopPendingUpdate(&update); 243 244 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 245 EXPECT_EQ(1U, update.paint_rects.size()); 246 247 EXPECT_EQ(scroll_rect, update.paint_rects[0]); 248 } 249 250 TEST(PaintAggregator, LargeContainedPaintBeforeScroll) { 251 PaintAggregator greg; 252 253 gfx::Rect paint_rect(0, 0, 10, 9); // Repaint 90% 254 greg.InvalidateRect(paint_rect); 255 256 gfx::Rect scroll_rect(0, 0, 10, 10); 257 greg.ScrollRect(gfx::Vector2d(0, 1), scroll_rect); 258 259 EXPECT_TRUE(greg.HasPendingUpdate()); 260 PaintAggregator::PendingUpdate update; 261 greg.PopPendingUpdate(&update); 262 263 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 264 EXPECT_EQ(1U, update.paint_rects.size()); 265 266 EXPECT_EQ(scroll_rect, update.paint_rects[0]); 267 } 268 269 TEST(PaintAggregator, OverlappingPaintBeforeScroll) { 270 PaintAggregator greg; 271 272 gfx::Rect paint_rect(4, 4, 10, 2); 273 greg.InvalidateRect(paint_rect); 274 275 gfx::Rect scroll_rect(0, 0, 10, 10); 276 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 277 278 gfx::Rect expected_paint_rect = gfx::UnionRects(scroll_rect, paint_rect); 279 280 EXPECT_TRUE(greg.HasPendingUpdate()); 281 PaintAggregator::PendingUpdate update; 282 greg.PopPendingUpdate(&update); 283 284 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 285 EXPECT_EQ(1U, update.paint_rects.size()); 286 287 EXPECT_EQ(expected_paint_rect, update.paint_rects[0]); 288 } 289 290 TEST(PaintAggregator, OverlappingPaintAfterScroll) { 291 PaintAggregator greg; 292 293 gfx::Rect scroll_rect(0, 0, 10, 10); 294 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 295 296 gfx::Rect paint_rect(4, 4, 10, 2); 297 greg.InvalidateRect(paint_rect); 298 299 gfx::Rect expected_paint_rect = gfx::UnionRects(scroll_rect, paint_rect); 300 301 EXPECT_TRUE(greg.HasPendingUpdate()); 302 PaintAggregator::PendingUpdate update; 303 greg.PopPendingUpdate(&update); 304 305 EXPECT_TRUE(update.scroll_rect.IsEmpty()); 306 EXPECT_EQ(1U, update.paint_rects.size()); 307 308 EXPECT_EQ(expected_paint_rect, update.paint_rects[0]); 309 } 310 311 TEST(PaintAggregator, DisjointPaintBeforeScroll) { 312 PaintAggregator greg; 313 314 gfx::Rect paint_rect(4, 4, 10, 2); 315 greg.InvalidateRect(paint_rect); 316 317 gfx::Rect scroll_rect(0, 0, 2, 10); 318 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 319 320 EXPECT_TRUE(greg.HasPendingUpdate()); 321 PaintAggregator::PendingUpdate update; 322 greg.PopPendingUpdate(&update); 323 324 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 325 EXPECT_EQ(1U, update.paint_rects.size()); 326 327 EXPECT_EQ(paint_rect, update.paint_rects[0]); 328 EXPECT_EQ(scroll_rect, update.scroll_rect); 329 } 330 331 TEST(PaintAggregator, DisjointPaintAfterScroll) { 332 PaintAggregator greg; 333 334 gfx::Rect scroll_rect(0, 0, 2, 10); 335 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 336 337 gfx::Rect paint_rect(4, 4, 10, 2); 338 greg.InvalidateRect(paint_rect); 339 340 EXPECT_TRUE(greg.HasPendingUpdate()); 341 PaintAggregator::PendingUpdate update; 342 greg.PopPendingUpdate(&update); 343 344 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 345 EXPECT_EQ(1U, update.paint_rects.size()); 346 347 EXPECT_EQ(paint_rect, update.paint_rects[0]); 348 EXPECT_EQ(scroll_rect, update.scroll_rect); 349 } 350 351 TEST(PaintAggregator, ContainedPaintTrimmedByScroll) { 352 PaintAggregator greg; 353 354 gfx::Rect paint_rect(4, 4, 6, 6); 355 greg.InvalidateRect(paint_rect); 356 357 gfx::Rect scroll_rect(0, 0, 10, 10); 358 greg.ScrollRect(gfx::Vector2d(2, 0), scroll_rect); 359 360 // The paint rect should have become narrower. 361 gfx::Rect expected_paint_rect(6, 4, 4, 6); 362 363 EXPECT_TRUE(greg.HasPendingUpdate()); 364 PaintAggregator::PendingUpdate update; 365 greg.PopPendingUpdate(&update); 366 367 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 368 EXPECT_EQ(1U, update.paint_rects.size()); 369 370 EXPECT_EQ(expected_paint_rect, update.paint_rects[0]); 371 EXPECT_EQ(scroll_rect, update.scroll_rect); 372 } 373 374 TEST(PaintAggregator, ContainedPaintEliminatedByScroll) { 375 PaintAggregator greg; 376 377 gfx::Rect paint_rect(4, 4, 6, 6); 378 greg.InvalidateRect(paint_rect); 379 380 gfx::Rect scroll_rect(0, 0, 10, 10); 381 greg.ScrollRect(gfx::Vector2d(6, 0), scroll_rect); 382 383 EXPECT_TRUE(greg.HasPendingUpdate()); 384 PaintAggregator::PendingUpdate update; 385 greg.PopPendingUpdate(&update); 386 387 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 388 EXPECT_TRUE(update.paint_rects.empty()); 389 390 EXPECT_EQ(scroll_rect, update.scroll_rect); 391 } 392 393 TEST(PaintAggregator, ContainedPaintAfterScrollTrimmedByScrollDamage) { 394 PaintAggregator greg; 395 396 gfx::Rect scroll_rect(0, 0, 10, 10); 397 greg.ScrollRect(gfx::Vector2d(4, 0), scroll_rect); 398 399 gfx::Rect paint_rect(2, 0, 4, 10); 400 greg.InvalidateRect(paint_rect); 401 402 gfx::Rect expected_scroll_damage(0, 0, 4, 10); 403 gfx::Rect expected_paint_rect(4, 0, 2, 10); 404 405 EXPECT_TRUE(greg.HasPendingUpdate()); 406 PaintAggregator::PendingUpdate update; 407 greg.PopPendingUpdate(&update); 408 409 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 410 EXPECT_EQ(1U, update.paint_rects.size()); 411 412 EXPECT_EQ(scroll_rect, update.scroll_rect); 413 EXPECT_EQ(expected_scroll_damage, update.GetScrollDamage()); 414 EXPECT_EQ(expected_paint_rect, update.paint_rects[0]); 415 } 416 417 TEST(PaintAggregator, ContainedPaintAfterScrollEliminatedByScrollDamage) { 418 PaintAggregator greg; 419 420 gfx::Rect scroll_rect(0, 0, 10, 10); 421 greg.ScrollRect(gfx::Vector2d(4, 0), scroll_rect); 422 423 gfx::Rect paint_rect(2, 0, 2, 10); 424 greg.InvalidateRect(paint_rect); 425 426 gfx::Rect expected_scroll_damage(0, 0, 4, 10); 427 428 EXPECT_TRUE(greg.HasPendingUpdate()); 429 PaintAggregator::PendingUpdate update; 430 greg.PopPendingUpdate(&update); 431 432 EXPECT_FALSE(update.scroll_rect.IsEmpty()); 433 EXPECT_TRUE(update.paint_rects.empty()); 434 435 EXPECT_EQ(scroll_rect, update.scroll_rect); 436 EXPECT_EQ(expected_scroll_damage, update.GetScrollDamage()); 437 } 438 439 } // namespace content 440