|
1 <!-- |
|
2 |
|
3 /* |
|
4 ** Copyright (c) 2012 The Khronos Group Inc. |
|
5 ** |
|
6 ** Permission is hereby granted, free of charge, to any person obtaining a |
|
7 ** copy of this software and/or associated documentation files (the |
|
8 ** "Materials"), to deal in the Materials without restriction, including |
|
9 ** without limitation the rights to use, copy, modify, merge, publish, |
|
10 ** distribute, sublicense, and/or sell copies of the Materials, and to |
|
11 ** permit persons to whom the Materials are furnished to do so, subject to |
|
12 ** the following conditions: |
|
13 ** |
|
14 ** The above copyright notice and this permission notice shall be included |
|
15 ** in all copies or substantial portions of the Materials. |
|
16 ** |
|
17 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
18 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
19 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
20 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|
21 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|
22 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|
23 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. |
|
24 */ |
|
25 |
|
26 --> |
|
27 <!DOCTYPE html> |
|
28 <html> |
|
29 <head> |
|
30 <meta charset="utf-8"> |
|
31 <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
|
32 <script src="../../resources/js-test-pre.js"></script> |
|
33 <script src="../resources/webgl-test.js"></script> |
|
34 <script src="../resources/webgl-test-utils.js"></script> |
|
35 <title>WebGL WEBGL_depth_texture Conformance Tests</title> |
|
36 </head> |
|
37 <body> |
|
38 <script id="vshader" type="x-shader/x-vertex"> |
|
39 attribute vec4 a_position; |
|
40 void main() |
|
41 { |
|
42 gl_Position = a_position; |
|
43 } |
|
44 </script> |
|
45 |
|
46 <script id="fshader" type="x-shader/x-fragment"> |
|
47 precision mediump float; |
|
48 uniform sampler2D u_texture; |
|
49 uniform vec2 u_resolution; |
|
50 void main() |
|
51 { |
|
52 vec2 texcoord = gl_FragCoord.xy / u_resolution; |
|
53 gl_FragColor = texture2D(u_texture, texcoord); |
|
54 } |
|
55 </script> |
|
56 <div id="description"></div> |
|
57 <div id="console"></div> |
|
58 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> |
|
59 <script> |
|
60 if (window.initNonKhronosFramework) { |
|
61 window.initNonKhronosFramework(false); |
|
62 } |
|
63 description("This test verifies the functionality of the WEBGL_depth_texture extension, if it is available."); |
|
64 |
|
65 debug(""); |
|
66 |
|
67 var wtu = WebGLTestUtils; |
|
68 var canvas = document.getElementById("canvas"); |
|
69 var gl = wtu.create3DContext(canvas, {antialias: false}); |
|
70 var program = wtu.setupTexturedQuad(gl); |
|
71 var ext = null; |
|
72 var vao = null; |
|
73 var tex; |
|
74 var name; |
|
75 var supportedFormats; |
|
76 |
|
77 if (!gl) { |
|
78 testFailed("WebGL context does not exist"); |
|
79 } else { |
|
80 testPassed("WebGL context exists"); |
|
81 |
|
82 // Run tests with extension disabled |
|
83 runTestDisabled(); |
|
84 |
|
85 // Query the extension and store globally so shouldBe can access it |
|
86 ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture"); |
|
87 if (!ext) { |
|
88 testPassed("No WEBGL_depth_texture support -- this is legal"); |
|
89 runSupportedTest(false); |
|
90 } else { |
|
91 testPassed("Successfully enabled WEBGL_depth_texture extension"); |
|
92 |
|
93 runSupportedTest(true); |
|
94 runTestExtension(); |
|
95 } |
|
96 } |
|
97 |
|
98 function runSupportedTest(extensionEnabled) { |
|
99 var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture"); |
|
100 if (name !== undefined) { |
|
101 if (extensionEnabled) { |
|
102 testPassed("WEBGL_depth_texture listed as supported and getExtension succeeded"); |
|
103 } else { |
|
104 testFailed("WEBGL_depth_texture listed as supported but getExtension failed"); |
|
105 } |
|
106 } else { |
|
107 if (extensionEnabled) { |
|
108 testFailed("WEBGL_depth_texture not listed as supported but getExtension succeeded"); |
|
109 } else { |
|
110 testPassed("WEBGL_depth_texture not listed as supported and getExtension failed -- this is legal"); |
|
111 } |
|
112 } |
|
113 } |
|
114 |
|
115 |
|
116 function runTestDisabled() { |
|
117 debug("Testing binding enum with extension disabled"); |
|
118 |
|
119 var tex = gl.createTexture(); |
|
120 gl.bindTexture(gl.TEXTURE_2D, tex); |
|
121 shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null)'); |
|
122 shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null)'); |
|
123 } |
|
124 |
|
125 |
|
126 function dumpIt(gl, res, msg) { |
|
127 return; // comment out to debug |
|
128 debug(msg); |
|
129 var actualPixels = new Uint8Array(res * res * 4); |
|
130 gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels); |
|
131 |
|
132 for (var yy = 0; yy < res; ++yy) { |
|
133 var strs = []; |
|
134 for (var xx = 0; xx < res; ++xx) { |
|
135 var actual = (yy * res + xx) * 4; |
|
136 strs.push("(" + actualPixels[actual] + "," + actualPixels[actual+1] + "," + actualPixels[actual + 2] + "," + actualPixels[actual + 3] + ")"); |
|
137 } |
|
138 debug(strs.join(" ")); |
|
139 } |
|
140 } |
|
141 function runTestExtension() { |
|
142 debug("Testing WEBGL_depth_texture"); |
|
143 |
|
144 var res = 8; |
|
145 |
|
146 // make canvas for testing. |
|
147 canvas2 = document.createElement("canvas"); |
|
148 canvas2.width = res; |
|
149 canvas2.height = res; |
|
150 var ctx = canvas2.getContext("2d"); |
|
151 ctx.fillStyle = "blue"; |
|
152 ctx.fillRect(0, 0, canvas2.width, canvas2.height); |
|
153 |
|
154 var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_position']); |
|
155 gl.useProgram(program); |
|
156 gl.uniform2f(gl.getUniformLocation(program, "u_resolution"), res, res); |
|
157 |
|
158 var buffer = gl.createBuffer(); |
|
159 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); |
|
160 gl.bufferData( |
|
161 gl.ARRAY_BUFFER, |
|
162 new Float32Array( |
|
163 [ 1, 1, 1, |
|
164 -1, 1, 0, |
|
165 -1, -1, -1, |
|
166 1, 1, 1, |
|
167 -1, -1, -1, |
|
168 1, -1, 0, |
|
169 ]), |
|
170 gl.STATIC_DRAW); |
|
171 gl.enableVertexAttribArray(0); |
|
172 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); |
|
173 |
|
174 var types = [ |
|
175 {obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_SHORT', data: 'new Uint16Array(1)' }, |
|
176 {obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_INT', data: 'new Uint32Array(1)' }, |
|
177 {obj: 'ext', attachment: 'DEPTH_STENCIL_ATTACHMENT', format: 'DEPTH_STENCIL', type: 'UNSIGNED_INT_24_8_WEBGL', data: 'new Uint32Array(1)' } |
|
178 ]; |
|
179 |
|
180 for (var ii = 0; ii < types.length; ++ii) { |
|
181 var typeInfo = types[ii]; |
|
182 var type = typeInfo.type; |
|
183 var typeStr = typeInfo.obj + '.' + type; |
|
184 |
|
185 debug(""); |
|
186 debug("testing: " + type); |
|
187 |
|
188 // check that cubemaps are not allowed. |
|
189 var cubeTex = gl.createTexture(); |
|
190 gl.bindTexture(gl.TEXTURE_CUBE_MAP, cubeTex); |
|
191 var targets = [ |
|
192 'TEXTURE_CUBE_MAP_POSITIVE_X', |
|
193 'TEXTURE_CUBE_MAP_NEGATIVE_X', |
|
194 'TEXTURE_CUBE_MAP_POSITIVE_Y', |
|
195 'TEXTURE_CUBE_MAP_NEGATIVE_Y', |
|
196 'TEXTURE_CUBE_MAP_POSITIVE_Z', |
|
197 'TEXTURE_CUBE_MAP_NEGATIVE_Z' |
|
198 ]; |
|
199 for (var tt = 0; tt < targets.length; ++tt) { |
|
200 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.' + targets[ii] + ', 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)'); |
|
201 } |
|
202 |
|
203 // check 2d textures. |
|
204 tex = gl.createTexture(); |
|
205 gl.bindTexture(gl.TEXTURE_2D, tex); |
|
206 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
|
207 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
|
208 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); |
|
209 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
|
210 |
|
211 // test level > 0 |
|
212 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)'); |
|
213 |
|
214 // test with data |
|
215 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')'); |
|
216 |
|
217 // test with canvas |
|
218 shouldGenerateGLError(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', gl.' + typeInfo.format + ', ' + typeStr + ', canvas2)'); |
|
219 |
|
220 // test copyTexImage2D |
|
221 shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 0, 0, 1, 1, 0)'); |
|
222 |
|
223 // test real thing |
|
224 shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', ' + res + ', ' + res + ', 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)'); |
|
225 |
|
226 // test texSubImage2D |
|
227 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')'); |
|
228 |
|
229 // test copyTexSubImage2D |
|
230 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)'); |
|
231 |
|
232 // test generateMipmap |
|
233 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.generateMipmap(gl.TEXTURE_2D)'); |
|
234 |
|
235 var fbo = gl.createFramebuffer(); |
|
236 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); |
|
237 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, tex, 0); |
|
238 // TODO: remove this check if the spec is updated to require these combinations to work. |
|
239 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) |
|
240 { |
|
241 // try adding a color buffer. |
|
242 var colorTex = gl.createTexture(); |
|
243 gl.bindTexture(gl.TEXTURE_2D, colorTex); |
|
244 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
|
245 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
|
246 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); |
|
247 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
|
248 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, res, res, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); |
|
249 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0); |
|
250 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE'); |
|
251 } |
|
252 |
|
253 // use the default texture to render with while we return to the depth texture. |
|
254 gl.bindTexture(gl.TEXTURE_2D, null); |
|
255 |
|
256 // render the z-quad |
|
257 gl.enable(gl.DEPTH_TEST); |
|
258 gl.clearColor(1, 0, 0, 1); |
|
259 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); |
|
260 gl.drawArrays(gl.TRIANGLES, 0, 6); |
|
261 |
|
262 dumpIt(gl, res, "--first--"); |
|
263 |
|
264 // render the depth texture. |
|
265 gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
|
266 gl.bindTexture(gl.TEXTURE_2D, tex); |
|
267 gl.clearColor(0, 0, 1, 1); |
|
268 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); |
|
269 gl.drawArrays(gl.TRIANGLES, 0, 6); |
|
270 |
|
271 var actualPixels = new Uint8Array(res * res * 4); |
|
272 gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels); |
|
273 |
|
274 dumpIt(gl, res, "--depth--"); |
|
275 |
|
276 // Check that each pixel's RGB are the same and that it's value is less |
|
277 // than the previous pixel in either direction. Basically verify we have a |
|
278 // gradient. |
|
279 var success = true; |
|
280 for (var yy = 0; yy < res; ++yy) { |
|
281 for (var xx = 0; xx < res; ++xx) { |
|
282 var actual = (yy * res + xx) * 4; |
|
283 var left = actual - 4; |
|
284 var down = actual - res * 4; |
|
285 |
|
286 if (actualPixels[actual + 0] != actualPixels[actual + 1]) { |
|
287 testFailed('R != G'); |
|
288 success = false; |
|
289 } |
|
290 if (actualPixels[actual + 0] != actualPixels[actual + 2]) { |
|
291 testFailed('R != B'); |
|
292 success = false; |
|
293 } |
|
294 // ALPHA is implementation dependent |
|
295 if (actualPixels[actual + 3] != 0xFF && actualPixels[actual + 3] != actualPixels[actual + 0]) { |
|
296 testFailed('A != 255 && A != R'); |
|
297 success = false; |
|
298 } |
|
299 |
|
300 if (xx > 0) { |
|
301 if (actualPixels[actual] <= actualPixels[left]) { |
|
302 testFailed("actual(" + actualPixels[actual] + ") < left(" + actualPixels[left] + ")"); |
|
303 success = false; |
|
304 } |
|
305 } |
|
306 if (yy > 0) { |
|
307 if (actualPixels[actual] <= actualPixels[down]) { |
|
308 testFailed("actual(" + actualPixels[actual] + ") < down(" + actualPixels[down] + ")"); |
|
309 success = false; |
|
310 } |
|
311 } |
|
312 } |
|
313 } |
|
314 |
|
315 // Check that bottom left corner is vastly different thatn top right. |
|
316 if (actualPixels[(res * res - 1) * 4] - actualPixels[0] < 0xC0) { |
|
317 testFailed("corners are not different enough"); |
|
318 success = false; |
|
319 } |
|
320 |
|
321 if (success) { |
|
322 testPassed("depth texture rendered correctly."); |
|
323 } |
|
324 |
|
325 // check limitations |
|
326 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); |
|
327 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, null, 0); |
|
328 var badAttachment = typeInfo.attachment == 'DEPTH_ATTACHMENT' ? 'DEPTH_STENCIL_ATTACHMENT' : 'DEPTH_ATTACHMENT'; |
|
329 shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.' + badAttachment + ', gl.TEXTURE_2D, tex, 0)'); |
|
330 shouldNotBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE'); |
|
331 shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, 'gl.clear(gl.DEPTH_BUFFER_BIT)'); |
|
332 gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
|
333 shouldBe('gl.getError()', 'gl.NO_ERROR'); |
|
334 } |
|
335 } |
|
336 |
|
337 debug(""); |
|
338 successfullyParsed = true; |
|
339 </script> |
|
340 <script src="../../resources/js-test-post.js"></script> |
|
341 </body> |
|
342 </html> |
|
343 |