summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance/rendering
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html146
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html266
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html116
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html64
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-default-framebuffer-with-scissor-test.html68
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html26
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html111
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html71
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html127
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/default-texture-draw-bug.html69
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-arrays-out-of-bounds.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-elements-out-of-bounds.html33
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-webgl-to-canvas-2d-repeatedly.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html114
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-switch.html91
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html97
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-switch.html87
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html67
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawarrays.html82
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawelements.html97
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html78
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-test.html95
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-viewport-test.html112
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-loop-tri-fan.html229
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-rendering-quality.html27
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html123
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.html98
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html126
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html136
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html55
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html129
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html166
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html119
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/polygon-offset.html173
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/preservedrawingbuffer-leak.html44
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html183
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html92
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html63
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html77
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/texture-switch-performance.html101
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html73
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/vertex-texture-fetch.html91
46 files changed, 4593 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt
new file mode 100644
index 0000000000..9cd801f558
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/00_test_list.txt
@@ -0,0 +1,44 @@
+--min-version 1.0.4 bind-framebuffer-flush-bug.html
+--min-version 1.0.4 blending.html
+--min-version 1.0.4 canvas-alpha-bug.html
+--min-version 1.0.4 clear-default-framebuffer-with-scissor-test.html
+--min-version 1.0.4 --max-version 1.9.9 clipping-wide-points.html
+--min-version 1.0.4 color-mask-preserved-during-implicit-clears.html
+--min-version 1.0.4 color-mask-should-not-affect-antialiased-framebuffer-resolution.html
+--min-version 1.0.2 culling.html
+--min-version 1.0.4 default-texture-draw-bug.html
+draw-arrays-out-of-bounds.html
+draw-elements-out-of-bounds.html
+--min-version 1.0.4 draw-webgl-to-canvas-2d-repeatedly.html
+--min-version 1.0.4 draw-with-changing-start-vertex-bug.html
+--min-version 1.0.3 framebuffer-switch.html
+--min-version 1.0.3 framebuffer-texture-switch.html
+gl-clear.html
+--min-version 1.0.3 gl-drawarrays.html
+gl-drawelements.html
+gl-scissor-test.html
+--min-version 1.0.2 gl-scissor-fbo-test.html
+--min-version 1.0.3 gl-scissor-canvas-dimensions.html
+--min-version 1.0.3 gl-viewport-test.html
+--min-version 1.0.4 line-rendering-quality.html
+--min-version 1.0.3 many-draw-calls.html
+more-than-65536-indices.html
+multisample-corruption.html
+--min-version 1.0.3 negative-one-index.html
+out-of-bounds-array-buffers.html
+out-of-bounds-index-buffers.html
+--min-version 1.0.3 point-no-attributes.html
+point-size.html
+--min-version 1.0.4 point-specific-shader-variables.html
+--min-version 1.0.3 point-with-gl-pointcoord-in-fragment-shader.html
+--min-version 1.0.3 polygon-offset.html
+--min-version 1.0.4 preservedrawingbuffer-leak.html
+--min-version 1.0.4 rendering-sampling-feedback-loop.html
+--min-version 1.0.4 scissor-rect-repeated-rendering.html
+--min-version 1.0.2 simple.html
+triangle.html
+line-loop-tri-fan.html
+--min-version 1.0.4 framebuffer-texture-clear.html
+--min-version 1.0.4 clear-after-copyTexImage2D.html
+--min-version 1.0.4 texture-switch-performance.html
+--min-version 1.0.4 rendering-stencil-large-viewport.html
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html
new file mode 100644
index 0000000000..357af132a3
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/bind-framebuffer-flush-bug.html
@@ -0,0 +1,146 @@
+<!--
+Copyright (c) 2020 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>
+"use strict";
+const wtu = WebGLTestUtils;
+
+function runTest() {
+ let canvas = document.createElement('canvas');
+ document.body.appendChild(canvas);
+ const gl = wtu.create3DContext(canvas);
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ const size = 100;
+
+ debug('Setup');
+ canvas.width = size;
+ canvas.height = size;
+
+ const texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ const backbuffer = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, backbuffer);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+ const vertexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, 32, gl.DYNAMIC_DRAW);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, new Float32Array([
+ 1, 1,
+ 1, -1,
+ -1, 1,
+ -1, -1,
+ ]));
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 8, 0);
+ gl.enableVertexAttribArray(0);
+
+ const blitTextureProgram = gl.createProgram();
+ const blitTextureVertex = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(blitTextureVertex, `
+ precision mediump float;
+ attribute vec2 pos;
+ varying vec2 uv;
+ void main(){
+ uv = (pos + vec2(1.0)) / 2.0;
+ gl_Position=vec4(pos*2.-1.,0.,1.);
+ }
+ `);
+ gl.compileShader(blitTextureVertex);
+ gl.attachShader(blitTextureProgram, blitTextureVertex);
+ const blitTextureFragment = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(blitTextureFragment, `
+ precision mediump float;
+ uniform sampler2D texture;
+ varying vec2 uv;
+ void main(){
+ gl_FragColor=texture2D(texture, uv);
+ }
+ `);
+ gl.compileShader(blitTextureFragment);
+ gl.attachShader(blitTextureProgram, blitTextureFragment);
+ gl.linkProgram(blitTextureProgram);
+
+ const solidColorProgram = gl.createProgram();
+ const solidColorVertex = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(solidColorVertex, `
+ precision mediump float;
+ attribute vec2 pos;
+ void main(){
+ gl_Position=vec4(pos,0.,1.);
+ }
+ `);
+ gl.compileShader(solidColorVertex);
+ gl.attachShader(solidColorProgram, solidColorVertex);
+ const solidColorFragment = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(solidColorFragment, `
+ precision mediump float;
+ void main(){
+ gl_FragColor=vec4(0.,0.,1.,1.);
+ }
+ `);
+ gl.compileShader(solidColorFragment);
+ gl.attachShader(solidColorProgram, solidColorFragment);
+ gl.bindAttribLocation(solidColorProgram, 0, "pos");
+ gl.linkProgram(solidColorProgram);
+ gl.clearColor(1, 0, 0, 1);
+
+ debug('Drawing');
+ // Draw blue rectangle to backbuffer texture
+ gl.bindFramebuffer(gl.FRAMEBUFFER, backbuffer);
+ gl.useProgram(solidColorProgram);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ // Blit backbuffer texture to screen
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.useProgram(blitTextureProgram);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ // Clear backbuffer texture to red
+ gl.bindFramebuffer(gl.FRAMEBUFFER, backbuffer);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Blit backbuffer texture to screen
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.useProgram(blitTextureProgram);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ debug('Expected: canvas should be red');
+ debug('Buggy: canvas is blue');
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 0], 'should be red');
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verifies workaround for bug in Intel drivers where clear and drawArrays calls are reordered across bindFramebuffer.');
+debug('Regression test for <a href="http://crbug.com/1018028">http://crbug.com/1018028</a>');
+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/rendering/blending.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html
new file mode 100644
index 0000000000..b14705cd50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html
@@ -0,0 +1,266 @@
+<!--
+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="eVsSrc" type="text/plain">
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+
+<script id="eFsSrc" type="text/plain">
+precision mediump float;
+uniform vec4 uColor;
+
+void main()
+{
+ gl_FragColor = uColor;
+}
+</script>
+
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Blending tests');
+
+const wtu = WebGLTestUtils;
+
+function CreateContext() {
+ const gl = wtu.create3DContext();
+ gl.viewport(0, 0, 1, 1);
+
+ gl.prog = wtu.setupProgram(gl, [eVsSrc.innerHTML, eFsSrc.innerHTML]);
+ gl.prog.uColor = (() => {
+ const loc = gl.getUniformLocation(gl.prog, 'uColor');
+ return x => gl.uniform4fv(loc, x);
+ })();
+ gl.useProgram(gl.prog);
+ gl.prog.uColor([1 / 255, 2 / 255, 3 / 255, 4 / 255]);
+
+ gl.drawAndRead = type => {
+ gl.drawArrays(gl.POINTS, 0, 1);
+ let ret;
+ if (type == gl.UNSIGNED_BYTE) {
+ ret = new Uint8Array(4);
+ } else if (type == gl.FLOAT) {
+ ret = new Float32Array(4);
+ }
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, type, ret);
+ return ret;
+ };
+
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.CONSTANT_COLOR, gl.ZERO);
+
+ return gl;
+}
+
+function CreateValidFb(gl, formats) {
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ for (let i in formats) {
+ i = i|0; // Otherwise i is a string. :(
+ const f = formats[i];
+ if (!f)
+ continue;
+ if (f.length == 1) {
+ const rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, f[0], 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
+ gl.RENDERBUFFER, rb);
+ continue;
+ }
+ if (f.length == 3) {
+ let internalFormat = f[0];
+ if (internalFormat === undefined) {
+ internalFormat = f[1];
+ }
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1,1,0, f[1],f[2], null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
+ gl.TEXTURE_2D, tex, 0);
+ continue;
+ }
+ throw new Error('Invalid format length: ' + f);
+ }
+
+ const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != gl.FRAMEBUFFER_COMPLETE) {
+ gl.deleteFramebuffer(fb);
+ return null;
+ }
+ return fb;
+}
+
+let was, fb;
+
+const TESTS = [
+ () => {
+ debug('');
+ debug('Clamping of blendColor args:');
+
+ const gl = wtu.create3DContext();
+ if (!gl.texImage3D) { // WebGL 1.0
+ // WebGL 1.0 clamps without EXT_color_buffer_half_float or WEBGL_color_buffer_float.
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.getParameter(gl.BLEND_COLOR);
+ expectArray(was, [1, 1, 1, 1]);
+
+ const ext = gl.getExtension('EXT_color_buffer_half_float') ||
+ gl.getExtension('WEBGL_color_buffer_float');
+ if (!ext) return;
+ }
+
+ // WebGL 2.0 or extended WebGL 1.0 may still clamp the value on store
+ // when the underlying platform does the same.
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.getParameter(gl.BLEND_COLOR);
+ if (was[0] == 1000) {
+ expectArray(was, [1000, 1, 1, 1]);
+ } else {
+ debug("Platform does not support unclamped blend color.")
+ expectArray(was, [1, 1, 1, 1]);
+ }
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA8:');
+
+ const gl = CreateContext();
+ fb = CreateValidFb(gl, [[gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE]]);
+ shouldBeNonNull('fb');
+
+ // Regardless of the context version and enabled extensions,
+ // the value will be clamped at draw time,
+ gl.blendColor(10, 1, 1, 1);
+ const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
+ expectArray(was, [1, 2, 3, 4]);
+
+ if (gl.getExtension('EXT_color_buffer_half_float') ||
+ gl.getExtension('WEBGL_color_buffer_float') ||
+ gl.getExtension('EXT_color_buffer_float'))
+ {
+ debug('Enable floating-point color buffers and retest');
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
+ expectArray(was, [1, 2, 3, 4]);
+ }
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA16F:');
+
+ const gl = CreateContext();
+
+ // Set the value before enabling the extension.
+ // It must be clamped only on WebGL 1.0 contexts.
+ gl.blendColor(10, 1, 1, 1);
+ if (!gl.getExtension('EXT_color_buffer_half_float')) {
+ testPassed('Missing ext EXT_color_buffer_half_float is optional, skipping.');
+ return;
+ }
+ if (!gl.texImage3D) { // WebGL 1.0
+ const ext = gl.getExtension('OES_texture_half_float');
+ gl.HALF_FLOAT = ext.HALF_FLOAT_OES; // These aren't the same value, but this'll work.
+ }
+
+ fb = CreateValidFb(gl, [[gl.RGBA16F, gl.RGBA, gl.HALF_FLOAT]]);
+ shouldBeNonNull('fb');
+ gl.prog.uColor([1, 2, 3, 4]);
+
+ let was = gl.drawAndRead(gl.FLOAT);
+ if (!gl.texImage3D) { // WebGL 1.0
+ expectArray(was, [1, 2, 3, 4]);
+ } else {
+ // Some WebGL 2.0 implementations may clamp the blend color anyway.
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ expectArray(was, [r, 2, 3, 4]);
+ }
+
+ // Re-set the value after the extension was enabled.
+ gl.blendColor(100, 1, 1, 1);
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ was = gl.drawAndRead(gl.FLOAT);
+ expectArray(was, [r, 2, 3, 4]);
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA32F:');
+
+ const gl = CreateContext();
+
+ // Set the value before enabling the extension.
+ // It must be clamped only on WebGL 1.0 contexts.
+ gl.blendColor(10, 1, 1, 1);
+ if (gl.texImage3D) { // WebGL 2.0
+ if (!gl.getExtension('EXT_color_buffer_float')) {
+ testPassed('Missing ext EXT_color_buffer_float is optional, skipping.');
+ return;
+ }
+ } else {
+ if (!gl.getExtension('WEBGL_color_buffer_float')) {
+ testPassed('Missing ext WEBGL_color_buffer_float is optional, skipping.');
+ return;
+ }
+ gl.getExtension('OES_texture_float');
+ }
+ fb = CreateValidFb(gl, [[gl.RGBA32F, gl.RGBA, gl.FLOAT]]);
+ shouldBeNonNull('fb');
+ gl.prog.uColor([1, 2, 3, 4]);
+
+ let was = gl.drawAndRead(gl.FLOAT);
+ if (!gl.texImage3D) { // WebGL 1.0
+ expectArray(was, [1, 2, 3, 4]);
+ } else {
+ // Some WebGL 2.0 implementations may clamp the blend color anyway.
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ expectArray(was, [r, 2, 3, 4]);
+ }
+
+ // Re-set the value after the extension was enabled.
+ gl.blendColor(100, 1, 1, 1);
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ was = gl.drawAndRead(gl.FLOAT);
+
+ if (!gl.getExtension('EXT_float_blend')) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'Should not be able to blend 32F formats.');
+ return;
+ }
+ wtu.glErrorShouldBe(gl, 0, 'Should be able to blend 32F formats.');
+ expectArray(was, [r, 2, 3, 4]);
+ },
+];
+
+async function Test() {
+ for (const fn of TESTS) {
+ await wtu.dispatchPromise(fn);
+ }
+ wtu.destroyAllContexts();
+ finishTest();
+}
+
+Test();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html
new file mode 100644
index 0000000000..f6225ffae2
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/canvas-alpha-bug.html
@@ -0,0 +1,116 @@
+<!--
+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>Alpha blending bug on WebGL canvas</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="128" height="128"> </canvas>
+
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec2 a_position;
+varying vec2 v_uv;
+void main()
+{
+ v_uv = a_position.xy * vec2(0.5, 0.5) + vec2(0.5, 0.5);
+ gl_Position = vec4(a_position.xy, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec2 v_uv;
+uniform sampler2D u_texture;
+uniform vec4 u_color;
+void main()
+{
+ vec4 tex = texture2D(u_texture, v_uv);
+ gl_FragColor = tex * u_color;
+}
+</script>
+
+<script>
+"use strict";
+// This test exposes an Intel driver issue on macOS.
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+
+var program;
+var offscreen_tex;
+var fbo;
+
+function init()
+{
+ // Init program
+ program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position"]);
+
+ // Init offscreen render targets and specify the format of offscreen texture to be RGB.
+ offscreen_tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, offscreen_tex);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, canvas.width, canvas.height, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
+
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, offscreen_tex, 0);
+
+ // Init blend state
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+}
+
+function draw_rect()
+{
+ gl.useProgram(program);
+
+ gl.bindTexture(gl.TEXTURE_2D, offscreen_tex);
+ var u_tex_loc = gl.getUniformLocation(program, 'u_texture');
+ gl.uniform1i(u_tex_loc, 0);
+
+ wtu.setupUnitQuad(gl);
+ wtu.drawFloatColorQuad(gl, [1.0, 1.0, 1.0, 1.0]);
+}
+
+function test_canvas_alpha() {
+ init();
+
+ // Clear offscreen texture to Green
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Clear default framebuffer
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Enable alpha blending and render to default framebuffer
+ gl.enable(gl.BLEND);
+ draw_rect();
+ wtu.checkCanvasRect(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, [0, 255, 0, 255]);
+}
+
+test_canvas_alpha();
+
+description("Exposes alpha blending bug in Intel drivers on macOS - see https://crbug.com/886970");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html
new file mode 100644
index 0000000000..576b0cc6ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-after-copyTexImage2D.html
@@ -0,0 +1,64 @@
+<!--
+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 clear after copyTexImage2D with a non-pure color</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="128" height="128"> </canvas>
+<script>
+"use strict";
+// This test verifies a Intel D3D driver bug.
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas", {"antialias" : "true"});
+
+function testClearAfterCopyTexImage2DWithoutPureOneOrZero(clearColor, expectedColor)
+{
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var width = 16;
+ var height = 16;
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, width, height, 0);
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.checkCanvasRect(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, expectedColor);
+
+ gl.bindTexture(gl.TEXTURE_2D, null);
+ gl.deleteTexture(texture);
+}
+
+description("Test that if clear with a color that has non-0/1 RGB components after copyTexImage2D, the final render color should be consistent with the clear color.");
+
+for(var index = 0; index < 3; index++)
+{
+ var clearColor = [0, 0, 0, 1];
+ var expectedColor = [0, 0, 0, 255];
+ clearColor[index] = 0.8;
+ expectedColor[index] = 255 * clearColor[index];
+ testClearAfterCopyTexImage2DWithoutPureOneOrZero(clearColor, expectedColor);
+}
+
+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/rendering/clear-default-framebuffer-with-scissor-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-default-framebuffer-with-scissor-test.html
new file mode 100644
index 0000000000..d33555f2bb
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clear-default-framebuffer-with-scissor-test.html
@@ -0,0 +1,68 @@
+<!--
+Copyright (c) 2021 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>Clear with scissor bug on WebGL canvas</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-webgl" width="20" height="20"> </canvas>
+<canvas id="canvas-2d" width="20" height="20"> </canvas>
+
+<script>
+"use strict";
+// This test exposes an issue in older Intel D3D drivers.
+var wtu = WebGLTestUtils;
+
+function test_clear_with_scissor_on_canvas()
+{
+ var canvasWebGL = document.getElementById("canvas-webgl");
+ var gl = canvasWebGL.getContext("webgl", { antialias:false });
+ const scissorRectSize = 16;
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(0, 0, scissorRectSize, scissorRectSize);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // The issue is found in the Chromium compositor so we need another canvas element for reproduction.
+ var canvas2D = document.getElementById("canvas-2d");
+ var context2D = canvas2D.getContext('2d');
+ context2D.drawImage(canvasWebGL, 0, 0);
+ context2D.fill();
+
+ var imageData =
+ context2D.getImageData(0, canvas2D.clientHeight - scissorRectSize, scissorRectSize, scissorRectSize);
+ var data = imageData.data;
+ var expectedColor = [0, 255, 0, 255];
+ for (var pixelIndex = 0; pixelIndex < scissorRectSize * scissorRectSize; ++pixelIndex) {
+ for (var colorIndex = 0; colorIndex < 4; ++colorIndex) {
+ if (data[pixelIndex * 4 + colorIndex] !== expectedColor[colorIndex]) {
+ var y = Math.floor(pixelIndex / scissorRectSize);
+ var x = pixelIndex % scissorRectSize;
+ testFailed("The canvas color at (" + x + ", " + y + ") is not expected");
+ return;
+ }
+ }
+ }
+}
+
+test_clear_with_scissor_on_canvas();
+
+description("Exposes clearing WebGL canvas with scissor bug on Intel D3D drivers - see https://crbug.com/1206763");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html
new file mode 100644
index 0000000000..f38aa0c4d5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/clipping-wide-points.html
@@ -0,0 +1,26 @@
+<!--
+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>
+<title>Clipping wide points test</title>
+<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>
+</head>
+<body>
+<canvas id="testbed" width="1" height="1"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/clipping-wide-points.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html
new file mode 100644
index 0000000000..4aa8740cbe
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-preserved-during-implicit-clears.html
@@ -0,0 +1,111 @@
+<!--
+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>ColorMask Must Be Preserved During Implicit Clears</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="canvases"></div>
+<div id="console"></div>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+const sz = 128;
+let frames;
+let gl;
+let tests = [
+ { alpha: false, antialias: false, premultipliedAlpha: false },
+ { alpha: false, antialias: false, premultipliedAlpha: true },
+ { alpha: false, antialias: true, premultipliedAlpha: false },
+ { alpha: false, antialias: true, premultipliedAlpha: true },
+];
+let currentTest;
+let testIndex = 0;
+
+function initTest() {
+ description();
+ debug('ColorMask must be preserved during implicit clears of textures.');
+ debug('Regression test for <a href="http://crbug.com/911918">http://crbug.com/911918</a>');
+
+ requestAnimationFrame(nextTest);
+}
+
+function nextTest() {
+ if (testIndex >= tests.length) {
+ finishTest();
+ return;
+ }
+
+ frames = 20;
+ let canvases = document.getElementById('canvases');
+ let canvas = document.createElement('canvas');
+ canvas.width = sz;
+ canvas.height = sz;
+ canvases.appendChild(canvas);
+ currentTest = tests[testIndex];
+ ++testIndex;
+ gl = wtu.create3DContext(canvas, currentTest);
+ requestAnimationFrame(runTest);
+}
+
+function runTest() {
+ // Create a user-defined framebuffer which has an alpha channel.
+ let fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ // Set color mask to disable alpha writes. This is important; see below.
+ gl.colorMask(true, true, true, false);
+ let tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sz, sz, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ // Upload a sub-rectangle. In Chrome, this was lazily clearing level 0 of the
+ // texture using OpenGL, setting the driver's color mask to (true, true, true,
+ // true) in the process. Because the user's color mask was set to (true, true,
+ // true, false) above, incorrect caching code was failing to reset the
+ // driver's color mask later. On macOS, Chrome implements alpha:false WebGL
+ // contexts on top of RGBA textures whose alpha channel is cleared to 1.0 and
+ // where the color mask is set to (true, true, true, false) during all writes.
+ // This bug was allowing that texture's alpha channel to be destroyed.
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ // We have to issue one clear to this framebuffer to get the color mask
+ // latched into the internal caching code.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Switch back to default framebuffer.
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ // Set clear color to transparent green.
+ gl.clearColor(0, 1, 0, 0);
+ // Clear. Result should be opaque green. Was transparent green when
+ // bug was encountered.
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.checkCanvasRect(gl, 0, 0, sz, sz,
+ [ 0, 255, 0, 255 ],
+ "default framebuffer should be opaque green for " + JSON.stringify(currentTest));
+
+ gl.deleteFramebuffer(fb);
+ gl.deleteTexture(tex);
+
+ --frames;
+ if (frames == 0) {
+ requestAnimationFrame(nextTest);
+ } else {
+ requestAnimationFrame(runTest);
+ }
+}
+
+requestAnimationFrame(initTest);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html
new file mode 100644
index 0000000000..7bba52e9a9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/color-mask-should-not-affect-antialiased-framebuffer-resolution.html
@@ -0,0 +1,71 @@
+<!--
+Copyright (c) 2021 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 ColorMask Should Not Affect Antialiased Framebuffer Resolution</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="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description("This test verifies that the colorMask state does not affect resolution of the antialiased framebuffer.");
+
+debug('Regression test for <a href="https://crbug.com/1257769">https://crbug.com/1257769</a> and <a href="https://bugs.webkit.org/show_bug.cgi?id=220129">https://bugs.webkit.org/show_bug.cgi?id=220129</a>');
+
+function run() {
+ const gl = wtu.create3DContext("canvas", { antialias: true, alpha: true });
+
+ if (!gl) {
+ testFailed("WebGL context does not exist");
+ finishTest();
+ return;
+ }
+
+ testPassed("WebGL context exists");
+
+ const program = wtu.setupColorQuad(gl);
+
+ // Clear the default (multisampled) framebuffer to red.
+ gl.clearColor(1, 0, 0, 1);
+ gl.colorMask(true, true, true, true);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw a transparent green quad.
+ gl.useProgram(program);
+ wtu.drawFloatColorQuad(gl, [ 0, 255, 0, 0 ]);
+
+ // Clear the alpha channel.
+ gl.colorMask(false, false, false, true);
+ gl.clearColor(0, 0, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // At this point, even setting the colorMask to all-true won't
+ // work around the bug, since that state is latched inside ANGLE
+ // only during draws / clears.
+
+ wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "should be green", 1);
+ finishTest();
+}
+
+var successfullyParsed = true;
+
+requestAnimationFrame(run);
+
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html
new file mode 100644
index 0000000000..74321f5cdd
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/culling.html
@@ -0,0 +1,127 @@
+<!--
+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/x-vertex">
+attribute vec2 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 0, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 col;
+
+void main()
+{
+ gl_FragColor = col;
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+function draw(gl, arr, colLoc, col) {
+ var vertices = new Float32Array(arr);
+ var vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ gl.uniform4fv(colLoc, col);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 2);
+}
+
+function clear(gl, col) {
+ gl.clearColor(col[0], col[1], col[2], col[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+}
+
+function check(gl, winding, shoulddraw) {
+ var msg = winding + ' face was ' + (shoulddraw ? '' : 'not ') + 'drawn.';
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0, 255], msg);
+}
+
+function runTest() {
+ var cwVertices = [-1, -1, -1, 1, 1, -1, 1, 1];
+ var ccwVertices = [-1, 1, -1, -1, 1, 1, 1, -1];
+ var red = [1, 0, 0, 1];
+ var green = [0, 1, 0, 1];
+ var ok;
+
+ var gl = wtu.create3DContext('testbed', { antialias: false });
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos']);
+ var colLoc = gl.getUniformLocation(program, 'col');
+
+ gl.enableVertexAttribArray(0);
+
+ debug('CULL_FACE should be off by default');
+ clear(gl, red);
+ draw(gl, ccwVertices, colLoc, green);
+ check(gl, 'CCW', true);
+ clear(gl, red);
+ draw(gl, cwVertices, colLoc, green);
+ check(gl, 'CW', true);
+
+ debug('Enabling CULL_FACE');
+ gl.enable(gl.CULL_FACE);
+
+ debug('BACK and CCW should be set by default');
+ clear(gl, red);
+ draw(gl, ccwVertices, colLoc, green);
+ check(gl, 'CCW', true);
+ clear(gl, green);
+ draw(gl, cwVertices, colLoc, red);
+ check(gl, 'CW', false);
+
+ var tests = [{ cullFace : 'BACK', frontFace : 'CCW', drawCCW : true, drawCW : false},
+ { cullFace : 'BACK', frontFace : 'CW', drawCCW : false, drawCW : true},
+ { cullFace : 'FRONT', frontFace : 'CCW', drawCCW : false, drawCW : true },
+ { cullFace : 'FRONT', frontFace : 'CW', drawCCW : true, drawCW : false},
+ { cullFace : 'FRONT_AND_BACK', frontFace : 'CCW', drawCCW : false, drawCW : false},
+ { cullFace : 'FRONT_AND_BACK', frontFace : 'CW', drawCCW : false, drawCW : false}];
+
+ for (var i = 0; i < tests.length; ++i) {
+ var t = tests[i];
+ debug('Setting ' + t.cullFace + ' and ' + t.frontFace);
+ gl.cullFace(gl[t.cullFace]);
+ gl.frontFace(gl[t.frontFace]);
+ clear(gl, t.drawCCW ? red : green);
+ draw(gl, ccwVertices, colLoc, t.drawCCW ? green : red);
+ check(gl, 'CCW', t.drawCCW);
+ clear(gl, t.drawCW ? red : green);
+ draw(gl, cwVertices, colLoc, t.drawCW ? green : red);
+ check(gl, 'CW', t.drawCW);
+ }
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="16" height="16" style="width:50px; height:50px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that culling 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/rendering/default-texture-draw-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/default-texture-draw-bug.html
new file mode 100644
index 0000000000..0d71a0aaa5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/default-texture-draw-bug.html
@@ -0,0 +1,69 @@
+<!--
+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.
+-->
+
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL Default Texture Draw Bug 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>
+<canvas id="c"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test attempts to provoke a Chrome bug that occured when drawing with textures when one was never bound. <a href='http://crbug.com/524144'>crbug.com/524144</a>");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c");
+var canvas = gl.canvas;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ runDrawTests();
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+function runDrawTests(drawType) {
+ debug("Test that drawing with a texture when no textures have been bound gives the expected black output");
+ canvas.width = 50; canvas.height = 50;
+ gl.viewport(0, 0, canvas.width, canvas.height);
+
+ // Set up a program that will draw with a texture
+ var program = wtu.setupNoTexCoordTextureProgram(gl);
+
+ wtu.setupIndexedQuad(gl);
+ for (var i = 0 ; i < 100 && _bufferedConsoleLogs != null; ++i) {
+ // Clear to white.
+ gl.clearColor(1.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ // Draw without binding any textures.
+ gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
+
+ // Check to ensure the entire canvas is black.
+ wtu.checkCanvasRect(gl, 0.0, 0.0, canvas.width, canvas.height,
+ [0.0, 0.0, 0.0], "Draw should pass", 2);
+ }
+}
+
+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/rendering/draw-arrays-out-of-bounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-arrays-out-of-bounds.html
new file mode 100644
index 0000000000..6577fa0b0a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-arrays-out-of-bounds.html
@@ -0,0 +1,33 @@
+<!--
+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/out-of-bounds-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test of drawArrays with out-of-bounds parameters");
+
+OutOfBoundsTest.runDrawArraysTest('gl.drawArrays(gl.TRIANGLES, $(offset), $(count))',
+ WebGLTestUtils.create3DContext(), WebGLTestUtils);
+
+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/rendering/draw-elements-out-of-bounds.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-elements-out-of-bounds.html
new file mode 100644
index 0000000000..74f7f8eaf5
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-elements-out-of-bounds.html
@@ -0,0 +1,33 @@
+<!--
+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/out-of-bounds-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+description("Test of drawElements with out-of-bounds parameters");
+
+OutOfBoundsTest.runDrawElementsTest("gl.drawElements(gl.TRIANGLES, $(count), $(type), $(offset))",
+ WebGLTestUtils.create3DContext(), WebGLTestUtils);
+
+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/rendering/draw-webgl-to-canvas-2d-repeatedly.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-webgl-to-canvas-2d-repeatedly.html
new file mode 100644
index 0000000000..d9a83e9166
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-webgl-to-canvas-2d-repeatedly.html
@@ -0,0 +1,91 @@
+<!--
+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>Draw WebGL to Canvas2D Repeatedly</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-webgl" width="256" height="256"></canvas>
+<canvas id="canvas-2d" width="256" height="256"></canvas>
+<script>
+"use strict";
+const wtu = WebGLTestUtils;
+
+const sz = 256;
+
+function drawTo2DCanvas(c2, webGLCanvas) {
+ // Always clear 2D canvas to solid green first.
+ c2.clearRect(0, 0, sz, sz);
+ c2.fillStyle = 'rgb(0,255,0)';
+ c2.fillRect(0, 0, sz, sz);
+ // Draw WebGL canvas to this canvas.
+ c2.drawImage(webGLCanvas, 0, 0);
+}
+
+function runTest() {
+ description();
+ debug('Repeatedly drawing a WebGL canvas to a 2D canvas should only draw the most recently rendered WebGL content.');
+ debug('Regression test for <a href="http://crbug.com/894021">http://crbug.com/894021</a>');
+
+ let c2 = document.getElementById('canvas-2d').getContext('2d');
+ let webGLCanvas = document.getElementById('canvas-webgl');
+ let gl = wtu.create3DContext(webGLCanvas, { alpha: true, antialias: false, premultipliedAlpha: true });
+ let tolerance = 2;
+
+ // Clear left half of WebGL canvas to red and right half to
+ // transparent black.
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.scissor(0, 0, sz / 2, sz);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Draw to 2D canvas.
+ drawTo2DCanvas(c2, webGLCanvas);
+
+ // Clear right half of WebGL canvas to red and left half to
+ // transparent black.
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.scissor(sz / 2, 0, sz / 2, sz);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(1.0, 0.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Draw to 2D canvas.
+ drawTo2DCanvas(c2, webGLCanvas);
+
+ // Clear WebGL canvas to transparent black.
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ // Draw to 2D canvas.
+ drawTo2DCanvas(c2, webGLCanvas);
+
+ // 2D canvas should be green.
+ // In the error case, the rendering results from earlier draws were
+ // being accumulated, so the 2D canvas was ultimately red.
+ wtu.checkCanvasRect(c2, 0, 0, sz, sz,
+ [ 0, 255, 0, 255 ],
+ "should be green",
+ tolerance);
+
+ finishTest();
+}
+
+requestAnimationFrame(runTest);
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html
new file mode 100644
index 0000000000..8b8dc71f59
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/draw-with-changing-start-vertex-bug.html
@@ -0,0 +1,114 @@
+<!--
+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.
+-->
+
+<!--
+This bug would occur after the app would render several times with the
+same vertex attributes and buffers, but using a different start offset.
+One of the buffers would likely have to be DYNAMIC.
+
+See http://anglebug.com/1327 and http://crbug.com/594509
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Draw with changing start vertex 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="canvas" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute mediump vec4 position;
+attribute mediump vec4 test;
+attribute mediump vec4 expected;
+varying mediump vec4 color;
+void main(void)
+{
+ gl_Position = position;
+ vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
+ color = vec4(lessThanEqual(abs(test - expected), threshold));
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+varying mediump vec4 color;
+void main(void)
+{
+ gl_FragColor = color;
+}
+</script>
+
+<script>
+"use strict";
+description("Test calling drawArrays with repeatedly with a different start vertex");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas1");
+var gl = wtu.create3DContext(canvas);
+
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["position", "test", "expected"]);
+
+var vertexCount = 24;
+var testData = new Float32Array(vertexCount);
+
+for (var index = 0; index < vertexCount; ++index) {
+ testData[index] = index;
+}
+
+var quadData = new Float32Array(14)
+quadData[0] = -1.0; quadData[1] = 1.0;
+quadData[2] = -1.0; quadData[3] = -1.0;
+quadData[4] = 1.0; quadData[5] = -1.0;
+quadData[6] = -1.0; quadData[7] = 1.0;
+quadData[8] = 1.0; quadData[9] = -1.0;
+quadData[10] = 1.0; quadData[11] = 1.0;
+quadData[12] = 0.0; quadData[13] = 0.0;
+
+var quadBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, quadData, gl.STATIC_DRAW);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(0);
+
+// Must be STATIC to trigger the bug.
+var testBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, testBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, testData, gl.STATIC_DRAW);
+gl.vertexAttribPointer(1, 1, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(1);
+
+// Must be DYNAMIC to trigger the bug.
+var expectedBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, expectedBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, testData, gl.DYNAMIC_DRAW);
+gl.vertexAttribPointer(2, 1, gl.FLOAT, false, 0, 0);
+gl.enableVertexAttribArray(2);
+
+function check() {
+ wtu.checkCanvas(gl, [255, 255, 255, 255], "should be white");
+}
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+check()
+
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+check()
+
+gl.drawArrays(gl.TRIANGLES, 1, 6);
+check()
+
+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/rendering/framebuffer-switch.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-switch.html
new file mode 100644
index 0000000000..df2a9ef55e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-switch.html
@@ -0,0 +1,91 @@
+<!--
+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 framebuffer switching conformance 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="canvas" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test framebuffer switching. The test switches between two framebuffers, copying rendering results from one to the other.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupTexturedQuad(gl);
+
+var tex1 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex1);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+var fb1 = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
+
+var tex2 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex2);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+var fb2 = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2, 0);
+
+gl.bindTexture(gl.TEXTURE_2D, tex1);
+gl.clearColor(1.0, 1.0, 1.0, 1.0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var iterate = function(checkFBOs, iterations) {
+ for (var i = 0; i < iterations; ++i) {
+ debug("Clearing framebuffer 1 to white");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb1);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ debug("Copying framebuffer 1 to framebuffer 2");
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+ // Read what is in fb2
+ wtu.checkCanvas(gl, [255,255,255,255], "Framebuffer 2 should be white");
+};
+
+debug("");
+debug("Warm-up iteration");
+iterate(true, 1);
+
+debug("");
+debug("Iterating the test a few times since at least one bug it has exposed is somewhat flaky.");
+for (var i = 0; i < 3; ++i) {
+ debug("");
+ debug("Iteration " + (i + 1));
+ iterate(false, 2);
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html
new file mode 100644
index 0000000000..dc5d60def8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-clear.html
@@ -0,0 +1,97 @@
+<!--
+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 framebuffer clearColor with pure 0/1</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";
+// This test verifies a Mac Intel HD 6000/6100 driver bug. See crbug.com/710443.
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("canvas");
+
+function InitializeRGBAData(width, height)
+{
+ var size = 4 * width * height;
+ var data = new Uint8Array(size);
+ for (var i = 0; i < size; i++) {
+ data[i] = 128;
+ }
+ return data;
+}
+
+function testFramebufferTextureClearWithPureZeroOrOne(clearColor, expectedColor) {
+ var width = 32;
+ var height = 32;
+ var texture0 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ // It seems that if we add texParameteri here, all cases can pass no matter
+ // you use texParameteri or not in Line 85.
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ var texData = InitializeRGBAData(width, height);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, texData);
+
+ var fbo0 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo0);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture0, 0);
+ gl.viewport(0, 0, width, height);
+ gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var texture1 = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture1);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ var fbo1 = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture1, 0);
+
+ wtu.setupTexturedQuad(gl);
+
+ gl.bindTexture(gl.TEXTURE_2D, texture0);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1);
+ gl.viewport(0, 0, width, height);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, expectedColor);
+
+ gl.deleteTexture(texture0);
+ gl.deleteFramebuffer(fbo0);
+ gl.deleteTexture(texture1);
+ gl.deleteFramebuffer(fbo1);
+}
+
+description("Test that if clear fbo texture color with pure 0/1 and sample this texture to draw to another fbo, the final render color should be consistent with the clear color.");
+
+for(var index = 0; index < 16; index++)
+{
+ var r = (index & 8) / 8;
+ var g = (index & 4) / 4;
+ var b = (index & 2) / 2;
+ var a = index & 1;
+ var clearColor = [r, g, b, a];
+ var expectedColor = [r * 255, g * 255, b * 255, a * 255];
+ testFramebufferTextureClearWithPureZeroOrOne(clearColor, expectedColor);
+}
+
+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/rendering/framebuffer-texture-switch.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-switch.html
new file mode 100644
index 0000000000..0043bc74de
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/framebuffer-texture-switch.html
@@ -0,0 +1,87 @@
+<!--
+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 framebuffer texture attachment switching conformance 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="canvas" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Test framebuffer texture attachment switching. The test uses one framebuffer object and switches its color attachment.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+
+var gl = wtu.create3DContext("canvas");
+var program = wtu.setupTexturedQuad(gl);
+
+var fb = gl.createFramebuffer();
+gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+var tex2 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex2);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+var tex1 = gl.createTexture();
+gl.bindTexture(gl.TEXTURE_2D, tex1);
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+
+gl.clearColor(1.0, 1.0, 1.0, 1.0);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var iterate = function(checkFBOs, iterations) {
+ for (var i = 0; i < iterations; ++i) {
+ debug("Clearing tex1 to white");
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ debug("Copying tex1 to tex2");
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2, 0);
+ if (checkFBOs)
+ shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+ // Read what is in tex2
+ wtu.checkCanvas(gl, [255,255,255,255], "tex2 should be white");
+};
+
+debug("");
+debug("Warm-up iteration");
+iterate(true, 1);
+
+debug("");
+debug("Iterating the test a few times since at least one bug it has exposed is somewhat flaky.");
+for (var i = 0; i < 3; ++i) {
+ debug("");
+ debug("Iteration " + (i + 1));
+ iterate(false, 2);
+}
+
+debug("");
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
+
+finishTest();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html
new file mode 100644
index 0000000000..e9c7210e81
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-clear.html
@@ -0,0 +1,67 @@
+<!--
+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 clear conformance 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="1" height="1" style="width: 256px; height: 48px;"></canvas>
+<div id="description"></div><div id="console"></div>
+<script>
+"use strict";
+description("Test clear.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupTexturedQuad(gl);
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [0,0,0,0], "should be 0,0,0,0");
+
+gl.clearColor(1,1,1,1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [255,255,255,255], "should be 255,255,255,255");
+
+gl.clearColor(0,0,0,0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [0,0,0,0], "should be 0,0,0,0");
+
+gl.colorMask(false, false, false, true);
+gl.clearColor(1,1,1,1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [0,0,0,255], "should be 0,0,0,255");
+
+var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(
+ gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array([128, 128, 128, 192]));
+
+gl.disable(gl.DEPTH_TEST);
+gl.disable(gl.BLEND);
+gl.colorMask(true, true, true, true);
+gl.drawArrays(gl.TRIANGLES, 0, 6);
+wtu.checkCanvas(gl, [128,128,128,192], "should be 128,128,128,192");
+
+gl.colorMask(false, false, false, true);
+gl.clearColor(1,1,1,1);
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvas(gl, [128,128,128,255], "should be 128,128,128,255");
+
+// TODO: Test depth and stencil clearing.
+
+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/rendering/gl-drawarrays.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawarrays.html
new file mode 100644
index 0000000000..7d06e99897
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawarrays.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">
+<title>WebGL drawArrays Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<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(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description(document.title);
+
+ function checkDrawArrays(mode, count, expect, msg) {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(mode, 0, count);
+ wtu.glErrorShouldBe(gl, expect, msg);
+ }
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+
+ checkDrawArrays(gl.TRIANGLES, 3,
+ gl.INVALID_OPERATION, "gl.DrawArrays with no buffer attached to VAO should return INVALID_OPERATION");
+
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ checkDrawArrays(gl.TRIANGLES, 3,
+ gl.NO_ERROR, "can call gl.DrawArrays with gl.TRIANGLES");
+
+ checkDrawArrays(
+ desktopGL['QUAD_STRIP'], 4,
+ gl.INVALID_ENUM, "gl.DrawArrays with QUAD_STRIP should return INVALID_ENUM");
+ checkDrawArrays(
+ desktopGL['QUADS'], 4,
+ gl.INVALID_ENUM, "gl.DrawArrays with QUADS should return INVALID_ENUM");
+ checkDrawArrays(
+ desktopGL['POLYGON'], 4,
+ gl.INVALID_ENUM, "gl.DrawArrays with POLYGON should return INVALID_ENUM");
+}
+
+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/rendering/gl-drawelements.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawelements.html
new file mode 100644
index 0000000000..347d539dbc
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-drawelements.html
@@ -0,0 +1,97 @@
+<!--
+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 drawElements Test</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/desktop-gl-constants.js"></script>
+<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(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>"use strict";
+description(document.title);
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([ 0, 1, 2]), gl.STATIC_DRAW);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)");
+
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2, 0]), gl.STATIC_DRAW);
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0)");
+
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(desktopGL.QUAD_STRIP, 4, gl.UNSIGNED_BYTE, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(desktopGL.QUADS, 4, gl.UNSIGNED_BYTE, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(desktopGL.POLYGON, 4, gl.UNSIGNED_BYTE, 0)");
+
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([ 0, 1, 2]), gl.STATIC_DRAW);
+
+wtu.shouldGenerateGLError(gl,
+ wtu.getDefault3DContextVersion() > 1 ? gl.NO_ERROR : gl.INVALID_ENUM,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)");
+
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.FLOAT, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.SHORT, 0)");
+
+// Index validation
+gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,1,2,2000, 40802, 5887992]), gl.STATIC_DRAW);
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 1)");
+wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
+ "gl.drawElements(gl.TRIANGLES, 2, gl.UNSIGNED_SHORT, 2)");
+var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR],
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 2)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 3)");
+wtu.shouldGenerateGLError(gl, indexValidationError,
+ "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 7, gl.UNSIGNED_SHORT, 0)");
+wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
+ "gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 2)");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html
new file mode 100644
index 0000000000..6e2f2baf30
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-canvas-dimensions.html
@@ -0,0 +1,78 @@
+<!--
+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 Scissor Canvas Dimensions 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>
+<style>
+canvas {
+ border: 1px solid #000;
+ width: 64px;
+ height: 64px;
+}
+</style>
+</head>
+<body>
+<canvas id="canvas1" width="16" height="16"> </canvas>
+<canvas id="canvas2" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Check that scissoring is initially disabled and that the scissor rect does not change when canvas size changes.");
+
+var wtu = WebGLTestUtils;
+
+function testInit(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ debug("Testing that scissor test is initially disabled");
+ // Setting the scissor rect should have no effect on drawing.
+ gl.scissor(0, 0, 1, 1);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [0, 255, 0, 255], "whole canvas should be green");
+}
+
+function testCanvasSizeChange(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ debug("Testing that scissor rect dimensions do not change if the canvas is resized.");
+ canvas.width = 32;
+ canvas.height = 32;
+ gl.viewport(0, 0, 32, 32);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0, 255, 0, 255], "area inside scissor should be green");
+ wtu.checkCanvasRect(gl, 0, 16, 32, 16, [0, 0, 0, 0], "area outside scissor should be black");
+ wtu.checkCanvasRect(gl, 16, 0, 16, 16, [0, 0, 0, 0], "area outside scissor should be black");
+}
+
+testInit(document.getElementById("canvas1"), {antialias: false});
+debug("");
+testCanvasSizeChange(document.getElementById("canvas2"), {antialias: false});
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html
new file mode 100644
index 0000000000..9b402a8206
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-fbo-test.html
@@ -0,0 +1,121 @@
+<!--
+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 Scissor FBO 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="canvas" width="16" height="16" style="width: 40px; height: 40px;"> </canvas>
+<canvas id="canvas2" width="16" height="16" style="width: 40px; height: 40px;"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Checks the scissor does not change when switching framebuffers.");
+
+var wtu = WebGLTestUtils;
+var gl;
+
+function makeFramebuffer(width, height) {
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ var fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+ shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ return fb;
+}
+
+function checkCanvasRect(x, y, width, height, color, msg) {
+ debug("checking: " + x + ", " + y + ", " + width + ", " + height);
+ wtu.checkCanvasRect(gl, x, y, width, height, color, msg);
+}
+
+function runEntireTest(canvasName, antialias) {
+ debug("");
+ debug("== Running scissor fbo test with antialias:" + antialias + " ==");
+ debug("");
+
+ gl = wtu.create3DContext(canvasName, {antialias: antialias});
+ if (!gl) {
+ testFailed("context does not exist");
+ return;
+ }
+ testPassed("context exists");
+
+ var fb8x8 = makeFramebuffer(8, 8);
+ var fb32x32 = makeFramebuffer(32, 32);
+
+ var testScissor = function(scissorX, scissorY, scissorWidth, scissorHeight, msg) {
+ debug("");
+ debug(msg);
+
+ var test = function(fb, size) {
+ debug("");
+ debug("checking size: " + size);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ var scissorRight = Math.min(scissorX + scissorWidth, size);
+ var scissorTop = Math.min(scissorY + scissorHeight, size);
+ var scWidth = scissorRight - scissorX;
+ var scHeight = scissorTop - scissorY;
+ var rightWidth = Math.min(size - scissorRight, 0);
+ var topHeight = Math.max(size - scissorTop, 0);
+ checkCanvasRect(scissorX, scissorY, scWidth, scHeight, [0, 255, 0, 255], "should be green");
+ checkCanvasRect(0, 0, size, scissorY, [255, 0, 0, 255], "should be red");
+ checkCanvasRect(0, scissorTop, size, topHeight, [255, 0, 0, 255], "should be red");
+ checkCanvasRect(0, 0, scissorX, size, [255, 0, 0, 255], "should be red");
+ checkCanvasRect(scissorRight, 0, scissorX, rightWidth, [255, 0, 0, 255], "should be red");
+ };
+
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(1, 0, 0, 1);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb8x8);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb32x32);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb32x32);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.scissor(scissorX, scissorY, scissorWidth, scissorHeight);
+ test(null, 16);
+ test(fb8x8, 8);
+ test(fb32x32, 32);
+ test(null, 16);
+ };
+
+ testScissor(2, 4, 12, 10, "test scissor in middle");
+ testScissor(0, 0, 12, 10, "test scissor at 0,0");
+ testScissor(0, 0, 16, 16, "test scissor with size that matches drawingbuffer");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+runEntireTest("canvas", false);
+runEntireTest("canvas2", true);
+
+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/rendering/gl-scissor-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-test.html
new file mode 100644
index 0000000000..fe78e0452e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-scissor-test.html
@@ -0,0 +1,95 @@
+<!--
+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 Scissor 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>
+<style>
+canvas {
+ border: 1px solid #000;
+ width: 64px;
+ height: 64px;
+}
+</style>
+</head>
+<body>
+<canvas id="canvas1" width="16" height="16"> </canvas>
+<canvas id="canvas2" width="16" height="16"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("Check if glScissor setting works.");
+
+var wtu = WebGLTestUtils;
+
+function test(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+
+ function test(func) {
+ gl.disable(gl.SCISSOR_TEST);
+ gl.clearColor(0,0,0,0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.enable(gl.SCISSOR_TEST);
+
+ var size = 16;
+ for (var ii = 0; ii < size; ++ii) {
+ // clear a portion of the WebGL drawing buffer
+ gl.scissor(ii, ii, 1, 1);
+ func();
+ }
+
+ for (var ii = 0; ii < size; ++ii) {
+ wtu.checkCanvasRect(gl, 0, ii, ii, 1, [0, 0, 0, 0], "should be black");
+ wtu.checkCanvasRect(gl, ii, ii, 1, 1, [0, 255, 0, 255], "should be green");
+ wtu.checkCanvasRect(gl, ii + 1, ii, size - ii - 1, 1, [0, 0, 0, 0], "should be black");
+ }
+ }
+
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ debug("");
+ debug("test with clear");
+ test(function() {
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ });
+
+ wtu.setupColorQuad(gl);
+
+ debug("");
+ debug("test with draw");
+ test(function() {
+ wtu.drawFloatColorQuad(gl, [0, 1, 0, 1]);
+ });
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+debug("test antialias: false");
+test(document.getElementById("canvas1"), {antialias: false});
+
+debug("");
+debug("test antialias: true");
+test(document.getElementById("canvas2"), {antialias: true});
+
+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/rendering/gl-viewport-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-viewport-test.html
new file mode 100644
index 0000000000..d56588098f
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/gl-viewport-test.html
@@ -0,0 +1,112 @@
+<!--
+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 Viewport 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>
+<style>
+canvas {
+ border: 1px solid #000;
+}
+</style>
+</head>
+<body>
+<canvas id="canvas1" width="64" height="128"> </canvas>
+<canvas id="canvas2" width="64" height="128"> </canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+var wtu = WebGLTestUtils;
+
+function test(canvas, attribs) {
+ var gl = wtu.create3DContext(canvas, attribs);
+
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ var blue = [0, 0, 255, 255];
+ var black = [0, 0, 0, 0];
+
+ var draw = function(viewportX, viewportY, viewportWidth, viewportHeight) {
+ gl.viewport(viewportX, viewportY, viewportWidth, viewportHeight);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ wtu.drawUByteColorQuad(gl, blue);
+ };
+
+ var drawAndCheck = function(viewportX, viewportY, viewportWidth, viewportHeight) {
+ var clipSpaceToPixelSpace = function(clip, viewportOffset, viewportSize, max) {
+ var pixel = viewportSize / 2 * clip + viewportOffset + viewportSize / 2;
+ return Math.min(max, Math.max(0, pixel));
+ };
+
+ var x1 = clipSpaceToPixelSpace(-0.5, viewportX, viewportWidth, gl.canvas.width);
+ var x2 = clipSpaceToPixelSpace( 0.5, viewportX, viewportWidth, gl.canvas.width);
+ var y1 = clipSpaceToPixelSpace(-0.5, viewportY, viewportHeight, gl.canvas.height);
+ var y2 = clipSpaceToPixelSpace( 0.5, viewportY, viewportHeight, gl.canvas.height);
+ var width = x2 - x1;
+ var height = y2 - y1;
+
+ debug("checking viewport: " + viewportX + ", " + viewportY + ", " + viewportWidth + ", " + viewportHeight);
+ debug("rect: " + x1 + ", " + y1 + ", " + width + ", " + height);
+ draw(viewportX, viewportY, viewportWidth, viewportHeight);
+ wtu.checkAreaInAndOut(gl, x1, y1, width, height, blue, black);
+ };
+
+ var program = wtu.setupSimpleColorProgram(gl);
+ wtu.setupQuad(gl, {scale: 0.5});
+
+ var w = gl.canvas.width;
+ var h = gl.canvas.height;
+
+ drawAndCheck(0, 0, w, h);
+ drawAndCheck(0, 0, w/2, h/4);
+ drawAndCheck(0, 0, w/4, h/2);
+ drawAndCheck(0, 0, w*2, h*2);
+
+ drawAndCheck(-w, 0, w, h);
+ drawAndCheck(0, -h, w, h);
+ drawAndCheck(w, 0, w, h);
+ drawAndCheck(0, h, w, h);
+
+ drawAndCheck(w/4, h/2, w, h);
+ drawAndCheck(w/4, h/2, w/2, h/4);
+ drawAndCheck(w/2, h/4, w/4, h/2);
+ drawAndCheck(w/2, h/4, w, h*2);
+
+ drawAndCheck(-w, 0, w*2, h);
+ drawAndCheck(0, -h/4, w/2, h);
+ drawAndCheck(-w/4, 0, w, h/2);
+ drawAndCheck(0, -h, w*2, h*2);
+
+ debug("");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ }
+}
+
+debug("test antialias: false");
+test(document.getElementById("canvas1"), {antialias: false});
+
+debug("");
+debug("test antialias: true");
+test(document.getElementById("canvas2"), {antialias: true});
+
+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/rendering/line-loop-tri-fan.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-loop-tri-fan.html
new file mode 100644
index 0000000000..e024157fc9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-loop-tri-fan.html
@@ -0,0 +1,229 @@
+<!--
+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/x-vertex">
+attribute vec2 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 0, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main()
+{
+ gl_FragColor = vec4(0, 1, 0, 1);
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+// Check a single 32-bit RGBA pixel.
+function checkPixel(buf, index, correct) {
+ for (var i = 0; i < 4; ++i) {
+ if (buf[index + i] != correct[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Check the line loop by reading the pixels and making sure just the edge
+// pixels are green and the rest are black.
+function checkLineLoop(gl, w) {
+ var buf = new Uint8Array(w * w * 4);
+ gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var green = [0,255,0,255];
+ var black = [0,0,0,255];
+ var isCorrect = true;
+ for (var j = 0; j < w * w * 4; j += 4) {
+ var correct = black;
+ if (j < w * 4 || j > w * (w - 1) * 4 || j % (w * 4) == 0 || j % (w * 4) == (w - 1) * 4) {
+ correct = green;
+ }
+ // ignore corner pixels
+ if ((j == 0) || (j == 4*(w-1)) || (j == 4*w*(w-1)) || (j== 4*(w*w - 1))) {
+ continue;
+ }
+ if (!checkPixel(buf, j, correct)) {
+ isCorrect = false;
+ break;
+ }
+ }
+ if (isCorrect) {
+ testPassed("Line loop was drawn correctly.");
+ } else {
+ testFailed("Line loop was drawn incorrectly.");
+ }
+}
+
+// Check the tri fan by reading the pixels and making sure they are all green.
+function checkTriFan(gl, w) {
+ var buf = new Uint8Array(w * w * 4);
+ gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+ var filled = true;
+ for (var j = 0; j < w * w * 4; j += 4) {
+ if (!checkPixel(buf, j, [0,255,0,255])) {
+ filled = false;
+ break;
+ }
+ }
+ if (filled) {
+ testPassed("Triangle fan was drawn correctly.");
+ } else {
+ testFailed("Triangle fan was drawn incorrectly.");
+ }
+}
+
+function runTest() {
+ var gl = wtu.create3DContext('testbed', { antialias: false });
+ if (!gl) {
+ testFailed('could not create context');
+ return;
+ }
+ gl.clearColor(0, 0, 0, 1);
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos'])
+ var w = document.getElementById('testbed').width;
+
+ gl.enableVertexAttribArray(0);
+
+ //---------- LINE_LOOP----------
+ var d = 1/w;
+ var vertices = new Float32Array([-1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
+ var vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ var indBuf = gl.createBuffer();
+ var indices = new Uint16Array([0, 1, 2, 3]);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a square using a line loop and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.LINE_LOOP, 0, vertices.length / 2);
+ checkLineLoop(gl, w);
+
+ debug('Draw a square using an indexed line loop and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
+ checkLineLoop(gl, w);
+
+ vertices = new Float32Array([0, 0, 0, 0, 0, 0, -1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indBuf = gl.createBuffer();
+ indices = new Uint16Array([0, 1, 2, 3, 4, 5, 6]);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a square using a line loop with a vertex buffer offset and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.LINE_LOOP, 3, vertices.length / 2 - 3);
+ checkLineLoop(gl, w);
+
+ debug('Draw a square using an indexed line loop with an index buffer offset and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.LINE_LOOP, indices.length - 3, gl.UNSIGNED_SHORT, 3 * 2);
+ checkLineLoop(gl, w);
+
+ //---------- LINE_LOOP UBYTE ----------
+ var degenVerts = new Array(252 * 2);
+ for (var j = 0; j < 252 * 2; ++j) {
+ degenVerts[j] = -1+d;
+ }
+ degenVerts = degenVerts.concat([-1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
+ vertices = new Float32Array(degenVerts);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indBuf = gl.createBuffer();
+ var degenInd = new Array(252);
+ for (var j = 0; j < 252; ++j) {
+ degenInd[j] = j;
+ }
+ degenInd = degenInd.concat([252, 253, 254, 255]);
+ indices = new Uint16Array(degenInd);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a square using an ubyte indexed line loop with 256 indices and verify that it draws all four sides and nothing else.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
+ checkLineLoop(gl, w);
+
+ //---------- TRIANGLE_FAN ----------
+ vertices = new Float32Array([0, 0, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1]);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indices = new Uint16Array([0,1,2,3,4,5]);
+ indBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a filled square using a triangle fan and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length / 2);
+ checkTriFan(gl, w);
+
+ debug('Draw a filled square using an indexed triangle fan and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLE_FAN, indices.length, gl.UNSIGNED_SHORT, 0);
+ checkTriFan(gl, w);
+
+ vertices = new Float32Array([1, 1, 1, 1, 1, 1, 0, 0, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1]);
+ vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+ indices = new Uint16Array([0,1,2,3,4,5,6,7,8]);
+ indBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug('Draw a filled square using a triangle fan with a vertex buffer offset and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLE_FAN, 3, vertices.length / 2 - 3);
+ checkTriFan(gl, w);
+
+ debug('Draw a filled square using an indexed triangle fan with an index buffer offset and verify that it fills the entire canvas.');
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLE_FAN, indices.length - 3, gl.UNSIGNED_SHORT, 3 * 2);
+ checkTriFan(gl, w);
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="10" height="10" style="width:50px; height:50px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that LINE_LOOP and TRIANGLE_FAN works correctly.');
+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/rendering/line-rendering-quality.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-rendering-quality.html
new file mode 100644
index 0000000000..15faa02c2b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/line-rendering-quality.html
@@ -0,0 +1,27 @@
+<!--
+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>
+<title>Line rendering quality test</title>
+<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>
+</head>
+<body>
+<canvas id="testbed" width="256" height="256"></canvas>
+<canvas id="testbed2" width="256" height="256"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+var contextVersion = 1;
+</script>
+<script src="../../js/tests/line-rendering-quality.js"></script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html
new file mode 100644
index 0000000000..2c0a2232ce
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/many-draw-calls.html
@@ -0,0 +1,138 @@
+<!--
+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>
+</head>
+<body>
+<script id="vshader" type="x-shader/x-vertex">
+uniform mat4 transformMatrix;
+uniform vec3 positionOffset;
+attribute vec2 aPosition;
+void main() {
+ gl_Position = transformMatrix * vec4(aPosition, 0.0, 1.0) + vec4(positionOffset, 0.0);
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">
+void main() {
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+<div id="description"></div>
+<canvas id="canvas" width="256" height="256"></canvas>
+<div id="console"></div>
+<script>
+"use strict";
+enableJSTestPreVerboseLogging();
+description("Test many draw calls and uniform updates per frame");
+
+debug('Regression test for Chromium <a href="http://crbug.com/320724">Issue 320724</a> and <a href="http://crbug.com/322726">Issue 322726</a>');
+debug('');
+
+var contextWasLost = false;
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById('canvas');
+var gl = wtu.create3DContext(canvas);
+canvas.addEventListener('webglcontextlost', function(event) { contextWasLost = true; }, false);
+var program = wtu.setupProgram(gl, ["vshader", "fshader"], [ "aPosition" ]);
+if (!program) {
+ testFailed("failed to create test program");
+}
+
+gl.useProgram(program);
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.enableVertexAttribArray(0);
+
+// Initialize vertices
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1.0, 1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0,
+ -1.0, -1.0,
+ 1.0, -1.0 ]), gl.STATIC_DRAW);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+gl.clearColor(0.3, 0.3, 0.3, 1.0);
+
+// Initialize uniforms
+var transformLoc = gl.getUniformLocation(program, 'transformMatrix');
+var offsetLoc = gl.getUniformLocation(program, 'positionOffset');
+
+// This many draw calls appear to be necessary to trigger the original bug reliably.
+var tilesPerSide = 100;
+var numDrawsThisFrame = 0;
+
+var doNextDraw = function() {
+ // Sometimes, the original bug can't be caught cooperatively, and it
+ // causes the entire tab to hang irrevocably.
+ if (contextWasLost) {
+ testFailed("WebGL context was lost while running the test");
+ finishTest();
+ return;
+ }
+
+ var totalDraws = tilesPerSide * tilesPerSide;
+ if (numDrawsThisFrame >= totalDraws) {
+ testPassed("All draw calls completed successfully");
+ finishTest();
+ return;
+ }
+
+ numDrawsThisFrame += tilesPerSide;
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ var transformMatrix = new Float32Array(16);
+ transformMatrix[15] = 1.0;
+ var scaleFactor = 1.0 / tilesPerSide;
+ transformMatrix[0] = scaleFactor;
+ transformMatrix[5] = scaleFactor;
+ transformMatrix[10] = scaleFactor;
+
+ var offset = new Float32Array(3);
+
+ var drawsDoneThisFrame = 0;
+ for (var yy = 0; yy < tilesPerSide; ++yy) {
+ for (var xx = 0; xx < tilesPerSide; ++xx) {
+ if (drawsDoneThisFrame >= numDrawsThisFrame)
+ break;
+
+ gl.uniformMatrix4fv(transformLoc, false, transformMatrix);
+
+ offset[0] = 2.0 * ((0.5 + xx) / tilesPerSide) - 1.0;
+ offset[1] = 2.0 * ((0.5 + yy) / tilesPerSide) - 1.0;
+ gl.uniform3f(offsetLoc, offset[0], offset[1], offset[2]);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ ++drawsDoneThisFrame;
+ }
+
+ if (drawsDoneThisFrame >= numDrawsThisFrame)
+ break;
+ }
+
+ var iterations = numDrawsThisFrame / tilesPerSide;
+ if (iterations % 10 === 0) {
+ // Needed to avoid test timeout within the harness on some slower platforms
+ testPassed("Completed " + iterations + " iterations");
+ }
+
+ wtu.requestAnimFrame(doNextDraw);
+}
+
+wtu.requestAnimFrame(doNextDraw);
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html
new file mode 100644
index 0000000000..02a0fe594e
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/more-than-65536-indices.html
@@ -0,0 +1,123 @@
+<!--
+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 More than 65536 indices.</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="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vs" type="text/something-not-javascript">
+attribute vec4 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main() {
+ gl_Position = vPosition;
+ gl_PointSize = 1.0;
+ color = vColor;
+}
+</script>
+<script id="fs" type="text/something-not-javascript">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description("checks that rendering with more than 65536 indices works.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vColor"]);
+var bufferObjects = wtu.setupUnitQuad(gl, 0, 1);
+
+gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[0]);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1, 1,
+ 1, 1,
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ 1, 1,
+ -1, -1,
+ 1, -1]), gl.STATIC_DRAW);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[1]);
+gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255,
+ 0, 255, 0, 255]), gl.STATIC_DRAW);
+gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after program setup");
+
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");
+var numQuads = Math.floor(65536 / 6) + 4;
+var numPoints = numQuads * 6;
+debug("numQuads: " + numQuads);
+debug("numPoints: " + numPoints);
+var indexBuf = new ArrayBuffer(numPoints);
+var indices = new Uint8Array(indexBuf);
+var indexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
+
+var modes = [
+ {mode: 'POINTS', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'LINES', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'LINE_LOOP', offsets: [0, 1, 2, 3, 2, 1], skip: 1},
+ {mode: 'LINE_STRIP', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'TRIANGLES', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'TRIANGLE_STRIP', offsets: [0, 1, 2, 3, 2, 1], skip: 0},
+ {mode: 'TRIANGLE_FAN', offsets: [0, 1, 3, 2, 2, 1], skip: 1}
+];
+
+for (var mm = 0; mm < modes.length; ++mm) {
+ var modeInfo = modes[mm];
+ var mode = modeInfo.mode;
+ var offsets = modeInfo.offsets;
+ var skip = modeInfo.skip;
+
+ for (var ii = 0; ii < numQuads; ++ii) {
+ var offset = ii * 6;
+ var quad = (ii == 0 || ii == (numQuads - 1)) ? 4 : 0;
+ for (var jj = 0; jj < 6; ++jj) {
+ indices[offset + jj] = quad + offsets[jj];
+ }
+ }
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ debug("");
+ debug("testing: " + mode);
+ // Draw without last 6 points.
+ gl.drawElements(gl[mode], numPoints - (skip + 1) * 6, gl.UNSIGNED_BYTE, skip * 6);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red.");
+ // Draw with last 6 points.
+ gl.drawElements(gl[mode], numPoints, gl.UNSIGNED_BYTE, 0);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "Should be green.");
+}
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
+
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html
new file mode 100644
index 0000000000..3836949e6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/multisample-corruption.html
@@ -0,0 +1,44 @@
+<!--
+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 Multisample Renderbuffer Corruption 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/iterable-test.js"> </script>
+</head>
+<body>
+<canvas id="example" width="2048" height="2048" style="width: 128px; height: 128px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+enableJSTestPreVerboseLogging();
+description(document.title);
+debug('Regression test for <a href="https://code.google.com/p/chromium/issues/detail?id=137303">Chromium bug 137303</a>');
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext("example", {antialias: true, preserveDrawingBuffer: true});
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var test = IterableTest.createMultisampleCorruptionTest(gl);
+ var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 25;
+ IterableTest.run(test, iterations);
+}
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.html
new file mode 100644
index 0000000000..69a59940a8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/negative-one-index.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">
+<title>-1 Index Rendering 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";
+function init()
+{
+ description(document.title);
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var contextVersion = wtu.getDefault3DContextVersion();
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ var vertexData = new Float32Array(65536 * 3);
+ vertexData[0 * 3 + 0] = 0.0;
+ vertexData[0 * 3 + 1] = 0.5;
+ vertexData[0 * 3 + 2] = 0.0;
+ vertexData[1 * 3 + 0] = -0.5;
+ vertexData[1 * 3 + 1] = -0.5;
+ vertexData[1 * 3 + 2] = 0.0;
+ vertexData[65535 * 3 + 0] = 0.5;
+ vertexData[65535 * 3 + 1] = -0.5;
+ vertexData[65535 * 3 + 2] = 0.0;
+ gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indices = new Uint16Array([0, 1, -1]);
+ var indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+
+ if (contextVersion <= 1) {
+ // This should render a green triangle in the middle of the canvas.
+ // Some implementations may incorrectly interpret the -1 index as
+ // a primitive restart and not render anything.
+
+ // Test several locations
+ // First line should be all black
+ wtu.checkCanvasRect(gl, 0, 0, 50, 1, [0, 0, 0, 0]);
+
+ // Line 15 should be green for at least 10 pixels starting from row 20
+ wtu.checkCanvasRect(gl, 20, 15, 10, 1, [0, 255, 0, 255]);
+
+ // Last line should be all black
+ wtu.checkCanvasRect(gl, 0, 49, 50, 1, [0, 0, 0, 0]);
+ } else {
+ // For WebGL 2, PRIMITIVE_RESTART_FIXED_INDEX is always enabled.
+ // Nothing should be drawn on the canvas.
+ wtu.checkCanvasRect(gl, 0, 0, 50, 50, [0, 0, 0, 0]);
+ }
+}
+
+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/rendering/out-of-bounds-array-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html
new file mode 100644
index 0000000000..04d4d55af1
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html
@@ -0,0 +1,126 @@
+<!--
+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 Out-of-Bounds Array Buffer Conformance Test</title>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vsCheckOutOfBounds" type="x-shader/x-vertex">
+ precision mediump float;
+ attribute vec2 position;
+ attribute vec4 vecRandom;
+ varying vec4 v_color;
+
+ // Per the spec, each component can either contain existing contents
+ // of the buffer or 0.
+ bool testFloatComponent(float component) {
+ return (component == 0.2 || component == 0.0);
+ }
+ // The last component is additionally allowed to be 1.0.
+ bool testLastFloatComponent(float component) {
+ return testFloatComponent(component) || component == 1.0;
+ }
+
+ void main() {
+ if (testFloatComponent(vecRandom.x) &&
+ testFloatComponent(vecRandom.y) &&
+ testFloatComponent(vecRandom.z) &&
+ testLastFloatComponent(vecRandom.w)) {
+ v_color = vec4(0.0, 1.0, 0.0, 1.0); // green -- We're good
+ } else {
+ v_color = vec4(1.0, 0.0, 0.0, 1.0); // red -- Unexpected value
+ }
+ gl_Position = vec4(position, 0.0, 1.0);
+ }
+</script>
+<script>
+"use strict";
+description("This test verifies that out-of-bounds array buffers behave according to spec.");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+
+var numberOfQuads = 200;
+
+// Draw out-of-bounds beginning with the start offset passed in.
+// Ensure that drawArrays flags either no error or INVALID_OPERATION. In the case of INVALID_OPERATION,
+// no canvas pixels can be touched. In the case of NO_ERROR, all written values must either be the
+// zero vertex or a value in the vertex buffer. See vsCheckOutOfBounds shader.
+function drawAndVerifyOutOfBoundsArrays(gl, first, count) {
+ gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.drawArrays(gl.TRIANGLES, first, count);
+ var error = gl.getError();
+ if (error === gl.INVALID_OPERATION) {
+ testPassed("drawArrays flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
+ wtu.checkCanvas(gl, [0, 0, 255, 255]);
+ } else if (error === gl.NO_ERROR) {
+ testPassed("drawArrays flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ } else {
+ testFailed("Invalid error flagged by drawArrays. Should be INVALID_OPERATION or NO_ERROR");
+ }
+}
+
+// Create a vertex buffer with 200 properly formed triangle quads. These quads will cover the
+// canvas texture such that every single pixel is touched by the fragment shader.
+var glQuadBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glQuadBuffer);
+var quadPositions = new Float32Array(numberOfQuads * /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/6);
+for (var i = 0; i < quadPositions.length; i += /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/6) {
+ quadPositions[i+0] = -1.0; // upper left
+ quadPositions[i+1] = 1.0;
+ quadPositions[i+2] = 1.0; // upper right
+ quadPositions[i+3] = 1.0;
+ quadPositions[i+4] = -1.0; // lower left
+ quadPositions[i+5] = -1.0;
+ quadPositions[i+6] = 1.0; // upper right
+ quadPositions[i+7] = 1.0;
+ quadPositions[i+8] = 1.0; // lower right
+ quadPositions[i+9] = -1.0;
+ quadPositions[i+10] = -1.0; // lower left
+ quadPositions[i+11] = -1.0;
+}
+gl.bufferData(gl.ARRAY_BUFFER, quadPositions, gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+
+// Create a small vertex buffer with determined-ahead-of-time "random" values (0.2). This buffer will be
+// the one read past the end.
+var glVertexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glVertexBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.2, 0.2, 0.2, 0.2, 0.2, 0.2]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+
+// Setup the verification program.
+var glProgram = wtu.setupProgram(gl, ["vsCheckOutOfBounds", wtu.simpleVertexColorFragmentShader], ["position", "vecRandom"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Shader and buffer setup should not generate errors");
+
+debug("Test -- Draw off the end of the vertex buffer near the beginning of the out of bounds area.");
+drawAndVerifyOutOfBoundsArrays(gl, /*first*/6, /*count*/6);
+
+debug("");
+
+debug("Test -- Draw off the end of the vertex buffer near the end of the out of bounds area.")
+drawAndVerifyOutOfBoundsArrays(gl, /*first*/(numberOfQuads - 1) * 6, /*count*/6);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html
new file mode 100644
index 0000000000..0eb2bfebfa
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.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 Out-of-Bounds Index Buffer Conformance Test</title>
+</head>
+<body>
+<canvas id="canvas" width="8" height="8" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vsCheckOutOfBounds" type="x-shader/x-vertex">
+ precision mediump float;
+ attribute vec2 position;
+ attribute vec4 vecRandom;
+ varying vec4 v_color;
+
+ // Per the spec, each component can either contain existing contents
+ // of the buffer or 0.
+ bool testFloatComponent(float component) {
+ return (component == 0.2 || component == 0.0);
+ }
+ // The last component is additionally allowed to be 1.0.
+ bool testLastFloatComponent(float component) {
+ return testFloatComponent(component) || component == 1.0;
+ }
+
+ void main() {
+ if (testFloatComponent(vecRandom.x) &&
+ testFloatComponent(vecRandom.y) &&
+ testFloatComponent(vecRandom.z) &&
+ testLastFloatComponent(vecRandom.w)) {
+ v_color = vec4(0.0, 1.0, 0.0, 1.0); // green -- We're good
+ } else {
+ v_color = vec4(1.0, 0.0, 0.0, 1.0); // red -- Unexpected value
+ }
+ gl_Position = vec4(position, 0.0, 1.0);
+ }
+</script>
+<script>
+"use strict";
+description("This test verifies that out-of-bounds index buffers behave according to spec.");
+
+// Prepare an element array buffer that indexes out-of-bounds beginning with the start index passed in.
+// Ensure that drawElements flags either no error or INVALID_OPERATION. In the case of INVALID_OPERATION,
+// no canvas pixels can be touched. In the case of NO_ERROR, all written values must either be the
+// zero vertex or a value in the vertex buffer. See vsCheckOutOfBounds shader.
+function drawAndVerifyOutOfBoundsIndex(gl, startIndex) {
+ gl.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ prepareElementArrayBuffer(gl, /*StartIndex*/startIndex);
+
+ gl.drawElements(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_SHORT, /*offset*/0);
+ var error = gl.getError();
+ if (error === gl.INVALID_OPERATION) {
+ testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
+ wtu.checkCanvas(gl, [0, 0, 255, 255]);
+ } else if (error === gl.NO_ERROR) {
+ testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
+ wtu.checkCanvas(gl, [0, 255, 0, 255]);
+ } else {
+ testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
+ }
+}
+
+// Create an element array buffer with a tri-strip that starts at startIndex and make
+// it the active element array buffer.
+function prepareElementArrayBuffer(gl, startIndex) {
+ var glElementArrayBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, glElementArrayBuffer);
+ var quadIndices = new Uint16Array(4);
+ for (var i = 0; i < quadIndices.length; i++) {
+ quadIndices[i] = startIndex + i;
+ }
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, quadIndices, gl.STATIC_DRAW);
+}
+
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+
+var numberOfQuads = 200;
+
+// Create a vertex buffer with 200 properly formed tri-strip quads. These quads will cover the canvas texture
+// such that every single pixel is touched by the fragment shader.
+var glQuadBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glQuadBuffer);
+var quadPositions = new Float32Array(numberOfQuads * /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4);
+for (var i = 0; i < quadPositions.length; i += /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4) {
+ quadPositions[i+0] = -1.0; // upper left
+ quadPositions[i+1] = 1.0;
+ quadPositions[i+2] = 1.0; // upper right
+ quadPositions[i+3] = 1.0;
+ quadPositions[i+4] = -1.0; // lower left
+ quadPositions[i+5] = -1.0;
+ quadPositions[i+6] = 1.0; // lower right
+ quadPositions[i+7] = -1.0;
+}
+gl.bufferData(gl.ARRAY_BUFFER, quadPositions, gl.STATIC_DRAW);
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+// Create a small vertex buffer with determined-ahead-of-time "random" values (0.2). This buffer will be
+// the one indexed off the end.
+var glVertexBuffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, glVertexBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.2, 0.2, 0.2, 0.2]), gl.STATIC_DRAW);
+gl.enableVertexAttribArray(1);
+gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
+
+// Setup the verification program.
+var glProgram = wtu.setupProgram(gl, ["vsCheckOutOfBounds", wtu.simpleVertexColorFragmentShader], ["position", "vecRandom"]);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Shader and buffer setup should not generate errors");
+
+debug("Test -- Index off the end of the vertex buffer near the beginning of the out of bounds area.");
+drawAndVerifyOutOfBoundsIndex(gl, /*StartIndex*/4);
+
+debug("");
+
+debug("Test -- Index off the end of the vertex buffer near the end of the out of bounds area.")
+drawAndVerifyOutOfBoundsIndex(gl, /*StartIndex*/numberOfQuads - 4);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html
new file mode 100644
index 0000000000..3b67f34942
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-no-attributes.html
@@ -0,0 +1,55 @@
+<!--
+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/x-vertex">
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+
+void main()
+{
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="1" height="1" style="width: 100px; height: 100px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that drawing a point without enabling any attributes succeeds');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('testbed');
+
+var program1 = wtu.setupProgram(gl, ['vshader', 'fshader']);
+
+debug('Draw a point with a shader that takes no attributes and verify it fills the whole canvas.');
+
+gl.drawArrays(gl.POINTS, 0, 1);
+wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+wtu.checkCanvas(gl, [0, 255, 0, 255]);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html
new file mode 100644
index 0000000000..d458428221
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-size.html
@@ -0,0 +1,129 @@
+<!--
+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/x-vertex">
+attribute vec3 pos;
+attribute vec4 colorIn;
+uniform float pointSize;
+varying vec4 color;
+
+void main()
+{
+ gl_PointSize = pointSize;
+ color = colorIn;
+ gl_Position = vec4(pos, 1.0);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+varying vec4 color;
+
+void main()
+{
+ gl_FragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="2" height="2"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify GL_VERTEX_PROGRAM_POINT_SIZE is enabled in WebGL');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext('testbed', { antialias: false });
+shouldBeNonNull("gl");
+
+gl.disable(gl.BLEND);
+
+// The choice of (0.4, 0.4) ensures that the centers of the surrounding
+// pixels are not contained within the point when it is of size 1, but
+// that they definitely are when it is of size 2.
+var vertices = new Float32Array([
+ 0.4, 0.4, 0.0]);
+var colors = new Uint8Array([
+ 255, 0, 0, 255]);
+
+var colorOffset = vertices.byteLength;
+
+var buf = new Uint8Array(2 * 2 * 4);
+var index = 0;
+
+var vbo = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
+gl.bufferData(gl.ARRAY_BUFFER, colorOffset + colors.byteLength, gl.STATIC_DRAW);
+gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices);
+gl.bufferSubData(gl.ARRAY_BUFFER, colorOffset, colors);
+
+function test(program) {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, colorOffset);
+ gl.enableVertexAttribArray(1);
+
+ var locPointSize = gl.getUniformLocation(program, 'pointSize');
+
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ debug('Draw a point of size 1 and verify it does not touch any other pixels.');
+
+ gl.uniform1f(locPointSize, 1.0);
+ gl.drawArrays(gl.POINTS, 0, vertices.length / 3);
+
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+
+ for (var y = 0; y < 2; ++y) {
+ for (var x = 0; x < 2; ++x) {
+ var correctColor = (x == 1 && y == 1) ? [255, 0, 0] : [0, 0, 0];
+ wtu.checkCanvasRect(gl, x, y, 1, 1, correctColor);
+ }
+ }
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ debug('Draw a point of size 2 and verify it fills the appropriate region.');
+
+ var pointSizeRange = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
+ if (pointSizeRange[1] >= 2.0) {
+ gl.uniform1f(locPointSize, 2.0);
+ gl.drawArrays(gl.POINTS, 0, vertices.length / 3);
+ shouldBe('gl.getError()', 'gl.NO_ERROR');
+ wtu.checkCanvasRect(gl, 0, 0, 2, 2, [255, 0, 0]);
+ }
+}
+
+debug('');
+debug('Pass 1');
+var program1 = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn']);
+shouldBe('gl.getError()', 'gl.NO_ERROR');
+test(program1);
+
+// Under some versions of ANGLE point sprite shader programs were
+// incorrectly reloaded from cache. Rebuilding the shader program and
+// repeating the test simulates the conditions that caused it to fail
+debug('');
+debug('Pass 2');
+var program2 = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn']);
+shouldBe('gl.getError()', 'gl.NO_ERROR');
+test(program2);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html
new file mode 100644
index 0000000000..71f0bcad50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-specific-shader-variables.html
@@ -0,0 +1,166 @@
+<!--
+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>Point-specific shader variables 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="c" width="64" height="64"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vs-assign" type="x-shader/x-vertex">
+attribute vec2 aPosition;
+
+varying vec2 vPos;
+
+void main()
+{
+ gl_Position = vec4(aPosition, 0, 1);
+ vPos = aPosition;
+
+ gl_PointSize = 1.0;
+}
+</script>
+
+<script id="vs-conditional" type="x-shader/x-vertex">
+uniform float renderingPoints; // not assigned, equal to 0.0
+attribute vec2 aPosition;
+
+varying vec2 vPos;
+
+void main()
+{
+ gl_Position = vec4(aPosition, 0, 1);
+ vPos = aPosition;
+
+ if (renderingPoints > 0.0) {
+ gl_PointSize = 1.0;
+ }
+}
+</script>
+
+<script id="fs-overwrite" type="x-shader/x-fragment">
+varying mediump vec2 vPos;
+
+void main()
+{
+ gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
+ gl_FragColor = vec4(vPos * -2.0, 0, 1);
+}
+</script>
+
+<script id="fs-unused-branch" type="x-shader/x-fragment">
+varying mediump vec2 vPos;
+uniform mediump float uDefaultsToZero;
+
+void main()
+{
+ gl_FragColor = vec4(vPos * -2.0, 0, 1);
+ if (uDefaultsToZero == 1.0) {
+ gl_FragColor = vec4(gl_PointCoord.xy, 0, 1);
+ }
+}
+</script>
+
+<script>
+"use strict";
+description(document.title);
+
+debug('This test verifies rendering with programs referencing shader variables specific to rendering of POINTS primitives.');
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c", {depth: false});
+
+var prog_overwrite = wtu.setupProgram(gl, ["vs-assign", "fs-overwrite"], ["aPosition"]);
+var prog_branch = wtu.setupProgram(gl, ["vs-assign", "fs-unused-branch"], ["aPosition"]);
+var prog_cond_overwrite = wtu.setupProgram(gl, ["vs-conditional", "fs-overwrite"], ["aPosition"]);
+var prog_cond_branch = wtu.setupProgram(gl, ["vs-conditional", "fs-unused-branch"], ["aPosition"]);
+
+var vertData = new Float32Array([
+ -1, -1,
+ +1, -1,
+ -1, +1,
+]);
+
+var vertexObject = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+gl.bufferData(gl.ARRAY_BUFFER, vertData, gl.STATIC_DRAW);
+
+gl.enableVertexAttribArray(0);
+gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+//////////
+
+debug("");
+debug("prog-overwrite");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_overwrite);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+
+//////////
+
+debug("");
+debug("prog-branch");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_branch);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+//////////
+
+debug("");
+debug("prog-cond-overwrite");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_cond_overwrite);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+
+//////////
+
+debug("");
+debug("prog-cond-branch");
+
+gl.clear(gl.COLOR_BUFFER_BIT);
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0]); // Bottom-left
+
+gl.useProgram(prog_cond_branch);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 255, 0, 255]); // Bottom-left
+wtu.checkCanvasRect(gl, 63, 63, 1, 1, [0, 0, 0, 0]); // Top-right
+
+var successfullyParsed = true;
+</script>
+
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html
new file mode 100644
index 0000000000..802d5f1172
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/point-with-gl-pointcoord-in-fragment-shader.html
@@ -0,0 +1,119 @@
+<!--
+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 Point with gl_PointCoord in Fragment Shader 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>
+<div id="description"></div>
+<canvas id="canvas" width="64" height="64"> </canvas>
+<div id="console"></div>
+<script id="vs" type="x-shader/x-vertex">
+varying vec4 v_color;
+
+// The X and Y coordinates of the center of the point.
+attribute vec2 a_vertex;
+
+uniform float u_pointSize;
+
+void main(void) {
+ gl_PointSize = u_pointSize;
+ gl_Position = vec4(a_vertex, 0.0, 1.0);
+
+ // The color of the point.
+ v_color = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+
+varying vec4 v_color;
+
+void main(void) {
+ // It seems as long as this mathematical expression references
+ // gl_PointCoord, the fragment's color is incorrect.
+ vec2 diff = gl_PointCoord - vec2(.5, .5);
+ if (length(diff) > 0.5)
+ discard;
+
+ // The point should be a solid color.
+ gl_FragColor = v_color;
+}
+</script>
+<script>
+"use strict";
+// Radar 13239314
+description("This is a regression test for a graphics driver bug affecting end caps on roads in MapsGL.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var canvasWidth = canvas.width;
+var canvasHeight = canvas.height;
+var output = document.getElementById("console");
+var gl = wtu.create3DContext(canvas);
+
+function runTest() {
+ var pointSizeRange = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
+ // This test can't really run without a maximum point size of at least 2
+ if (pointSizeRange[1] < 2.0) {
+ debug("This test needs a maximum ALIASED_POINT_SIZE_RANGE of at least 2");
+ return;
+ }
+
+ var vs = wtu.loadShaderFromScript(gl, "vs", gl.VERTEX_SHADER);
+ var fs = wtu.loadShaderFromScript(gl, "fs", gl.FRAGMENT_SHADER);
+ if (!vs || !fs) {
+ testFailed("Loading shaders failed");
+ return;
+ }
+
+ var program = wtu.setupProgram(gl, [vs, fs], ['a_vertex']);
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+
+ gl.useProgram(program);
+ gl.clearColor(0, 0, 0, 1.0);
+ gl.disable(gl.DEPTH_TEST);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // uniform float u_pointSize;
+ var uni = gl.getUniformLocation(program, 'u_pointSize');
+ gl.uniform1f(uni, Math.min(20.0, pointSizeRange[1]));
+
+ // vertex
+ var buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ var vertexData = new Float32Array([
+ 0, 0,
+ ]);
+ gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.checkCanvasRect(gl, canvasWidth / 2, canvasHeight / 2, 1, 1,
+ [0, 255, 0, 255], "Center pixel should be green", 2);
+}
+
+runTest();
+
+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/rendering/polygon-offset.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/polygon-offset.html
new file mode 100644
index 0000000000..dfc0a0cca9
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/polygon-offset.html
@@ -0,0 +1,173 @@
+<!--
+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/x-vertex">
+attribute vec3 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 1);
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 col;
+
+void main()
+{
+ gl_FragColor = col;
+}
+</script>
+
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+
+function draw(gl, arr, colLoc, col)
+{
+ var vertices = new Float32Array(arr);
+ var vertBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+ gl.uniform4fv(colLoc, col);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertices.length / 3);
+}
+
+function clear(gl, col, z)
+{
+ gl.clearColor(col[0], col[1], col[2], col[3]);
+ gl.clearDepth(z);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+}
+
+function check(gl)
+{
+ wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0, 255, 0, 255], 'result should be green');
+}
+
+function runTest()
+{
+ var flatSquare = [-1, -1, 0,
+ -1, 1, 0,
+ 1, -1, 0,
+ 1, 1, 0];
+ var slantedSquare = [-1, -1, -0.5,
+ -1, 1, -0.5,
+ 1, -1, 0.5,
+ 1, 1, 0.5];
+ var red = [1, 0, 0, 1];
+ var green = [0, 1, 0, 1];
+ var blue = [0, 0, 1, 1];
+
+ var gl = wtu.create3DContext('testbed', { antialias: false });
+ if (!gl)
+ {
+ testFailed('could not create context');
+ return;
+ }
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos']);
+ var colLoc = gl.getUniformLocation(program, 'col');
+
+ gl.enableVertexAttribArray(0);
+
+ gl.enable(gl.DEPTH_TEST);
+ gl.depthFunc(gl.LEQUAL);
+
+ debug('Polygon offset fill should be off by default');
+ clear(gl, red, 1.0);
+ draw(gl, slantedSquare, colLoc, blue);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Polygon offset units should have no effect when fill is off');
+ clear(gl, red, 1.0);
+ draw(gl, slantedSquare, colLoc, blue);
+ gl.polygonOffset(0, 10);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Polygon offset factor should have no effect when fill is off');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0, 0);
+ draw(gl, slantedSquare, colLoc, blue);
+ gl.polygonOffset(1.0, 0);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Zero polygon offset units and factor should have no effect');
+ clear(gl, red, 1.0);
+ gl.enable(gl.POLYGON_OFFSET_FILL);
+ gl.polygonOffset(0, 0);
+ draw(gl, slantedSquare, colLoc, blue);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ // It appears to be VERY common for drivers to implement the units offset in
+ // floating-point arithmetic, which results in rount-to-nearest-even to cause
+ // an offset of 1 to sometimes not alter the order between these polygons.
+ debug('Polygon offset units of 2 should alter order of flat polygons');
+ clear(gl, red, 1.0);
+ draw(gl, flatSquare, colLoc, green);
+ gl.polygonOffset(0, 2);
+ draw(gl, flatSquare, colLoc, blue);
+ check(gl);
+
+ debug('Polygon offset factor of 0.1 should alter order of slanted polygons');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0, 0);
+ draw(gl, slantedSquare, colLoc, green);
+ gl.polygonOffset(0.1, 0);
+ draw(gl, slantedSquare, colLoc, blue);
+ check(gl);
+
+ debug('Polygon offset factor of 0.1 should not alter order of flat polygons');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0, 0);
+ draw(gl, flatSquare, colLoc, blue);
+ gl.polygonOffset(0.1, 0);
+ draw(gl, flatSquare, colLoc, green);
+ check(gl);
+
+ debug('Disabling polygon offset fill should leave order unaffected');
+ clear(gl, red, 1.0);
+ gl.polygonOffset(0.1, 1);
+ gl.disable(gl.POLYGON_OFFSET_FILL);
+ draw(gl, slantedSquare, colLoc, blue);
+ draw(gl, slantedSquare, colLoc, green);
+ check(gl);
+
+ debug('Enabling polygon offset fill should affect order again');
+ clear(gl, red, 1.0);
+ draw(gl, slantedSquare, colLoc, green);
+ gl.enable(gl.POLYGON_OFFSET_FILL);
+ draw(gl, slantedSquare, colLoc, blue);
+ check(gl);
+}
+</script>
+</head>
+<body>
+<canvas id="testbed" width="16" height="16" style="width:50px; height:50px"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Verify that polygon offset 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/rendering/preservedrawingbuffer-leak.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/preservedrawingbuffer-leak.html
new file mode 100644
index 0000000000..2002db1836
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/preservedrawingbuffer-leak.html
@@ -0,0 +1,44 @@
+<!--
+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 PreserveDrawingBuffer Leak 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/iterable-test.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4096" height="4096" style="width: 128px; height: 128px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+enableJSTestPreVerboseLogging();
+description(document.title);
+debug('Regression test for <a href="https://code.google.com/p/chromium/issues/detail?id=682482">Chromium bug 682482</a>');
+
+var wtu = WebGLTestUtils;
+
+var gl = wtu.create3DContext("example", {preserveDrawingBuffer: true});
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var test = IterableTest.createPreserveDrawingBufferLeakTest(gl);
+ var iterations = parseInt(wtu.getUrlOptions().iterations, 10) || 50;
+ IterableTest.run(test, iterations);
+}
+
+var successfullyParsed = true;
+</script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html
new file mode 100644
index 0000000000..888ee99aec
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-sampling-feedback-loop.html
@@ -0,0 +1,183 @@
+<!--
+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 Rendering and Sampling Feedback Loop 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>
+<canvas id="example" width="8" height="8"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script id="vs100" type="x-shader/x-vertex">
+attribute vec4 aPosition;
+attribute vec2 aTexCoord;
+varying vec2 texCoord;
+void main() {
+ gl_Position = aPosition;
+ texCoord = aTexCoord;
+}
+</script>
+
+<script id="fs100" type="x-shader/x-fragment">
+#extension GL_EXT_draw_buffers : require
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main() {
+ gl_FragData[0] = texture2D(tex, texCoord);
+ gl_FragData[1] = texture2D(tex, texCoord);
+}
+</script>
+
+<script id="fs100-no-ext-draw-buffers" type="x-shader/x-fragment">
+precision mediump float;
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main() {
+ gl_FragData[0] = texture2D(tex, texCoord);
+}
+</script>
+
+<script id="vs300" type="x-shader/x-vertex">#version 300 es
+in highp vec4 aPosition;
+in vec2 aTexCoord;
+out vec2 texCoord;
+void main() {
+ gl_Position = aPosition;
+ texCoord = aTexCoord;
+}
+</script>
+
+<script id="fs300" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform sampler2D tex;
+in vec2 texCoord;
+out vec4 oColor;
+void main() {
+ oColor = texture(tex, texCoord);
+}
+</script>
+
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description("This test verifies the functionality of rendering to the same texture where it samples from.");
+
+const gl = wtu.create3DContext("example");
+
+const width = 8;
+const height = 8;
+let tex;
+let fbo;
+let drawBuffers = null;
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ if (gl.drawBuffers) {
+ debug("Using webgl2.drawBuffers.");
+ drawBuffers = (x) => gl.drawBuffers(x);
+ } else {
+ const ext = gl.getExtension("WEBGL_draw_buffers");
+ if (ext) {
+ debug("Using WEBGL_draw_buffers.drawBuffersWEBGL.");
+ drawBuffers = (x) => ext.drawBuffersWEBGL(x);
+ }
+ }
+
+ init();
+
+ // The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
+ allocate_resource();
+
+ rendering_sampling_feedback_loop(null);
+ if (drawBuffers) {
+ rendering_sampling_feedback_loop([gl.NONE]);
+ rendering_sampling_feedback_loop([gl.COLOR_ATTACHMENT0,
+ gl.COLOR_ATTACHMENT0+1]);
+ rendering_sampling_feedback_loop([gl.NONE,
+ gl.COLOR_ATTACHMENT0+1]);
+ }
+}
+
+function init() {
+ let shaders = ["vs100", "fs100"];
+ if (gl.texStorage2D) {
+ shaders = ["vs300", "fs300"];
+ } else if (!drawBuffers) {
+ shaders = ["vs100", "fs100-no-ext-draw-buffers"];
+ }
+ const program = wtu.setupProgram(gl, shaders, ["aPosition", "aTexCoord"], [0, 1]);
+ const positionLoc = gl.getAttribLocation(program, "aPosition");
+ const texCoordLoc = gl.getAttribLocation(program, "aTexCoord");
+ if (!program || positionLoc < 0 || texCoordLoc < 0) {
+ testFailed("Set up program failed");
+ return;
+ }
+ const texLoc = gl.getUniformLocation(program, "tex");
+ gl.uniform1i(texLoc, 0);
+ testPassed("Set up program succeeded");
+
+ wtu.setupUnitQuad(gl, 0, 1);
+ gl.viewport(0, 0, width, height);
+}
+
+function allocate_resource() {
+ tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ fbo = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
+}
+
+function rendering_sampling_feedback_loop(draw_buffers) {
+ debug("draw_buffers: " + JSON.stringify(draw_buffers));
+
+ if (draw_buffers) {
+ drawBuffers(draw_buffers);
+ }
+
+ // Make sure framebuffer is complete before feedback loop detection
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+ testFailed("Framebuffer incomplete.");
+ return;
+ }
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Feedback loop detection should ignore drawBuffers settings.");
+
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
+ // The texture will be mipmap incomplete, so feedback cannot occur nor be consistently evaluated.
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Feedback loop detection should ignore sampled incomplete textures.");
+
+ if (draw_buffers) {
+ drawBuffers([gl.COLOR_ATTACHMENT0]);
+ }
+}
+
+gl.deleteTexture(tex);
+gl.deleteFramebuffer(fbo);
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html
new file mode 100644
index 0000000000..1202106c13
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/rendering-stencil-large-viewport.html
@@ -0,0 +1,92 @@
+<!--
+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 Rendering Stencil large viewport 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>
+
+<script id="vs" type="x-shader/x-vertex">
+attribute vec4 a_Position;
+void main()
+{
+ gl_Position = a_Position;
+}
+</script>
+<script id="fs" type="x-shader/x-fragment">
+precision mediump float;
+uniform vec4 u_draw_color;
+void main()
+{
+ gl_FragColor = u_draw_color;
+}
+</script>
+
+</head>
+<body>
+<canvas id="example" width="4" height="4"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+"use strict";
+
+var wtu = WebGLTestUtils;
+description("This test reproduces a driver bug on Intel windows platforms http://crbug.com/782317.");
+
+var gl = wtu.create3DContext("example", {stencil: true});
+
+var program, colorLoc;
+
+// Rendering with large viewport and stencil buffer enabled will lead to
+// memory leak and driver crash on d3d11 driver on Intel platforms.
+function render_stencil() {
+ var canvas = document.getElementById("example");
+ gl.uniform4f(colorLoc, 1.0, 0.0, 0.0, 1.0);
+
+ canvas.width = 32767;
+ canvas.height = 32767;
+ gl.viewport(0, 0, 32767, 32767);
+
+ gl.enable(gl.STENCIL_TEST);
+
+ var kStencilRef = 4;
+ gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
+ gl.stencilFunc(gl.ALWAYS, kStencilRef, 0xFF);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR);
+ wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 0, 255],
+ "stencil test should be red");
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+
+ program = wtu.setupProgram(gl, ["vs", "fs"], ["a_Position"]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after program initialization");
+ shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
+
+ colorLoc = gl.getUniformLocation(program, "u_draw_color")
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "query uniform location");
+ shouldBeNonNull('colorLoc');
+ wtu.setupUnitQuad(gl, 0);
+
+ render_stencil();
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html
new file mode 100644
index 0000000000..f76da1614a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/scissor-rect-repeated-rendering.html
@@ -0,0 +1,63 @@
+<!--
+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>Scissor Rectangle Repeated Rendering 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="128" height="128"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+description();
+debug('Regression test for <a href="https://code.google.com/p/chromium/issues/detail?id=778770">Chromium bug 778770</a>');
+
+var wtu = WebGLTestUtils;
+
+// These context creation attributes are significant to reproduce the bug.
+var gl = wtu.create3DContext("example", {alpha: false, antialias: false});
+
+// Draw into the upper right quadrant.
+var x = 64;
+var y = 64;
+var width = 64;
+var height = 64;
+
+var numRenders = 10;
+
+function render() {
+ gl.viewport(x, y, width, height);
+ gl.scissor(x, y, width, height);
+ gl.enable(gl.SCISSOR_TEST);
+ gl.clearColor(0.0, 1.0, 0.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // If anything but black is ever seen in the un-drawn region of
+ // the canvas, the test fails.
+ var black = [0, 0, 0, 255];
+ wtu.checkCanvasRect(gl, 10, 10, 10, 10, black, "should be black", 1);
+
+ if (--numRenders > 0) {
+ window.requestAnimationFrame(render);
+ } else {
+ finishTest();
+ }
+}
+
+window.requestAnimationFrame(render);
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html
new file mode 100644
index 0000000000..c01d213577
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/simple.html
@@ -0,0 +1,77 @@
+<!--
+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>Simple Rendering 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 a_Position;
+void main()
+{
+ gl_Position = a_Position;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main()
+{
+ gl_FragColor = vec4(0,1,0,1);
+}
+</script>
+<script>
+"use strict";
+var wtu = WebGLTestUtils;
+function init()
+{
+ description();
+
+ var gl = wtu.create3DContext("example");
+ var program = wtu.loadProgramFromScript(gl, "vshader", "fshader");
+ gl.useProgram(program);
+ var loc = gl.getAttribLocation(program, "a_Position");
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array(
+ [ 1, 1,
+ -1, 1,
+ -1, -1,
+ 1, 1,
+ -1, -1,
+ 1, -1]),
+ gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(loc);
+ gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ wtu.checkCanvas(gl, [0,0,0,0], "should be black", 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ wtu.checkCanvas(gl, [0,255,0,255], "should be green", 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+}
+
+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/rendering/texture-switch-performance.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/texture-switch-performance.html
new file mode 100644
index 0000000000..bdc9099a6b
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/texture-switch-performance.html
@@ -0,0 +1,101 @@
+<!--
+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 Texture Switch 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>
+<script>
+"use strict";
+description("Ensures that switching the texture referenced by a sampler uniform performs reasonably well.");
+var wtu = WebGLTestUtils;
+var canvas = document.createElement('canvas');
+canvas.width = 32;
+canvas.height = 32;
+var gl = wtu.create3DContext(canvas);
+if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+} else {
+ var program = wtu.setupTexturedQuad(gl);
+ var tex = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var tex2 = gl.createTexture();
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+ var loc = gl.getUniformLocation(program, "tex");
+
+ var RUNTIME = 2000;
+ var THRESHOLD = 0.8;
+ var baseStartTime = 0;
+ var baseFrameCount = 0;
+ var testStartTime = 0;
+ var testFrameCount = 0;
+
+ baseStartTime = Date.now();
+ function drawBaseline() {
+ for (var i = 0; i < 400; ++i) {
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ ++baseFrameCount;
+
+ if (Date.now() - baseStartTime > RUNTIME) {
+ testStartTime = Date.now();
+ requestAnimationFrame(drawTest);
+ } else {
+ requestAnimationFrame(drawBaseline);
+ }
+ }
+
+ function drawTest() {
+ for (var i = 0; i < 400; ++i) {
+ gl.uniform1i(loc, 0);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ gl.uniform1i(loc, 1);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ }
+
+ ++testFrameCount;
+
+ if (Date.now() - testStartTime > RUNTIME) {
+ var perfString = " - achieved " + testFrameCount + " frames in " + ((Date.now() - testStartTime) / 1000.0) +
+ " seconds (" + (testFrameCount / baseFrameCount).toFixed(2) + " times baseline performance)";
+ if (testFrameCount > baseFrameCount * THRESHOLD) {
+ testPassed("Texture switching did not significantly hurt performance" + perfString);
+ } else {
+ testFailed("Texture switching significantly hurt performance" + perfString);
+ }
+ console.log(testFrameCount);
+ finishTest();
+ } else {
+ requestAnimationFrame(drawTest);
+ }
+ }
+
+ requestAnimationFrame(drawBaseline);
+}
+var successfullyParsed = true;
+</script>
+</body>
+</html>
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html
new file mode 100644
index 0000000000..98a04c9050
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/triangle.html
@@ -0,0 +1,73 @@
+<!--
+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>Rendering 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">
+void main()
+{
+ gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+"use strict";
+function init()
+{
+ description(document.title);
+
+ var wtu = WebGLTestUtils;
+ var gl = wtu.create3DContext("example");
+ var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+ // Test several locations
+ // First line should be all black
+ wtu.checkCanvasRect(gl, 0, 0, 50, 1, [0, 0, 0, 0]);
+
+ // Line 15 should be red for at least 10 red pixels starting 20 pixels in
+ wtu.checkCanvasRect(gl, 20, 15, 10, 1, [255, 0, 0, 255]);
+
+ // Last line should be all black
+ wtu.checkCanvasRect(gl, 0, 49, 50, 1, [0, 0, 0, 0]);
+}
+
+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/rendering/vertex-texture-fetch.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/vertex-texture-fetch.html
new file mode 100644
index 0000000000..7b014e1d66
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/vertex-texture-fetch.html
@@ -0,0 +1,91 @@
+<!--
+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 Texture Fetch.</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="1" height="1" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vs" type="text/something-not-javascript">
+attribute vec4 a_position;
+attribute vec2 a_texCoord;
+uniform sampler2D u_texture;
+varying vec4 color;
+void main() {
+ gl_Position = a_position;
+ color = texture2D(u_texture, a_texCoord);
+}
+</script>
+<script id="fs" type="text/something-not-javascript">
+precision mediump float;
+varying vec4 color;
+void main() {
+ gl_FragColor = color;
+}
+</script>
+<script>
+"use strict";
+description("checks that vertex texture fetch, if supported, operates correctly.");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example");
+if (!gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS)) {
+ testPassed("No vertex texture image units (vertex texture fetch not supported) -- this is legal");
+} else {
+ var texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE,
+ new Uint8Array([
+ 255, 0, 0, 255,
+ 0, 255, 0, 255,
+ 0, 0, 255, 255,
+ 255, 255, 0, 255]));
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");
+
+ var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vTexCoord"]);
+ gl.uniform1i(gl.getUniformLocation(program, "u_texture"), 0);
+ gl.disable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initWebGL");
+ var bufferObjects = wtu.setupUnitQuad(gl, 0);
+ gl.disableVertexAttribArray(1);
+
+ gl.vertexAttrib2f(1, 0, 0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red.");
+
+ gl.vertexAttrib2f(1, 1, 0);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "Should be green.");
+
+ gl.vertexAttrib2f(1, 0, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [0, 0, 255, 255], "Should be blue.");
+
+ gl.vertexAttrib2f(1, 1, 1);
+ wtu.clearAndDrawUnitQuad(gl);
+ wtu.checkCanvas(gl, [255, 255, 0, 255], "Should be yellow.");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
+}
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>