|
1 <!DOCTYPE html> |
|
2 <html> |
|
3 <head> |
|
4 <meta charset="utf-8"> |
|
5 <title>WebGL Uninitialized GL Resources Tests</title> |
|
6 <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
|
7 <script src="../../resources/js-test-pre.js"></script> |
|
8 <script src="../resources/webgl-test.js"></script> |
|
9 <script src="../resources/webgl-test-utils.js"></script> |
|
10 </head> |
|
11 <body> |
|
12 <div id="description"></div> |
|
13 <div id="console"></div> |
|
14 <canvas id="canvas" width="2" height="2"> </canvas> |
|
15 <script> |
|
16 description("Tests to check user code cannot access uninitialized data from GL resources."); |
|
17 |
|
18 var wtu = WebGLTestUtils; |
|
19 var gl = wtu.create3DContext("canvas"); |
|
20 if (!gl) |
|
21 testFailed("Context created."); |
|
22 else |
|
23 testPassed("Context created."); |
|
24 |
|
25 function setupTexture(texWidth, texHeight) { |
|
26 var texture = gl.createTexture(); |
|
27 gl.bindTexture(gl.TEXTURE_2D, texture); |
|
28 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); |
|
29 |
|
30 // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits |
|
31 // into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem) |
|
32 // with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time. |
|
33 |
|
34 var badData = new Uint8Array(texWidth * texHeight * 4); |
|
35 for (var i = 0; i < badData.length; ++i) |
|
36 badData[i] = i % 255; |
|
37 |
|
38 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); |
|
39 gl.finish(); // make sure it has been uploaded |
|
40 |
|
41 gl.deleteTexture(texture); |
|
42 gl.finish(); // make sure it has been deleted |
|
43 |
|
44 var texture = gl.createTexture(); |
|
45 gl.bindTexture(gl.TEXTURE_2D, texture); |
|
46 return texture; |
|
47 } |
|
48 |
|
49 function checkNonZeroPixels(texture, texWidth, texHeight, skipX, skipY, skipWidth, skipHeight, skipR, skipG, skipB, skipA) { |
|
50 gl.bindTexture(gl.TEXTURE_2D, null); |
|
51 var fb = gl.createFramebuffer(); |
|
52 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
|
53 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); |
|
54 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); |
|
55 |
|
56 var data = new Uint8Array(texWidth * texHeight * 4); |
|
57 gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, data); |
|
58 |
|
59 var k = 0; |
|
60 for (var y = 0; y < texHeight; ++y) { |
|
61 for (var x = 0; x < texWidth; ++x) { |
|
62 var index = (y * texWidth + x) * 4; |
|
63 if (x >= skipX && x < skipX + skipWidth && y >= skipY && y < skipY + skipHeight) { |
|
64 if (data[index] != skipR || data[index + 1] != skipG || data[index + 2] != skipB || data[index + 3] != skipA) { |
|
65 testFailed("non-zero pixel values are wrong at (" + x + ", " + y + "), data was (" + |
|
66 data[index] + "," + data[index + 1] + "," + data[index + 2] + "," + data[index + 3] + |
|
67 ") should have been (" + skipR + "," + skipG + "," + skipB + "," + skipA + ")"); |
|
68 return; |
|
69 } |
|
70 } else { |
|
71 for (var i = 0; i < 4; ++i) { |
|
72 if (data[index + i] != 0) |
|
73 k++; |
|
74 } |
|
75 } |
|
76 } |
|
77 } |
|
78 if (k) { |
|
79 testFailed("Found " + k + " non-zero bytes"); |
|
80 } else { |
|
81 testPassed("All data initialized"); |
|
82 } |
|
83 } |
|
84 |
|
85 var width = 512; |
|
86 var height = 512; |
|
87 |
|
88 debug(""); |
|
89 debug("Reading an uninitialized texture (texImage2D) should succeed with all bytes set to 0."); |
|
90 |
|
91 var tex = setupTexture(width, height); |
|
92 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); |
|
93 checkNonZeroPixels(tex, width, height, 0, 0, 0, 0, 0, 0, 0, 0); |
|
94 gl.deleteTexture(tex); |
|
95 gl.finish(); |
|
96 glErrorShouldBe(gl, gl.NO_ERROR); |
|
97 |
|
98 debug(""); |
|
99 debug("Reading an uninitialized portion of a texture (copyTexImage2D) should succeed with all bytes set to 0."); |
|
100 |
|
101 var tex = setupTexture(width, height); |
|
102 var fbo = gl.createFramebuffer(); |
|
103 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); |
|
104 var rbo = gl.createRenderbuffer(); |
|
105 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); |
|
106 var fboWidth = 16; |
|
107 var fboHeight = 16; |
|
108 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight); |
|
109 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); |
|
110 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); |
|
111 gl.clearColor(1.0, 0.0, 0.0, 1.0); |
|
112 gl.clear(gl.COLOR_BUFFER_BIT); |
|
113 glErrorShouldBe(gl, gl.NO_ERROR); |
|
114 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0); |
|
115 checkNonZeroPixels(tex, width, height, 0, 0, fboWidth, fboHeight, 255, 0, 0, 255); |
|
116 gl.deleteTexture(tex); |
|
117 gl.finish(); |
|
118 glErrorShouldBe(gl, gl.NO_ERROR); |
|
119 |
|
120 debug(""); |
|
121 debug("Reading an uninitialized portion of a texture (copyTexImage2D with negative x and y) should succeed with all bytes set to 0."); |
|
122 |
|
123 var tex = setupTexture(width, height); |
|
124 var fbo = gl.createFramebuffer(); |
|
125 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); |
|
126 var rbo = gl.createRenderbuffer(); |
|
127 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); |
|
128 var fboWidth = 16; |
|
129 var fboHeight = 16; |
|
130 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight); |
|
131 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); |
|
132 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); |
|
133 gl.clearColor(1.0, 0.0, 0.0, 1.0); |
|
134 gl.clear(gl.COLOR_BUFFER_BIT); |
|
135 glErrorShouldBe(gl, gl.NO_ERROR); |
|
136 var x = -8; |
|
137 var y = -8; |
|
138 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, x, y, width, height, 0); |
|
139 checkNonZeroPixels(tex, width, height, -x, -y, fboWidth, fboHeight, 255, 0, 0, 255); |
|
140 gl.deleteTexture(tex); |
|
141 gl.finish(); |
|
142 glErrorShouldBe(gl, gl.NO_ERROR); |
|
143 |
|
144 debug(""); |
|
145 debug("Reading an uninitialized portion of a texture (copyTexImage2D from WebGL internal fbo) should succeed with all bytes set to 0."); |
|
146 |
|
147 var tex = setupTexture(width, height); |
|
148 gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
|
149 gl.clearColor(0.0, 1.0, 0.0, 0.0); |
|
150 gl.clear(gl.COLOR_BUFFER_BIT); |
|
151 glErrorShouldBe(gl, gl.NO_ERROR); |
|
152 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0); |
|
153 checkNonZeroPixels(tex, width, height, 0, 0, gl.canvas.width, gl.canvas.height, 0, 255, 0, 0); |
|
154 gl.deleteTexture(tex); |
|
155 gl.finish(); |
|
156 glErrorShouldBe(gl, gl.NO_ERROR); |
|
157 |
|
158 //TODO: uninitialized vertex array buffer |
|
159 //TODO: uninitialized vertex elements buffer |
|
160 //TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?) |
|
161 //TODO: uninitialized renderbuffer? (implementations would need to do a GL clear at first binding?) |
|
162 //TODO: uninitialized uniform arrays? |
|
163 |
|
164 debug(""); |
|
165 successfullyParsed = true; |
|
166 </script> |
|
167 <script>finishTest();</script> |
|
168 </body> |
|
169 </html> |
|
170 |