|
1 <!-- |
|
2 Copyright (c) 2011 The Chromium Authors. All rights reserved. |
|
3 Use of this source code is governed by a BSD-style license that can be |
|
4 found in the LICENSE file. |
|
5 --> |
|
6 <!DOCTYPE html> |
|
7 <html> |
|
8 <head> |
|
9 <meta charset="utf-8"> |
|
10 <title>WebGL ReadPixels conformance test.</title> |
|
11 <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
|
12 <script src="../../resources/js-test-pre.js"></script> |
|
13 <script src="../resources/webgl-test.js"> </script> |
|
14 <script src="../resources/webgl-test-utils.js"> </script> |
|
15 </head> |
|
16 <body> |
|
17 <canvas id="example" width="200" height="200" style="width: 20px; height: 20px"></canvas> |
|
18 <div id="description"></div> |
|
19 <div id="console"></div> |
|
20 <script> |
|
21 description("Checks that ReadPixels works as expected."); |
|
22 testPassed("read-pixels-test start: " + (new Date().getTime())); |
|
23 |
|
24 var wtu = WebGLTestUtils; |
|
25 var canvas = document.getElementById("example"); |
|
26 var gl = create3DContext(canvas); |
|
27 |
|
28 if (window.initNonKhronosFramework) { |
|
29 window.initNonKhronosFramework(true); |
|
30 } |
|
31 |
|
32 var actual; |
|
33 var expected; |
|
34 var width = 2; |
|
35 var height = 2; |
|
36 var continueTestFunc = continueTestPart1; |
|
37 |
|
38 gl.clearColor(1, 1, 1, 1); |
|
39 gl.clear(gl.COLOR_BUFFER_BIT); |
|
40 |
|
41 // Resize the canvas to 2x2. This is an attempt to get stuff in the backbuffer. |
|
42 // that shouldn't be there. |
|
43 canvas.addEventListener("webglcontextlost", function(e) { e.preventDefault(); }, false); |
|
44 canvas.addEventListener("webglcontextrestored", continueTestAfterContextRestored, false); |
|
45 canvas.width = width; |
|
46 canvas.height = height; |
|
47 if (gl.getError() != gl.CONTEXT_LOST_WEBGL) { |
|
48 continueTestPart1(); |
|
49 } |
|
50 |
|
51 function continueTestAfterContextRestored() { |
|
52 window.gl = create3DContext(canvas); |
|
53 var func = continueTestFunc; |
|
54 window.continueTestFunc = function() { testFailed("should not be here"); }; |
|
55 func(); |
|
56 } |
|
57 |
|
58 function continueTestPart1() { |
|
59 gl.clearColor(0.5, 0.7, 1.0, 1); |
|
60 gl.clear(gl.COLOR_BUFFER_BIT); |
|
61 |
|
62 var innerColor = [0.5, 0.7, 1.0, 1]; |
|
63 var outerColor = [0, 0, 0, 0]; |
|
64 |
|
65 var tests = [ |
|
66 { msg: 'in range', checkColor: innerColor, x: 0, y: 0, |
|
67 oneColor: innerColor, oneX: 0, oneY: 0}, |
|
68 { msg: 'off top left', checkColor: outerColor, x: -1, y: -1, |
|
69 oneColor: innerColor, oneX: 1, oneY: 1}, |
|
70 { msg: 'off bottom right', checkColor: outerColor, x: 1, y: 1, |
|
71 oneColor: innerColor, oneX: 0, oneY: 0}, |
|
72 { msg: 'completely off top ', checkColor: outerColor, x: 0, y: -2, |
|
73 oneColor: outerColor, oneX: 0, oneY: 0}, |
|
74 { msg: 'completely off bottom', checkColor: outerColor, x: 0, y: 2, |
|
75 oneColor: outerColor, oneX: 0, oneY: 0}, |
|
76 { msg: 'completely off left', checkColor: outerColor, x: -2, y: 0, |
|
77 oneColor: outerColor, oneX: 0, oneY: 0}, |
|
78 { msg: 'completeley off right', checkColor: outerColor, x: 2, y: 0, |
|
79 oneColor: outerColor, oneX: 0, oneY: 0} |
|
80 ]; |
|
81 |
|
82 for (var tt = 0; tt < tests.length; ++tt) { |
|
83 var test = tests[tt]; |
|
84 debug(""); |
|
85 debug("checking: " + test.msg); |
|
86 checkBuffer(test.checkColor, test.x, test.y, |
|
87 test.oneColor, test.oneX, test.oneY); |
|
88 } |
|
89 |
|
90 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors"); |
|
91 |
|
92 function checkBuffer(checkColor, x, y, oneColor, oneX, oneY) { |
|
93 var buf = new Uint8Array(width * height * 4); |
|
94 gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf); |
|
95 for (var yy = 0; yy < height; ++yy) { |
|
96 for (var xx = 0; xx < width; ++xx) { |
|
97 var offset = (yy * width + xx) * 4; |
|
98 var expectedColors = (oneX == xx && oneY == yy) ? oneColor : checkColor; |
|
99 for (var cc = 0; cc < 4; ++cc) { |
|
100 var expectedColor = expectedColors[cc] * 255; |
|
101 var color = buf[offset + cc]; |
|
102 var diff = Math.abs(expectedColor - color); |
|
103 assertMsg(diff < 3, |
|
104 "color pixel at " + xx + ", " + yy + " should be about " + expectedColor); |
|
105 } |
|
106 } |
|
107 } |
|
108 } |
|
109 |
|
110 var badFormats = [ |
|
111 { |
|
112 format: gl.RGB, |
|
113 type: gl.UNSIGNED_BYTE, |
|
114 dest: new Uint8Array(3), |
|
115 error: gl.INVALID_OPERATION |
|
116 }, |
|
117 { |
|
118 format: gl.RGB, |
|
119 type: gl.UNSIGNED_SHORT_5_6_5, |
|
120 dest: new Uint8Array(3), |
|
121 error: gl.INVALID_OPERATION |
|
122 }, |
|
123 { |
|
124 format: gl.RGBA, |
|
125 type: gl.UNSIGNED_SHORT_5_5_5_1, |
|
126 dest: new Uint16Array(1), |
|
127 error: gl.INVALID_OPERATION |
|
128 }, |
|
129 { |
|
130 format: gl.RGBA, |
|
131 type: gl.UNSIGNED_SHORT_4_4_4_4, |
|
132 dest: new Uint16Array(1), |
|
133 error: gl.INVALID_OPERATION |
|
134 }, |
|
135 { |
|
136 format: gl.ALPHA, |
|
137 type: gl.UNSIGNED_BYTE, |
|
138 dest: new Uint8Array(1), |
|
139 error: gl.INVALID_OPERATION |
|
140 }, |
|
141 { |
|
142 format: gl.LUMINANCE, |
|
143 type: gl.UNSIGNED_BYTE, |
|
144 dest: new Uint8Array(1), |
|
145 error: gl.INVALID_ENUM |
|
146 }, |
|
147 { |
|
148 format: gl.LUMINANCE_ALPHA, |
|
149 type: gl.UNSIGNED_BYTE, |
|
150 dest: new Uint8Array(2), |
|
151 error: gl.INVALID_ENUM |
|
152 } |
|
153 ]; |
|
154 debug(""); |
|
155 debug("check disallowed formats"); |
|
156 for (var tt = 0; tt < badFormats.length; ++ tt) { |
|
157 var info = badFormats[tt] |
|
158 var format = info.format; |
|
159 var type = info.type; |
|
160 var dest = info.dest; |
|
161 var error = info.error; |
|
162 gl.readPixels(0, 0, 1, 1, format, type, dest); |
|
163 // note that the GL error is INVALID_OPERATION if both format and type are invalid, but |
|
164 // INVALID_ENUM if only one is. |
|
165 glErrorShouldBe( |
|
166 gl, error, |
|
167 "Should not be able to read as " + wtu.glEnumToString(gl, format) + |
|
168 " / " + wtu.glEnumToString(gl, type)); |
|
169 } |
|
170 |
|
171 debug(""); |
|
172 debug("check reading with lots of drawing"); |
|
173 continueTestFunc = continueTestPart2; |
|
174 width = 1024; |
|
175 height = 1024; |
|
176 canvas.width = width; |
|
177 canvas.height = height; |
|
178 if (gl.getError() != gl.CONTEXT_LOST_WEBGL) { |
|
179 continueTestPart2(); |
|
180 } |
|
181 } |
|
182 |
|
183 function continueTestPart2() { |
|
184 testPassed("read-pixels-test continueTestPart2: " + (new Date().getTime())); |
|
185 gl.viewport(0, 0, 1024, 1024); |
|
186 testPassed("read-pixels-test before setupTexturedQuad: " + (new Date().getTime())); |
|
187 var program = wtu.setupTexturedQuad(gl); |
|
188 testPassed("read-pixels-test after setupTexturedQuad: " + (new Date().getTime())); |
|
189 var loc = gl.getUniformLocation(program, "tex"); |
|
190 gl.disable(gl.BLEND); |
|
191 gl.disable(gl.DEPTH_TEST); |
|
192 var colors = [[255, 0, 0, 255], [0, 255, 0, 255], [0, 0, 255, 255]]; |
|
193 var textures = []; |
|
194 var results = []; |
|
195 testPassed("read-pixels-test before first loop: " + (new Date().getTime())); |
|
196 for (var ii = 0; ii < colors.length; ++ii) { |
|
197 gl.activeTexture(gl.TEXTURE0 + ii); |
|
198 var tex = gl.createTexture(); |
|
199 testPassed("read-pixels-test first loop, ii = " + ii + ", before fillTexture: " + (new Date().getTime())); |
|
200 wtu.fillTexture(gl, tex, 1, 1, colors[ii]); |
|
201 testPassed("read-pixels-test first loop, ii = " + ii + ", after fillTexture: " + (new Date().getTime())); |
|
202 textures.push(tex); |
|
203 } |
|
204 for (var ii = 0; ii < colors.length; ++ii) { |
|
205 testPassed("read-pixels-test second loop, ii = " + ii + ": " + (new Date().getTime())); |
|
206 for (var jj = 0; jj < 300 + ii + 1; ++jj) { |
|
207 gl.uniform1i(loc, jj % 3); |
|
208 gl.drawArrays(gl.TRIANGLES, 0, 6); |
|
209 } |
|
210 var buf = new Uint8Array(4); |
|
211 testPassed("read-pixels-test second loop, before readpixels: " + (new Date().getTime())); |
|
212 gl.readPixels(512, 512, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf); |
|
213 testPassed("read-pixels-test second loop, after readpixels: " + (new Date().getTime())); |
|
214 results.push(buf); |
|
215 for (var kk = 0; kk < 99; ++kk) { |
|
216 gl.uniform1i(loc, (jj + kk) % 3); |
|
217 gl.drawArrays(gl.TRIANGLES, 0, 6); |
|
218 } |
|
219 testPassed("read-pixels-test second loop end: " + (new Date().getTime())); |
|
220 } |
|
221 for (var ii = 0; ii < colors.length; ++ii) { |
|
222 testPassed("read-pixels-test third loop, ii = " + ii + ": " + (new Date().getTime())); |
|
223 var buf = results[ii]; |
|
224 var color = colors[ii]; |
|
225 actual = [buf[0], buf[1], buf[2], buf[3]]; |
|
226 expected = [color[0], color[1], color[2], color[3]]; |
|
227 shouldBe("actual", "expected"); |
|
228 testPassed("read-pixels-test third loop end: " + (new Date().getTime())); |
|
229 } |
|
230 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors"); |
|
231 |
|
232 debug(""); |
|
233 |
|
234 // bug 763355: temporary logging of exceptions here to understand intermittent timeout |
|
235 // in this test, apparently in this finishTest() call. |
|
236 try { |
|
237 testPassed("read-pixels-test calling finishTest: " + (new Date().getTime())); |
|
238 finishTest(); |
|
239 testPassed("read-pixels-test after finishTest: " + (new Date().getTime())); |
|
240 } catch(e) { |
|
241 testFailed("finishTest generated exception: " + e); |
|
242 } |
|
243 } |
|
244 </script> |
|
245 </body> |
|
246 </html> |
|
247 |