diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/misc')
9 files changed, 1648 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/00_test_list.txt new file mode 100644 index 0000000000..8f1343f91d --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/00_test_list.txt @@ -0,0 +1,8 @@ +--min-version 2.0.1 blend-integer.html +expando-loss-2.html +getextension-while-pbo-bound-stability.html +instanceof-test.html +--min-version 2.0.1 null-object-behaviour-2.html +object-deletion-behaviour-2.html +uninitialized-test-2.html +views-with-offsets.html diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/blend-integer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/blend-integer.html new file mode 100644 index 0000000000..40ccfd0d86 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/blend-integer.html @@ -0,0 +1,176 @@ +<!-- +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 2 Blend Integer 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 id="outputVertexShader" type="x-shader/x-vertex"> +#version 300 es +in vec4 vPosition; +void main() +{ + gl_Position = vPosition; +} +</script> +<script id="outputFragmentShaderSigned" type="x-shader/x-fragment"> +#version 300 es +layout(location = 1) out highp vec4 o_drawBuffer1; +layout(location = 2) out highp ivec4 o_drawBuffer2; +layout(location = 3) out highp vec4 o_drawBuffer3; +void main(void) +{ + o_drawBuffer1 = vec4(0, 0, 0, 0); + o_drawBuffer2 = ivec4(0, 0, 0, 0); + o_drawBuffer3 = vec4(0, 0, 0, 0); +} +</script> +<script id="outputFragmentShaderUnsigned" type="x-shader/x-fragment"> + #version 300 es + layout(location = 1) out highp vec4 o_drawBuffer1; + layout(location = 2) out highp uvec4 o_drawBuffer2; + layout(location = 3) out highp vec4 o_drawBuffer3; + void main(void) + { + o_drawBuffer1 = vec4(0, 0, 0, 0); + o_drawBuffer2 = uvec4(0, 0, 0, 0); + o_drawBuffer3 = vec4(0, 0, 0, 0); + } + </script> + +<script> +"use strict"; +description("This test verifies correct behavior of min/max blending operations on integer attachments."); + +debug(""); + +const wtu = WebGLTestUtils; +const gl = wtu.create3DContext(null, undefined, 2); + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + debug("") + debug("GL_MIN"); + runTest(false, gl.MIN); + runTest(true, gl.MIN); + + debug("") + debug("GL_MAX"); + runTest(false, gl.MAX); + runTest(true, gl.MAX); +} + +function compareValue(value, attachment, isSigned) { + const pixel = isSigned ? new Int32Array(4) : new Uint32Array(4); + gl.readBuffer(attachment); + gl.readPixels(0, 0, 1, 1, gl.RGBA_INTEGER, isSigned ? gl.INT : gl.UNSIGNED_INT, pixel); + let pass = true; + for (let i = 0; i < 4; i++) { + if (value[i] != pixel[i]) { + testFailed(`Read value of channel ${i} should be ${pixel[i]}, was ${value[i]}.`); + pass = false; + } + } + return pass; +} + +function runTest(isSigned, operation) { + gl.viewport(0, 0, 1, 1); + gl.disable(gl.BLEND); + + const program = wtu.setupProgram(gl, + ["outputVertexShader", + isSigned ? "outputFragmentShaderSigned" : "outputFragmentShaderUnsigned"], + ['vPosition'], [0]); + const quadParameters = wtu.setupUnitQuad(gl, 0, 1); + + // Setup render targets + const fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + const rb1 = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, rb1); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 50, 50); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, rb1); + + const rb2 = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, rb2); + gl.renderbufferStorage(gl.RENDERBUFFER, isSigned ? gl.RGBA32I : gl.RGBA32UI, 50, 50); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.RENDERBUFFER, rb2); + + const rb3 = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, rb3); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 50, 50); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT3, gl.RENDERBUFFER, rb3); + + gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3]); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Pipeline setup complete."); + + if (isSigned) { + const clearValue = new Int32Array([-1, 2, -3, 4]); + gl.clearBufferiv(gl.COLOR, 2, clearValue); + if (compareValue(clearValue, gl.COLOR_ATTACHMENT2, isSigned)) { + testPassed("Signed clear passed."); + } else { + testFailed("Signed clear failed."); + } + } else { + const clearValue = new Uint32Array([1, 2, 3, 4]); + gl.clearBufferuiv(gl.COLOR, 2, clearValue); + if (compareValue(clearValue, gl.COLOR_ATTACHMENT2, isSigned)) { + testPassed("Unsigned clear passed."); + } else { + testFailed("Unsigned clear failed."); + } + } + + gl.blendEquation(operation); + gl.enable(gl.BLEND); + + wtu.drawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Draw complete."); + + if (isSigned) { + const drawValue = new Int32Array([0, 0, 0, 0]); + if (compareValue(drawValue, gl.COLOR_ATTACHMENT2, isSigned)) { + testPassed("Signed draw passed."); + } else { + testFailed("Signed draw failed."); + } + } else { + const drawValue = new Uint32Array([0, 0, 0, 0]); + if (compareValue(drawValue, gl.COLOR_ATTACHMENT2, isSigned)) { + testPassed("Unsigned draw passed."); + } else { + testFailed("Unsigned draw failed."); + } + } + gl.deleteRenderbuffer(rb1); + gl.deleteRenderbuffer(rb2); + gl.deleteRenderbuffer(rb3); + gl.deleteFramebuffer(fb); + gl.deleteProgram(program); +} + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/expando-loss-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/expando-loss-2.html new file mode 100644 index 0000000000..141a5377a8 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/expando-loss-2.html @@ -0,0 +1,285 @@ +<!-- +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 2 Object Expandos Conformance Test</title> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> +<script> +"use strict"; +description("This test verifies that WebGL object expandos are preserved across garbage collections."); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, {antialias: false}, 2); + +// Helpers that set expandos and verify they are set to the correct value. +var expandoValue = "WebGL is awesome!" +function setTestExpandos(instance, extra) { + instance.expando1 = expandoValue; + instance.expando2 = { subvalue : expandoValue }; + instance.expando_extra = extra; +} +function verifyTestExpandos(instance, msg, extra) { + assertMsg(instance.expando1 === expandoValue, msg + ": Expect basic expando to survive despite GC."); + assertMsg(instance.expando2 && instance.expando2.subvalue === expandoValue, msg + ": Expect subobject expando to survive despite GC."); + assertMsg(instance.expando_extra === extra, msg + ": Expect extra expando to survive despite GC."); +} + +// Tests that we don't get expando loss for bound resources where the +// only remaining reference is internal to WebGL +function testBasicBindings() { + debug('Basic Bindings'); + + // Test data that describes how to create, bind, and retrieve an object off of the context + var glProt = Object.getPrototypeOf(gl); + var simpleData = [ + { + typeName: 'WebGLSampler', + creationFn: glProt.createSampler, + bindFn: glProt.bindSampler, + bindConstant: 0, + retrieveConstant: glProt.SAMPLER_BINDING, + name: "SAMPLER_BINDING", + }, + { + typeName: 'WebGLTransformFeedback', + creationFn: glProt.createTransformFeedback, + bindFn: glProt.bindTransformFeedback, + bindConstant: glProt.TRANSFORM_FEEDBACK, + retrieveConstant: glProt.TRANSFORM_FEEDBACK_BINDING, + name: "TRANSFORM_FEEDBACK_BINDING", + }, + { + typeName: 'WebGLVertexArrayObject', + creationFn: glProt.createVertexArray, + bindFn: glProt.bindVertexArray, + bindConstant: null, + retrieveConstant: glProt.VERTEX_ARRAY_BINDING, + name: "VERTEX_ARRAY_BINDING", + }, + { + typeName: 'WebGLTexture', + creationFn: glProt.createTexture, + bindFn: glProt.bindTexture, + bindConstant: glProt.TEXTURE_3D, + retrieveConstant: glProt.TEXTURE_BINDING_3D, + name: "TEXTURE_BINDING_3D", + }, + { + typeName: 'WebGLTexture', + creationFn: glProt.createTexture, + bindFn: glProt.bindTexture, + bindConstant: glProt.TEXTURE_2D_ARRAY, + retrieveConstant: glProt.TEXTURE_BINDING_2D_ARRAY, + name: "TEXTURE_BINDING_2D_ARRAY", + }, + { + typeName: 'WebGLFramebuffer', + creationFn: glProt.createFramebuffer, + bindFn: glProt.bindFramebuffer, + bindConstant: glProt.READ_FRAMEBUFFER, + retrieveConstant: glProt.READ_FRAMEBUFFER_BINDING, + name: "READ_FRAMEBUFFER_BINDING", + }, + { + typeName: 'WebGLFramebuffer', + creationFn: glProt.createFramebuffer, + bindFn: glProt.bindFramebuffer, + bindConstant: glProt.DRAW_FRAMEBUFFER, + retrieveConstant: glProt.DRAW_FRAMEBUFFER_BINDING, + name: "DRAW_FRAMEBUFFER_BINDING", + }, + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBuffer, + bindConstant: glProt.COPY_READ_BUFFER, + retrieveConstant: glProt.COPY_READ_BUFFER_BINDING, + name: "COPY_READ_BUFFER_BINDING", + }, + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBuffer, + bindConstant: glProt.COPY_WRITE_BUFFER, + retrieveConstant: glProt.COPY_WRITE_BUFFER_BINDING, + name: "COPY_WRITE_BUFFER_BINDING", + }, + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBuffer, + bindConstant: glProt.PIXEL_PACK_BUFFER, + retrieveConstant: glProt.PIXEL_PACK_BUFFER_BINDING, + name: "PIXEL_PACK_BUFFER_BINDING", + }, + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBuffer, + bindConstant: glProt.PIXEL_UNPACK_BUFFER, + retrieveConstant: glProt.PIXEL_UNPACK_BUFFER_BINDING, + name: "PIXEL_UNPACK_BUFFER_BINDING", + }, + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBuffer, + bindConstant: glProt.TRANSFORM_FEEDBACK_BUFFER, + retrieveConstant: glProt.TRANSFORM_FEEDBACK_BUFFER_BINDING, + name: "TRANSFORM_FEEDBACK_BUFFER_BINDING", + }, + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBuffer, + bindConstant: glProt.UNIFORM_BUFFER, + retrieveConstant: glProt.UNIFORM_BUFFER_BINDING, + name: "UNIFORM_BUFFER_BINDING", + }, + ]; + + simpleData.forEach(function(test) { + var instance = test.creationFn.call(gl); + var msg = "getParameter(" + test.name + ")"; + setTestExpandos(instance); + + if (test.bindConstant === null) { + test.bindFn.call(gl, instance); + } else { + test.bindFn.call(gl, test.bindConstant, instance); + } + assertMsg(instance === gl.getParameter(test.retrieveConstant), msg + " returns instance that was bound."); + + // Garbage collect Javascript references. Remaining references should be internal to WebGL. + instance = null; + webglHarnessCollectGarbage(); + + var retrievedObject = gl.getParameter(test.retrieveConstant); + verifyTestExpandos(retrievedObject, msg); + shouldBeType(retrievedObject, test.typeName); + debug(''); + }); +} + +function testIndexedBindings() { + debug('Indexed Bindings'); + + // Test data that describes how to create, bind, and retrieve an indexed object off of the context + var glProt = Object.getPrototypeOf(gl); + var simpleData = [ + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBufferBase, + indexMax: gl.getParameter(glProt.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS) - 1, + bindConstant: glProt.TRANSFORM_FEEDBACK_BUFFER, + retrieveConstant: glProt.TRANSFORM_FEEDBACK_BUFFER_BINDING, + name: "TRANSFORM_FEEDBACK_BUFFER_BINDING", + }, + { + typeName: 'WebGLBuffer', + creationFn: glProt.createBuffer, + bindFn: glProt.bindBufferBase, + indexMax: gl.getParameter(glProt.MAX_UNIFORM_BUFFER_BINDINGS) - 1, + bindConstant: glProt.UNIFORM_BUFFER, + retrieveConstant: glProt.UNIFORM_BUFFER_BINDING, + name: "UNIFORM_BUFFER_BINDING", + }, + ]; + + simpleData.forEach(function(test) { + // This test sets all of the separate indexed bindings first, then + // tests them all. It puts a different extra expando on each indexed + // parameter so that we can ensure they're all distinct. + var instances = []; + for (var i = 0; i <= test.indexMax; i++) { + var instance = test.creationFn.call(gl); + var msg = "getIndexedParameter(" + test.name + ", " + i + ")"; + setTestExpandos(instance, i); + instances[i] = instance; + test.bindFn.call(gl, test.bindConstant, i, instance); + } + + for (var i = 0; i <= test.indexMax; i++) { + var msg = "getIndexedParameter(" + test.name + ", " + i + ")"; + assertMsg(instances[i] === gl.getIndexedParameter(test.retrieveConstant, i), msg + " returns instance that was bound."); + } + + // Garbage collect Javascript references. Remaining references should be internal to WebGL. + instances = null; + webglHarnessCollectGarbage(); + + for (var i = 0; i <= test.indexMax; i++) { + var msg = "getIndexedParameter(" + test.name + ", " + i + ")"; + var retrievedObject = gl.getIndexedParameter(test.retrieveConstant, i); + verifyTestExpandos(retrievedObject, msg, i); + shouldBeType(retrievedObject, test.typeName); + debug(''); + } + }); +} + +function testQueries() { + debug('Query'); + + expandoValue = "First query"; + var query1 = gl.createQuery(); + setTestExpandos(query1); + gl.beginQuery(gl.ANY_SAMPLES_PASSED, query1); + + expandoValue = "Second query"; + var query2 = gl.createQuery(); + setTestExpandos(query2); + gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query2); + + + assertMsg(query1 === gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY), "CURRENT_QUERY returns instance that was bound."); + assertMsg(query2 === gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY), "CURRENT_QUERY returns instance that was bound."); + + // Garbage collect Javascript references. Remaining references should be internal to WebGL. + query1 = null; + query2 = null; + webglHarnessCollectGarbage(); + + var retrievedQuery1 = gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY); + var retrievedQuery2 = gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY); + expandoValue = "First query"; + verifyTestExpandos(retrievedQuery1, "Query"); + shouldBeType(retrievedQuery1, 'WebGLQuery'); + + expandoValue = "Second query"; + verifyTestExpandos(retrievedQuery2, "Query"); + shouldBeType(retrievedQuery2, 'WebGLQuery'); + + gl.endQuery(gl.ANY_SAMPLES_PASSED); + gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + + debug(''); +} + +// Run tests +testBasicBindings(); +testIndexedBindings(); +testQueries(); + +// FYI: There's no need to test WebGLSync objects because there is no notion of an "active" sync, +// and thus no way to query them back out of the context. + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/getextension-while-pbo-bound-stability.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/getextension-while-pbo-bound-stability.html new file mode 100644 index 0000000000..73e34fdc1d --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/getextension-while-pbo-bound-stability.html @@ -0,0 +1,57 @@ +<!-- +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>WebGL2 getExtension while PBO bound stability 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> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +var wtu = WebGLTestUtils; + +function runTest(extension_name) { + debug(""); + debug("getExtension('" + extension_name + "') while PIXEL_UNPACK_BUFFER bound should be stable"); + + var gl = wtu.create3DContext(null, undefined, 2); + if (!gl) { + testFailed("Fail to get a WebGL context"); + return; + } + + var pbo = gl.createBuffer(); + gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pbo); + var ext = gl.getExtension('EXT_color_buffer_float'); + var gl_texture_float_linear = gl.getExtension(extension_name); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Late-enable of extension should succeed"); + if (pbo != gl.getParameter(gl.PIXEL_UNPACK_BUFFER_BINDING)) { + testFailed("Fail to maintain PIXEL_UNPACK_BUFFER binding when enabling extension " + extension_name); + } +} + +function runTests() { + debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=641643'>Chromium Issue 641642</a>"); + runTest('EXT_color_buffer_float'); + runTest('OES_texture_float_linear'); +} + +runTests(); + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/instanceof-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/instanceof-test.html new file mode 100644 index 0000000000..4ecbd6e2d3 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/instanceof-test.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 instanceof 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="2" height="2" style="width: 40px; height: 40px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> +attribute vec4 vPosition; +varying vec2 texCoord; +void main() +{ + gl_Position = vPosition; +} +</script> +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; +uniform vec4 color; +void main() +{ + gl_FragColor = color; +} +</script> + +<script> +var contextVersion = 2; +</script> +<script src="../../js/tests/instanceof-test.js"></script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/null-object-behaviour-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/null-object-behaviour-2.html new file mode 100644 index 0000000000..1a65dc57bd --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/null-object-behaviour-2.html @@ -0,0 +1,61 @@ +<!-- +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> +<div id="description"></div> +<div id="console"></div> + +<script> +"use strict"; +var wtu = WebGLTestUtils; +description("Tests calling WebGL 2 APIs without providing the necessary objects"); + +var gl = wtu.create3DContext(undefined, undefined, 2); +var shouldGenerateGLError = wtu.shouldGenerateGLError; + + +for (let nullOrUndefined of [null, undefined]) { + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteQuery(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isQuery(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteSync(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isSync(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteTransformFeedback(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isTransformFeedback(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteSampler(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isSampler(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteVertexArray(${nullOrUndefined})`); + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isVertexArray(${nullOrUndefined})`); + + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindSampler(0, ${nullOrUndefined})`); + shouldThrow(`gl.samplerParameteri(${nullOrUndefined}, gl.TEXTURE_MAG_FILTER, gl.NEAREST)`); + shouldThrow(`gl.samplerParameterf(${nullOrUndefined}, gl.TEXTURE_MAX_LOD, 1)`); + shouldThrow(`gl.getSamplerParameter(${nullOrUndefined}, gl.TEXTURE_MAX_LOD)`); + + shouldThrow(`gl.waitSync(${nullOrUndefined}, 0, 0)`); + shouldThrow(`gl.clientWaitSync(${nullOrUndefined}, 0, 0)`); + shouldThrow(`gl.getSyncParameter(${nullOrUndefined}, gl.OBJECT_TYPE)`); + + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, ${nullOrUndefined})`); + shouldThrow(`gl.transformFeedbackVaryings(${nullOrUndefined}, [], gl.SEPARATE_ATTRIBS)`); + + shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindVertexArray(${nullOrUndefined})`); +} + + +var successfullyParsed = true; +</script> + +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/object-deletion-behaviour-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/object-deletion-behaviour-2.html new file mode 100644 index 0000000000..0551a1bd97 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/object-deletion-behaviour-2.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. +--> + +<!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> +<div id="description"></div> +<div id="console"></div> + +<script> +"use strict"; +description("Tests deletion behavior for WebGL2 buffer, sampler, vertexArray and transformFeedback objects."); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext(undefined, undefined, 2); +var shouldGenerateGLError = wtu.shouldGenerateGLError; + +debug(""); +debug("buffer deletion"); + +var bufferBaseUniform = gl.createBuffer(); +shouldBeNonNull("bufferBaseUniform"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, bufferBaseUniform)"); +shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "bufferBaseUniform"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferBaseUniform)"); +shouldBeFalse("gl.isBuffer(bufferBaseUniform)"); +shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); +shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, bufferBaseUniform)"); +shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); + +var bufferBaseTransformFeedback = gl.createBuffer(); +shouldBeNonNull("bufferBaseTransformFeedback"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferBaseTransformFeedback)"); +shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "bufferBaseTransformFeedback"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferBaseTransformFeedback)"); +shouldBeFalse("gl.isBuffer(bufferBaseTransformFeedback)"); +shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)"); +shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferBaseTransformFeedback)"); +shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)"); + +var bufferRangeUniform = gl.createBuffer(); +shouldBeNonNull("bufferRangeUniform"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, bufferRangeUniform, 0, gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT)"); +shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "bufferRangeUniform"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferRangeUniform)"); +shouldBeFalse("gl.isBuffer(bufferRangeUniform)"); +shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); +shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, bufferRangeUniform, 0, gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT)"); +shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); + +var bufferRangeTransformFeedback = gl.createBuffer(); +shouldBeNonNull("bufferRangeTransformFeedback"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferRangeTransformFeedback, 0, 4)"); +shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "bufferRangeTransformFeedback"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferRangeTransformFeedback)"); +shouldBeFalse("gl.isBuffer(bufferRangeTransformFeedback)"); +shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)"); +shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, bufferRangeTransformFeedback, 0, 4)"); +shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)"); + +debug(""); +debug("sampler deletion"); + +var sampler = gl.createSampler(); +shouldBeNonNull("sampler"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindSampler(0, sampler)"); +shouldBe("gl.getParameter(gl.SAMPLER_BINDING)", "sampler"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteSampler(sampler)"); +shouldBeFalse("gl.isSampler(sampler)"); +shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)"); +shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindSampler(0, sampler)"); +shouldBeNull("gl.getParameter(gl.SAMPLER_BINDING)"); + +debug(""); +debug("vertexArray deletion"); + +var vertexArray = gl.createVertexArray(); +shouldBeNonNull("vertexArray"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindVertexArray(vertexArray)"); +shouldBe("gl.getParameter(gl.VERTEX_ARRAY_BINDING)", "vertexArray"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteVertexArray(vertexArray)"); +shouldBeFalse("gl.isVertexArray(vertexArray)"); +shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)"); +shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindVertexArray(vertexArray)"); +shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)"); + +debug(""); +debug("transformFeedback deletion"); + +var transformFeedback = gl.createTransformFeedback(); +shouldBeNonNull("transformFeedback"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback)"); +shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "transformFeedback"); +shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTransformFeedback(transformFeedback)"); +shouldBeFalse("gl.isTransformFeedback(transformFeedback)"); +shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)"); +shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback)"); +shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)"); + +var successfullyParsed = true; +</script> + +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html new file mode 100644 index 0000000000..4befe35c93 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html @@ -0,0 +1,583 @@ +<!-- +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 2 Uninitialized GL Resources Tests</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="2" height="2"> </canvas> +<script> +"use strict"; +description("Tests to check user code cannot access uninitialized data from GL resources."); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("canvas", undefined, 2); +if (!gl) + testFailed("Context created."); +else + testPassed("Context created."); + +// This is the maximum size that will end up being allocated with the tests +// currently written as they are. It could need to be increased later. +var scratchBuffer = new ArrayBuffer(1024 * 1024 * 8 * 4); +function zeroArrayBuffer(arr) { + for (var i = 0; i < arr.length; ++i) { + arr[i] = 0; + } +} +function getUint32Array(length) { + var arr = new Uint32Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} +function getInt32Array(length) { + var arr = new Int32Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} +function getUint8Array(length) { + var arr = new Uint8Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} +function getInt8Array(length) { + var arr = new Int8Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} + +function setupTexture(target, texWidth, texHeight, texDepth) { + var is3d = (target == gl.TEXTURE_3D || target == gl.TEXTURE_2D_ARRAY); + var texture = gl.createTexture(); + gl.bindTexture(target, texture); + if (is3d) { + gl.texImage3D(target, 0, gl.RGBA8, texWidth, texHeight, texDepth, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } else if (target == gl.TEXTURE_2D) { + gl.texImage2D(target, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } else { + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } + + // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits + // into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem) + // with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time. + + var badData = getUint8Array(texWidth * texHeight * texDepth * 4); + for (var i = 0; i < badData.length; ++i) + badData[i] = i % 255; + + if (is3d) { + gl.texSubImage3D(target, 0, 0, 0, 0, texWidth, texHeight, texDepth, gl.RGBA, gl.UNSIGNED_BYTE, badData); + } else if (target == gl.TEXTURE_2D) { + gl.texSubImage2D(target, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + } else { + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + } + gl.finish(); // make sure it has been uploaded + + gl.deleteTexture(texture); + gl.finish(); // make sure it has been deleted + + var texture = gl.createTexture(); + gl.bindTexture(target, texture); + return texture; +} + +function checkNonZeroPixels(texture, target, format, type, texWidth, texHeight, level, layer, exceptions) { + var tol = 2; + var is3d = (target == gl.TEXTURE_3D || target == gl.TEXTURE_2D_ARRAY); + switch (target) { + case gl.TEXTURE_CUBE_MAP_POSITIVE_X: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_X: + case gl.TEXTURE_CUBE_MAP_POSITIVE_Y: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: + case gl.TEXTURE_CUBE_MAP_POSITIVE_Z: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: + gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); + break; + default: + gl.bindTexture(target, null); + break; + } + var fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + if (is3d) { + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, level, layer); + } else { + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, texture, level); + } + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); + + var data; + switch (type) { + case gl.UNSIGNED_INT: + data = getUint32Array(texWidth * texHeight * 4); + break; + case gl.INT: + data = getInt32Array(texWidth * texHeight * 4); + break; + case gl.UNSIGNED_BYTE: + default: + data = getUint8Array(texWidth * texHeight * 4); + break; + } + gl.readPixels(0, 0, texWidth, texHeight, format, type, data); + + var k = 0; + var failed_exceptions = 0; + for (var y = 0; y < texHeight; ++y) { + for (var x = 0; x < texWidth; ++x) { + var index = (y * texWidth + x) * 4; + var is_exception = false; + for (var ii = 0; ii < exceptions.length; ++ii) { + if (exceptions[ii].x == x && exceptions[ii].y == y) { + is_exception = true; + if (Math.abs(data[index] - exceptions[ii].r) > tol || + Math.abs(data[index + 1] - exceptions[ii].g) > tol || + Math.abs(data[index + 2] - exceptions[ii].b) > tol || + Math.abs(data[index + 3] - exceptions[ii].a) > tol) { + failed_exceptions++; + } + } + } + if (is_exception) + continue; + for (var i = 0; i < 4; ++i) { + if (data[index + i] != 0) { + k++; + } + } + } + } + var info = "Level = " + level; + if (is3d) + info += ", layer = " + layer; + info += " : "; + if (k) { + testFailed(info + "found " + k + " non-zero elements"); + } else { + testPassed(info + "all data initialized"); + } + if (exceptions.length > 0) { + if (failed_exceptions) { + testFailed(info + "found " + failed_exceptions + " elements incorrectly overwritten"); + } else { + testPassed(info + "all initialized elements stay untouched"); + } + } +} + +function testTexImage3D() { + + var max_3d_texture_size = Math.min(gl.getParameter(gl.MAX_3D_TEXTURE_SIZE), 1024); + + var test_cases = [ + // TEXTURE_3D + RGBA8 + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [ { x: 0, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [ { x: 0, y: 128, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [], + }, + + // TEXTURE_3D + RGBA8UI + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [ { x: 0, y: 255, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [ { x: 128, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [], + }, + + // TEXTURE_3D + RGBA8I + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [ { x: 128, y: 255, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [ { x: 128, y: 128, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [], + }, + + // TEXTURE_2D_ARRAY + RGBA8 + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 1024, + height: 1024, + depth: 8, + exceptions: [ { x: 1023, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 1024, + height: 1024, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [ { x: 63, y: 32, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [], + }, + + // TEXTURE_2D_ARRAY + RGBA8UI + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [ { x: 1023, y: 1023, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [ { x: 0, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [], + }, + + // TEXTURE_2D_ARRAY + RGBA8I + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [ { x: 512, y: 1023, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [ { x: 63, y: 32, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [], + }, + + // If more tests are added here, make sure to increase the size of + // scratchBuffer above, if needed. + ]; + + for (var ii = 0; ii < test_cases.length; ++ii) { + debug(""); + var test = test_cases[ii]; + debug("TexImage3D with target = " + test.target + ", internal_format = " + test.internal_format + + ", width = " + test.width + ", height = " + test.height + ", depth = " + test.depth); + var tex = setupTexture(gl[test.target], test.width, test.height, test.depth); + gl.texImage3D(gl[test.target], 0, gl[test.internal_format], test.width, test.height, test.depth, 0, test.format, test.type, null); + for (var jj = 0; jj < test.exceptions.length; ++jj) { + var exception = test.exceptions[jj]; + var data; + switch (test.type) { + case gl.BYTE: + data = getInt8Array(4 * test.depth); + break; + case gl.UNSIGNED_BYTE: + data = getUint8Array(4 * test.depth); + break; + default: + assert(false); + } + for (var pixel = 0; pixel < test.depth; ++pixel) { + data[pixel * 4] = exception.r; + data[pixel * 4 + 1] = exception.g; + data[pixel * 4 + 2] = exception.b; + data[pixel * 4 + 3] = exception.a; + } + gl.texSubImage3D(gl[test.target], 0, exception.x, exception.y, 0, 1, 1, test.depth, test.format, test.type, data); + } + for (var layer = 0; layer < test.depth; ++layer) + checkNonZeroPixels(tex, gl[test.target], test.format, test.read_type, test.width, test.height, 0, layer, test.exceptions); + gl.deleteTexture(tex); + gl.finish(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + } +} + +function testTexStorage2D() { + var targets = [ "TEXTURE_2D", "TEXTURE_CUBE_MAP" ]; + var width = 512; + var height = 512; + var levels = 5; + + for (var ii = 0; ii < targets.length; ++ii) { + debug(""); + debug("Reading an uninitialized texture (texStorage2D) should succeed with all bytes set to 0 : target = " + targets[ii]); + var tex = setupTexture(gl[targets[ii]], width, height, 1); + gl.texStorage2D(gl[targets[ii]], levels, gl.RGBA8, width, height); + for (var level = 0; level < levels; ++level) { + if (gl[targets[ii]] == gl.TEXTURE_2D) { + checkNonZeroPixels(tex, gl[targets[ii]], gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + } else { + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_X, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_Z, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + } + } + gl.deleteTexture(tex); + gl.finish(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + } +} + +function testTexStorage3D() { + var targets = [ "TEXTURE_3D", "TEXTURE_2D_ARRAY" ]; + var internal_formats = [ "RGBA8", "RGBA8UI", "RGBA8I" ]; + var formats = [ gl.RGBA, gl.RGBA_INTEGER, gl.RGBA_INTEGER ]; + var read_types = [ gl.UNSIGNED_BYTE, gl.UNSIGNED_INT, gl.INT ]; + var width = 256; // minimum MAX_3D_TEXTURE_SIZE is 256 + var height = 256; // minimum MAX_3D_TEXTURE_SIZE is 256 + var depth = 8; + var levels = 5; + + for (var ii = 0; ii < targets.length; ++ii) { + debug(""); + debug("Reading an uninitialized texture (texStorage3D) should succeed with all bytes set to 0 : target = " + targets[ii]); + for (var jj = 0; jj < internal_formats.length; ++jj) { + debug(""); + debug("Internal format : " + internal_formats[jj]); + var tex = setupTexture(gl[targets[ii]], width, height, depth); + gl.texStorage3D(gl[targets[ii]], levels, gl[internal_formats[jj]], width, height, depth); + var level_depth = depth; + for (var level = 0; level < levels; ++level) { + for (var layer = 0; layer < level_depth; ++layer) { + checkNonZeroPixels(tex, gl[targets[ii]], formats[jj], read_types[jj], width, height, level, layer, []); + } + if (gl[targets[ii]] == gl.TEXTURE_3D) + level_depth = Math.max(1, level_depth >> 1); + } + gl.deleteTexture(tex); + gl.finish(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + } + } +} + +testTexImage3D(); +testTexStorage2D(); +testTexStorage3D(); + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> + diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/views-with-offsets.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/views-with-offsets.html new file mode 100644 index 0000000000..8e89b4b78a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/views-with-offsets.html @@ -0,0 +1,320 @@ +<!-- +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/desktop-gl-constants.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> + +<script> +"use strict"; +description("Tests texture uploads with ArrayBufferView+offsets"); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext(null, undefined, 2); +console.log(gl.getParameter(gl.VERSION)); + +//// + +function arrToStr(arr) { + return "[" + arr.map(x => x.toString()).join(", ") + "]"; +} + +function shouldBeWas(shouldBe, was, info) { + var text = "Should be " + shouldBe + ", was " + was + "."; + if (info) { + text = info + ": " + text; + } + + if (shouldBe == was) { + testPassed(text); + return true; + } else { + testFailed(text); + return false; + } +} + +function shouldBeWasArr(shouldBe, was, info) { + if (shouldBe.length != was.length) { + testFailed("Length should be " + shouldBe.length + ", was " + was.length + "."); + return false; + } + + return shouldBeWas(arrToStr(shouldBe), arrToStr(was), info); +} + +//// + +// Textures + +var fibArr = [ + 0, 1, 1, 2, + 3, 5, 8, 13, + 21, 34, 55, 89, + 144, 233, +]; + +var fb = gl.createFramebuffer(); + +function probeWithBadOffset(fnTest, info) { + fnTest(+(-1|0)); + if (!gl.getError()) { + testFailed("Does not support " + info + " with offsets into views."); + return false; + } + return true; +} + +// fn(view, offset, expectedError, expectedResult) + +do { + var readPixelView = new Uint8Array(4); + var testView = new Uint8Array(fibArr); + + function testTexOrSubImage(funcName, fnTexOrSubImage) { + debug(""); + debug(funcName); + + var fnProbe = function(viewOffset) { + fnTexOrSubImage(gl.RGBA, gl.UNSIGNED_BYTE, testView, viewOffset); + }; + + if (!probeWithBadOffset(fnProbe, funcName)) + return; + + for (var i = 0; i <= testView.length+1; i++) { + debug("offset=" + i); + + fnTexOrSubImage(gl.RGBA, gl.UNSIGNED_BYTE, testView, i); + + var effectiveViewLen = testView.length - i; + + if (effectiveViewLen >= 4) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readPixelView); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBeWasArr(testView.slice(i, i+4), readPixelView); + + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION); + } + } + + debug(""); + + var yellow565 = (0x1f << 11) | (0x3f << 5); + var cyan565 = (0x3f << 5) | 0x1f; + var arr565 = [yellow565, cyan565]; + var view565 = new Uint16Array(arr565); + + function rgb888to565(arr888) { + return ((arr888[0] >> 3) << 11) | ((arr888[1] >> 2) << 5) | (arr888[2] >> 3); + } + + for (var i = 0; i <= arr565.length+1; i++) { + debug("rgb565, offset=" + i); + + fnTexOrSubImage(gl.RGB, gl.UNSIGNED_SHORT_5_6_5, view565, i); + + var effectiveViewLen = arr565.length - i; + + if (effectiveViewLen >= 1) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readPixelView); + debug(arrToStr(readPixelView)); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBeWas(arr565[i], rgb888to565(readPixelView)); + + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION); + } + } + } + + var fn2D = function(format, type, view, viewOffset) { + gl.texImage2D(gl.TEXTURE_2D, 0, format, 1, 1, 0, format, type, view, viewOffset); + } + + var fnSub2D = function(format, type, view, viewOffset) { + gl.texImage2D(gl.TEXTURE_2D, 0, format, 1, 1, 0, format, type, null); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, format, type, view, viewOffset); + } + + var fn3D = function(format, type, view, viewOffset) { + gl.texImage3D(gl.TEXTURE_3D, 0, format, 1, 1, 1, 0, format, type, view, viewOffset); + } + + var fnSub3D = function(format, type, view, viewOffset) { + gl.texImage3D(gl.TEXTURE_3D, 0, format, 1, 1, 1, 0, format, type, null); + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, format, type, view, viewOffset); + } + + //// + + var tex2d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex2d); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2d, 0); + + testTexOrSubImage("texImage2D", fn2D); + testTexOrSubImage("texSubImage2D", fnSub2D); + + //// + + var tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 1, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, 0); + + testTexOrSubImage("texImage3D", fn3D); + testTexOrSubImage("texSubImage3D", fnSub3D); +} while (false); + + +do { + var compressedFormat = 0; + var compressedByteCount; + + if (gl.getExtension("WEBGL_compressed_texture_s3tc")) { + var e = gl.getExtension("WEBGL_compressed_texture_s3tc"); + compressedFormat = e.COMPRESSED_RGB_S3TC_DXT1_EXT; + compressedByteCount = 8; + } else if (gl.getExtension("WEBGL_compressed_texture_etc")) { + var e = gl.getExtension("WEBGL_compressed_texture_etc"); + compressedFormat = e.COMPRESSED_RGB8_ETC2; + compressedByteCount = 8; + } else { + debug("No compressed texture format found. Skipping compressedTex(Sub)Image tests."); + break; + } + + //// + + var view = new Uint8Array(compressedByteCount+1); + + var fn2D = function(viewOffset) { + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, compressedFormat, 4, 4, 0, + view, viewOffset, compressedByteCount); + }; + + var fnSub2D = function(viewOffset) { + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, compressedFormat, 4, 4, 0, + view, 0, compressedByteCount); + gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, compressedFormat, + view, viewOffset, compressedByteCount); + }; + + var fn3D = function(viewOffset) { + gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, compressedFormat, 4, 4, 1, 0, + view, viewOffset, compressedByteCount); + }; + + var fnSub3D = function(viewOffset) { + gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, compressedFormat, 4, 4, 1, 0, + view, 0, compressedByteCount); + gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 1, compressedFormat, + view, viewOffset, compressedByteCount); + }; + + //// + + var testFunc = function(funcName, fnToTest) { + debug(""); + debug(funcName); + + if (!probeWithBadOffset(fnToTest, funcName)) + return; + + var viewLength = view.length; + var subViewLength = compressedByteCount; + + for (var i = 0; i <= viewLength+1; i++) { + debug("offset=" + i); + + fnToTest(i); + var effectiveViewLen = viewLength - i; + + if (effectiveViewLen >= subViewLength) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + } + } + }; + + var tex2d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex2d); + testFunc("compressedTexImage2D" , fn2D ); + testFunc("compressedTexSubImage2D", fnSub2D); + + var tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex3d); + testFunc("compressedTexImage3D" , fn3D ); + testFunc("compressedTexSubImage3D", fnSub3D); +} while (false); + +do { + debug(""); + debug("readPixels"); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + var testColor = [10, 20, 30, 40]; + gl.clearColor(testColor[0]/255.0, + testColor[1]/255.0, + testColor[2]/255.0, + testColor[3]/255.0); + gl.clear(gl.COLOR_BUFFER_BIT); + var readPixelView = new Uint8Array(6); + + function doReadPixels(viewOffset) { + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, readPixelView, viewOffset); + return readPixelView; + } + + if (!probeWithBadOffset(doReadPixels, "doReadPixels")) + break; + + for (var i = 0; i <= readPixelView.length+1; i++) { + debug("offset=" + i); + var res = doReadPixels(i); + var effectiveViewLen = readPixelView.length - i; + + if (effectiveViewLen >= 4) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBeWasArr(testColor, res.slice(i,i+4)); + + } else if (effectiveViewLen >= 0) { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION); + + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + } + } +} while (false); + +debug("") +var successfullyParsed = true; +</script> + +<script src="../../js/js-test-post.js"></script> +</body> +</html> |