2010-08-16 Paul Sawaya <psawaya@apple.com>
[WebKit-https.git] / LayoutTests / fast / canvas / webgl / read-pixels-pack-alignment.html
1 <html>
2 <head>
3 <link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
4 <script src="../../js/resources/js-test-pre.js"></script>
5 <script src="resources/webgl-test.js"></script>
6 <script id="vshader" type="x-shader/x-vertex">
7 attribute vec3 pos;
8 attribute vec4 colorIn;
9 varying vec4 color;
10
11 void main()
12 {
13     color = colorIn;
14     gl_Position = vec4(pos.xyz, 1.0);
15 }
16 </script>
17
18 <script id="fshader" type="x-shader/x-fragment">
19 varying highp vec4 color;
20
21 void main()
22 {
23     gl_FragColor = color;
24 }
25 </script>
26 </head>
27 <body>
28 <canvas id="example" width="32px" height="32px"></canvas>
29 <div id="description"></div>
30 <div id="console"></div>
31 <script>
32 var successfullyParsed = false;
33
34 // The below declarations need to be global for "shouldBe" to see them
35 var gl = null;
36 var array = null;
37 var pixel = [ 0, 0, 0, 0 ];
38 var expectedColor = [ 0, 0, 0, 0 ];
39 var pixelFormat = 0;
40 var pixelType = 0;
41
42 function calculatePixelBytes(format, type)
43 {
44     var size = 0;
45     switch (format) {
46     case gl.ALPHA:
47         size = 1;
48         break;
49     case gl.RGB:
50         size = 3;
51         break;
52     case gl.RGBA:
53         size = 4;
54         break;
55     default:
56         return -1;
57     }
58     switch (type) {
59     case gl.UNSIGNED_BYTE:
60         break;
61     case gl.UNSIGNED_SHORT_5_6_5:
62         if (format != gl.RGB)
63             return -1;
64         size = 2;
65         break;
66     case gl.UNSIGNED_SHORT_4_4_4_4:
67     case gl.UNSIGNED_SHORT_5_5_5_1:
68         if (format != gl.RGBA)
69             return -1;
70         size = 2;
71         break;
72     default:
73         return -1;
74     }
75     return size;
76 }
77
78 function calculatePaddingBytes(bytesPerPixel, packAlignment, width)
79 {
80     var padding = 0;
81     switch (packAlignment) {
82     case 1:
83     case 2:
84     case 4:
85     case 8:
86         padding = (bytesPerPixel * width) % packAlignment;
87         if (padding > 0)
88             padding = packAlignment - padding;
89         break;
90     default:
91         return -1;
92     }
93     return padding;
94 }
95
96 function packColor(format, type, r, g, b, a)
97 {
98     // FIXME: not sure if the color packing is correct for UNSIGNED_SHORT_*.
99     var color = [ 0, 0, 0, 0 ];
100     switch (type) {
101     case gl.UNSIGNED_BYTE:
102         switch (format) {
103         case gl.ALPHA:
104             color[0] = a;
105             break;
106         case gl.RGB:
107             color[0] = r;
108             color[1] = g;
109             color[2] = b;
110             break;
111         case gl.RGBA:
112             color[0] = r;
113             color[1] = g;
114             color[2] = b;
115             color[3] = a;
116             break;
117         default:
118             return null;
119         }
120         break;
121     case gl.UNSIGNED_SHORT_5_6_5:
122         if (format != gl.RGB)
123             return null;
124         r >>= 3;
125         g >>= 2;
126         b >>= 3;
127         color[0] = (r << 11) + (g << 5) + b;
128         break;
129     case gl.UNSIGNED_SHORT_4_4_4_4:
130         if (format != gl.RGBA)
131             return null;
132         r >>= 4;
133         g >>= 4;
134         b >>= 4;
135         a >>= 4;
136         color[0] = (r << 12) + (g << 8) + (b << 4) + a;
137         break;
138     case gl.UNSIGNED_SHORT_5_5_5_1:
139         if (format != gl.RGBA)
140             return null;
141         r >>= 3;
142         g >>= 3;
143         b >>= 3;
144         a >>= 7;
145         color[0] = (r << 11) + (g << 6) + (b << 1) + a;
146         break;
147     Default:
148         return null;
149     }
150     return color;
151 }
152
153 function runTestIteration(format, type, packAlignment, width, height)
154 {
155     debug("Testing PACK_ALIGNMENT = " + packAlignment + ", width = " + width + ", height = " + height);
156     gl.clearColor(1, 0.4, 0, 1);
157     gl.clear(gl.COLOR_BUFFER_BIT);
158     gl.pixelStorei(gl.PACK_ALIGNMENT, packAlignment);
159     shouldBe("gl.getError()", "gl.NO_ERROR");
160     var bytesPerPixel = calculatePixelBytes(format, type);
161     var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width);
162     var size = bytesPerPixel * width * height + padding * (height - 1);
163     var isShort = false;
164     switch (type) {
165     case gl.UNSIGNED_SHORT_5_6_5:
166     case gl.UNSIGNED_SHORT_4_4_4_4:
167     case gl.UNSIGNED_SHORT_5_5_5_1:
168         isShort = true;
169     }
170     if (isShort)
171         size /= 2;
172     if (size < 0)
173         size = 0;
174     if (type == gl.UNSIGNED_BYTE)
175         array = new Uint8Array(size);
176     else
177         array = new Uint16Array(size);
178     gl.readPixels(0, 0, width, height, format, type, array);
179     if (width < 0 || height < 0) {
180         shouldBe("gl.getError()", "gl.INVALID_VALUE");
181         return;
182     } else {
183         shouldBe("gl.getError()", "gl.NO_ERROR");
184         if (!array.length)
185             return;
186     }
187     // Check the last pixel of the last row.
188     var bytesPerRow = width * bytesPerPixel + padding;
189     var pos = bytesPerRow * (height - 1) + (width - 1) * bytesPerPixel;
190     var numComponents = bytesPerPixel;
191     if (isShort) {
192         pos /= 2;
193         numComponents /= 2;
194     }
195     for (var i = 0; i < numComponents; ++i)
196         pixel[i] = array[pos + i];
197     for (var i = numComponents; i < 4; ++i)
198         pixel[i] = 0;
199     expectedColor = packColor(format, type, 255, 102, 0, 255);
200     shouldBeNonNull(expectedColor);
201     shouldBe("pixel", "expectedColor");
202 }
203
204 function checkSupportedPixelFormatAndType()
205 {
206     debug("Check supported pixel format/type besides RGBA/UNSIGNED_BYTE");
207     shouldBe("gl.getError()", "gl.NO_ERROR");
208     pixelFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
209     pixelType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
210     shouldBe("gl.getError()", "gl.NO_ERROR");
211     shouldBeFalse("pixelFormat == gl.RGBA && pixelType == gl.UNSIGNED_BYTE");
212 }
213
214 description('Verify readPixels() works fine with various PACK_ALIGNMENT values.');
215
216 shouldBeNonNull("gl = initWebGL('example', 'vshader', 'fshader', [ 'pos', 'colorIn' ], [ 0, 0, 0, 1 ], 1)");
217 gl.disable(gl.BLEND);
218
219 checkSupportedPixelFormatAndType();
220
221 debug("Testing format = RGBA and type = UNSIGNED_BYTE");
222 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, 1, 2);
223 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 1, 2);
224 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 1, 2);
225 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 1, 2);
226 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 2, 2);
227 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 2, 2);
228 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 3, 2);
229 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 3, 2);
230 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 4, 2);
231 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 4, 2);
232 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 5, 1);
233 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 5, 2);
234 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 5, 2);
235 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 6, 2);
236 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 7, 2);
237 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 8, 2);
238 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, 0, 0);
239 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 0, 0);
240 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 0, 0);
241 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 0, 0);
242 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, -1, 1);
243 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 1, -1);
244 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 0, -1);
245 runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, -1, -1);
246
247 debug("Testing the other supported format/type combination");
248 runTestIteration(pixelFormat, pixelType, 1, 1, 2);
249 runTestIteration(pixelFormat, pixelType, 2, 1, 2);
250 runTestIteration(pixelFormat, pixelType, 4, 1, 2);
251 runTestIteration(pixelFormat, pixelType, 8, 1, 2);
252 runTestIteration(pixelFormat, pixelType, 4, 2, 2);
253 runTestIteration(pixelFormat, pixelType, 8, 2, 2);
254 runTestIteration(pixelFormat, pixelType, 4, 3, 2);
255 runTestIteration(pixelFormat, pixelType, 8, 3, 2);
256 runTestIteration(pixelFormat, pixelType, 4, 4, 2);
257 runTestIteration(pixelFormat, pixelType, 8, 4, 2);
258 runTestIteration(pixelFormat, pixelType, 8, 5, 1);
259 runTestIteration(pixelFormat, pixelType, 4, 5, 2);
260 runTestIteration(pixelFormat, pixelType, 8, 5, 2);
261 runTestIteration(pixelFormat, pixelType, 8, 6, 2);
262 runTestIteration(pixelFormat, pixelType, 8, 7, 2);
263 runTestIteration(pixelFormat, pixelType, 8, 8, 2);
264 runTestIteration(pixelFormat, pixelType, 1, 0, 0);
265 runTestIteration(pixelFormat, pixelType, 2, 0, 0);
266 runTestIteration(pixelFormat, pixelType, 4, 0, 0);
267 runTestIteration(pixelFormat, pixelType, 8, 0, 0);
268 runTestIteration(pixelFormat, pixelType, 1, -1, 1);
269 runTestIteration(pixelFormat, pixelType, 2, 1, -1);
270 runTestIteration(pixelFormat, pixelType, 4, 0, -1);
271 runTestIteration(pixelFormat, pixelType, 8, -1, -1);
272
273 successfullyParsed = true;
274 </script>
275 <script src="../../js/resources/js-test-post.js"></script>
276 </body>
277 </html>