diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance/attribs')
16 files changed, 1510 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/00_test_list.txt new file mode 100644 index 0000000000..317fe70233 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/00_test_list.txt @@ -0,0 +1,15 @@ +--min-version 1.0.3 gl-bindAttribLocation-aliasing.html +--min-version 1.0.3 gl-bindAttribLocation-matrix.html +--min-version 1.0.4 gl-bindAttribLocation-nonexistent-attribute.html +--min-version 1.0.4 gl-bindAttribLocation-repeated.html +--min-version 1.0.2 gl-disabled-vertex-attrib.html +--min-version 1.0.4 gl-disabled-vertex-attrib-update.html +gl-enable-vertex-attrib.html +--min-version 1.0.3 gl-matrix-attributes.html +--max-version 1.9.9 gl-vertex-attrib.html +gl-vertexattribpointer.html +gl-vertexattribpointer-offsets.html +--min-version 1.0.2 gl-vertex-attrib-render.html +gl-vertex-attrib-zero-issues.html +--min-version 1.0.4 gl-vertex-attrib-unconsumed-out-of-bounds.html +--min-version 1.0.4 gl-vertex-attrib-context-switch.html diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html new file mode 100644 index 0000000000..aae54715dc --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html @@ -0,0 +1,42 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<script src="../../js/tests/gl-bindattriblocation-aliasing.js"></script> +<title>bindAttribLocation with aliasing</title> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> +<script id="vertexShader" type="text/something-not-javascript"> +precision mediump float; +attribute $(type_1) a_1; +attribute $(type_2) a_2; +void main() { + gl_Position = $(gl_Position_1) + $(gl_Position_2); +} +</script> +<script> +"use strict"; +description("This test verifies combinations of valid, active attribute types cannot be bound to the same location with bindAttribLocation."); +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, {antialias: false}); +var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER); + +runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShader')); + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-matrix.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-matrix.html new file mode 100644 index 0000000000..ef5fd25b19 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-matrix.html @@ -0,0 +1,98 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<title>WebGL bindAttribLocation with Matrix Attributes Conformance Test</title> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> +<script> +"use strict"; +description("This test verifies that vectors placed via bindAttribLocation right after matricies will fail if there is insufficient room for the matrix."); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, {antialias: false}); + +// Make sure we have room for at least a mat4. +var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); +debug('MAX_VERTEX_ATTRIBUTES is ' + maxAttributes); +shouldBeGreaterThanOrEqual('maxAttributes', '4'); + +var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER); + +// Given a matrix dimension, load a vertex shader with a matrix of that dimension +// and a vector. Ensure that both the vector and matrix are active attributes. +// Return the compiled vertex shader. +function loadVertexShader(numMatrixDimensions) { + var strVertexShader = + 'attribute mat' + numMatrixDimensions + ' matrix;\n' + + 'attribute vec' + numMatrixDimensions + ' vector;\n' + + 'void main(void) { gl_Position = vec4(vector*matrix'; + // Ensure the vec4 has the correct number of dimensions in order to be assignable + // to gl_Position. + for (var ii = numMatrixDimensions; ii < 4; ++ii) { + strVertexShader += ",0.0"; + } + strVertexShader += ");}\n"; + return wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER); +} + +// Given a vertex shader, matrix location and vector location, create and link +// a program with glFragmentShader and a vertex shader returned by loadVertexShader +// attached. Bind the matrix to matrixLocation and the vector to vectorLocation. +// Return whether the link was successful. +function createAndLinkProgram(glVertexShader, matrixLocation, vectorLocation) { + var glProgram = gl.createProgram(); + gl.bindAttribLocation(glProgram, matrixLocation, 'matrix'); + gl.bindAttribLocation(glProgram, vectorLocation, 'vector'); + gl.attachShader(glProgram, glVertexShader); + gl.attachShader(glProgram, glFragmentShader); + gl.linkProgram(glProgram); + return gl.getProgramParameter(glProgram, gl.LINK_STATUS); +} + +// For each matrix dimension (mat2, mat3 and mat4) +for (var mm = 2; mm <= 4; ++mm) { + debug('Testing ' + mm + ' dimensional matrices'); + var glVertexShader = loadVertexShader(mm); + // Per the WebGL spec: "LinkProgram will fail if the attribute bindings assigned + // by bindAttribLocation do not leave enough space to assign a location for an + // active matrix attribute which requires multiple contiguous generic attributes." + // We will test this by placing the vector after the matrix attribute such that there + // is not enough room for the matrix. Vertify the link operation fails. + + // Run the test for each available attribute slot. Go to maxAttributes-mm to leave enough room + // for the matrix itself. Leave another slot open for the vector following the matrix. + for (var pp = 0; pp <= maxAttributes - mm - 1; ++pp) { + // For each matrix dimension, bind the vector right after the matrix such that we leave + // insufficient room for the matrix. Verify doing this will fail the link operation. + for (var ll = 0; ll < mm; ++ll) { + var vectorLocation = pp + ll; + assertMsg(!createAndLinkProgram(glVertexShader, /*matrixLocation*/pp, vectorLocation), + "Matrix with location " + pp + " and vector with location " + vectorLocation + " should not link."); + } + // Ensure that once we have left enough room for the matrix, the program links successfully. + var vectorLocation = pp + ll; + assertMsg(createAndLinkProgram(glVertexShader, /*matrixLocation*/pp, vectorLocation), + "Matrix with location " + pp + " and vector with location " + vectorLocation + " should link."); + debug(''); + } + debug(''); +} + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-nonexistent-attribute.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-nonexistent-attribute.html new file mode 100644 index 0000000000..d6968b5ea4 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-nonexistent-attribute.html @@ -0,0 +1,82 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<title>bindAttribLocation with nonexistent attribute name</title> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="8" height="8"></canvas> +<script id="vertexShader" type="text/something-not-javascript"> +precision highp float; +attribute vec4 attr; +void main() { + gl_Position = vec4(attr); +} +</script> +<script> +"use strict"; +description("This test verifies that calling bindAttribLocation with a non-existent attribute location is fine."); + +// OpenGL ES 2.0.25 section 2.10 page 34. + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas); +var fragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER); +var vertexShader = wtu.loadShaderFromScript(gl, 'vertexShader', gl.VERTEX_SHADER); +assertMsg(vertexShader != null, "Vertex shader compiled successfully."); + +var checkAttribLocation = function(program, expectedLocation) { + var location = gl.getAttribLocation(program, 'attr'); + if (location != expectedLocation) { + testFailed('Unexpected location for attr: ' + location); + } else { + testPassed('Location of attr is: ' + location); + } +} + +var testProgramNonExistentAttributeBound = function() { + var program = gl.createProgram(); + gl.bindAttribLocation(program, 0, 'attr'); + gl.bindAttribLocation(program, 1, 'bogus_attr'); + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + var linkStatus = gl.getProgramParameter(program, gl.LINK_STATUS); + expectTrue(linkStatus, "Link should succeed even if a non-existent attribute is bound."); + if (linkStatus) { + checkAttribLocation(program, 0); + } +}; +var testProgramNonExistentAttributeOverlap = function() { + var program = gl.createProgram(); + gl.bindAttribLocation(program, 1, 'attr'); + gl.bindAttribLocation(program, 1, 'bogus_attr'); + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + var linkStatus = gl.getProgramParameter(program, gl.LINK_STATUS); + expectTrue(linkStatus, "Link should succeed even if a non-existent attribute is bound to the same location as an attribute that's present in the shader text."); + if (linkStatus) { + checkAttribLocation(program, 1); + } +}; + +testProgramNonExistentAttributeBound(); +testProgramNonExistentAttributeOverlap(); + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-repeated.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-repeated.html new file mode 100644 index 0000000000..cfbea4fb63 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-repeated.html @@ -0,0 +1,68 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Repeated BindAttribLocation Test</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="example" width="50" height="50"> +</canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> + attribute vec4 vPosition; + void main() + { + gl_Position = vPosition; + } +</script> + +<script id="fshader" type="x-shader/x-fragment"> + void main() + { + gl_FragColor = vec4(0.0,1.0,0.0,1.0); + } +</script> + +<script> +"use strict"; +description("Test repeated loading of programs involving bindAttribLocation calls"); +debug("Regression test for <a href='https://code.google.com/p/chromium/issues/detail?id=510637'>crbug.com/510637</a>"); +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("example"); +var g_program; +var g_attribLocation; +function setup(attribIndex) { + var program = wtu.setupProgram( + gl, ['vshader', 'fshader'], ['vPosition'], [attribIndex]); + g_program = program; + g_attribLocation = attribIndex; + shouldBe("gl.getAttribLocation(g_program, 'vPosition')", "g_attribLocation"); + return program; +} + +var p0 = setup(0); +var p3 = setup(3); +var p1 = setup(1); +// This call fails the getAttribLocation check on some drivers when +// Chrome's program binary cache is enabled. On the affected drivers, +// it returns the bound attribute location from the first binary +// created. Swapping 0 and 1 above will cause it to return 1 rather +// than 0. +p3 = setup(3); + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib-update.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib-update.html new file mode 100644 index 0000000000..3ef12fb9aa --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib-update.html @@ -0,0 +1,79 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Disabled Vertex Attrib Update Test</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="example" width="50" height="50"> +</canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> +attribute vec4 a_position; +attribute float a_actualValue; +uniform float u_expectedValue; +varying float v_result; +void main() { + gl_Position = a_position; + v_result = a_actualValue == u_expectedValue ? 1.0 : 0.0; +} +</script> + +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; +varying float v_result; +void main() { + gl_FragColor = v_result > 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0); +} +</script> + +<script> +// Tests that repeatedly updating a disabled vertex attribute works as expected. +// This covers an ANGLE bug where dirty bits for current values were ignoring repeated updates. +// Based on ANGLE test (VertexAttributeTest, DisabledAttribUpdates) from https://github.com/google/angle/blob/f7f0b8c3ab21c52cc2915048959361cf628d95f0/src/tests/gl_tests/VertexAttributeTest.cpp +"use strict"; +var wtu = WebGLTestUtils; +description(); + +var gl = wtu.create3DContext("example"); + +var program = wtu.setupProgram(gl, ['vshader', 'fshader']); +gl.useProgram(program); + +var positionLocation = gl.getAttribLocation(program, "a_position"); +var attribLoc = gl.getAttribLocation(program, "a_actualValue"); +gl.vertexAttribPointer(attribLoc, 1, gl.FLOAT, gl.FALSE, 0, 0); + +var uniLoc = gl.getUniformLocation(program, "u_expectedValue"); + +var gridRes = 1; +wtu.setupIndexedQuad(gl, gridRes, positionLocation); + +var testValues = [1, 2, 3, 4]; +for (var i = 0; i < testValues.length; ++i) { + var testValue = testValues[i]; + gl.uniform1f(uniLoc, testValue); + gl.vertexAttrib1f(attribLoc, testValue); + wtu.clearAndDrawIndexedQuad(gl, gridRes); + wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green"); +} + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> + diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib.html new file mode 100644 index 0000000000..f4f8997449 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-disabled-vertex-attrib.html @@ -0,0 +1,79 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Disabled Vertex Attrib Test</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="example" width="50" height="50"> +</canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> +attribute vec4 a_position; +attribute vec4 a_color; +varying vec4 v_color; +bool isCorrectColor(vec4 v) { + return v.x == 0.0 && v.y == 0.0 && v.z == 0.0 && v.w == 1.0; +} +void main() { + gl_Position = a_position; + v_color = isCorrectColor(a_color) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1); +} +</script> + +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; +varying vec4 v_color; +void main() { + gl_FragColor = v_color; +} +</script> + +<script> +"use strict"; +var wtu = WebGLTestUtils; +description(); + +var gl = wtu.create3DContext("example"); + +var numVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); +for (var ii = 0; ii < numVertexAttribs; ++ii) { + var colorLocation = (ii + 1) % numVertexAttribs; + var positionLocation = colorLocation ? 0 : 1; + + if (positionLocation != 0) { + // We need to create a new 3d context for testing attrib 0 + // since we've already effected attrib 0 on other tests. + gl = wtu.create3DContext(); + } + + debug("testing attrib: " + colorLocation); + var program = wtu.setupProgram( + gl, + ['vshader', 'fshader'], + ['a_position', 'a_color'], + [positionLocation, colorLocation]); + var gridRes = 1; + wtu.setupIndexedQuad(gl, gridRes, positionLocation); + wtu.clearAndDrawIndexedQuad(gl, gridRes); + wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green"); +} +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> + diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-enable-vertex-attrib.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-enable-vertex-attrib.html new file mode 100644 index 0000000000..6425a33a7a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-enable-vertex-attrib.html @@ -0,0 +1,51 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> + <head> +<meta charset="utf-8"> + <title>WebGL Enable Vertex Attrib Test</title> + <link rel="stylesheet" href="../../resources/js-test-style.css"/> + <script src="../../js/js-test-pre.js"></script> + <script src="../../js/webgl-test-utils.js"> </script> + <script src="../../js/tests/invalid-vertex-attrib-test.js"></script> +</head> +<body> +<canvas id="example" width="50" height="50"> +</canvas> +<div id="description"></div> +<div id="console"></div> + +<script> +"use strict"; +description("tests that turning on attribs that have no buffer bound fails to draw"); +const wtu = WebGLTestUtils; +const gl = wtu.create3DContext("example"); + +async function runInvalidAttribTests() { + const invalidAttribTestFn = createInvalidAttribTestFn(gl); + + function drawArrays(gl) { + gl.drawArrays(gl.TRIANGLES, 0, 6); + } + + function drawElements(gl) { + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0); + } + + await invalidAttribTestFn(drawArrays); + await invalidAttribTestFn(drawElements); + finishTest(); +} +runInvalidAttribTests(); + +var successfullyParsed = true; +</script> + +</body> +</html> + diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html new file mode 100644 index 0000000000..fc7ab56b0f --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-matrix-attributes.html @@ -0,0 +1,136 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<title>WebGL Matrix Attribute Conformance Test</title> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> +<script> +"use strict"; +description("This tests ensures that matrix attribute locations do not clash with other shader attributes."); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, {antialias: false}); + +// Make sure we have room for at least a mat4. +var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); +debug('MAX_VERTEX_ATTRIBUTES is ' + maxAttributes); +shouldBeGreaterThanOrEqual('maxAttributes', '4'); + +var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShader, gl.FRAGMENT_SHADER); + +// prepareMatrixProgram creates a program with glFragmentShader as the fragment shader. +// The vertex shader has numVector number of vectors and a matrix with numMatrixDimensions +// dimensions at location numMatrixPosition in the list of attributes. +// Ensures that every vector and matrix is used by the program. +// Returns a valid program on successfull link; null on link failure. +function prepareMatrixProgram(numVectors, numMatrixDimensions, numMatrixPosition) { + // Add the matrix and vector attribute declarations. Declare the vectors + // to have the same number of components as the matrix so we can perform + // operations on them when we assign to gl_Position later on. + var strVertexShader = ""; + for (var ii = 1; ii <= numVectors; ++ii) { + if (numMatrixPosition === ii) { + strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n"; + } + strVertexShader += "attribute vec" + numMatrixDimensions + " vec_" + ii + ";\n"; + } + // numMatrixPosition will be one past numVectors if the caller wants it to be + // last. Hence, we need this check outside the loop as well as inside. + if (numMatrixPosition === ii) { + strVertexShader += "attribute mat" + numMatrixDimensions + " matrix;\n"; + } + // Add the body of the shader. Add up all of the vectors and multiply by the matrix. + // The operations we perform do not matter. We just need to ensure that all the vector and + // matrix attributes are used. + strVertexShader += "void main(void) { \ngl_Position = vec4(("; + for (var ii = 1; ii <= numVectors; ++ii) { + if (ii > 1) { + strVertexShader += "+" + } + strVertexShader += "vec_" + ii; + } + strVertexShader += ")*matrix"; + // Ensure the vec4 has the correct number of dimensions in order to be assignable + // to gl_Position. + for (var ii = numMatrixDimensions; ii < 4; ++ii) { + strVertexShader += ",0.0"; + } + strVertexShader += ");}\n"; + // Load the shader, attach it to a program, and return the link results + var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER); + var strTest = 'Load shader with ' + numVectors + ' vectors and 1 matrix'; + if (glVertexShader !== null) { + testPassed(strTest); + + var glProgram = gl.createProgram(); + gl.attachShader(glProgram, glVertexShader); + gl.attachShader(glProgram, glFragmentShader); + gl.linkProgram(glProgram); + if (gl.getProgramParameter(glProgram, gl.LINK_STATUS)) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'linkProgram'); + return glProgram; + } + } else { + testFailed(strTest); + } + return null; +} + +debug(''); + +// Test mat2, mat3 and mat4. +for (var mm = 2; mm <= 4; ++mm) { + // Add maxAttribute number of attributes by saving enough room in the attribute + // list for a matrix of mm dimensions. All of the other attribute slots will be + // filled with vectors. + var numVectors = maxAttributes - mm; + for (var pp = 1; pp <= numVectors + 1; ++pp) { + debug('Test ' + mm + ' dimensional matrix at position ' + pp); + var glProgram = prepareMatrixProgram(numVectors, /*numMatrixDimensions*/mm, /*numMatrixPosition*/pp); + shouldBeNonNull('glProgram'); + var attribMatrix = gl.getAttribLocation(glProgram, 'matrix'); + debug('Matrix is at attribute location ' + attribMatrix); + shouldBeTrue('attribMatrix > -1'); + // Per the spec, when an attribute is a matrix attribute, getAttribLocation + // returns the index of the first component of the matrix. The implementation must + // leave sufficient room for all the components. Here we ensure none of the vectors + // in the shader are assigned attribute locations that belong to the matrix. + for (var vv = 1; vv <= numVectors; ++vv) { + var strVector = 'vec_' + vv + var attribVector = gl.getAttribLocation(glProgram, strVector); + debug(strVector + ' is at attribute location ' + attribVector); + // Begin with the first attribute location where the matrix begins and ensure + // the vector's attribute location is not assigned to the matrix. Loop until + // we've checked all of the attribute locations that belong to the matrix. + for (var ii = attribMatrix; ii < attribMatrix + mm; ++ii) { + var testStr = strVector + ' attribute location: ' + attribVector + '. Should not be ' + ii; + if (attribVector !== ii) { + testPassed(testStr); + } else { + testFailed(testStr); + } + } + } + debug(''); + } + debug(''); +} + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-context-switch.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-context-switch.html new file mode 100644 index 0000000000..1db1c9a321 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-context-switch.html @@ -0,0 +1,60 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> + <head> +<meta charset="utf-8"> + <title>WebGL Vertex Attrib Context Switch Test</title> + <link rel="stylesheet" href="../../resources/js-test-style.css"/> + <script src="../../js/js-test-pre.js"></script> + <script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="one" width="50" height="50"> +</canvas> +<canvas id="two" width="50" height="50"> +</canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("tests that vertex attrib value is preserved across context switches"); +var wtu = WebGLTestUtils; +var positionLocation = 0; +var colorLocation = 1; +var gridRes = 1; + +var canvas1 = document.getElementById("one"); +var gl1 = wtu.create3DContext(canvas1); +var program1 = wtu.setupSimpleVertexColorProgram(gl1, positionLocation, colorLocation); +gl1.vertexAttrib4f(colorLocation, 0.0, 1.0, 0.0, 1.0); +wtu.setupIndexedQuad(gl1, gridRes, positionLocation); +wtu.clearAndDrawIndexedQuad(gl1, gridRes); +wtu.checkCanvas(gl1, [0, 255, 0, 255], "should be green 1"); + +var canvas2 = document.getElementById("two"); +var gl2 = wtu.create3DContext(canvas2); +var program2 = wtu.setupSimpleVertexColorProgram(gl2, positionLocation, colorLocation); +wtu.setupIndexedQuad(gl2, gridRes, positionLocation); +wtu.clearAndDrawIndexedQuad(gl2, gridRes); +wtu.checkCanvas(gl2, [0, 0, 0, 255], "should be black 1"); + +wtu.checkCanvas(gl1, [0, 255, 0, 255], "should be green 2"); + +wtu.clearAndDrawIndexedQuad(gl2, gridRes); +wtu.checkCanvas(gl2, [0, 0, 0, 255], "should be black 2"); + +wtu.clearAndDrawIndexedQuad(gl1, gridRes); +wtu.checkCanvas(gl1, [0, 255, 0, 255], "should be green 3"); + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> + diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-render.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-render.html new file mode 100644 index 0000000000..b10ebfe688 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-render.html @@ -0,0 +1,89 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<script id='vshader' type='x-shader'> +attribute vec4 a; +attribute vec2 p; +void main() { + gl_Position = vec4(p.x + a.x + a.y + a.z + a.w, p.y, 0.0, 1.0); +} +</script> +<script id='fshader' type='x-shader'> +precision mediump float; +void main() { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} +</script> +<script> +"use strict"; +function checkRedPortion(gl, w, low, high) { + var buf = new Uint8Array(w * w * 4); + gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf); + var i = 0; + for (; i < w; ++i) { + if (buf[i * 4 + 0] == 255 && buf[i * 4 + 1] == 0 && buf[i * 4 + 2] == 0 && buf[i * 4 + 3] == 255) { + break; + } + } + return low <= i && i <= high; +} + +function runTest() { + var wtu = WebGLTestUtils; + var gl = wtu.create3DContext('testbed', { preserveDrawingBuffer : true }); + if (!gl) { + testFailed('could not create context'); + return; + } + var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['p', 'a']) + + gl.enableVertexAttribArray(gl.p); + var pos = gl.createBuffer(); + pos.type = gl.FLOAT; + pos.size = 2; + pos.num = 4; + gl.bindBuffer(gl.ARRAY_BUFFER, pos); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW); + + gl.vertexAttribPointer(0, pos.size, pos.type, false, 0, 0); + + debug('Test vertexAttrib[1..4]fv by setting different combinations that add up to 1.5 and use that when rendering.'); + var vals = [[0.5], [0.1,0.4], [0.2,-0.2,0.5], [-1.0,0.3,0.2,2.0]]; + + for (var j = 0; j < 4; ++j) { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl['vertexAttrib' + (j+1) + 'fv'](1, vals[j]); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, pos.num); + + if (checkRedPortion(gl, 50, 50 * 0.7, 50 * 0.8)) { + testPassed('Attribute of size ' + (j+1) + ' was set correctly'); + } else { + testFailed('Attribute of size ' + (j+1) + ' was not set correctly'); + } + } +} +</script> +</head> +<body> +<canvas id="testbed" width="50" height="50"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description('Verify that using constant attributes works.'); +runTest(); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html new file mode 100644 index 0000000000..f704dd643b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html @@ -0,0 +1,191 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Unconsumed Vertex Attributes Out of Bounds Test</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="example" width="50" height="50"> +</canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> + void main() { } +</script> + +<script id="vshader_attrib" type="x-shader/x-vertex"> + attribute vec4 vPosition; + void main() { + gl_Position = vPosition; + } +</script> + +<script id="fshader" type="x-shader/x-fragment"> + void main() { + gl_FragColor = vec4(1); + } +</script> + +<script> +"use strict"; +description("Test that unconsumed vertex attributes are not read out of bounds"); +// Tests for http://crbug.com/756293 (driver crash on macOS) +// and a class of similar bugs that could exist on other systems. + +var wtu = WebGLTestUtils; +var contextVersion = wtu.getDefault3DContextVersion(); +var gl = wtu.create3DContext("example"); +var g_program; +var g_attribLocation; + +var numAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); +var allocatedBuffer; +var indexBuffer; + +function setupBuffers(numVerts) { + var vertices = new Float32Array(numVerts * 3); + allocatedBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, allocatedBuffer); + gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); + + var indices = new Uint16Array(numVerts); + for (var ii = 0; ii < numVerts; ++ii) { + indices[ii] = ii; + } + + indexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); +} + +var progNoAttribs = wtu.setupProgram(gl, ['vshader', 'fshader'], [], []); +var progAttrib1 = wtu.setupProgram(gl, ['vshader_attrib', 'fshader'], ['vPosition'], [1]); +var progAttrib2 = wtu.setupProgram(gl, ['vshader_attrib', 'fshader'], ['vPosition'], [2]); +setupBuffers(60000); + +var unallocatedBuffer = gl.createBuffer(); +var tests = []; + +debug(""); +debug("<u>Tests with one unconsumed attribute<u>"); + +tests.push({ + name: "drawArrays", + errors: gl.NO_ERROR, + draw: function() { gl.drawArrays(gl.TRIANGLES, 0, 3); } +}); +tests.push({ + name: "drawElements", + errors: gl.NO_ERROR, + draw: function() { gl.drawElements(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0); } +}); + +if (contextVersion >= 2) { + tests.push({ + name: "drawArraysInstanced", + errors: gl.NO_ERROR, + draw: function() { gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, 1); } + }); + tests.push({ + name: "drawElementsInstanced", + errors: gl.NO_ERROR, + draw: function() { gl.drawElementsInstanced(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0, 1); } + }); + tests.push({ + name: "drawRangeElements", + errors: gl.NO_ERROR, + draw: function() { gl.drawRangeElements(gl.TRIANGLES, 0, 60000, 60000, gl.UNSIGNED_SHORT, 0, 1); } + }); +} + +// Run tests + +// Bound forever +gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + +for (var attrib = 0; attrib < numAttribs; ++attrib) { + debug("Attrib " + attrib + " unconsumed"); + for (var i = 0; i < tests.length; ++i) { + var test = tests[i]; + gl.useProgram(progNoAttribs); + + gl.enableVertexAttribArray(attrib); + gl.bindBuffer(gl.ARRAY_BUFFER, unallocatedBuffer); + gl.vertexAttribPointer(attrib, 3, gl.FLOAT, false, 0, 0); + + test.draw(); + + gl.disableVertexAttribArray(attrib); + wtu.glErrorShouldBe(gl, test.errors, test.name); + } +} + +debug(""); +debug("<u>Tests with one consumed attribute and one unconsumed attribute<u>"); + +var ext = gl.getExtension("ANGLE_instanced_arrays"); +if (!ext) { + debug("ANGLE_instanced_arrays not available - skipped"); +} else { + tests.push({ + name: "drawArraysInstancedANGLE", + errors: gl.NO_ERROR, + draw: function() { + ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 3, 1); + } + }); + tests.push({ + name: "drawElementsInstancedANGLE", + errors: gl.NO_ERROR, + draw: function() { + ext.drawElementsInstancedANGLE(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0, 1); + } + }); +} + +// Note these don't trigger the macOS driver crash (http://crbug.com/756293) +// but they still add potentially useful coverage. +for (var attrib = 0; attrib < numAttribs; ++attrib) { + var consumedAttrib = attrib == 1 ? 2 : 1; + var prog = consumedAttrib == 1 ? progAttrib1 : progAttrib2; + debug("Attrib " + attrib + + " unconsumed (attrib " + consumedAttrib + " consumed)"); + + for (var i = 0; i < tests.length; ++i) { + var test = tests[i]; + gl.useProgram(prog); + + gl.enableVertexAttribArray(attrib); + gl.bindBuffer(gl.ARRAY_BUFFER, unallocatedBuffer); + gl.vertexAttribPointer(attrib, 3, gl.FLOAT, false, 0, 0); + + // Needed because ANGLE_instanced_arrays requires at least one consumed + // attribute to have divisor=0 (which is the default, so we don't need to + // call vertexAttribDivisorANGLE here). + gl.enableVertexAttribArray(consumedAttrib); + gl.bindBuffer(gl.ARRAY_BUFFER, allocatedBuffer); + gl.vertexAttribPointer(consumedAttrib, 3, gl.FLOAT, false, 0, 0); + + test.draw(); + + gl.disableVertexAttribArray(attrib); + gl.disableVertexAttribArray(consumedAttrib); + wtu.glErrorShouldBe(gl, test.errors, test.name); + } +} + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-zero-issues.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-zero-issues.html new file mode 100644 index 0000000000..9de9439911 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib-zero-issues.html @@ -0,0 +1,131 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Enable Vertex Attrib Zero Test</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="example" width="50" height="50"> +</canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> + attribute vec4 vPosition; + void main() + { + gl_Position = vPosition; + } +</script> + +<script id="fshader" type="x-shader/x-fragment"> + void main() + { + gl_FragColor = vec4(0.0,1.0,0.0,1.0); + } +</script> + +<script> +"use strict"; +description("Test some of the issues of the difference between attrib 0 on OpenGL vs WebGL"); +debug(""); +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("example"); +var g_program; +var g_attribLocation; +function setup(attribIndex) { + var program = wtu.setupProgram( + gl, ['vshader', 'fshader'], ['vPosition'], [attribIndex]); + g_program = program; + g_attribLocation = attribIndex; + shouldBe("g_attribLocation", "gl.getAttribLocation(g_program, 'vPosition')"); + return program; +} + +function setupVerts(numVerts) { + var verts = [ + 1.0, 1.0, 0.0, + -1.0, 1.0, 0.0, + -1.0, -1.0, 0.0, + 1.0, 1.0, 0.0, + -1.0, -1.0, 0.0, + 1.0, -1.0, 0.0 + ]; + var positions = new Float32Array(numVerts * 3); + var indices = new Uint16Array(numVerts); + for (var ii = 0; ii < numVerts; ++ii) { + var ndx = ii % 6; + var dst = ii * 3; + var src = ndx * 3; + for (var jj = 0; jj < 3; ++jj) { + positions[dst + jj] = verts[src + jj]; + } + indices[ii] = ii; + } + var vertexObject = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); + var indexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); +} + +var p0 = setup(0); +var p3 = setup(3); +setupVerts(60000); + +for (var ii = 0; ii < 5; ++ii) { + // test drawing with attrib 0 + gl.useProgram(p0); + gl.enableVertexAttribArray(0); + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.drawElements(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0); + wtu.glErrorShouldBe( + gl, gl.NO_ERROR, + "drawing using attrib 0 with 6 verts"); + wtu.checkCanvas(gl, [0, 255, 0, 255], "canvas should be green"); + gl.disableVertexAttribArray(0); + + // test drawing without attrib 0 + gl.useProgram(p3); + gl.enableVertexAttribArray(3); + gl.vertexAttribPointer(3, 3, gl.FLOAT, false, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.drawArrays(gl.TRIANGLES, 0, 60000); + wtu.glErrorShouldBe( + gl, gl.NO_ERROR, + "drawing using attrib 3 with 60000 verts"); + wtu.checkCanvas(gl, [0, 255, 0, 255], "canvas should be green"); + gl.disableVertexAttribArray(3); + + // This second test of drawing without attrib0 uncovered a bug in chrome + // where after the draw without attrib0 the attrib 0 emulation code disabled + // attrib 0 and it was never re-enabled so this next draw failed. + gl.useProgram(p3); + gl.enableVertexAttribArray(3); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.drawElements(gl.TRIANGLES, 60000, gl.UNSIGNED_SHORT, 0); + wtu.glErrorShouldBe( + gl, gl.NO_ERROR, + "drawing using attrib 3 with 60000 verts"); + wtu.checkCanvas(gl, [0, 255, 0, 255], "canvas should be green"); + gl.disableVertexAttribArray(3); +} + + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> + diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib.html new file mode 100644 index 0000000000..aa69c5e7bc --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertex-attrib.html @@ -0,0 +1,28 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL vertexAttrib Conformance Tests</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="2" height="2"> </canvas> + +<script> +var contextVersion = 1; +</script> +<script src="../../js/tests/gl-vertex-attrib.js"></script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer-offsets.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer-offsets.html new file mode 100644 index 0000000000..3cb8bd84a6 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer-offsets.html @@ -0,0 +1,190 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> + <head> +<meta charset="utf-8"> + <title>vertexattribpointer offsets test</title> + <link rel="stylesheet" href="../../resources/js-test-style.css"/> + <script src="../../js/js-test-pre.js"></script> + <script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="example" width="50" height="50"> +There is supposed to be an example drawing here, but it's not important. +</canvas> +<div id="description"></div> +<div id="console"></div> + <script id="vshader" type="x-shader/x-vertex"> + attribute vec4 vPosition; + void main() + { + gl_Position = vPosition; + } + </script> + + <script id="fshader" type="x-shader/x-fragment"> + precision mediump float; + uniform vec4 color; + void main() + { + gl_FragColor = color; + } + </script> + + <script> + "use strict"; + function init() + { + description("test vertexattribpointer offsets work"); + + var wtu = WebGLTestUtils; + var gl = wtu.create3DContext("example"); + var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]); + + var tests = [ + { data: new Float32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]), + type: gl.FLOAT, + componentSize: 4, + normalize: false, + }, + { data: new Uint16Array([ 0, 32767, 0, 32767, 0, 0, 0, 0, 0]), + type: gl.SHORT, + componentSize: 2, + normalize: true, + }, + { data: new Uint16Array([ 0, 65535, 0, 65535, 0, 0, 0, 0, 0 ]), + type: gl.UNSIGNED_SHORT, + componentSize: 2, + normalize: true, + }, + { data: new Uint16Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]), + type: gl.UNSIGNED_SHORT, + componentSize: 2, + normalize: false, + }, + { data: new Uint16Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]), + type: gl.SHORT, + componentSize: 2, + normalize: false, + }, + { data: new Uint8Array([ 0, 127, 0, 127, 0, 0, 0, 0, 0 ]), + type: gl.BYTE, + componentSize: 1, + normalize: true, + }, + { data: new Uint8Array([ 0, 255, 0, 255, 0, 0, 0, 0, 0 ]), + type: gl.UNSIGNED_BYTE, + componentSize: 1, + normalize: true, + }, + { data: new Uint8Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]), + type: gl.BYTE, + componentSize: 1, + normalize: false, + }, + { data: new Uint8Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]), + type: gl.UNSIGNED_BYTE, + componentSize: 1, + normalize: false, + } + ]; + + if (wtu.getDefault3DContextVersion() >= 2) { + tests.push(...[ + { data: new Int32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0]), + type: gl.INT, + componentSize: 4, + normalize: false, + }, + { data: new Int32Array([ 0, 2147483647, 0, 2147483647, 0, 0, 0, 0, 0]), + type: gl.INT, + componentSize: 4, + normalize: true, + }, + { data: new Uint32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0]), + type: gl.UNSIGNED_INT, + componentSize: 4, + normalize: false, + }, + { data: new Uint32Array([ 0, 4294967295, 0, 4294967295, 0, 0, 0, 0, 0]), + type: gl.UNSIGNED_INT, + componentSize: 4, + normalize: true, + }, + { data: new Uint16Array([ 0, 0b11110000000000, 0, 0b11110000000000, 0, 0, 0, 0, 0]), + type: gl.HALF_FLOAT, + componentSize: 2, + normalize: false, + }, + { data: new Uint16Array([ 0, 0b11110000000000, 0, 0b11110000000000, 0, 0, 0, 0, 0]), + type: gl.HALF_FLOAT, + componentSize: 2, + normalize: false, + } + ]); + } + + var vertexObject = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW); + gl.enableVertexAttribArray(0); + + var colorLoc = gl.getUniformLocation(program, "color"); + var kNumVerts = 3; + var kNumComponents = 3; + + var count = 0; + for (var tt = 0; tt < tests.length; ++tt) { + var test = tests[tt]; + for (var oo = 0; oo < 3; ++oo) { + for (var ss = 0; ss < 3; ++ss) { + var offset = (oo + 1) * test.componentSize; + var color = (count % 2) ? [1, 0, 0, 1] : [0, 1, 0, 1]; + var stride = test.componentSize * kNumComponents + test.componentSize * ss; + debug(""); + debug("check with " + wtu.glEnumToString(gl, test.type) + " at offset: " + offset + " with stride:" + stride + " normalize: " + test.normalize); + gl.uniform4fv(colorLoc, color); + var data = new Uint8Array(test.componentSize * kNumVerts * kNumComponents + stride * (kNumVerts - 1)); + var view = new Uint8Array(test.data.buffer); + var size = test.componentSize * kNumComponents; + for (var jj = 0; jj < kNumVerts; ++jj) { + var off1 = jj * size; + var off2 = jj * stride; + for (var zz = 0; zz < size; ++zz) { + data[off2 + zz] = view[off1 + zz]; + } + } + gl.bufferSubData(gl.ARRAY_BUFFER, offset, data); + gl.vertexAttribPointer(0, 3, test.type, test.normalize, stride, offset); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.drawArrays(gl.TRIANGLES, 0, 3); + + var buf = new Uint8Array(50 * 50 * 4); + gl.readPixels(0, 0, 50, 50, gl.RGBA, gl.UNSIGNED_BYTE, buf); + + var black = [0, 0, 0, 0]; + var other = [color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255]; + var otherMsg = "should be " + ((count % 2) ? "red" : "green") + wtu.checkCanvasRect(gl, 0, 0, 1, 1, black, "should be black", 0); + wtu.checkCanvasRect(gl, 0, 49, 1, 1, black, "should be black", 0); + wtu.checkCanvasRect(gl, 26, 40, 1, 1, other, otherMsg, 0); + wtu.checkCanvasRect(gl, 26, 27, 1, 1, other, otherMsg, 0); + wtu.checkCanvasRect(gl, 40, 27, 1, 1, other, otherMsg, 0); + ++count; + } + } + } + } + + init(); + var successfullyParsed = true; + </script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer.html b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer.html new file mode 100644 index 0000000000..1276cec7c9 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-vertexattribpointer.html @@ -0,0 +1,171 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL vertexAttribPointer Conformance Tests</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="2" height="2"> </canvas> +<script> +"use strict"; +description("This test checks vertexAttribPointer behaviors in WebGL."); + +debug(""); +debug("Canvas.getContext"); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("canvas"); +if (!gl) { + testFailed("context does not exist"); +} else { + testPassed("context exists"); + + debug(""); + debug("Checking gl.vertexAttribPointer."); + + if (!gl.FIXED) { + gl.FIXED = 0x140C; + } + + var vertexObject = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(0), gl.STATIC_DRAW); + + + gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 4); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "vertexAttribPointer should fail if no buffer is bound and `offset` is non-zero."); + + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "vertexAttribPointer should succeed if no buffer is bound and `offset` is zero."); + + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + + + if (wtu.getDefault3DContextVersion() < 2) { + gl.vertexAttribPointer(0, 1, gl.INT, 0, 0, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, + "vertexAttribPointer should not support INT"); + gl.vertexAttribPointer(0, 1, gl.UNSIGNED_INT, 0, 0, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, + "vertexAttribPointer should not support UNSIGNED_INT"); + } + gl.vertexAttribPointer(0, 1, gl.FIXED, 0, 0, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, + "vertexAttribPointer should not support FIXED"); + + var checkVertexAttribPointer = function( + gl, err, reason, size, type, normalize, stride, offset) { + gl.vertexAttribPointer(0, size, type, normalize, stride, offset); + var succeeded = (err == gl.NO_ERROR); + wtu.glErrorShouldBe(gl, err, + "gl.vertexAttribPointer(0, " + size + + ", gl." + wtu.glEnumToString(gl, type) + + ", " + normalize + + ", " + stride + + ", " + offset + + ") should " + (succeeded ? "succeed " : "fail ") + reason); + if (succeeded) { + shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_SIZE)', size.toString()); + shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_TYPE)', 'gl.' + wtu.glEnumToString(gl, type)); + shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED)', normalize.toString()); + shouldBe('gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_STRIDE)', stride.toString()); + shouldBe('gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER)', offset.toString()); + } + } + + var types = [ + { type:gl.BYTE, bytesPerComponent: 1 }, + { type:gl.UNSIGNED_BYTE, bytesPerComponent: 1 }, + { type:gl.SHORT, bytesPerComponent: 2 }, + { type:gl.UNSIGNED_SHORT, bytesPerComponent: 2 }, + { type:gl.FLOAT, bytesPerComponent: 4 }, + ]; + + if (wtu.getDefault3DContextVersion() >= 2) { + types.push(...[ + { type:gl.INT, bytesPerComponent: 4 }, + { type:gl.UNSIGNED_INT, bytesPerComponent: 4 }, + { type:gl.HALF_FLOAT, bytesPerComponent: 2 }, + { type:gl.INT_2_10_10_10_REV, bytesPerComponent: 4, minSize: 4 }, + { type:gl.UNSIGNED_INT_2_10_10_10_REV, bytesPerComponent: 4, minSize: 4 }, + ]); + } + + for (var ii = 0; ii < types.length; ++ii) { + var info = types[ii]; + debug(""); + for (var size = 1; size <= 4; ++size) { + debug(""); + debug("checking: " + wtu.glEnumToString(gl, info.type) + " with size " + size); + var bytesPerElement = size * info.bytesPerComponent; + var offsetSet = [ + 0, + 1, + info.bytesPerComponent - 1, + info.bytesPerComponent, + info.bytesPerComponent + 1, + info.bytesPerComponent * 2]; + for (var jj = 0; jj < offsetSet.length; ++jj) { + var offset = offsetSet[jj]; + for (var kk = 0; kk < offsetSet.length; ++kk) { + var stride = offsetSet[kk]; + var err = gl.NO_ERROR; + var reason = "" + if (offset % info.bytesPerComponent != 0) { + reason = "because offset is bad"; + err = gl.INVALID_OPERATION; + } + if (stride % info.bytesPerComponent != 0) { + reason = "because stride is bad"; + err = gl.INVALID_OPERATION; + } + if (size < info.minSize) { + reason = "because size < minSize"; + err = gl.INVALID_OPERATION; + } + checkVertexAttribPointer( + gl, err, reason, size, info.type, false, stride, offset); + } + var stride = Math.floor(255 / info.bytesPerComponent) * info.bytesPerComponent; + + if (offset == 0) { + checkVertexAttribPointer( + gl, size < info.minSize ? gl.INVALID_OPERATION : gl.NO_ERROR, "at stride limit", + size, info.type, false, stride, offset); + checkVertexAttribPointer( + gl, size < info.minSize ? [gl.INVALID_OPERATION, gl.INVALID_VALUE] : gl.INVALID_VALUE, "over stride limit", + size, info.type, false, + stride + info.bytesPerComponent, offset); + } + } + } + } +} + +debug(""); +var successfullyParsed = true; + +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> |