diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance/rendering')
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> |