--- 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
@@ -24,16 +24,17 @@
-->
<!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;
@@ -45,46 +46,16 @@ void main() {
</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);
-var typeInfo = [
- { type: 'float', asVec4: 'vec4(0.0, $(var), 0.0, 1.0)' },
- { type: 'vec2', asVec4: 'vec4($(var), 0.0, 1.0)' },
- { type: 'vec3', asVec4: 'vec4($(var), 1.0)' },
- { type: 'vec4', asVec4: '$(var)' },
-];
-var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
-// Test all type combinations of a_1 and a_2.
-typeInfo.forEach(function(typeInfo1) {
- typeInfo.forEach(function(typeInfo2) {
- debug('attribute_1: ' + typeInfo1.type + ' attribute_2: ' + typeInfo2.type);
- var replaceParams = {
- type_1: typeInfo1.type,
- type_2: typeInfo2.type,
- gl_Position_1: wtu.replaceParams(typeInfo1.asVec4, {var: 'a_1'}),
- gl_Position_2: wtu.replaceParams(typeInfo2.asVec4, {var: 'a_2'})
- };
- var strVertexShader = wtu.replaceParams(wtu.getScript('vertexShader'), replaceParams);
- var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
- assertMsg(glVertexShader != null, "Vertex shader compiled successfully.");
- // Bind both a_1 and a_2 to the same position and verify the link fails.
- // Do so for all valid positions available.
- for (var l = 0; l < maxAttributes; l++) {
- var glProgram = gl.createProgram();
- gl.bindAttribLocation(glProgram, l, 'a_1');
- gl.bindAttribLocation(glProgram, l, 'a_2');
- gl.attachShader(glProgram, glVertexShader);
- gl.attachShader(glProgram, glFragmentShader);
- gl.linkProgram(glProgram);
- assertMsg(!gl.getProgramParameter(glProgram, gl.LINK_STATUS), "Link should fail when both types are aliased to location " + l);
- }
- });
-});
+
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShader'));
+
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/00_test_list.txt
@@ -1,11 +1,12 @@
buffer-bind-test.html
buffer-data-and-buffer-sub-data.html
--min-version 1.0.3 buffer-data-array-buffer-delete.html
+--min-version 1.0.4 buffer-data-dynamic-delay.html
--min-version 1.0.4 buffer-uninitialized.html
--min-version 1.0.2 element-array-buffer-delete-recreate.html
index-validation-copies-indices.html
index-validation-crash-with-buffer-sub-data.html
--min-version 1.0.2 index-validation-large-buffer.html
index-validation-verifies-too-many-indices.html
index-validation-with-resized-buffer.html
index-validation.html
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/buffers/buffer-data-dynamic-delay.html
@@ -0,0 +1,133 @@
+<!--
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>bufferData with DYNAMIC_DRAW and delay between updating data</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="canvas" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vshader" type="x-shader/x-vertex">
+ attribute vec2 a_position;
+ attribute vec2 a_color;
+ varying vec2 v_color;
+ void main()
+ {
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ v_color = a_color;
+ }
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+ precision mediump float;
+ varying vec2 v_color;
+ void main()
+ {
+ gl_FragColor = vec4(v_color, 0.0, 1.0);
+ }
+</script>
+
+<script>
+"use strict";
+description("Verifies that bufferData with DYNAMIC_DRAW updates the vertex attribute when there is a significant delay between updating the buffer.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
+
+// Initialize position vertex attribute to draw a square covering the entire canvas.
+var positionBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1.0, 1.0,
+ 1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0
+ ]), gl.DYNAMIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+// Initialize color vertex attribute to red.
+var colorBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 0.0,
+ ]), gl.DYNAMIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after setup");
+
+// Fill the canvas with red
+gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after first drawArrays");
+
+wtu.checkCanvasRect(gl, 0, 0, 50, 50, [255, 0, 0, 255], "Canvas should be red after the first drawArrays");
+
+// With the buffer set to DYNAMIC_DRAW, Angle internally changes the storage type of the vertex attribute from DYNAMIC to DIRECT
+// if the buffer has not been updated after ~4-5 draw calls. When the buffer is eventually updated, the vertex attribute
+// is updated back to DYNAMIC, but there was a bug in Angle where the data is not marked as dirty. The result is that the
+// vertex data is not updated with the new buffer data. This test verifies that the vertex data is updated.
+var iteration = 0;
+function draw() {
+ // Draw 10 times to ensure that the vertex attribute storage type is changed.
+ if (iteration < 10) {
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 2);
+ requestAnimationFrame(draw);
+ }
+ else {
+ // Update the buffer bound to the color vertex attribute to green and draw.
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 0.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 1.0,
+ ]), gl.DYNAMIC_DRAW);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No error after last drawArrays");
+
+ wtu.checkCanvasRect(gl, 0, 0, 50, 50, [0, 255, 0, 255], "Canvas should be green after 10 frames");
+
+ finishTest();
+ }
+
+ iteration++;
+}
+
+requestAnimationFrame(draw);
+
+</script>
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/context/context-lost-restored.html
@@ -152,16 +152,18 @@ function testLosingAndRestoringContext()
debug("");
debug("Test losing and restoring a context.");
canvas.addEventListener("webglcontextlost", function(e) {
testLostContext(e);
// restore the context after this event has exited.
setTimeout(function() {
shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()");
+ // Calling restoreContext() twice should not cause error or crash
+ shouldGenerateGLError(gl, gl.NO_ERROR, "WEBGL_lose_context.restoreContext()");
// The context should still be lost. It will not get restored until the
// webglrestorecontext event is fired.
shouldBeTrue("gl.isContextLost()");
shouldBe("gl.getError()", "gl.NO_ERROR");
// gl methods should still be no-ops
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP)");
}, 0);
});
--- a/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/webgl-specific-stencil-settings.html
@@ -106,17 +106,17 @@ gl.framebufferRenderbuffer(gl.FRAMEBUFFE
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "initial framebuffer setup")
function testStencilSettings(haveDepthBuffer, haveStencilBuffer, enableStencilTest, errIfMismatch) {
debug("");
debug("With depthbuffer=" + haveDepthBuffer +
", stencilbuffer=" + haveStencilBuffer +
", stencilTest=" + enableStencilTest +
- ", expecting error=" + wtu.glEnumToString(errIfMismatch) +
+ ", expecting error=" + wtu.glEnumToString(gl, errIfMismatch) +
" for mismatching mask or func settings.");
let rbo = null;
let attachment;
if (haveDepthBuffer || haveStencilBuffer) {
rbo = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/00_test_list.txt
@@ -1,5 +1,6 @@
+--min-version 2.0.1 gl-bindAttribLocation-aliasing-inactive.html
gl-vertex-attrib.html
gl-vertex-attrib-i-render.html
--min-version 2.0.1 gl-vertex-attrib-normalized-int.html
gl-vertexattribipointer.html
gl-vertexattribipointer-offsets.html
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html
@@ -0,0 +1,74 @@
+<!--
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+-->
+<!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 - inactive attributes</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="vertexShaderStaticallyUsedButInactive" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+in $(type_1) a_1;
+in $(type_2) a_2;
+void main() {
+ gl_Position = true ? $(gl_Position_1) : $(gl_Position_2);
+}
+</script>
+<script id="vertexShaderUnused" type="text/something-not-javascript">#version 300 es
+precision mediump float;
+in $(type_1) a_1;
+in $(type_2) a_2;
+void main() {
+ gl_Position = vec4(0.0);
+}
+</script>
+<script>
+"use strict";
+description("This test verifies combinations of valid inactive attributes cannot be bound to the same location with bindAttribLocation. GLSL ES 3.00.6 section 12.46.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false}, 2);
+var glFragmentShader = wtu.loadShader(gl, wtu.simpleColorFragmentShaderESSL300, gl.FRAGMENT_SHADER);
+
+debug("Testing with shader that has statically used but inactive attributes.");
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShaderStaticallyUsedButInactive'));
+
+debug("");
+debug("Testing with shader that has entirely unused attributes.");
+runBindAttribLocationAliasingTest(wtu, gl, glFragmentShader, wtu.getScript('vertexShaderUnused'));
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/00_test_list.txt
@@ -29,16 +29,17 @@ shader-linking.html
shader-with-1024-character-define.html
shader-with-1024-character-identifier.frag.html
shader-with-1025-character-define.html
shader-with-1025-character-identifier.frag.html
shader-with-invalid-characters.html
shader-with-mis-matching-uniform-block.html
short-circuiting-in-loop-condition.html
--min-version 2.0.1 switch-case.html
+--min-version 2.0.1 texture-offset-non-constant-offset.html
texture-offset-out-of-range.html
--min-version 2.0.1 texture-offset-uniform-texture-coordinate.html
--min-version 2.0.1 tricky-loop-conditions.html
--min-version 2.0.1 unary-minus-operator-in-dynamic-loop.html
uniform-block-layouts.html
uniform-block-layout-match.html
uniform-location-length-limits.html
--min-version 2.0.1 uniform-struct-with-non-square-matrix.html
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/switch-case.html
@@ -197,16 +197,39 @@ void main()
switch(u_zero)
{
case 0:
;
}
my_FragColor = vec4(0, 1, 0, 1);
}
</script>
+<script id="fshaderCaseInsideBlock" type="x-shader/x-fragment">#version 300 es
+
+precision highp float;
+
+out vec4 my_FragColor;
+
+uniform int u_zero;
+
+void main()
+{
+ // Case statements must not be nested in blocks.
+ // GLSL ES 3.00 spec is a bit vague on this but GLSL ES 3.10 section 6.2 is clearer.
+ switch(u_zero)
+ {
+ case 1:
+ {
+ case 0:
+ my_FragColor = vec4(1, 0, 0, 1);
+ }
+ }
+ my_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
<script type="application/javascript">
"use strict";
description();
// Covers bugs:
// http://anglebug.com/2177
// http://anglebug.com/2178
// http://anglebug.com/2179
@@ -257,14 +280,19 @@ GLSLConformanceTester.runTests([
linkSuccess: true,
passMsg: 'Constant statement should count as a statement for the purposes of switch statement validation.'
},
{
fShaderId: 'fshaderLastCaseHasEmptyStatement',
fShaderSuccess: true,
linkSuccess: true,
passMsg: 'Empty statement should count as a statement for the purposes of switch statement validation.'
+},
+{
+ fShaderId: 'fshaderCaseInsideBlock',
+ fShaderSuccess: false,
+ passMsg: 'Case statements must not be nested inside blocks.'
}
], 2);
</script>
</body>
</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/glsl3/texture-offset-non-constant-offset.html
@@ -0,0 +1,191 @@
+<!--
+
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>GLSL texture offset with non-constant offset 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/glsl-conformance-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script id="fshaderTextureOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureOffset(u_sampler, u_texCoord, offset);
+}
+</script>
+<script id="fshaderTextureProjOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureProjOffset(u_sampler, u_texCoord, offset);
+}
+</script>
+<script id="fshaderTextureLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform float u_lod;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureLodOffset(u_sampler, u_texCoord, u_lod, offset);
+}
+</script>
+<script id="fshaderTextureProjLodOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform float u_lod;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureProjLodOffset(u_sampler, u_texCoord, u_lod, offset);
+}
+</script>
+<script id="fshaderTextureGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, offset);
+}
+</script>
+<script id="fshaderTextureProjGradOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec4 u_texCoord;
+uniform vec2 u_dPdx;
+uniform vec2 u_dPdy;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = textureProjGradOffset(u_sampler, u_texCoord, u_dPdx, u_dPdy, offset);
+}
+</script>
+<script id="fshaderTexelFetchOffset" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+
+out vec4 my_FragColor;
+uniform sampler2D u_sampler;
+uniform vec2 u_texCoord;
+uniform vec2 u_lod;
+
+void main() {
+ ivec2 offset = ivec2(0);
+ my_FragColor = texelFetchOffset(u_sampler, ivec2(u_texCoord), int(u_lod), offset);
+}
+</script>
+<script type="application/javascript">
+"use strict";
+description("A non-constant offset is not valid in texture offset functions.");
+
+var wtu = WebGLTestUtils;
+
+var shaderTextureOffsetSrc = wtu.getScript('fshaderTextureOffset');
+var shaderTextureLodOffsetSrc = wtu.getScript('fshaderTextureLodOffset');
+var shaderTextureGradOffsetSrc = wtu.getScript('fshaderTextureGradOffset');
+var shaderTextureProjOffsetSrc = wtu.getScript('fshaderTextureProjOffset');
+var shaderTextureProjLodOffsetSrc = wtu.getScript('fshaderTextureProjLodOffset');
+var shaderTextureProjGradOffsetSrc = wtu.getScript('fshaderTextureProjGradOffset');
+var shaderTexelFetchOffsetSrc = wtu.getScript('fshaderTexelFetchOffset');
+
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+if (!gl) {
+ testFailed("Unable to initialize WebGL 2.0 context.");
+} else {
+ GLSLConformanceTester.runTests([
+ {
+ fShaderSource: shaderTextureOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureLodOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureLodOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureGradOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureGradOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureProjOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureProjOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureProjLodOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureProjLodOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTextureProjGradOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'textureProjGradOffset with non-constant offset is invalid'
+ },
+ {
+ fShaderSource: shaderTexelFetchOffsetSrc,
+ fShaderSuccess: false,
+ passMsg: 'texelFetchOffset with non-constant offset is invalid'
+ }
+ ], 2);
+}
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/clearbuffer-and-draw.html
@@ -0,0 +1,181 @@
+<!--
+
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test clearBuffer with drawing</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 onload="runTest()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<script>
+"use strict";
+description("This tests the operation of clearBuffer followed by a draw call.");
+
+debug("Verifies that these combined with preserveDrawingBuffer's implicit clears work properly together.");
+debug("Regression test for <a href='http://crbug.com/828262'>Chromium bug 828262</a>.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl;
+var testIndex = 0;
+var iterations = 0;
+var maxIterations = 10;
+var prog;
+var tests;
+var blackUint8 = [0, 0, 0, 255];
+var redFloat = [1.0, 0.0, 0.0, 0.0];
+var redUint8 = [255, 0, 0, 255];
+var greenFloat = [0.0, 1.0, 0.0, 0.0];
+var greenUint8 = [0, 255, 0, 255];
+
+function verifyOnePixel(kind, x, y, readFormat, readType, arrayType, expectedColor) {
+ var buffer = new arrayType(4);
+ gl.readPixels(Math.floor(x), Math.floor(y), 1, 1, readFormat, readType, buffer);
+ if (buffer[0] == expectedColor[0] &&
+ buffer[1] == expectedColor[1] &&
+ buffer[2] == expectedColor[2] &&
+ buffer[3] == expectedColor[3]) {
+ testPassed(kind + " succeeded");
+ } else {
+ testFailed(kind + " failed. Expected: " + expectedColor + ", got: " + buffer);
+ }
+}
+
+function testClearBufferAndDraw(test) {
+ test['clear']();
+ wtu.setFloatDrawColor(gl, greenFloat);
+ wtu.drawUnitQuad(gl);
+ // Back buffer has no alpha channel.
+ let readFormat = gl.RGBA;
+ let readType = gl.UNSIGNED_BYTE;
+ verifyOnePixel("Clearing", 0, 0, readFormat, readType, Uint8Array, test['bgColor']);
+ verifyOnePixel("Drawing", canvas.width / 2, canvas.height / 2,
+ readFormat, readType, Uint8Array, test['drawColor']);
+}
+
+function runNextTest() {
+ if (testIndex >= tests.length) {
+ finishTest();
+ return;
+ }
+
+
+ let test = tests[testIndex];
+ if (iterations == 0) {
+ debug('');
+ debug('Testing: ' + test['desc'])
+ }
+ testClearBufferAndDraw(test);
+
+ if (++iterations == maxIterations) {
+ iterations = 0;
+ ++testIndex;
+ }
+
+ wtu.waitForComposite(runNextTest);
+}
+
+function runTest() {
+ gl = wtu.create3DContext(canvas, { alpha:false }, 2);
+
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ } else {
+ testPassed("context exists");
+ }
+
+ prog = wtu.setupColorQuad(gl, 0, { scale: 0.5 });
+
+ tests = [
+ {
+ desc: 'Implicit clear',
+ clear: function() {},
+ bgColor: blackUint8,
+ // The implicit clear clears depth to 1.0, and since the quad is
+ // drawn at a depth of 0.0, it's always discarded.
+ drawColor: blackUint8,
+ },
+ {
+ desc: 'clearBufferfi only',
+ clear: function() {
+ gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 0.0, 0);
+ },
+ bgColor: blackUint8,
+ drawColor: greenUint8,
+ },
+ {
+ desc: 'clearBufferfv and clear',
+ clear: function() {
+ gl.clearBufferfv(gl.COLOR, 0, redFloat),
+ gl.clearDepth(0.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+ },
+ bgColor: redUint8,
+ drawColor: greenUint8,
+ },
+ {
+ desc: 'clearBuffer{fv} and {fi}',
+ clear: function() {
+ gl.clearBufferfv(gl.COLOR, 0, redFloat),
+ gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 0.0, 0);
+ },
+ bgColor: redUint8,
+ drawColor: greenUint8,
+ },
+ ];
+
+ // Clear canvas to something other than black to start.
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.enable(gl.DEPTH_TEST);
+ // Unreal Engine's depth test is reversed from the
+ // default. Including the clear of the depth buffer in this test
+ // case highlights the rendering error more clearly, since neither
+ // the background nor any rendered object show up.
+ gl.depthFunc(gl.GEQUAL);
+
+ // Must run in a requestAnimationFrame loop to provoke implicit
+ // clears of the canvas.
+ wtu.waitForComposite(runNextTest);
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+
+</body>
+</html>
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/sync/sync-webgl-specific.html
@@ -43,16 +43,17 @@
description("This test checks WebGL2 specific sync object behaviors");
debug("");
debug("Canvas.getContext");
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("canvas", null, 2);
var sync = null;
+var pixel = new Uint8Array(4);
if (!gl) {
testFailed("context does not exist");
finishTest();
} else {
testPassed("context exists");
debug("");
@@ -77,102 +78,100 @@ if (!gl) {
gl.clientWaitSync(sync, 0, max);
shouldBe("gl.getError()", "gl.NO_ERROR");
gl.clientWaitSync(sync, 0, max + 1);
shouldBe("gl.getError()", "gl.INVALID_OPERATION");
requestAnimationFrame(runGetSyncParameterTest);
}
-var signaling_retry_ms = 1000;
+var numRetries = 20000;
+var iteration = 0;
+
+function syncWithGLServer() {
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+}
function runGetSyncParameterTest() {
debug("");
debug("Verifying sync object isn't signaled too early");
sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
// Verify as best as possible that the implementation doesn't allow a sync
// object to become signaled until returning control to the event loop, by
// spin-looping for some time.
- var startTime = Date.now();
- while (Date.now() - startTime < signaling_retry_ms) {
- gl.flush();
- gl.finish();
+ var iter = numRetries;
+ while (--iter > 0) {
+ syncWithGLServer();
if (gl.getSyncParameter(sync, gl.SYNC_STATUS) == gl.SYNC_SIGNALED) {
testFailed("Sync object was signaled too early");
finishTest();
return;
}
}
testPassed("Sync object wasn't signaled too early");
- startTimeOfFinish = Date.now();
+ iteration = numRetries;
requestAnimationFrame(finishSyncParameterTest);
}
-var startTimeOfFinish = 0;
function finishSyncParameterTest() {
- if (startTimeOfFinish == 0) {
- startTimeOfFinish = Date.now();
- }
- if (Date.now() - startTimeOfFinish > signaling_retry_ms) {
- testFailed("Sync object wasn't signaled in a reasonable timeframe (" + (Date.now() - startTimeOfFinish) + " ms)");
+ if (--iteration == 0) {
+ testFailed("Sync object wasn't signaled in a reasonable timeframe (" + numRetries + " iterations)");
finishTest();
return;
}
var res = gl.getSyncParameter(sync, gl.SYNC_STATUS);
if (res == gl.SIGNALED) {
testPassed("Sync object was signaled");
requestAnimationFrame(runClientWaitSyncTest);
return;
}
// Try again.
+ syncWithGLServer();
requestAnimationFrame(finishSyncParameterTest);
}
function runClientWaitSyncTest() {
debug("");
debug("Verifying clientWaitSync doesn't complete too early");
sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
// Verify as best as possible that the implementation doesn't allow
// clientWaitSync to return CONDITION_SATISFIED or ALREADY_SIGNALED until
// returning control to the event loop, by spin-looping for some time.
- var startTime = Date.now();
- while (Date.now() - startTime < signaling_retry_ms) {
- gl.flush();
- gl.finish();
+ var iter = numRetries;
+ while (--iter > 0) {
+ syncWithGLServer();
var res = gl.clientWaitSync(sync, 0, 0);
if (res == gl.CONDITION_SATISFIED || res == gl.ALREADY_SIGNALED) {
testFailed("clientWaitSync completed successfully too early");
finishTest();
return;
}
}
testPassed("clientWaitSync didn't complete successfully too early");
- startTimeOfFinish = 0;
+ iteration = numRetries;
requestAnimationFrame(finishClientWaitSyncTest);
}
function finishClientWaitSyncTest() {
- if (startTimeOfFinish == 0) {
- startTimeOfFinish = Date.now();
- }
- if (Date.now() - startTimeOfFinish > signaling_retry_ms) {
- testFailed("clientWaitSync didn't complete in a reasonable timeframe");
+ if (--iteration == 0) {
+ testFailed("clientWaitSync didn't complete in a reasonable timeframe (" + numRetries + " iterations)");
finishTest();
return;
}
var res = gl.clientWaitSync(sync, 0, 0);
if (res == gl.CONDITION_SATISFIED || res == gl.ALREADY_SIGNALED) {
testPassed("clientWaitSync completed successfully");
// This is the last test right now.
finishTest();
return;
}
// Try again.
+ syncWithGLServer();
requestAnimationFrame(finishClientWaitSyncTest);
}
debug("");
var successfullyParsed = true;
</script>
</body>
</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-bindattriblocation-aliasing.js
@@ -0,0 +1,61 @@
+/*
+** Copyright (c) 2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+"use strict";
+
+var runBindAttribLocationAliasingTest = function(wtu, gl, glFragmentShader, vertexShaderTemplate) {
+ var typeInfo = [
+ { type: 'float', asVec4: 'vec4(0.0, $(var), 0.0, 1.0)' },
+ { type: 'vec2', asVec4: 'vec4($(var), 0.0, 1.0)' },
+ { type: 'vec3', asVec4: 'vec4($(var), 1.0)' },
+ { type: 'vec4', asVec4: '$(var)' },
+ ];
+ var maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
+ // Test all type combinations of a_1 and a_2.
+ typeInfo.forEach(function(typeInfo1) {
+ typeInfo.forEach(function(typeInfo2) {
+ debug('attribute_1: ' + typeInfo1.type + ' attribute_2: ' + typeInfo2.type);
+ var replaceParams = {
+ type_1: typeInfo1.type,
+ type_2: typeInfo2.type,
+ gl_Position_1: wtu.replaceParams(typeInfo1.asVec4, {var: 'a_1'}),
+ gl_Position_2: wtu.replaceParams(typeInfo2.asVec4, {var: 'a_2'})
+ };
+ var strVertexShader = wtu.replaceParams(vertexShaderTemplate, replaceParams);
+ var glVertexShader = wtu.loadShader(gl, strVertexShader, gl.VERTEX_SHADER);
+ assertMsg(glVertexShader != null, "Vertex shader compiled successfully.");
+ // Bind both a_1 and a_2 to the same position and verify the link fails.
+ // Do so for all valid positions available.
+ for (var l = 0; l < maxAttributes; l++) {
+ var glProgram = gl.createProgram();
+ gl.bindAttribLocation(glProgram, l, 'a_1');
+ gl.bindAttribLocation(glProgram, l, 'a_2');
+ gl.attachShader(glProgram, glVertexShader);
+ gl.attachShader(glProgram, glFragmentShader);
+ gl.linkProgram(glProgram);
+ var linkStatus = gl.getProgramParameter(glProgram, gl.LINK_STATUS);
+ assertMsg(!linkStatus, "Link should fail when both attributes are aliased to location " + l);
+ }
+ });
+ });
+};
\ No newline at end of file
--- a/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
+++ b/dom/canvas/test/webgl-conf/checkout/js/webgl-test-utils.js
@@ -52,16 +52,20 @@ var loggingOff = function() {
/**
* Converts a WebGL enum to a string.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {number} value The enum value.
* @return {string} The enum as a string.
*/
var glEnumToString = function(gl, value) {
+ // Avoid returning "NO_ERROR" if the arguments are totally wrong.
+ if (gl.NO_ERROR === undefined || value === undefined) {
+ return undefined;
+ }
// Optimization for the most common enum:
if (value === gl.NO_ERROR) {
return "NO_ERROR";
}
for (var p in gl) {
if (gl[p] == value) {
if (p == 'drawingBufferWidth' || p == 'drawingBufferHeight') {
continue;
@@ -186,16 +190,29 @@ var simpleVertexShader = [
var simpleColorFragmentShader = [
'precision mediump float;',
'uniform vec4 u_color;',
'void main() {',
' gl_FragData[0] = u_color;',
'}'].join('\n');
/**
+ * A fragment shader for a uniform color.
+ * @type {string}
+ */
+var simpleColorFragmentShaderESSL300 = [
+ '#version 300 es',
+ 'precision mediump float;',
+ 'out vec4 out_color;',
+ 'uniform vec4 u_color;',
+ 'void main() {',
+ ' out_color = u_color;',
+ '}'].join('\n');
+
+/**
* A vertex shader for vertex colors.
* @type {string}
*/
var simpleVertexColorVertexShader = [
'attribute vec4 vPosition;',
'attribute vec4 a_color;',
'varying vec4 v_color;',
'void main() {',
@@ -436,53 +453,62 @@ var setupSimpleColorProgram = function(g
[opt_positionLocation]);
};
/**
* Creates buffers for a textured unit quad and attaches them to vertex attribs.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {number} opt_positionLocation The attrib location for position.
* @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @param {!Object} various options. See setupQuad for details.
* @return {!Array.<WebGLBuffer>} The buffer objects that were
* created.
*/
-var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation) {
- return setupUnitQuadWithTexCoords(gl, [ 0.0, 0.0 ], [ 1.0, 1.0 ],
- opt_positionLocation, opt_texcoordLocation);
+var setupUnitQuad = function(gl, opt_positionLocation, opt_texcoordLocation, options) {
+ return setupQuadWithTexCoords(gl, [ 0.0, 0.0 ], [ 1.0, 1.0 ],
+ opt_positionLocation, opt_texcoordLocation,
+ options);
};
/**
- * Creates buffers for a textured unit quad with specified lower left
+ * Creates buffers for a textured quad with specified lower left
* and upper right texture coordinates, and attaches them to vertex
* attribs.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
* @param {!Array.<number>} upperRightTexCoords The texture coordinates for the upper right corner.
* @param {number} opt_positionLocation The attrib location for position.
* @param {number} opt_texcoordLocation The attrib location for texture coords.
+ * @param {!Object} various options. See setupQuad for details.
* @return {!Array.<WebGLBuffer>} The buffer objects that were
* created.
*/
-var setupUnitQuadWithTexCoords = function(
+var setupQuadWithTexCoords = function(
gl, lowerLeftTexCoords, upperRightTexCoords,
- opt_positionLocation, opt_texcoordLocation) {
- return setupQuad(gl, {
+ opt_positionLocation, opt_texcoordLocation, options) {
+ var defaultOptions = {
positionLocation: opt_positionLocation || 0,
texcoordLocation: opt_texcoordLocation || 1,
lowerLeftTexCoords: lowerLeftTexCoords,
upperRightTexCoords: upperRightTexCoords
- });
+ };
+ if (options) {
+ for (var prop in options) {
+ defaultOptions[prop] = options[prop]
+ }
+ }
+ return setupQuad(gl, defaultOptions);
};
/**
* Makes a quad with various options.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {!Object} options
*
- * scale: scale to multiple unit quad values by. default 1.0.
+ * scale: scale to multiply unit quad values by. default 1.0.
* positionLocation: attribute location for position.
* texcoordLocation: attribute location for texcoords.
* If this does not exist no texture coords are created.
* lowerLeftTexCoords: an array of 2 values for the
* lowerLeftTexCoords.
* upperRightTexCoords: an array of 2 values for the
* upperRightTexCoords.
*/
@@ -530,36 +556,38 @@ var setupQuad = function(gl, options) {
/**
* Creates a program and buffers for rendering a textured quad.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {number} opt_positionLocation The attrib location for
* position. Default = 0.
* @param {number} opt_texcoordLocation The attrib location for
* texture coords. Default = 1.
+ * @param {!Object} various options. See setupQuad for details.
* @return {!WebGLProgram}
*/
var setupTexturedQuad = function(
- gl, opt_positionLocation, opt_texcoordLocation) {
+ gl, opt_positionLocation, opt_texcoordLocation, options) {
var program = setupSimpleTextureProgram(
gl, opt_positionLocation, opt_texcoordLocation);
- setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+ setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation, options);
return program;
};
/**
* Creates a program and buffers for rendering a color quad.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {number} opt_positionLocation The attrib location for position.
+ * @param {!Object} various options. See setupQuad for details.
* @return {!WebGLProgram}
*/
-var setupColorQuad = function(gl, opt_positionLocation) {
+var setupColorQuad = function(gl, opt_positionLocation, options) {
opt_positionLocation = opt_positionLocation || 0;
var program = setupSimpleColorProgram(gl, opt_positionLocation);
- setupUnitQuad(gl, opt_positionLocation);
+ setupUnitQuad(gl, opt_positionLocation, 0, options);
return program;
};
/**
* Creates a program and buffers for rendering a textured quad with
* specified lower left and upper right texture coordinates.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {!Array.<number>} lowerLeftTexCoords The texture coordinates for the lower left corner.
@@ -568,18 +596,18 @@ var setupColorQuad = function(gl, opt_po
* @param {number} opt_texcoordLocation The attrib location for texture coords.
* @return {!WebGLProgram}
*/
var setupTexturedQuadWithTexCoords = function(
gl, lowerLeftTexCoords, upperRightTexCoords,
opt_positionLocation, opt_texcoordLocation) {
var program = setupSimpleTextureProgram(
gl, opt_positionLocation, opt_texcoordLocation);
- setupUnitQuadWithTexCoords(gl, lowerLeftTexCoords, upperRightTexCoords,
- opt_positionLocation, opt_texcoordLocation);
+ setupQuadWithTexCoords(gl, lowerLeftTexCoords, upperRightTexCoords,
+ opt_positionLocation, opt_texcoordLocation);
return program;
};
/**
* Creates a program and buffers for rendering a textured quad with
* a cube map texture.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {number} opt_positionLocation The attrib location for
@@ -587,17 +615,17 @@ var setupTexturedQuadWithTexCoords = fun
* @param {number} opt_texcoordLocation The attrib location for
* texture coords. Default = 1.
* @return {!WebGLProgram}
*/
var setupTexturedQuadWithCubeMap = function(
gl, opt_positionLocation, opt_texcoordLocation) {
var program = setupSimpleCubeMapTextureProgram(
gl, opt_positionLocation, opt_texcoordLocation);
- setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation);
+ setupUnitQuad(gl, opt_positionLocation, opt_texcoordLocation, undefined);
return program;
};
/**
* Creates a unit quad with only positions of a given resolution.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {number} gridRes The resolution of the mesh grid,
* expressed in the number of quads across and down.
@@ -948,23 +976,26 @@ var drawUByteColorQuad = function(gl, co
/**
* Draws a previously setupUnitQuad.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
*/
var drawUnitQuad = function(gl) {
gl.drawArrays(gl.TRIANGLES, 0, 6);
};
-var noopProgram = null;
+var dummyProgram = null;
var dummySetProgramAndDrawNothing = function(gl) {
- if (!noopProgram) {
- noopProgram = setupProgram(gl, ["void main() {}", "void main() {}"], [], []);
+ if (!dummyProgram) {
+ dummyProgram = setupProgram(gl, [
+ "void main() { gl_Position = vec4(0.0); }",
+ "void main() { gl_FragColor = vec4(0.0); }"
+ ], [], []);
}
- gl.useProgram(noopProgram);
- gl.drawArrays(gl.TRIANGLES, 0, 0);
+ gl.useProgram(dummyProgram);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
};
/**
* Clears then Draws a previously setupUnitQuad.
* @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
* @param {!Array.<number>} opt_color The color to fill clear with before
* drawing. A 4 element array where each element is in the range 0 to
* 255. Default [255, 255, 255, 255]
@@ -1886,21 +1917,16 @@ var loadShader = function(
var shader = gl.createShader(shaderType);
if (shader == null) {
errFn("*** Error: unable to create shader '"+shaderSource+"'");
return null;
}
// Load the shader source
gl.shaderSource(shader, shaderSource);
- var err = gl.getError();
- if (err != gl.NO_ERROR) {
- errFn("*** Error loading shader '" + shader + "':" + glEnumToString(gl, err));
- return null;
- }
// Compile the shader
gl.compileShader(shader);
if (opt_logShaders) {
var label = shaderType == gl.VERTEX_SHADER ? 'vertex shader' : 'fragment_shader';
if (opt_shaderLabel) {
label = opt_shaderLabel + ' ' + label;
@@ -3171,28 +3197,28 @@ var API = {
makeVideo: makeVideo,
error: error,
shallowCopyObject: shallowCopyObject,
setDefault3DContextVersion: setDefault3DContextVersion,
setupColorQuad: setupColorQuad,
setupProgram: setupProgram,
setupTransformFeedbackProgram: setupTransformFeedbackProgram,
setupQuad: setupQuad,
+ setupQuadWithTexCoords: setupQuadWithTexCoords,
setupIndexedQuad: setupIndexedQuad,
setupIndexedQuadWithOptions: setupIndexedQuadWithOptions,
setupSimpleColorProgram: setupSimpleColorProgram,
setupSimpleTextureProgram: setupSimpleTextureProgram,
setupSimpleCubeMapTextureProgram: setupSimpleCubeMapTextureProgram,
setupSimpleVertexColorProgram: setupSimpleVertexColorProgram,
setupNoTexCoordTextureProgram: setupNoTexCoordTextureProgram,
setupTexturedQuad: setupTexturedQuad,
setupTexturedQuadWithTexCoords: setupTexturedQuadWithTexCoords,
setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
setupUnitQuad: setupUnitQuad,
- setupUnitQuadWithTexCoords: setupUnitQuadWithTexCoords,
setFloatDrawColor: setFloatDrawColor,
setUByteDrawColor: setUByteDrawColor,
startPlayingAndWaitForVideo: startPlayingAndWaitForVideo,
startsWith: startsWith,
shouldGenerateGLError: shouldGenerateGLError,
readFile: readFile,
readFileList: readFileList,
replaceParams: replaceParams,
@@ -3216,16 +3242,17 @@ var API = {
none: false
};
Object.defineProperties(API, {
noTexCoordTextureVertexShader: { value: noTexCoordTextureVertexShader, writable: false },
simpleTextureVertexShader: { value: simpleTextureVertexShader, writable: false },
simpleColorFragmentShader: { value: simpleColorFragmentShader, writable: false },
+ simpleColorFragmentShaderESSL300: { value: simpleColorFragmentShaderESSL300, writable: false },
simpleVertexShader: { value: simpleVertexShader, writable: false },
simpleTextureFragmentShader: { value: simpleTextureFragmentShader, writable: false },
simpleCubeMapTextureFragmentShader: { value: simpleCubeMapTextureFragmentShader, writable: false },
simpleVertexColorFragmentShader: { value: simpleVertexColorFragmentShader, writable: false },
simpleVertexColorVertexShader: { value: simpleVertexColorVertexShader, writable: false }
});
return API;
--- a/dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html
+++ b/dom/canvas/test/webgl-conf/checkout/webgl-conformance-tests.html
@@ -236,17 +236,17 @@ function start() {
this.folder = folder;
this.url = url;
this.totalTests = 0;
this.totalSuccessful = 0;
this.totalTimeouts = 0;
this.totalSkipped = 0;
this.totalFailed = 0;
this.testIndex = testIndex;
- this.startTime = 0;
+ this.startTime = new Date();
this.totalTime = 0;
var that = this;
this.elementId = "page" + pageCount++;
var li = reporter.localDoc.createElement('li');
li.id = this.elementId;
var div = reporter.localDoc.createElement('div');
div.classList.add('pageHeader');
@@ -300,25 +300,27 @@ function start() {
Page.prototype.addResult = function(msg, success, skipped) {
++this.totalTests;
if (success === undefined) {
++this.totalTimeouts;
var result = "timeout";
var css = "timeout";
} else if (success) {
- if(skipped) {
- ++this.totalSkipped;
- } else {
- ++this.totalSuccessful;
- }
+ ++this.totalSuccessful;
// don't report success.
return;
} else {
++this.totalFailed;
+ if (skipped) {
+ // Skipped tests are counted as both skips and failures (because we
+ // don't want to accidentally accept a conformance submission with
+ // skipped tests).
+ ++this.totalSkipped;
+ }
var result = "failed";
var css = "fail";
}
var node = this.reporter.localDoc.createTextNode(result + ': ' + msg);
var li = this.reporter.localDoc.createElement('li');
li.appendChild(node);
li.setAttribute('class', css);
@@ -406,16 +408,28 @@ function start() {
};
Page.prototype.disableTest = function(re) {
if (this.url.match(re)) {
this.check.checked = false;
}
};
+ Page.prototype.toJSON = function() {
+ return {
+ 'subtests': this.totalTests,
+ 'successful': this.totalSuccessful,
+ 'skipped': this.totalSkipped,
+ 'failed': this.totalFailed,
+ 'timedOut': this.totalTimeouts,
+ 'totalTime': this.totalTime,
+ };
+ };
+
+
var Folder = function(reporter, folder, depth, opt_name) {
this.reporter = reporter;
this.depth = depth;
this.name = opt_name || "";
this.displayName = this.name;
if (folder && folder.displayName) {
this.displayName = folder.displayName + '/' + this.displayName;
}
@@ -723,17 +737,17 @@ function start() {
}
this.noWebGL = !ctx;
this.contextInfo = {};
this.root = new Folder(this, null, 0, "all");
this.resultElem.appendChild(this.root.elem);
this.callbacks = { };
- this.startTime = 0;
+ this.startTime = new Date();
if (ctx) {
this.contextInfo["VENDOR"] = ctx.getParameter(ctx.VENDOR);
this.contextInfo["VERSION"] = ctx.getParameter(ctx.VERSION);
this.contextInfo["RENDERER"] = ctx.getParameter(ctx.RENDERER);
this.contextInfo["RED_BITS"] = ctx.getParameter(ctx.RED_BITS);
this.contextInfo["GREEN_BITS"] = ctx.getParameter(ctx.GREEN_BITS);
this.contextInfo["BLUE_BITS"] = ctx.getParameter(ctx.BLUE_BITS);
@@ -810,103 +824,149 @@ function start() {
xhr.open('POST', "/finishIndividualTest", true);
xhr.send(null);
}
};
Reporter.prototype.displayFinalResults = function(msg, success) {
if (success) {
var totalTests = 0;
- var totalSuccessful = 0;
- var totalTimeouts = 0;
- var totalSkipped = 0;
- var totalFailed = 0;
+ var testsSucceeded = 0;
+ var testsFailed = 0;
+ var testsSkipped = 0;
+ var testsTimedOut = 0;
+
+ var subtestsHit = 0;
+ var subtestsSucceeded = 0;
+ var subtestsTimedOut = 0;
+ var subtestsSkipped = 0;
+ var subtestsFailed = 0;
+
var totalTime = Date.now() - this.startTime;
+
for (var url in this.pagesByURL) {
var page = this.pagesByURL[url];
- totalTests += page.totalTests;
- totalSuccessful += page.totalSuccessful;
- totalTimeouts += page.totalTimeouts;
- totalSkipped += page.totalSkipped;
- totalFailed += page.totalFailed;
+ totalTests += 1;
+ if (page.totalSkipped) {
+ testsSkipped += 1;
+ }
+ if (page.totalFailed) {
+ testsFailed += 1;
+ } else if (page.totalTimeouts) {
+ testsTimedOut += 1;
+ } else if (page.totalSuccessful) {
+ if (page.totalSuccessful != page.totalTests)
+ throw successes_not_equal_total;
+ testsSucceeded += 1;
+ }
+
+ subtestsHit += page.totalTests;
+ subtestsSucceeded += page.totalSuccessful;
+ subtestsTimedOut += page.totalTimeouts;
+ subtestsSkipped += page.totalSkipped;
+ subtestsFailed += page.totalFailed;
}
- var passedMsg = 'Passed ' + totalSuccessful + '/' + totalTests + ' (' + (totalSuccessful * 100.0 / totalTests).toFixed(2) + '%)';
- var timeout = '';
- if (totalTimeouts > 0) {
- timeout = ', ' + totalTimeouts + ' timed out';
+
+ function ratio_str(x, y, name) {
+ return x + '/' + y + ' ' + name + ' (' + (x / y * 100).toFixed(2) + '%)';
}
+ var testsSucceededRatio = ratio_str(testsSucceeded, totalTests, 'tests');
+ var passedMsg = 'Passed ' + testsSucceededRatio + ', ' +
+ ratio_str(subtestsSucceeded, subtestsHit, 'subtests');
var skippedMsg = '';
- if (totalSkipped > 0) {
- skippedMsg = ' Skipped ' + totalSkipped + '/' + totalTests + ' (' + (totalSkipped * 100.0 / totalTests).toFixed(2) + '%)';
+ if (testsSkipped > 0) {
+ skippedMsg = ' Skipped ' + ratio_str(testsSkipped, totalTests, 'tests');
}
var failedMsg = '';
- if (totalFailed > 0) {
- failedMsg = ' Failed ' + totalFailed + '/' + totalTests + ' (' + (totalFailed * 100.0 / totalTests).toFixed(2) + '%)';
+ if (testsFailed > 0) {
+ failedMsg = ' Failed ' + ratio_str(testsFailed, totalTests, 'tests') + ', ' +
+ ratio_str(subtestsFailed, subtestsHit, 'subtests');
}
var timeoutMsg = '';
- if (totalTimeouts > 0) {
- timeoutMsg = ' Timeout ' + totalTimeouts + '/' + totalTests + ' (' + (totalTimeouts * 100.0 / totalTests).toFixed(2) + '%)';
+ if (testsTimedOut > 0) {
+ timeoutMsg = ' Timeout ' + ratio_str(testsTimedOut, totalTests, 'tests');
}
var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg;
this.fullResultsNode.textContent = msg;
// generate a text summary
var tx = "";
tx += "WebGL Conformance Test Results\n";
tx += "Version " + OPTIONS.version + "\n";
+ tx += "Generated on: " + (new Date()).toString() + "\n";
tx += "\n";
tx += "-------------------\n\n";
tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n";
tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n";
tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n";
tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n";
tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n";
tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n";
tx += "WebGL R/G/B/A/Depth/Stencil bits (default config): " + this.contextInfo["RED_BITS"] + "/" + this.contextInfo["GREEN_BITS"] + "/" + this.contextInfo["BLUE_BITS"] + "/" + this.contextInfo["ALPHA_BITS"] + "/" + this.contextInfo["DEPTH_BITS"] + "/" + this.contextInfo["STENCIL_BITS"] + "\n";
- tx += "\n";
- tx += "-------------------\n\n";
- tx += "Test Summary (" + totalTests + " total tests):\n";
- tx += "Tests ran in " + (totalTime / 1000.0).toFixed(2) + " seconds\n";
- tx += "Tests PASSED: " + totalSuccessful + "\n";
- tx += "Tests FAILED: " + (totalTests - totalSuccessful - totalSkipped) + "\n";
- tx += "Tests TIMED OUT: " + totalTimeouts + "\n";
- tx += "Tests SKIPPED: " + totalSkipped + "\n";
- tx += "\n";
- tx += "-------------------\n\n";
- if (totalSuccessful < totalTests) {
- tx += "Failures:\n\n";
- for (var url in this.pagesByURL) {
- var page = this.pagesByURL[url];
- var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
- if (!(page.totalTests == 0 && page.totalTimeouts == 0) &&
- pageTotalFail > 0)
- {
- tx += url + ": " + pageTotalFail + " tests failed";
- if (page.totalTimeouts)
- tx += " (" + page.totalTimeouts + " timed out)";
- tx += "\n";
- }
- }
+ tx += "\n-------------------\n\n";
+
+ var result;
+ if (totalTests && testsSucceeded == totalTests) {
+ result = 'PASS';
} else {
- tx += "All tests PASSED\n\n";
+ result = 'FAIL';
+ }
+ tx += "Test Summary: " + result + " (" + totalTests + " tests):\n";
+ tx += subtestsHit + " subtests ran in " + (totalTime / 1000.0).toFixed(2) + " seconds\n";
+ function record(what, tests, subtests) {
+ tx += what + ": " + tests + " tests, " + subtests + " subtests\n";
}
- tx += "\n";
- tx += "-------------------\n\n";
- tx += "Complete Test Results (total / pass / fail / timeout / skipped):\n\n";
+ record('PASSED', testsSucceeded, subtestsSucceeded);
+ record('NOT PASSED', totalTests - testsSucceeded, subtestsHit - subtestsSucceeded);
+
+ record('FAILED', testsFailed, subtestsFailed);
+ record('TIMED OUT', testsTimedOut, subtestsTimedOut);
+ record('SKIPPED', testsSkipped, subtestsSkipped);
+
+ tx += "\n-------------------\n\n";
+
+ const failureLines = [];
+ const timeoutLines = [];
+ const resultLines = [];
+
for (var url in this.pagesByURL) {
var page = this.pagesByURL[url];
- var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
- if (!(page.totalTests == 0 && page.totalTimeouts == 0)) {
- tx += url + ": " + page.totalTests + " / " +
- page.totalSuccessful + " / " + pageTotalFail + " / " + page.totalTimeouts + " / " + page.totalSkipped + "\n";
+ resultLines.push(' "' + url + '":' + JSON.stringify(page.toJSON()));
+
+ if (page.totalFailed) {
+ failureLines.push(' "' + url + '",');
+ }
+ if (page.totalTimeouts) {
+ timeoutLines.push(' "' + url + '",');
}
}
- tx += "\n";
- tx += "-------------------\n\n";
- tx += "Generated on: " + (new Date()).toString() + "\n";
+
+ const lines = [].concat(
+ [
+ '{',
+ ' "failures": [',
+ ],
+ failureLines,
+ [
+ ' ],',
+ ' "timeouts": [',
+ ],
+ timeoutLines,
+ [
+ ' ],',
+ ' "results": {',
+ ],
+ resultLines,
+ [
+ ' },',
+ '}',
+ ]
+ );
+
+ tx += lines.join('\n');
var r = document.getElementById("testResultsAsText");
while (r.firstChild) r.removeChild(r.firstChild);
r.appendChild(document.createTextNode(tx));
document.getElementById("showTextSummary").style.visibility = "visible";
document.getElementById("dlTextSummary").style.visibility = "visible";
this.postResultsToServer(tx);
--- a/dom/canvas/test/webgl-conf/cherry_picks.txt
+++ b/dom/canvas/test/webgl-conf/cherry_picks.txt
@@ -1,10 +1,19 @@
+commit bce0801d759def1b8c75b049150049aaadc7a6ff
+Author: Jeff Gilbert <jdashg@gmail.com>
+Date: Fri Apr 6 19:52:35 2018 -0700
+
+ wtu.loadShader's gl.shaderSource should be treated as infallible.
Cherries picked
================================================================================
Merge base
-commit e899c531173da8ba956df8de6dd74fb7d9b1fa9c
-Author: Patrick To <patrto@microsoft.com>
-Date: Fri Mar 30 13:18:38 2018 -0700
+commit fefa32a950127f6e01a5cdd1536d639a949cd82b
+Author: Olli Etuaho <olli.etuaho@gmail.com>
+Date: Fri Apr 6 20:00:43 2018 +0300
- Add unpack flip y test for depth textures (#2609)
+ Add a test for having a case statement inside a block (#2630)
+
+ This was not being validated correctly by ANGLE until recently, though
+ this would not cause issues if the native drivers were working
+ correctly.
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>
+ Mochitest wrapper for WebGL Conformance Test Suite tests
+ </title>
+ <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+ <script src='/tests/SimpleTest/SimpleTest.js'></script>
+ <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+ </head>
+ <body>
+ <iframe src='../mochi-single.html?checkout/conformance2/attribs/gl-bindAttribLocation-aliasing-inactive.html?webglVersion=2'></iframe>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>
+ Mochitest wrapper for WebGL Conformance Test Suite tests
+ </title>
+ <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+ <script src='/tests/SimpleTest/SimpleTest.js'></script>
+ <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+ </head>
+ <body>
+ <iframe src='../mochi-single.html?checkout/conformance2/glsl3/texture-offset-non-constant-offset.html?webglVersion=2'></iframe>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_2_conformance__buffers__buffer-data-dynamic-delay.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>
+ Mochitest wrapper for WebGL Conformance Test Suite tests
+ </title>
+ <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+ <script src='/tests/SimpleTest/SimpleTest.js'></script>
+ <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+ </head>
+ <body>
+ <iframe src='../mochi-single.html?checkout/conformance/buffers/buffer-data-dynamic-delay.html?webglVersion=2'></iframe>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/generated/test_conformance__buffers__buffer-data-dynamic-delay.html
@@ -0,0 +1,17 @@
+<!-- GENERATED FILE, DO NOT EDIT -->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>
+ Mochitest wrapper for WebGL Conformance Test Suite tests
+ </title>
+ <link rel='stylesheet' type='text/css' href='../iframe-passthrough.css'/>
+
+ <script src='/tests/SimpleTest/SimpleTest.js'></script>
+ <link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css'/>
+ </head>
+ <body>
+ <iframe src='../mochi-single.html?checkout/conformance/buffers/buffer-data-dynamic-delay.html'></iframe>
+ </body>
+</html>