Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "painting/PaintAggregator.h"
     33 
     34 #include <gtest/gtest.h>
     35 
     36 using namespace WebCore;
     37 using namespace WebKit;
     38 
     39 namespace {
     40 
     41 TEST(PaintAggregator, InitialState)
     42 {
     43     PaintAggregator greg;
     44     EXPECT_FALSE(greg.hasPendingUpdate());
     45 }
     46 
     47 TEST(PaintAggregator, SingleInvalidation)
     48 {
     49     PaintAggregator greg;
     50 
     51     IntRect rect(2, 4, 10, 16);
     52     greg.invalidateRect(rect);
     53 
     54     EXPECT_TRUE(greg.hasPendingUpdate());
     55     PaintAggregator::PendingUpdate update;
     56     greg.popPendingUpdate(&update);
     57 
     58     EXPECT_TRUE(update.scrollRect.isEmpty());
     59     ASSERT_EQ(1U, update.paintRects.size());
     60 
     61     EXPECT_EQ(rect, update.paintRects[0]);
     62 }
     63 
     64 TEST(PaintAggregator, DoubleDisjointInvalidation)
     65 {
     66     PaintAggregator greg;
     67 
     68     IntRect r1(2, 4, 2, 40);
     69     IntRect r2(4, 2, 40, 2);
     70 
     71     greg.invalidateRect(r1);
     72     greg.invalidateRect(r2);
     73 
     74     IntRect expectedBounds = unionRect(r1, r2);
     75 
     76     EXPECT_TRUE(greg.hasPendingUpdate());
     77     PaintAggregator::PendingUpdate update;
     78     greg.popPendingUpdate(&update);
     79 
     80     EXPECT_TRUE(update.scrollRect.isEmpty());
     81     EXPECT_EQ(2U, update.paintRects.size());
     82 
     83     EXPECT_EQ(expectedBounds, update.calculatePaintBounds());
     84 }
     85 
     86 TEST(PaintAggregator, DisjointInvalidationsCombined)
     87 {
     88     PaintAggregator greg;
     89 
     90     // Make the rectangles such that they don't overlap but cover a very large
     91     // percentage of the area of covered by their union. This is so we're not
     92     // very sensitive to the combining heuristic in the paint aggregator.
     93     IntRect r1(2, 4, 2, 1000);
     94     IntRect r2(5, 2, 2, 1000);
     95 
     96     greg.invalidateRect(r1);
     97     greg.invalidateRect(r2);
     98 
     99     IntRect expectedBounds = unionRect(r1, r2);
    100 
    101     EXPECT_TRUE(greg.hasPendingUpdate());
    102     PaintAggregator::PendingUpdate update;
    103     greg.popPendingUpdate(&update);
    104 
    105     EXPECT_TRUE(update.scrollRect.isEmpty());
    106     ASSERT_EQ(1U, update.paintRects.size());
    107 
    108     EXPECT_EQ(expectedBounds, update.paintRects[0]);
    109 }
    110 
    111 TEST(PaintAggregator, SingleScroll)
    112 {
    113     PaintAggregator greg;
    114 
    115     IntRect rect(1, 2, 3, 4);
    116     IntPoint delta(1, 0);
    117     greg.scrollRect(delta.x(), delta.y(), rect);
    118 
    119     EXPECT_TRUE(greg.hasPendingUpdate());
    120     PaintAggregator::PendingUpdate update;
    121     greg.popPendingUpdate(&update);
    122 
    123     EXPECT_TRUE(update.paintRects.isEmpty());
    124     EXPECT_FALSE(update.scrollRect.isEmpty());
    125 
    126     EXPECT_EQ(rect, update.scrollRect);
    127 
    128     EXPECT_EQ(delta.x(), update.scrollDelta.x());
    129     EXPECT_EQ(delta.y(), update.scrollDelta.y());
    130 
    131     IntRect resultingDamage = update.calculateScrollDamage();
    132     IntRect expectedDamage(1, 2, 1, 4);
    133     EXPECT_EQ(expectedDamage, resultingDamage);
    134 }
    135 
    136 TEST(PaintAggregator, DoubleOverlappingScroll)
    137 {
    138     PaintAggregator greg;
    139 
    140     IntRect rect(1, 2, 3, 4);
    141     IntPoint delta1(1, 0);
    142     IntPoint delta2(1, 0);
    143     greg.scrollRect(delta1.x(), delta1.y(), rect);
    144     greg.scrollRect(delta2.x(), delta2.y(), rect);
    145 
    146     EXPECT_TRUE(greg.hasPendingUpdate());
    147     PaintAggregator::PendingUpdate update;
    148     greg.popPendingUpdate(&update);
    149 
    150     EXPECT_TRUE(update.paintRects.isEmpty());
    151     EXPECT_FALSE(update.scrollRect.isEmpty());
    152 
    153     EXPECT_EQ(rect, update.scrollRect);
    154 
    155     IntPoint expectedDelta(delta1.x() + delta2.x(),
    156                            delta1.y() + delta2.y());
    157     EXPECT_EQ(expectedDelta.x(), update.scrollDelta.x());
    158     EXPECT_EQ(expectedDelta.y(), update.scrollDelta.y());
    159 
    160     IntRect resultingDamage = update.calculateScrollDamage();
    161     IntRect expectedDamage(1, 2, 2, 4);
    162     EXPECT_EQ(expectedDamage, resultingDamage);
    163 }
    164 
    165 TEST(PaintAggregator, NegatingScroll)
    166 {
    167     PaintAggregator greg;
    168 
    169     // Scroll twice in opposite directions by equal amounts. The result
    170     // should be no scrolling.
    171 
    172     IntRect rect(1, 2, 3, 4);
    173     IntPoint delta1(1, 0);
    174     IntPoint delta2(-1, 0);
    175     greg.scrollRect(delta1.x(), delta1.y(), rect);
    176     greg.scrollRect(delta2.x(), delta2.y(), rect);
    177 
    178     EXPECT_FALSE(greg.hasPendingUpdate());
    179 }
    180 
    181 TEST(PaintAggregator, DiagonalScroll)
    182 {
    183     PaintAggregator greg;
    184 
    185     // We don't support optimized diagonal scrolling, so this should result in
    186     // repainting.
    187 
    188     IntRect rect(1, 2, 3, 4);
    189     IntPoint delta(1, 1);
    190     greg.scrollRect(delta.x(), delta.y(), rect);
    191 
    192     EXPECT_TRUE(greg.hasPendingUpdate());
    193     PaintAggregator::PendingUpdate update;
    194     greg.popPendingUpdate(&update);
    195 
    196     EXPECT_TRUE(update.scrollRect.isEmpty());
    197     ASSERT_EQ(1U, update.paintRects.size());
    198 
    199     EXPECT_EQ(rect, update.paintRects[0]);
    200 }
    201 
    202 TEST(PaintAggregator, ContainedPaintAfterScroll)
    203 {
    204     PaintAggregator greg;
    205 
    206     IntRect scrollRect(0, 0, 10, 10);
    207     greg.scrollRect(2, 0, scrollRect);
    208 
    209     IntRect paintRect(4, 4, 2, 2);
    210     greg.invalidateRect(paintRect);
    211 
    212     EXPECT_TRUE(greg.hasPendingUpdate());
    213     PaintAggregator::PendingUpdate update;
    214     greg.popPendingUpdate(&update);
    215 
    216     // expecting a paint rect inside the scroll rect
    217     EXPECT_FALSE(update.scrollRect.isEmpty());
    218     EXPECT_EQ(1U, update.paintRects.size());
    219 
    220     EXPECT_EQ(scrollRect, update.scrollRect);
    221     EXPECT_EQ(paintRect, update.paintRects[0]);
    222 }
    223 
    224 TEST(PaintAggregator, ContainedPaintBeforeScroll)
    225 {
    226     PaintAggregator greg;
    227 
    228     IntRect paintRect(4, 4, 2, 2);
    229     greg.invalidateRect(paintRect);
    230 
    231     IntRect scrollRect(0, 0, 10, 10);
    232     greg.scrollRect(2, 0, scrollRect);
    233 
    234     EXPECT_TRUE(greg.hasPendingUpdate());
    235     PaintAggregator::PendingUpdate update;
    236     greg.popPendingUpdate(&update);
    237 
    238     // Expecting a paint rect inside the scroll rect
    239     EXPECT_FALSE(update.scrollRect.isEmpty());
    240     EXPECT_EQ(1U, update.paintRects.size());
    241 
    242     paintRect.move(2, 0);
    243 
    244     EXPECT_EQ(scrollRect, update.scrollRect);
    245     EXPECT_EQ(paintRect, update.paintRects[0]);
    246 }
    247 
    248 TEST(PaintAggregator, ContainedPaintsBeforeAndAfterScroll)
    249 {
    250     PaintAggregator greg;
    251 
    252     IntRect paintRect1(4, 4, 2, 2);
    253     greg.invalidateRect(paintRect1);
    254 
    255     IntRect scrollRect(0, 0, 10, 10);
    256     greg.scrollRect(2, 0, scrollRect);
    257 
    258     IntRect paintRect2(6, 4, 2, 2);
    259     greg.invalidateRect(paintRect2);
    260 
    261     IntRect expectedPaintRect = paintRect2;
    262 
    263     EXPECT_TRUE(greg.hasPendingUpdate());
    264     PaintAggregator::PendingUpdate update;
    265     greg.popPendingUpdate(&update);
    266 
    267     // Expecting a paint rect inside the scroll rect
    268     EXPECT_FALSE(update.scrollRect.isEmpty());
    269     EXPECT_EQ(1U, update.paintRects.size());
    270 
    271     EXPECT_EQ(scrollRect, update.scrollRect);
    272     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
    273 }
    274 
    275 TEST(PaintAggregator, LargeContainedPaintAfterScroll)
    276 {
    277     PaintAggregator greg;
    278 
    279     IntRect scrollRect(0, 0, 10, 10);
    280     greg.scrollRect(0, 1, scrollRect);
    281 
    282     IntRect paintRect(0, 0, 10, 9); // Repaint 90%
    283     greg.invalidateRect(paintRect);
    284 
    285     EXPECT_TRUE(greg.hasPendingUpdate());
    286     PaintAggregator::PendingUpdate update;
    287     greg.popPendingUpdate(&update);
    288 
    289     EXPECT_TRUE(update.scrollRect.isEmpty());
    290     EXPECT_EQ(1U, update.paintRects.size());
    291 
    292     EXPECT_EQ(scrollRect, update.paintRects[0]);
    293 }
    294 
    295 TEST(PaintAggregator, LargeContainedPaintBeforeScroll)
    296 {
    297     PaintAggregator greg;
    298 
    299     IntRect paintRect(0, 0, 10, 9); // Repaint 90%
    300     greg.invalidateRect(paintRect);
    301 
    302     IntRect scrollRect(0, 0, 10, 10);
    303     greg.scrollRect(0, 1, scrollRect);
    304 
    305     EXPECT_TRUE(greg.hasPendingUpdate());
    306     PaintAggregator::PendingUpdate update;
    307     greg.popPendingUpdate(&update);
    308 
    309     EXPECT_TRUE(update.scrollRect.isEmpty());
    310     EXPECT_EQ(1U, update.paintRects.size());
    311 
    312     EXPECT_EQ(scrollRect, update.paintRects[0]);
    313 }
    314 
    315 TEST(PaintAggregator, OverlappingPaintBeforeScroll)
    316 {
    317     PaintAggregator greg;
    318 
    319     IntRect paintRect(4, 4, 10, 2);
    320     greg.invalidateRect(paintRect);
    321 
    322     IntRect scrollRect(0, 0, 10, 10);
    323     greg.scrollRect(2, 0, scrollRect);
    324 
    325     IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
    326 
    327     EXPECT_TRUE(greg.hasPendingUpdate());
    328     PaintAggregator::PendingUpdate update;
    329     greg.popPendingUpdate(&update);
    330 
    331     EXPECT_TRUE(update.scrollRect.isEmpty());
    332     EXPECT_EQ(1U, update.paintRects.size());
    333 
    334     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
    335 }
    336 
    337 TEST(PaintAggregator, OverlappingPaintAfterScroll)
    338 {
    339     PaintAggregator greg;
    340 
    341     IntRect scrollRect(0, 0, 10, 10);
    342     greg.scrollRect(2, 0, scrollRect);
    343 
    344     IntRect paintRect(4, 4, 10, 2);
    345     greg.invalidateRect(paintRect);
    346 
    347     IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
    348 
    349     EXPECT_TRUE(greg.hasPendingUpdate());
    350     PaintAggregator::PendingUpdate update;
    351     greg.popPendingUpdate(&update);
    352 
    353     EXPECT_TRUE(update.scrollRect.isEmpty());
    354     EXPECT_EQ(1U, update.paintRects.size());
    355 
    356     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
    357 }
    358 
    359 TEST(PaintAggregator, DisjointPaintBeforeScroll)
    360 {
    361     PaintAggregator greg;
    362 
    363     IntRect paintRect(4, 4, 10, 2);
    364     greg.invalidateRect(paintRect);
    365 
    366     IntRect scrollRect(0, 0, 2, 10);
    367     greg.scrollRect(2, 0, scrollRect);
    368 
    369     EXPECT_TRUE(greg.hasPendingUpdate());
    370     PaintAggregator::PendingUpdate update;
    371     greg.popPendingUpdate(&update);
    372 
    373     EXPECT_FALSE(update.scrollRect.isEmpty());
    374     EXPECT_EQ(1U, update.paintRects.size());
    375 
    376     EXPECT_EQ(paintRect, update.paintRects[0]);
    377     EXPECT_EQ(scrollRect, update.scrollRect);
    378 }
    379 
    380 TEST(PaintAggregator, DisjointPaintAfterScroll)
    381 {
    382     PaintAggregator greg;
    383 
    384     IntRect scrollRect(0, 0, 2, 10);
    385     greg.scrollRect(2, 0, scrollRect);
    386 
    387     IntRect paintRect(4, 4, 10, 2);
    388     greg.invalidateRect(paintRect);
    389 
    390     EXPECT_TRUE(greg.hasPendingUpdate());
    391     PaintAggregator::PendingUpdate update;
    392     greg.popPendingUpdate(&update);
    393 
    394     EXPECT_FALSE(update.scrollRect.isEmpty());
    395     EXPECT_EQ(1U, update.paintRects.size());
    396 
    397     EXPECT_EQ(paintRect, update.paintRects[0]);
    398     EXPECT_EQ(scrollRect, update.scrollRect);
    399 }
    400 
    401 TEST(PaintAggregator, ContainedPaintTrimmedByScroll)
    402 {
    403     PaintAggregator greg;
    404 
    405     IntRect paintRect(4, 4, 6, 6);
    406     greg.invalidateRect(paintRect);
    407 
    408     IntRect scrollRect(0, 0, 10, 10);
    409     greg.scrollRect(2, 0, scrollRect);
    410 
    411     // The paint rect should have become narrower.
    412     IntRect expectedPaintRect(6, 4, 4, 6);
    413 
    414     EXPECT_TRUE(greg.hasPendingUpdate());
    415     PaintAggregator::PendingUpdate update;
    416     greg.popPendingUpdate(&update);
    417 
    418     EXPECT_FALSE(update.scrollRect.isEmpty());
    419     EXPECT_EQ(1U, update.paintRects.size());
    420 
    421     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
    422     EXPECT_EQ(scrollRect, update.scrollRect);
    423 }
    424 
    425 TEST(PaintAggregator, ContainedPaintEliminatedByScroll)
    426 {
    427     PaintAggregator greg;
    428 
    429     IntRect paintRect(4, 4, 6, 6);
    430     greg.invalidateRect(paintRect);
    431 
    432     IntRect scrollRect(0, 0, 10, 10);
    433     greg.scrollRect(6, 0, scrollRect);
    434 
    435     EXPECT_TRUE(greg.hasPendingUpdate());
    436     PaintAggregator::PendingUpdate update;
    437     greg.popPendingUpdate(&update);
    438 
    439     EXPECT_FALSE(update.scrollRect.isEmpty());
    440     EXPECT_TRUE(update.paintRects.isEmpty());
    441 
    442     EXPECT_EQ(scrollRect, update.scrollRect);
    443 }
    444 
    445 TEST(PaintAggregator, ContainedPaintAfterScrollTrimmedByScrollDamage)
    446 {
    447     PaintAggregator greg;
    448 
    449     IntRect scrollRect(0, 0, 10, 10);
    450     greg.scrollRect(4, 0, scrollRect);
    451 
    452     IntRect paintRect(2, 0, 4, 10);
    453     greg.invalidateRect(paintRect);
    454 
    455     IntRect expectedScrollDamage(0, 0, 4, 10);
    456     IntRect expectedPaintRect(4, 0, 2, 10);
    457 
    458     EXPECT_TRUE(greg.hasPendingUpdate());
    459     PaintAggregator::PendingUpdate update;
    460     greg.popPendingUpdate(&update);
    461 
    462     EXPECT_FALSE(update.scrollRect.isEmpty());
    463     EXPECT_EQ(1U, update.paintRects.size());
    464 
    465     EXPECT_EQ(scrollRect, update.scrollRect);
    466     EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());
    467     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
    468 }
    469 
    470 TEST(PaintAggregator, ContainedPaintAfterScrollEliminatedByScrollDamage)
    471 {
    472     PaintAggregator greg;
    473 
    474     IntRect scrollRect(0, 0, 10, 10);
    475     greg.scrollRect(4, 0, scrollRect);
    476 
    477     IntRect paintRect(2, 0, 2, 10);
    478     greg.invalidateRect(paintRect);
    479 
    480     IntRect expectedScrollDamage(0, 0, 4, 10);
    481 
    482     EXPECT_TRUE(greg.hasPendingUpdate());
    483     PaintAggregator::PendingUpdate update;
    484     greg.popPendingUpdate(&update);
    485 
    486     EXPECT_FALSE(update.scrollRect.isEmpty());
    487     EXPECT_TRUE(update.paintRects.isEmpty());
    488 
    489     EXPECT_EQ(scrollRect, update.scrollRect);
    490     EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());
    491 }
    492 
    493 } // namespace
    494