• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "web/painting/PaintAggregator.h"
33 
34 #include <gtest/gtest.h>
35 
36 using namespace WebCore;
37 using namespace blink;
38 
39 namespace {
40 
TEST(PaintAggregator,InitialState)41 TEST(PaintAggregator, InitialState)
42 {
43     PaintAggregator greg;
44     EXPECT_FALSE(greg.hasPendingUpdate());
45 }
46 
TEST(PaintAggregator,SingleInvalidation)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 
TEST(PaintAggregator,DoubleDisjointInvalidation)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 
TEST(PaintAggregator,DisjointInvalidationsCombined)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 
TEST(PaintAggregator,SingleScroll)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 
TEST(PaintAggregator,DoubleOverlappingScroll)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 
TEST(PaintAggregator,NegatingScroll)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 
TEST(PaintAggregator,DiagonalScroll)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 
TEST(PaintAggregator,ContainedPaintAfterScroll)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 
TEST(PaintAggregator,ContainedPaintBeforeScroll)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 
TEST(PaintAggregator,ContainedPaintsBeforeAndAfterScroll)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 
TEST(PaintAggregator,LargeContainedPaintAfterScroll)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 
TEST(PaintAggregator,LargeContainedPaintBeforeScroll)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 
TEST(PaintAggregator,OverlappingPaintBeforeScroll)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 
TEST(PaintAggregator,OverlappingPaintAfterScroll)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 
TEST(PaintAggregator,DisjointPaintBeforeScroll)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 
TEST(PaintAggregator,DisjointPaintAfterScroll)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 
TEST(PaintAggregator,ContainedPaintTrimmedByScroll)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 
TEST(PaintAggregator,ContainedPaintEliminatedByScroll)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 
TEST(PaintAggregator,ContainedPaintAfterScrollTrimmedByScrollDamage)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 
TEST(PaintAggregator,ContainedPaintAfterScrollEliminatedByScrollDamage)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