Backed out changeset b462e7b742d8 (bug 1908261) for causing multiple reftest failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance / extensions / oes-element-index-uint.html
blobf30acaba28109ccba21dfb37b46fa44b758636b6
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 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
10 <meta charset="utf-8">
11 <title>WebGL OES_element_index_uint Conformance Tests</title>
12 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
13 <script src="../../js/js-test-pre.js"></script>
14 <script src="../../js/webgl-test-utils.js"></script>
16 <script id="vs" type="x-shader/x-vertex">
17 attribute vec4 vPosition;
18 attribute vec4 vColor;
19 varying vec4 color;
20 void main() {
21 gl_Position = vPosition;
22 color = vColor;
24 </script>
25 <script id="fs" type="x-shader/x-fragment">
26 precision mediump float;
27 varying vec4 color;
28 void main() {
29 gl_FragColor = color;
31 </script>
33 </head>
34 <body>
35 <div id="description"></div>
36 <div id="console"></div>
37 <script>
38 "use strict";
39 description("This test verifies the functionality of the OES_element_index_uint extension, if it is available.");
41 debug("");
43 var wtu = WebGLTestUtils;
44 var gl = null;
45 var ext = null;
46 var canvas = null;
48 // Test both STATIC_DRAW and DYNAMIC_DRAW as a regression test
49 // for a bug in ANGLE which has since been fixed.
50 for (var ii = 0; ii < 2; ++ii) {
51 canvas = document.createElement("canvas");
52 canvas.width = 50;
53 canvas.height = 50;
55 gl = wtu.create3DContext(canvas);
57 if (!gl) {
58 testFailed("WebGL context does not exist");
59 } else {
60 testPassed("WebGL context exists");
62 var drawType = (ii == 0) ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW;
63 debug("Testing " + ((ii == 0) ? "STATIC_DRAW" : "DYNAMIC_DRAW"));
66 // Query the extension and store globally so shouldBe can access it
67 ext = gl.getExtension("OES_element_index_uint");
68 if (!ext) {
69 testPassed("No OES_element_index_uint support -- this is legal");
71 runSupportedTest(false);
72 } else {
73 testPassed("Successfully enabled OES_element_index_uint extension");
75 runSupportedTest(true);
77 runDrawTests(drawType);
79 // These tests are tweaked duplicates of the buffers/index-validation* tests
80 // using unsigned int indices to ensure that behavior remains consistent
81 runIndexValidationTests(drawType);
82 runCopiesIndicesTests(drawType);
83 runResizedBufferTests(drawType);
84 runVerifiesTooManyIndicesTests(drawType);
85 runCrashWithBufferSubDataTests(drawType);
87 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
92 function runSupportedTest(extensionEnabled) {
93 var supported = gl.getSupportedExtensions();
94 if (supported.indexOf("OES_element_index_uint") >= 0) {
95 if (extensionEnabled) {
96 testPassed("OES_element_index_uint listed as supported and getExtension succeeded");
97 } else {
98 testFailed("OES_element_index_uint listed as supported but getExtension failed");
100 } else {
101 if (extensionEnabled) {
102 testFailed("OES_element_index_uint not listed as supported but getExtension succeeded");
103 } else {
104 testPassed("OES_element_index_uint not listed as supported and getExtension failed -- this is legal");
109 function runDrawTests(drawType) {
110 debug("Test that draws with unsigned integer indices produce the expected results");
112 canvas.width = 50; canvas.height = 50;
113 gl.viewport(0, 0, canvas.width, canvas.height);
115 var program = wtu.setupSimpleColorProgram(gl);
117 function setupDraw(s) {
118 // Create a vertex buffer that cannot be fully indexed via shorts
119 var quadArrayLen = 65537 * 3;
120 var quadArray = new Float32Array(quadArrayLen);
122 // Leave all but the last 4 values zero-ed out
123 var idx = quadArrayLen - 12;
125 // Initialized the last 4 values to a quad
126 quadArray[idx++] = 1.0 * s;
127 quadArray[idx++] = 1.0 * s;
128 quadArray[idx++] = 0.0;
130 quadArray[idx++] = -1.0 * s;
131 quadArray[idx++] = 1.0 * s;
132 quadArray[idx++] = 0.0;
134 quadArray[idx++] = -1.0 * s;
135 quadArray[idx++] = -1.0 * s;
136 quadArray[idx++] = 0.0;
138 quadArray[idx++] = 1.0 * s;
139 quadArray[idx++] = -1.0 * s;
140 quadArray[idx++] = 0.0;
142 var vertexObject = gl.createBuffer();
143 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
144 gl.bufferData(gl.ARRAY_BUFFER, quadArray, drawType);
146 // Create an unsigned int index buffer that indexes the last 4 vertices
147 var baseIndex = (quadArrayLen / 3) - 4;
149 var indexObject = gl.createBuffer();
150 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
151 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([
152 baseIndex + 0,
153 baseIndex + 1,
154 baseIndex + 2,
155 baseIndex + 2,
156 baseIndex + 3,
157 baseIndex + 0]), drawType);
159 var opt_positionLocation = 0;
160 gl.enableVertexAttribArray(opt_positionLocation);
161 gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0);
163 function testPixel(blockList, allowList) {
164 function testList(list, expected) {
165 for (var n = 0; n < list.length; n++) {
166 var l = list[n];
167 var x = -Math.floor(l * canvas.width / 2) + canvas.width / 2;
168 var y = -Math.floor(l * canvas.height / 2) + canvas.height / 2;
169 wtu.checkCanvasRect(gl, x, y, 1, 1, [expected, expected, expected],
170 "Draw should pass", 2);
173 testList(blockList, 0);
174 testList(allowList, 255);
176 function verifyDraw(s) {
177 gl.clearColor(1.0, 1.0, 1.0, 1.0);
178 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
179 wtu.setFloatDrawColor(gl, [0.0, 0.0, 0.0, 1.0]);
180 gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
182 var blockList = [];
183 var allowList = [];
184 var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
185 for (var n = 0; n < points.length; n++) {
186 if (points[n] <= s) {
187 blockList.push(points[n]);
188 } else {
189 allowList.push(points[n]);
192 testPixel(blockList, allowList);
195 setupDraw(0.5);
196 verifyDraw(0.5);
199 function runIndexValidationTests(drawType) {
200 description("Tests that index validation verifies the correct number of indices");
202 function sizeInBytes(type) {
203 switch (type) {
204 case gl.BYTE:
205 case gl.UNSIGNED_BYTE:
206 return 1;
207 case gl.SHORT:
208 case gl.UNSIGNED_SHORT:
209 return 2;
210 case gl.INT:
211 case gl.UNSIGNED_INT:
212 case gl.FLOAT:
213 return 4;
214 default:
215 throw "unknown type";
219 var program = wtu.loadStandardProgram(gl);
221 // 3 vertices => 1 triangle, interleaved data
222 var dataComplete = new Float32Array([0, 0, 0, 1,
223 0, 0, 1,
224 1, 0, 0, 1,
225 0, 0, 1,
226 1, 1, 1, 1,
227 0, 0, 1]);
228 var dataIncomplete = new Float32Array([0, 0, 0, 1,
229 0, 0, 1,
230 1, 0, 0, 1,
231 0, 0, 1,
232 1, 1, 1, 1]);
233 var indices = new Uint32Array([0, 1, 2]);
235 debug("Testing with valid indices");
237 var bufferComplete = gl.createBuffer();
238 gl.bindBuffer(gl.ARRAY_BUFFER, bufferComplete);
239 gl.bufferData(gl.ARRAY_BUFFER, dataComplete, drawType);
240 var elements = gl.createBuffer();
241 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
242 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
243 gl.useProgram(program);
244 var vertexLoc = gl.getAttribLocation(program, "a_vertex");
245 var normalLoc = gl.getAttribLocation(program, "a_normal");
246 gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
247 gl.enableVertexAttribArray(vertexLoc);
248 gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
249 gl.enableVertexAttribArray(normalLoc);
250 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
251 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
252 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
253 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
255 debug("Testing with out-of-range indices");
257 var bufferIncomplete = gl.createBuffer();
258 gl.bindBuffer(gl.ARRAY_BUFFER, bufferIncomplete);
259 gl.bufferData(gl.ARRAY_BUFFER, dataIncomplete, drawType);
260 gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
261 gl.enableVertexAttribArray(vertexLoc);
262 gl.disableVertexAttribArray(normalLoc);
263 debug("Enable vertices, valid");
264 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
265 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
266 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
267 debug("Enable normals, out-of-range");
268 gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
269 gl.enableVertexAttribArray(normalLoc);
270 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
271 wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
272 'gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
274 debug("Test with enabled attribute that does not belong to current program");
276 gl.disableVertexAttribArray(normalLoc);
277 var extraLoc = Math.max(vertexLoc, normalLoc) + 1;
278 gl.enableVertexAttribArray(extraLoc);
279 debug("Enable an extra attribute with null");
280 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
281 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
282 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
283 debug("Enable an extra attribute with insufficient data buffer");
284 gl.vertexAttribPointer(extraLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
285 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
286 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
287 debug("Pass large negative index to vertexAttribPointer");
288 gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
289 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
290 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
293 function runCopiesIndicesTests(drawType) {
294 debug("Test that client data is always copied during bufferData and bufferSubData calls");
296 var program = wtu.loadStandardProgram(gl);
298 gl.useProgram(program);
299 var vertexObject = gl.createBuffer();
300 gl.enableVertexAttribArray(0);
301 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
302 // 4 vertices -> 2 triangles
303 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0,0, 0,1,0, 1,0,0, 1,1,0 ]), drawType);
304 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
306 var indexObject = gl.createBuffer();
308 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
309 var indices = new Uint32Array([ 10000, 0, 1, 2, 3, 10000 ]);
310 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
311 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 4)");
312 var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
313 "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 0)");
314 wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 8)");
315 indices[0] = 2;
316 indices[5] = 1;
317 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 4)");
318 wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 0)");
319 wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 8)");
322 function runResizedBufferTests(drawType) {
323 debug("Test that updating the size of a vertex buffer is properly noticed by the WebGL implementation.");
325 var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vColor"]);
326 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initialization");
328 var vertexObject = gl.createBuffer();
329 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
330 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
331 [-1,1,0, 1,1,0, -1,-1,0,
332 -1,-1,0, 1,1,0, 1,-1,0]), drawType);
333 gl.enableVertexAttribArray(0);
334 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
335 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex setup");
337 var texCoordObject = gl.createBuffer();
338 gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
339 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
340 [0,0, 1,0, 0,1,
341 0,1, 1,0, 1,1]), drawType);
342 gl.enableVertexAttribArray(1);
343 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
344 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coord setup");
346 // Now resize these buffers because we want to change what we're drawing.
347 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
348 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
349 -1,1,0, 1,1,0, -1,-1,0, 1,-1,0,
350 -1,1,0, 1,1,0, -1,-1,0, 1,-1,0]), drawType);
351 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex redefinition");
352 gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
353 gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([
354 255, 0, 0, 255,
355 255, 0, 0, 255,
356 255, 0, 0, 255,
357 255, 0, 0, 255,
358 0, 255, 0, 255,
359 0, 255, 0, 255,
360 0, 255, 0, 255,
361 0, 255, 0, 255]), drawType);
362 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, false, 0, 0);
363 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coordinate / color redefinition");
365 var numQuads = 2;
366 var indices = new Uint32Array(numQuads * 6);
367 for (var ii = 0; ii < numQuads; ++ii) {
368 var offset = ii * 6;
369 var quad = (ii == (numQuads - 1)) ? 4 : 0;
370 indices[offset + 0] = quad + 0;
371 indices[offset + 1] = quad + 1;
372 indices[offset + 2] = quad + 2;
373 indices[offset + 3] = quad + 2;
374 indices[offset + 4] = quad + 1;
375 indices[offset + 5] = quad + 3;
377 var indexObject = gl.createBuffer();
378 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
379 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
380 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
381 gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_INT, 0);
382 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
385 function runVerifiesTooManyIndicesTests(drawType) {
386 description("Tests that index validation for drawElements does not examine too many indices");
388 var program = wtu.loadStandardProgram(gl);
390 gl.useProgram(program);
391 var vertexObject = gl.createBuffer();
392 gl.enableVertexAttribArray(0);
393 gl.disableVertexAttribArray(1);
394 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
395 // 4 vertices -> 2 triangles
396 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0,0, 0,1,0, 1,0,0, 1,1,0 ]), drawType);
397 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
399 var indexObject = gl.createBuffer();
401 debug("Test out of range indices")
402 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
403 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([ 10000, 0, 1, 2, 3, 10000 ]), drawType);
404 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 4)");
405 var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
406 "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 0)");
407 wtu.shouldGenerateGLError(gl, indexValidationError, "gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_INT, 8)");
410 function runCrashWithBufferSubDataTests(drawType) {
411 debug('Verifies that the index validation code which is within bufferSubData does not crash.')
413 var elementBuffer = gl.createBuffer();
414 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
415 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 256, drawType);
416 var data = new Uint32Array(127);
417 gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 64, data);
418 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "after attempting to update a buffer outside of the allocated bounds");
419 testPassed("bufferSubData, when buffer object was initialized with null, did not crash");
422 debug("");
423 var successfullyParsed = true;
424 </script>
425 <script src="../../js/js-test-post.js"></script>
427 </body>
428 </html>