OLD | NEW |
---|---|
1 // Asynchronous tests should manually call finishRepaintTest at the appropriate | 1 // Asynchronous tests should manually call finishRepaintTest at the appropriate |
2 // time. | 2 // time. |
3 window.testIsAsync = false; | 3 window.testIsAsync = false; |
4 window.outputRepaintRects = true; | 4 window.outputRepaintRects = true; |
5 window.generateMinimumRepaint = true; // See comments about 'Minimum repaint' be low. | |
enne (OOO)
2014/06/06 19:55:16
Default to false?
Xianzhu
2014/06/07 05:23:06
Sorry, I uploaded the version for local testing th
| |
5 | 6 |
6 function runRepaintTest() | 7 function runRepaintTest() |
7 { | 8 { |
8 if (!window.testRunner || !window.internals) { | 9 if (!window.testRunner || !window.internals) { |
9 setTimeout(repaintTest, 500); | 10 setTimeout(repaintTest, 500); |
10 return; | 11 return; |
11 } | 12 } |
12 | 13 |
13 // TODO(enne): this is a workaround for multiple svg onload events. | 14 // TODO(enne): this is a workaround for multiple svg onload events. |
14 // See: http://crbug.com/372946 | 15 // See: http://crbug.com/372946 |
15 if (window.hasRunRepaintTest) | 16 if (window.hasRunRepaintTest) |
16 return; | 17 return; |
17 window.hasRunRepaintTest = true; | 18 window.hasRunRepaintTest = true; |
18 | 19 |
19 if (window.enablePixelTesting) | 20 if (window.enablePixelTesting) |
20 testRunner.dumpAsTextWithPixelResults(); | 21 testRunner.dumpAsTextWithPixelResults(); |
21 else | 22 else |
22 testRunner.dumpAsText(); | 23 testRunner.dumpAsText(); |
23 | 24 |
24 // All repaint tests are asynchronous. | 25 // All repaint tests are asynchronous. |
25 testRunner.waitUntilDone(); | 26 testRunner.waitUntilDone(); |
26 | 27 |
27 testRunner.displayAsyncThen(function() { | 28 function continueRepaintTest() |
29 { | |
28 window.internals.startTrackingRepaints(document); | 30 window.internals.startTrackingRepaints(document); |
29 repaintTest(); | 31 repaintTest(); |
30 if (!window.testIsAsync) | 32 if (!window.testIsAsync) |
31 finishRepaintTest(); | 33 finishRepaintTest(); |
32 }); | 34 } |
35 | |
36 if (window.generateMinimumRepaint) { | |
37 testRunner.capturePixelsAsyncThen(function(width, height, snapshot) { | |
38 window.widthBeforeRepaint = width; | |
39 window.heightBeforeRepaint = height; | |
40 window.snapshotBeforeRepaint = snapshot; | |
41 continueRepaintTest(); | |
42 }); | |
43 } else { | |
44 testRunner.displayAsyncThen(continueRepaintTest); | |
45 }; | |
33 } | 46 } |
34 | 47 |
35 function runRepaintAndPixelTest() | 48 function runRepaintAndPixelTest() |
36 { | 49 { |
37 window.enablePixelTesting = true; | 50 window.enablePixelTesting = true; |
38 runRepaintTest(); | 51 runRepaintTest(); |
39 } | 52 } |
40 | 53 |
41 function forceStyleRecalc() | 54 function forceStyleRecalc() |
42 { | 55 { |
43 if (document.body) | 56 if (document.body) |
44 document.body.offsetTop; | 57 document.body.offsetTop; |
45 else if (document.documentElement) | 58 else if (document.documentElement) |
46 document.documentElement.offsetTop; | 59 document.documentElement.offsetTop; |
47 } | 60 } |
48 | 61 |
49 function finishRepaintTest() | 62 function finishRepaintTest() |
50 { | 63 { |
51 // Force a style recalc. | 64 // Force a style recalc. |
52 forceStyleRecalc(); | 65 forceStyleRecalc(); |
53 | 66 |
54 var repaintRects = window.internals.layerTreeAsText(document, window.interna ls.LAYER_TREE_INCLUDES_REPAINT_RECTS); | 67 var repaintRects = window.internals.layerTreeAsText(document, window.interna ls.LAYER_TREE_INCLUDES_REPAINT_RECTS); |
55 | 68 |
56 internals.stopTrackingRepaints(document); | 69 internals.stopTrackingRepaints(document); |
57 | 70 |
58 // Play nice with JS tests which may want to print out assert results. | 71 function repaintTestDone() |
59 if (window.isJsTest) | 72 { |
60 window.outputRepaintRects = false; | 73 // Play nice with JS tests which may want to print out assert results. |
74 if (window.isJsTest) | |
75 window.outputRepaintRects = false; | |
61 | 76 |
62 if (window.outputRepaintRects) | 77 if (window.outputRepaintRects) |
63 testRunner.setCustomTextOutput(repaintRects); | 78 testRunner.setCustomTextOutput(repaintRects); |
64 | 79 |
65 if (window.afterTest) | 80 if (window.afterTest) |
66 window.afterTest(); | 81 window.afterTest(); |
67 | 82 |
68 // Play nice with async JS tests which want to notifyDone themselves. | 83 // Play nice with async JS tests which want to notifyDone themselves. |
69 if (!window.jsTestIsAsync) | 84 if (!window.jsTestIsAsync) |
70 testRunner.notifyDone(); | 85 testRunner.notifyDone(); |
86 } | |
87 | |
88 if (window.generateMinimumRepaint) { | |
89 internals.forceFullRepaint(document); | |
90 testRunner.capturePixelsAsyncThen(function(width, height, snapshot) { | |
91 if (window.outputRepaintRects) { | |
92 var minimumRepaint = computeMinimumRepaint(width, height, snapsh ot); | |
93 if (minimumRepaint.length) | |
94 repaintRects += '\nMinimum repaint:\n' + JSON.stringify(mini mumRepaint, null, 2); | |
95 } | |
96 repaintTestDone(); | |
97 }); | |
98 } else { | |
99 repaintTestDone(); | |
100 } | |
71 } | 101 } |
102 | |
103 // Minimum repaint | |
104 // | |
105 // Definitions | |
106 // - minimum-repaint = region(diff(snapshot-before-repaintTest, | |
107 // snapshot-after-repaintTest-and-full-repaint)) | |
108 // It includes all pixels that should be changed after repaintTest. | |
109 // - actual-repaint = repaint rects recorded during repaintTest() and | |
110 // forceStyleRecalc(). | |
111 // - potential-under-repaint = subtract(minimum-repaint, actual-repaint) | |
112 // Potential-under-repaint will be shown in layout test overlay in black if | |
113 // any minimum-repaint region is not covered by actual-repaint. | |
114 // | |
115 // Potential-under-repaints don't always mean bug: | |
116 // - Some know visualization issues (crbug.com/381221) may cause false | |
117 // under-repaint; | |
118 // - Screen updates caused by composited layer re-compositing may not need | |
119 // repaint. | |
120 // | |
121 // How to use | |
122 // 1. Set window.generateMinimumRepaint to true in some repaint test or change | |
123 // this script to force window.generateMinimumRepaint to true. | |
124 // 2. Run layout tests. Repaint tests will result text diffs, which is because | |
125 // of the minimum repaint output in the actual results and doesn't mean the | |
126 // tests failed. | |
127 // 3. In layout test result page, click 'overlay' link or expand the test to | |
128 // see the 'overlay' pane. | |
129 // 4. Click 'Highlight under-repaint' button. You'll see black region if there | |
130 // is any under-repaint. | |
131 // | |
132 // Known issues | |
133 // crbug.com/381221 | |
134 | |
135 function computeMinimumRepaint(width, height, snapshot) | |
136 { | |
137 var result = []; | |
138 if (width > widthBeforeRepaint) { | |
139 result.push([widthBeforeRepaint, 0, width - widthBeforeRepaint, Math.max (height, heightBeforeRepaint)]); | |
140 width = widthBeforeRepaint; | |
141 } | |
142 if (height > heightBeforeRepaint) { | |
143 result.push([0, heightBeforeRepaint, width, height - heightBeforeRepaint ]); | |
144 height = heightBeforeRepaint; | |
145 } | |
146 | |
147 var dataBefore = new Uint32Array(snapshotBeforeRepaint); | |
148 var dataAfter = new Uint32Array(snapshot); | |
149 var rectsMayContinue = []; | |
150 var index = 0; | |
151 for (var y = 0; y < height; ++y) { | |
152 var x = 0; | |
153 var rectsMayContinueIndex = 0; | |
154 var nextRectsMayContinue = []; | |
155 while (true) { | |
156 while (x < width && dataBefore[index] == dataAfter[index]) { | |
157 ++x; | |
158 ++index; | |
159 } | |
160 xBegin = x; | |
161 while (x < width && dataBefore[index] != dataAfter[index]) { | |
162 ++x; | |
163 ++index; | |
164 } | |
165 xEnd = x; | |
166 | |
167 var xWidth = xEnd - xBegin; | |
168 if (!xWidth) | |
169 break; | |
170 | |
171 var rectMayContinue = rectsMayContinue[rectsMayContinueIndex]; | |
172 while (rectMayContinue && rectMayContinue[0] < xBegin) | |
173 rectMayContinue = rectsMayContinue[++rectsMayContinueIndex]; | |
174 | |
175 if (rectMayContinue && rectMayContinue[0] == xBegin && rectMayContin ue[2] == xWidth) { | |
176 ++rectMayContinue[3]; | |
177 nextRectsMayContinue.push(rectMayContinue); | |
178 } else { | |
179 var newRect = [xBegin, y, xWidth, 1]; | |
180 nextRectsMayContinue.push(newRect); | |
181 result.push(newRect); | |
182 } | |
183 } | |
184 rectsMayContinue = nextRectsMayContinue; | |
185 } | |
186 return result; | |
187 } | |
OLD | NEW |