uninitialized-test.html (10171B)
1 <!-- 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 <!DOCTYPE html> 7 <html> 8 <head> 9 <meta charset="utf-8"> 10 <title>WebGL Uninitialized GL Resources Tests</title> 11 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 12 <script src="../../js/js-test-pre.js"></script> 13 <script src="../../js/webgl-test-utils.js"></script> 14 </head> 15 <body> 16 <div id="description"></div> 17 <div id="console"></div> 18 <canvas id="canvas" width="2" height="2"> </canvas> 19 <script> 20 "use strict"; 21 description("Tests to check user code cannot access uninitialized data from GL resources."); 22 23 var wtu = WebGLTestUtils; 24 var gl = wtu.create3DContext("canvas"); 25 if (!gl) 26 testFailed("Context created."); 27 else 28 testPassed("Context created."); 29 30 function setupTexture(texWidth, texHeight) { 31 var texture = gl.createTexture(); 32 gl.bindTexture(gl.TEXTURE_2D, texture); 33 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 34 35 // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits 36 // into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem) 37 // with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time. 38 39 var badData = new Uint8Array(texWidth * texHeight * 4); 40 for (var i = 0; i < badData.length; ++i) 41 badData[i] = i % 255; 42 43 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); 44 gl.finish(); // make sure it has been uploaded 45 46 gl.deleteTexture(texture); 47 gl.finish(); // make sure it has been deleted 48 49 var texture = gl.createTexture(); 50 gl.bindTexture(gl.TEXTURE_2D, texture); 51 return texture; 52 } 53 54 function checkNonZeroPixels(texture, texWidth, texHeight, skipX, skipY, skipWidth, skipHeight, skipR, skipG, skipB, skipA) { 55 gl.bindTexture(gl.TEXTURE_2D, null); 56 var fb = gl.createFramebuffer(); 57 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 58 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); 59 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); 60 61 var data = new Uint8Array(texWidth * texHeight * 4); 62 gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, data); 63 64 var k = 0; 65 for (var y = 0; y < texHeight; ++y) { 66 for (var x = 0; x < texWidth; ++x) { 67 var index = (y * texWidth + x) * 4; 68 if (x >= skipX && x < skipX + skipWidth && y >= skipY && y < skipY + skipHeight) { 69 if (data[index] != skipR || data[index + 1] != skipG || data[index + 2] != skipB || data[index + 3] != skipA) { 70 testFailed("non-zero pixel values are wrong"); 71 return; 72 } 73 } else { 74 for (var i = 0; i < 4; ++i) { 75 if (data[index + i] != 0) 76 k++; 77 } 78 } 79 } 80 } 81 if (k) { 82 testFailed("Found " + k + " non-zero bytes"); 83 } else { 84 testPassed("All data initialized"); 85 } 86 } 87 88 var width = 512; 89 var height = 512; 90 91 debug(""); 92 debug("Reading an uninitialized texture (texImage2D) should succeed with all bytes set to 0."); 93 94 var tex = setupTexture(width, height); 95 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 96 checkNonZeroPixels(tex, width, height, 0, 0, 0, 0, 0, 0, 0, 0); 97 gl.deleteTexture(tex); 98 gl.finish(); 99 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 100 101 debug(""); 102 debug("Reading a partially initialized texture (texImage2D) should succeed with all uninitialized bytes set to 0 and initialized bytes untouched."); 103 104 var tex = setupTexture(width, height); 105 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 106 var data = new Uint8Array(4); 107 var r = 108; 108 var g = 72; 109 var b = 36; 110 var a = 9; 111 data[0] = r; 112 data[1] = g; 113 data[2] = b; 114 data[3] = a; 115 gl.texSubImage2D(gl.TEXTURE_2D, 0, width/2, height/2, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data); 116 checkNonZeroPixels(tex, width, height, width/2, height/2, 1, 1, r, g, b, a); 117 gl.deleteTexture(tex); 118 gl.finish(); 119 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 120 121 debug(""); 122 debug("Reading an uninitialized portion of a texture (copyTexImage2D) should succeed with all bytes set to 0."); 123 124 var tex = setupTexture(width, height); 125 var fbo = gl.createFramebuffer(); 126 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 127 var rbo = gl.createRenderbuffer(); 128 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 129 var fboWidth = 16; 130 var fboHeight = 16; 131 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight); 132 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); 133 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); 134 gl.clearColor(1.0, 0.0, 0.0, 1.0); 135 gl.clear(gl.COLOR_BUFFER_BIT); 136 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 137 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0); 138 checkNonZeroPixels(tex, width, height, 0, 0, fboWidth, fboHeight, 255, 0, 0, 255); 139 gl.deleteTexture(tex); 140 gl.finish(); 141 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 142 143 debug(""); 144 debug("Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should succeed with all bytes set to 0."); 145 146 var tex = setupTexture(width, height); 147 var fbo = gl.createFramebuffer(); 148 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 149 var rbo = gl.createRenderbuffer(); 150 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 151 var fboWidth = 16; 152 var fboHeight = 16; 153 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight); 154 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); 155 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); 156 gl.clearColor(1.0, 0.0, 0.0, 1.0); 157 gl.clear(gl.COLOR_BUFFER_BIT); 158 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 159 var x = -8; 160 var y = -8; 161 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, x, y, width, height, 0); 162 checkNonZeroPixels(tex, width, height, -x, -y, fboWidth, fboHeight, 255, 0, 0, 255); 163 gl.deleteTexture(tex); 164 gl.finish(); 165 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 166 167 debug(""); 168 debug("Reading an uninitialized portion of a texture (copyTexImage2D from WebGL internal fbo) should succeed with all bytes set to 0."); 169 170 var tex = setupTexture(width, height); 171 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 172 gl.clearColor(0.0, 1.0, 0.0, 0.0); 173 gl.clear(gl.COLOR_BUFFER_BIT); 174 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 175 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0); 176 checkNonZeroPixels(tex, width, height, 0, 0, gl.canvas.width, gl.canvas.height, 0, 255, 0, 0); 177 gl.deleteTexture(tex); 178 gl.finish(); 179 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 180 181 debug(""); 182 debug("Reading an uninitialized portion of a texture (copyTexSubImage2D) should succeed with all bytes set to 0."); 183 184 var tex = gl.createTexture(); 185 gl.bindTexture(gl.TEXTURE_2D, tex); 186 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 187 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 188 var fbo = gl.createFramebuffer(); 189 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 190 var rbo = gl.createRenderbuffer(); 191 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 192 var fboWidth = 16; 193 var fboHeight = 16; 194 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight); 195 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); 196 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); 197 gl.clearColor(1.0, 0.0, 0.0, 1.0); 198 gl.clear(gl.COLOR_BUFFER_BIT); 199 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 200 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height); 201 checkNonZeroPixels(tex, width, height, 0, 0, fboWidth, fboHeight, 255, 0, 0, 255); 202 gl.deleteTexture(tex); 203 gl.finish(); 204 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 205 206 debug(""); 207 debug("Reading an uninitialized portion of a texture (copyTexSubImage2D with negative x and y) should succeed with all bytes set to 0."); 208 209 var tex = gl.createTexture(); 210 gl.bindTexture(gl.TEXTURE_2D, tex); 211 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 212 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 213 var fbo = gl.createFramebuffer(); 214 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 215 var rbo = gl.createRenderbuffer(); 216 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 217 var fboWidth = 16; 218 var fboHeight = 16; 219 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight); 220 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); 221 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); 222 gl.clearColor(1.0, 0.0, 0.0, 1.0); 223 gl.clear(gl.COLOR_BUFFER_BIT); 224 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 225 var x = -8; 226 var y = -8; 227 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, x, y, width, height); 228 checkNonZeroPixels(tex, width, height, -x, -y, fboWidth, fboHeight, 255, 0, 0, 255); 229 gl.deleteTexture(tex); 230 gl.finish(); 231 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 232 233 debug(""); 234 debug("Reading an uninitialized portion of a texture (copyTexSubImage2D from WebGL internal fbo) should succeed with all bytes set to 0."); 235 236 var tex = gl.createTexture(); 237 gl.bindTexture(gl.TEXTURE_2D, tex); 238 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 239 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 240 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 241 gl.clearColor(0.0, 1.0, 0.0, 0.0); 242 gl.clear(gl.COLOR_BUFFER_BIT); 243 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 244 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height); 245 checkNonZeroPixels(tex, width, height, 0, 0, canvas.width, canvas.height, 0, 255, 0, 0); 246 gl.deleteTexture(tex); 247 gl.finish(); 248 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 249 250 //TODO: uninitialized vertex array buffer 251 //TODO: uninitialized vertex elements buffer 252 //TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?) 253 //TODO: uninitialized renderbuffer? (implementations would need to do a GL clear at first binding?) 254 //TODO: uninitialized uniform arrays? 255 256 debug(""); 257 var successfullyParsed = true; 258 </script> 259 <script src="../../js/js-test-post.js"></script> 260 </body> 261 </html>