| OLD | NEW |
| (Empty) |
| 1 <!DOCTYPE html> | |
| 2 <html> | |
| 3 <head> | |
| 4 <meta charset="utf-8"> | |
| 5 <script src="../../../resources/js-test.js"></script> | |
| 6 <script src="resources/webgl-test.js"></script> | |
| 7 <script src="resources/webgl-test-utils.js"></script> | |
| 8 <title>WebGL WEBGL_depth_texture Conformance Tests</title> | |
| 9 </head> | |
| 10 <body> | |
| 11 <script id="vshader" type="x-shader/x-vertex"> | |
| 12 attribute vec4 a_position; | |
| 13 void main() | |
| 14 { | |
| 15 gl_Position = a_position; | |
| 16 } | |
| 17 </script> | |
| 18 | |
| 19 <script id="fshader" type="x-shader/x-fragment"> | |
| 20 precision mediump float; | |
| 21 uniform sampler2D u_texture; | |
| 22 uniform vec2 u_resolution; | |
| 23 void main() | |
| 24 { | |
| 25 vec2 texcoord = gl_FragCoord.xy / u_resolution; | |
| 26 gl_FragColor = texture2D(u_texture, texcoord); | |
| 27 } | |
| 28 </script> | |
| 29 <div id="description"></div> | |
| 30 <div id="console"></div> | |
| 31 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canv
as> | |
| 32 <script> | |
| 33 if (window.initNonKhronosFramework) { | |
| 34 window.initNonKhronosFramework(false); | |
| 35 } | |
| 36 description("This test verifies the functionality of the WEBGL_depth_texture ext
ension, if it is available."); | |
| 37 | |
| 38 debug(""); | |
| 39 | |
| 40 if (window.internals) | |
| 41 window.internals.settings.setWebGLErrorsToConsoleEnabled(false); | |
| 42 | |
| 43 var wtu = WebGLTestUtils; | |
| 44 var canvas = document.getElementById("canvas"); | |
| 45 var gl = wtu.create3DContext(canvas, {antialias: false}); | |
| 46 var program = wtu.setupTexturedQuad(gl); | |
| 47 var ext = null; | |
| 48 var vao = null; | |
| 49 var tex; | |
| 50 var name; | |
| 51 var supportedFormats; | |
| 52 | |
| 53 if (!gl) { | |
| 54 testFailed("WebGL context does not exist"); | |
| 55 } else { | |
| 56 testPassed("WebGL context exists"); | |
| 57 | |
| 58 // Run tests with extension disabled | |
| 59 runTestDisabled(); | |
| 60 | |
| 61 // Query the extension and store globally so shouldBe can access it | |
| 62 ext = gl.getExtension("WEBGL_depth_texture"); | |
| 63 if (!ext) { | |
| 64 testPassed("No WEBGL_depth_texture support -- this is legal"); | |
| 65 runSupportedTest(false); | |
| 66 } else { | |
| 67 testPassed("Successfully enabled WEBGL_depth_texture extension"); | |
| 68 | |
| 69 runSupportedTest(true); | |
| 70 runTestExtension(); | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 function runSupportedTest(extensionEnabled) { | |
| 75 var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_depth_textu
re"); | |
| 76 if (name !== undefined) { | |
| 77 if (extensionEnabled) { | |
| 78 testPassed("WEBGL_depth_texture listed as supported and getExtension
succeeded"); | |
| 79 } else { | |
| 80 testFailed("WEBGL_depth_texture listed as supported but getExtension
failed"); | |
| 81 } | |
| 82 } else { | |
| 83 if (extensionEnabled) { | |
| 84 testFailed("WEBGL_depth_texture not listed as supported but getExten
sion succeeded"); | |
| 85 } else { | |
| 86 testPassed("WEBGL_depth_texture not listed as supported and getExten
sion failed -- this is legal"); | |
| 87 } | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 | |
| 92 function runTestDisabled() { | |
| 93 debug("Testing binding enum with extension disabled"); | |
| 94 | |
| 95 var tex = gl.createTexture(); | |
| 96 gl.bindTexture(gl.TEXTURE_2D, tex); | |
| 97 shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE], 'gl.texImage2
D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED
_SHORT, null)'); | |
| 98 shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE], 'gl.texImage2
D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED
_INT, null)'); | |
| 99 } | |
| 100 | |
| 101 | |
| 102 function dumpIt(gl, res, msg) { | |
| 103 return; // comment out to debug | |
| 104 debug(msg); | |
| 105 var actualPixels = new Uint8Array(res * res * 4); | |
| 106 gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels); | |
| 107 | |
| 108 for (var yy = 0; yy < res; ++yy) { | |
| 109 var strs = []; | |
| 110 for (var xx = 0; xx < res; ++xx) { | |
| 111 var actual = (yy * res + xx) * 4; | |
| 112 strs.push("(" + actualPixels[actual] + "," + actualPixels[actual+1] + ","
+ actualPixels[actual + 2] + "," + actualPixels[actual + 3] + ")"); | |
| 113 } | |
| 114 debug(strs.join(" ")); | |
| 115 } | |
| 116 } | |
| 117 function runTestExtension() { | |
| 118 debug("Testing WEBGL_depth_texture"); | |
| 119 | |
| 120 var res = 8; | |
| 121 | |
| 122 // make canvas for testing. | |
| 123 canvas2 = document.createElement("canvas"); | |
| 124 canvas2.width = res; | |
| 125 canvas2.height = res; | |
| 126 var ctx = canvas2.getContext("2d"); | |
| 127 ctx.fillStyle = "blue"; | |
| 128 ctx.fillRect(0, 0, canvas2.width, canvas2.height); | |
| 129 | |
| 130 var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_position']); | |
| 131 gl.useProgram(program); | |
| 132 gl.uniform2f(gl.getUniformLocation(program, "u_resolution"), res, res); | |
| 133 | |
| 134 var buffer = gl.createBuffer(); | |
| 135 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); | |
| 136 gl.bufferData( | |
| 137 gl.ARRAY_BUFFER, | |
| 138 new Float32Array( | |
| 139 [ 1, 1, 1, | |
| 140 -1, 1, 0, | |
| 141 -1, -1, -1, | |
| 142 1, 1, 1, | |
| 143 -1, -1, -1, | |
| 144 1, -1, 0, | |
| 145 ]), | |
| 146 gl.STATIC_DRAW); | |
| 147 gl.enableVertexAttribArray(0); | |
| 148 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); | |
| 149 | |
| 150 var types = [ | |
| 151 {obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMP
ONENT', type: 'UNSIGNED_SHORT', data: 'new Uint16Array(1)' }, | |
| 152 {obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMP
ONENT', type: 'UNSIGNED_INT', data: 'new Uint32Array(1)' }, | |
| 153 {obj: 'ext', attachment: 'DEPTH_STENCIL_ATTACHMENT', format: 'DEPTH_STEN
CIL', type: 'UNSIGNED_INT_24_8_WEBGL', data: 'new Uint32Array(1)' } | |
| 154 ]; | |
| 155 | |
| 156 for (var ii = 0; ii < types.length; ++ii) { | |
| 157 var typeInfo = types[ii]; | |
| 158 var type = typeInfo.type; | |
| 159 var typeStr = typeInfo.obj + '.' + type; | |
| 160 | |
| 161 debug(""); | |
| 162 debug("testing: " + type); | |
| 163 | |
| 164 // check that cubemaps are not allowed. | |
| 165 var cubeTex = gl.createTexture(); | |
| 166 gl.bindTexture(gl.TEXTURE_CUBE_MAP, cubeTex); | |
| 167 var targets = [ | |
| 168 'TEXTURE_CUBE_MAP_POSITIVE_X', | |
| 169 'TEXTURE_CUBE_MAP_NEGATIVE_X', | |
| 170 'TEXTURE_CUBE_MAP_POSITIVE_Y', | |
| 171 'TEXTURE_CUBE_MAP_NEGATIVE_Y', | |
| 172 'TEXTURE_CUBE_MAP_POSITIVE_Z', | |
| 173 'TEXTURE_CUBE_MAP_NEGATIVE_Z' | |
| 174 ]; | |
| 175 for (var tt = 0; tt < targets.length; ++tt) { | |
| 176 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.'
+ targets[ii] + ', 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.forma
t + ', ' + typeStr + ', null)'); | |
| 177 } | |
| 178 | |
| 179 // check 2d textures. | |
| 180 tex = gl.createTexture(); | |
| 181 gl.bindTexture(gl.TEXTURE_2D, tex); | |
| 182 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); | |
| 183 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); | |
| 184 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); | |
| 185 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); | |
| 186 | |
| 187 // test level > 0 | |
| 188 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTUR
E_2D, 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + ty
peStr + ', null)'); | |
| 189 | |
| 190 // test with data | |
| 191 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTUR
E_2D, 0, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + ty
peStr + ', ' + typeInfo.data + ')'); | |
| 192 | |
| 193 // test with canvas | |
| 194 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)'); | |
| 195 | |
| 196 // test copyTexImage2D | |
| 197 shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.c
opyTexImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 0, 0, 1, 1, 0)'); | |
| 198 | |
| 199 // test real thing | |
| 200 shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.texImage2D(gl.TEXTURE_2D, 0,
gl.' + typeInfo.format + ', ' + res + ', ' + res + ', 0, gl.' + typeInfo.format
+ ', ' + typeStr + ', null)'); | |
| 201 | |
| 202 // test texSubImage2D | |
| 203 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texSubImage2D(gl.TEX
TURE_2D, 0, 0, 0, 1, 1, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeIn
fo.data + ')'); | |
| 204 | |
| 205 // test copyTexSubImage2D | |
| 206 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.copyTexSubImage2D(gl
.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)'); | |
| 207 | |
| 208 // test generateMipmap | |
| 209 shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.generateMipmap(gl.TE
XTURE_2D)'); | |
| 210 | |
| 211 var fbo = gl.createFramebuffer(); | |
| 212 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
| 213 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXT
URE_2D, tex, 0); | |
| 214 // TODO: remove this check if the spec is updated to require these combi
nations to work. | |
| 215 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE
) | |
| 216 { | |
| 217 // try adding a color buffer. | |
| 218 var colorTex = gl.createTexture(); | |
| 219 gl.bindTexture(gl.TEXTURE_2D, colorTex); | |
| 220 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
; | |
| 221 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
; | |
| 222 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); | |
| 223 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); | |
| 224 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, res, res, 0, gl.RGBA, gl.UN
SIGNED_BYTE, null); | |
| 225 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEX
TURE_2D, colorTex, 0); | |
| 226 } | |
| 227 | |
| 228 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_CO
MPLETE'); | |
| 229 | |
| 230 // use the default texture to render with while we return to the depth t
exture. | |
| 231 gl.bindTexture(gl.TEXTURE_2D, null); | |
| 232 | |
| 233 // render the z-quad | |
| 234 gl.enable(gl.DEPTH_TEST); | |
| 235 gl.clearColor(1, 0, 0, 1); | |
| 236 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
| 237 gl.drawArrays(gl.TRIANGLES, 0, 6); | |
| 238 | |
| 239 dumpIt(gl, res, "--first--"); | |
| 240 | |
| 241 // render the depth texture. | |
| 242 gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
| 243 gl.bindTexture(gl.TEXTURE_2D, tex); | |
| 244 gl.clearColor(0, 0, 1, 1); | |
| 245 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
| 246 gl.drawArrays(gl.TRIANGLES, 0, 6); | |
| 247 | |
| 248 var actualPixels = new Uint8Array(res * res * 4); | |
| 249 gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels); | |
| 250 | |
| 251 dumpIt(gl, res, "--depth--"); | |
| 252 | |
| 253 // Check that each pixel's RGB are the same and that it's value is less | |
| 254 // than the previous pixel in either direction. Basically verify we have
a | |
| 255 // gradient. | |
| 256 var success = true; | |
| 257 for (var yy = 0; yy < res; ++yy) { | |
| 258 for (var xx = 0; xx < res; ++xx) { | |
| 259 var actual = (yy * res + xx) * 4; | |
| 260 var left = actual - 4; | |
| 261 var down = actual - res * 4; | |
| 262 | |
| 263 if (actualPixels[actual + 0] != actualPixels[actual + 1]) { | |
| 264 testFailed('R != G'); | |
| 265 success = false; | |
| 266 } | |
| 267 if (actualPixels[actual + 0] != actualPixels[actual + 2]) { | |
| 268 testFailed('R != B'); | |
| 269 success = false; | |
| 270 } | |
| 271 // ALPHA is implementation dependent | |
| 272 if (actualPixels[actual + 3] != 0xFF && actualPixels[actual + 3] !=
actualPixels[actual + 0]) { | |
| 273 testFailed('A != 255 && A != R'); | |
| 274 success = false; | |
| 275 } | |
| 276 | |
| 277 if (xx > 0) { | |
| 278 if (actualPixels[actual] <= actualPixels[left]) { | |
| 279 testFailed("actual(" + actualPixels[actual] + ") < left(" + ac
tualPixels[left] + ")"); | |
| 280 success = false; | |
| 281 } | |
| 282 } | |
| 283 if (yy > 0) { | |
| 284 if (actualPixels[actual] <= actualPixels[down]) { | |
| 285 testFailed("actual(" + actualPixels[actual] + ") < down(" +
actualPixels[down] + ")"); | |
| 286 success = false; | |
| 287 } | |
| 288 } | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 // Check that bottom left corner is vastly different thatn top right. | |
| 293 if (actualPixels[(res * res - 1) * 4] - actualPixels[0] < 0xC0) { | |
| 294 testFailed("corners are not different enough"); | |
| 295 success = false; | |
| 296 } | |
| 297 | |
| 298 if (success) { | |
| 299 testPassed("depth texture rendered correctly."); | |
| 300 } | |
| 301 | |
| 302 // check limitations | |
| 303 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
| 304 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXT
URE_2D, null, 0); | |
| 305 var badAttachment = typeInfo.attachment == 'DEPTH_ATTACHMENT' ? 'DEPTH_S
TENCIL_ATTACHMENT' : 'DEPTH_ATTACHMENT'; | |
| 306 shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.framebufferTexture2D(gl.FRAME
BUFFER, gl.' + badAttachment + ', gl.TEXTURE_2D, tex, 0)'); | |
| 307 shouldNotBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER
_COMPLETE'); | |
| 308 shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, 'gl.clear(gl
.DEPTH_BUFFER_BIT)'); | |
| 309 gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
| 310 shouldBe('gl.getError()', 'gl.NO_ERROR'); | |
| 311 } | |
| 312 } | |
| 313 | |
| 314 debug(""); | |
| 315 successfullyParsed = true; | |
| 316 if (window.nonKhronosFrameworkNotifyDone) { | |
| 317 window.nonKhronosFrameworkNotifyDone(); | |
| 318 } | |
| 319 </script> | |
| 320 </body> | |
| 321 </html> | |
| OLD | NEW |