OLD | NEW |
---|---|
(Empty) | |
1 // Visualizes under-repaint bugs. | |
2 // | |
3 // Definitions | |
4 // - minimum-repaint = region(diff(snapshot-before-repaintTest, | |
5 // snapshot-after-repaintTest-and-full-repaint)) | |
6 // It includes all pixels that should be changed after repaintTest. | |
7 // - actual-repaint = repaint rects recorded during repaintTest() and | |
8 // forceStyleRecalc(). | |
9 // - under-repaint = subtract(minimum-repaint, actual-repaint) | |
10 // Under-repaint will be shown in layout test overlay in black if any minimum- | |
11 // repaint region is not covered by actual-repaint. | |
12 // Any under-repaint means bug (given that we show it correct. See known | |
13 // issues below). | |
14 // | |
15 // How to use | |
16 // 1. For single repaint test: replace the original | |
17 // <script src="resources/text-based-repaint.js"> | |
18 // with | |
19 // <script src="resources/text-based-repaint-minimum-repaint.js"> | |
20 // For all repaint tests: copy text-based-repaint-minimum-repaint.js to | |
21 // text-based-repaint.js | |
22 // 2. Run layout tests. Repaint tests will result text diffs, which is because | |
23 // of the minimum repaint output in the actual results and doesn't mean the | |
24 // tests failed. | |
25 // 3. In layout test result page, click 'overlay' link or expand the test to | |
26 // see the 'overlay' pane. | |
27 // 4. Click 'Highlight under-repaint' button. You'll see black region if there | |
28 // is any under-repaint. | |
29 // | |
30 // Known issues | |
31 // crbug.com/381221 | |
32 | |
33 window.testIsAsync = false; | |
34 window.outputRepaintRects = true; | |
35 | |
36 function runRepaintTest() | |
enne (OOO)
2014/06/05 22:13:42
I'm not super happy with all the duplication here.
Xianzhu
2014/06/05 22:51:06
Agreed. Done.
| |
37 { | |
38 if (!window.testRunner || !window.internals) { | |
39 setTimeout(repaintTest, 500); | |
40 return; | |
41 } | |
42 | |
43 // TODO(enne): this is a workaround for multiple svg onload events. | |
44 // See: http://crbug.com/372946 | |
45 if (window.hasRunRepaintTest) | |
46 return; | |
47 window.hasRunRepaintTest = true; | |
48 | |
49 if (window.enablePixelTesting) | |
50 testRunner.dumpAsTextWithPixelResults(); | |
51 else | |
52 testRunner.dumpAsText(); | |
53 | |
54 // All repaint tests are asynchronous. | |
55 testRunner.waitUntilDone(); | |
56 | |
57 testRunner.capturePixelsAsyncThen(function(width, height, snapshot) { | |
58 window.widthBeforeRepaint = width; | |
59 window.heightBeforeRepaint = height; | |
60 window.snapshotBeforeRepaint = snapshot; | |
61 | |
62 window.internals.startTrackingRepaints(document); | |
63 repaintTest(); | |
64 if (!window.testIsAsync) | |
65 finishRepaintTest(); | |
66 }); | |
67 } | |
68 | |
69 function runRepaintAndPixelTest() | |
70 { | |
71 window.enablePixelTesting = true; | |
72 runRepaintTest(); | |
73 } | |
74 | |
75 function forceStyleRecalc() | |
76 { | |
77 if (document.body) | |
78 document.body.offsetTop; | |
79 else if (document.documentElement) | |
80 document.documentElement.offsetTop; | |
81 } | |
82 | |
83 function finishRepaintTest() | |
84 { | |
85 // Force a style recalc. | |
86 forceStyleRecalc(); | |
87 | |
88 var repaintRects = window.internals.layerTreeAsText(document, window.interna ls.LAYER_TREE_INCLUDES_REPAINT_RECTS); | |
89 | |
90 internals.stopTrackingRepaints(document); | |
91 | |
92 internals.forceFullRepaint(document); | |
93 testRunner.capturePixelsAsyncThen(function(width, height, snapshot) { | |
94 // Play nice with JS tests which may want to print out assert results. | |
95 if (window.isJsTest) | |
96 window.outputRepaintRects = false; | |
97 | |
98 if (window.outputRepaintRects) { | |
99 var minimumRepaint = computeMinimumRepaint(width, height, snapshot); | |
100 if (minimumRepaint.length) | |
101 repaintRects += '\nMinimum repaint:\n' + JSON.stringify(minimumR epaint, null, 2); | |
102 testRunner.setCustomTextOutput(repaintRects); | |
103 } | |
104 | |
105 if (window.afterTest) | |
106 window.afterTest(); | |
107 | |
108 // Play nice with async JS tests which want to notifyDone themselves. | |
109 if (!window.jsTestIsAsync) | |
110 testRunner.notifyDone(); | |
111 }); | |
112 } | |
113 | |
114 function computeMinimumRepaint(width, height, snapshot) | |
115 { | |
116 var result = []; | |
117 if (width > widthBeforeRepaint) { | |
118 result.push([widthBeforeRepaint, 0, width - widthBeforeRepaint, Math.max (height, heightBeforeRepaint)]); | |
119 width = widthBeforeRepaint; | |
120 } | |
121 if (height > heightBeforeRepaint) { | |
122 result.push([0, heightBeforeRepaint, width, height - heightBeforeRepaint ]); | |
123 height = heightBeforeRepaint; | |
124 } | |
125 | |
126 var dataBefore = new Uint32Array(snapshotBeforeRepaint); | |
127 var dataAfter = new Uint32Array(snapshot); | |
128 var rectsMayContinue = []; | |
129 var index = 0; | |
130 for (var y = 0; y < height; ++y) { | |
131 var x = 0; | |
132 var rectsMayContinueIndex = 0; | |
133 var nextRectsMayContinue = []; | |
134 while (true) { | |
135 while (x < width && dataBefore[index] == dataAfter[index]) { | |
136 ++x; | |
137 ++index; | |
138 } | |
139 xBegin = x; | |
140 while (x < width && dataBefore[index] != dataAfter[index]) { | |
141 ++x; | |
142 ++index; | |
143 } | |
144 xEnd = x; | |
145 | |
146 var xWidth = xEnd - xBegin; | |
147 if (!xWidth) | |
148 break; | |
149 | |
150 var rectMayContinue = rectsMayContinue[rectsMayContinueIndex]; | |
151 while (rectMayContinue && rectMayContinue[0] < xBegin) | |
152 rectMayContinue = rectsMayContinue[++rectsMayContinueIndex]; | |
153 | |
154 if (rectMayContinue && rectMayContinue[0] == xBegin && rectMayContin ue[2] == xWidth) { | |
155 ++rectMayContinue[3]; | |
156 nextRectsMayContinue.push(rectMayContinue); | |
157 } else { | |
158 var newRect = [xBegin, y, xWidth, 1]; | |
159 nextRectsMayContinue.push(newRect); | |
160 result.push(newRect); | |
161 } | |
162 } | |
163 rectsMayContinue = nextRectsMayContinue; | |
164 } | |
165 return result; | |
166 } | |
OLD | NEW |