diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc')
25 files changed, 4906 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/00_test_list.txt new file mode 100644 index 000000000..a25c3ec81 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/00_test_list.txt @@ -0,0 +1,23 @@ +--min-version 2.0.1 active-3d-texture-bug.html +copy-texture-image.html +copy-texture-image-luma-format.html +copy-texture-image-webgl-specific.html +gl-get-tex-parameter.html +--min-version 2.0.1 integer-cubemap-texture-sampling.html +--min-version 2.0.1 integer-cubemap-specification-order-bug.html +mipmap-fbo.html +tex-3d-size-limit.html +tex-image-and-sub-image-with-array-buffer-view-sub-source.html +tex-image-with-bad-args.html +tex-image-with-bad-args-from-dom-elements.html +tex-image-with-different-data-source.html +tex-input-validation.html +tex-mipmap-levels.html +tex-new-formats.html +--min-version 2.0.1 tex-srgb-mipmap.html +tex-storage-2d.html +tex-storage-and-subimage-3d.html +tex-storage-compressed-formats.html +tex-unpack-params.html +texel-fetch-undefined.html +texture-npot.html diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/active-3d-texture-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/active-3d-texture-bug.html new file mode 100644 index 000000000..99cd0136b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/active-3d-texture-bug.html @@ -0,0 +1,145 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Active TEXTURE1 Bug 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> +<canvas id="canvas" width="64" height="64"> </canvas> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex">#version 300 es +precision mediump float; +in vec4 a_position; +in vec2 a_coord; +out vec2 v_coord; +void main() { + gl_Position = a_position; + v_coord = a_coord; +} +</script> +<script id="fshader" type="x-shader/x-fragment">#version 300 es +precision mediump float; +in vec2 v_coord; +uniform mediump sampler3D u_sampler; +out vec4 o_color; +void main () { + o_color = texture(u_sampler, vec3(v_coord, 0.0)); +} +</script> +<script> +"use strict"; +description("Test for a MacOSX 10.12 with Intel GPUs driver crash bug activating TEXTURE1 for 3d texture"); +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var samplerLoc; + +function render(textureUnit, width, height, expectedColor, msg) { + gl.uniform1i(samplerLoc, textureUnit); + wtu.setupUnitQuad(gl, 0, 1); + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, msg); +} + +function activeTextureTest() { + var texture = gl.createTexture(); + var sampler = gl.createSampler(); + var width = 64; + var height = 64; + var depth = 4; + var black = [0, 0, 0, 255]; + var size = width * height * depth * 4; + + var buf = new Uint8Array(size); + for (var i = 0; i < size; i += 4) { + buf[i + 0] = 0; + buf[i + 1] = 255; + buf[i + 2] = 0; + buf[i + 3] = 255; + } + + var program = wtu.setupProgram(gl, ["vshader", "fshader"], ['a_position', 'a_coord'], [0, 1]); + samplerLoc = gl.getUniformLocation(program, "u_sampler"); + + gl.viewport(0, 0, width, height); + + gl.bindTexture(gl.TEXTURE_3D, texture); + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, buf); + // texture is unbound from the default texture unit TEXTURE0, + // then a default black texture will be bound to TEXTURE0. + gl.bindTexture(gl.TEXTURE_3D, null); + + // Active TEXTURE1 and 3d texture are necessary to reproduce the crash bug. + gl.activeTexture(gl.TEXTURE1); + + gl.bindSampler(0, sampler); + gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.bindTexture(gl.TEXTURE_3D, texture); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + // Render using sampler + // When rendering from texture unit 0, the black texture will be drawn. + render(0, width, height, black, "Result pixels rendering from TEXTURE0 should be black"); + + gl.bindSampler(0, null); + gl.deleteSampler(sampler); + + // Render using texture + // When rendering from texture unit 0, the black texture will be drawn. + // Crash happens when calling gl.drawArrays during this rendering. + render(0, width, height, black, "Result pixels rendering from TEXTURE0 should be black"); + + gl.bindTexture(gl.TEXTURE_3D, null); + gl.deleteTexture(texture); + gl.deleteProgram(program); +} + +if (!gl) { + testFailed("Fail to get a WebGL2 context"); +} else { + testPassed("Created WebGL2 context successfully"); + activeTextureTest(); +} + +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/textures/misc/compressed-tex-image.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-image.html new file mode 100644 index 000000000..4423a8fd1 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/compressed-tex-image.html @@ -0,0 +1,94 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL CompressedTexImage and CompressedTexSubImage 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("This test ensures WebGL implementations correctly implement compressedTexImage2D and compressedTexSubImage2D."); + +debug(""); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext(undefined, undefined, 2); + +var formats = null; + +if (!gl) { + testFailed("context does not exist"); +} else { + testPassed("context exists"); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 0, new Uint8Array(16))"); + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.ETC1_RGB8_OES, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_3D, 0, gl.COMPRESSED_R11_EAC, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_R11_EAC, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexSubImage2D(gl.TEXTURE_3D, 0, 0, 0, 4, 4, gl.COMPRESSED_R11_EAC, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, gl.COMPRESSED_R11_EAC, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_SIGNED_R11_EAC, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RG11_EAC, 4, 4, 0, new Uint8Array(16))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_SIGNED_RG11_EAC, 4, 4, 0, new Uint8Array(16))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGB8_ETC2, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_SRGB8_ETC2, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 0, new Uint8Array(8))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 0, new Uint8Array(16))"); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 4, 0, new Uint8Array(16))"); + + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)"); + shouldBeNonNull("formats"); + shouldBe("formats.length", "10"); + + debug(""); + shouldThrow("gl.compressedTexImage2D(gl.TEXTURE_2D, 0, gl.COMPRESSED_R11_EAC, 4, 4, 0, null)"); + shouldThrow("gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.COMPRESSED_R11_EAC, null)"); + shouldThrow("gl.compressedTexImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.COMPRESSED_R11_EAC, 4, 4, 4, 0, null)"); + shouldThrow("gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, 0, 0, 0, gl.COMPRESSED_R11_EAC, null)"); +} + +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-luma-format.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-luma-format.html new file mode 100644 index 000000000..a4279af3e --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-luma-format.html @@ -0,0 +1,187 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL CopyTexSubImage 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 src="../../../js/glsl-conformance-test.js"></script> +</head> +<body> +<div id="description"></div> +<canvas id="canvas" width="64px" height="32px"> </canvas> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex">#version 300 es +in highp vec4 a_position; +in highp vec2 a_coord; +out highp vec2 v_coord; +void main(void) { + gl_Position = a_position; + v_coord = a_coord; +} +</script> +<script id="fshader_luminance_alpha" type="x-shader/x-fragment">#version 300 es +in highp vec2 v_coord; +uniform highp sampler3D u_sampler0; +out highp vec4 o_color0; +void main (void) { + o_color0 = vec4(texture(u_sampler0,vec3(v_coord, 0))); +} +</script> +<script> +"use strict"; +description("This test verifies the behavior of copTexSubImage3D with luminance textures."); +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); + +function copytexsubimage3D_luma_format() { + + var testGroup = [ + { + name: '3d_alpha', + format: gl.ALPHA, + width: 64, + height: 32, + depth: 2 + }, + { + name: '3d_luminance', + format: gl.LUMINANCE, + width: 64, + height: 32, + depth: 2 + }, + { + name: '3d_luminance_alpha', + format: gl.LUMINANCE_ALPHA, + width: 64, + height: 32, + depth: 2 + } + ]; + + testGroup.forEach(function(testcase) { + debug(""); + debug("Testing copytexsubimage3d_luma_format_" + testcase.name); + + var texture = []; + texture[0] = gl.createTexture(); + texture[1] = gl.createTexture(); + var layer = 0; + var width = testcase.width; + var height = testcase.height; + var depth = testcase.depth; + var msg; + var uint1 = new Uint8Array(width * height * 4); + for (var i = 0; i < uint1.length - 1; ++i) { + uint1[i + 1] = (uint1[i] + 10) % 255; + } + + gl.bindTexture(gl.TEXTURE_2D, texture[0]); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint1); + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0); + + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + gl.bindTexture(gl.TEXTURE_3D, texture[1]); + setUpTexStatus(); + gl.texImage3D(gl.TEXTURE_3D, 0, testcase.format, width, height, depth, 0, testcase.format, gl.UNSIGNED_BYTE, null); + gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer, 0, 0,width, height); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + var program = wtu.setupProgram(gl, ["vshader", "fshader_luminance_alpha"]); + wtu.setupUnitQuad(gl, 0, 1); + wtu.drawUnitQuad(gl); + + for (var y = 0; y < height; ++y) { + for (var x = 0; x < width; ++x) { + var cur = y * width * 4 + x * 4; + if (testcase.format == gl.ALPHA) { + wtu.checkCanvasRect(gl, x, y, 1, 1, [ 0, 0, + 0, uint1[cur + 3]], msg, [1, 1, 1, 1]); + } else if (testcase.format == gl.LUMINANCE) { + wtu.checkCanvasRect(gl, x, y, 1, 1, [uint1[cur], uint1[cur], + uint1[cur], 255], msg, [1, 1, 1, 1]); + } else { // gl.LUMINANCE_ALPHA + wtu.checkCanvasRect(gl, x, y, 1, 1, [uint1[cur], uint1[cur], + uint1[cur], uint1[cur + 3]], msg, [1, 1, 1, 1]); + } + } + } + } else { + testFailed("framebuffer not complete"); + } + + gl.bindTexture(gl.TEXTURE_3D, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + gl.deleteTexture(texture[0]); + gl.deleteTexture(texture[1]); + gl.deleteProgram(program); + }); +} + +function setUpTexStatus() { + gl.texParameteri( + gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST + ); + gl.texParameteri( + gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST + ); + gl.texParameteri( + gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE + ); + gl.texParameteri( + gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE + ); + gl.texParameteri( + gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE + ); +} + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + copytexsubimage3D_luma_format(); +} + +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/textures/misc/copy-texture-image-webgl-specific.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-webgl-specific.html new file mode 100644 index 000000000..dcb364489 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image-webgl-specific.html @@ -0,0 +1,324 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL CopyTexImage 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="2" height="2"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +var wtu = WebGLTestUtils; +description("This test verifies the functionality of copyTexImage."); + +var gl = wtu.create3DContext("example", undefined, 2); + +function copytexsubimage3d_invalid_operation_feedbackloops() { + debug(""); + debug("Testing copytexsubimage3d_invalid_operation_feedbackloops"); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, texture); + var uint8 = new Uint8Array(32); + var layer = 0; + var width = 2; + var height = 2; + var depth = 2; + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, 0, layer); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer, 0, 0, width, height); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "gl.INVALID_OPERATION is generated"); + } else { + testFailed("framebuffer not complete"); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + gl.deleteTexture(texture); +}; + +function copytexsubimage3d_valid_operation_diff_level() { + debug(""); + debug("Testing copytexsubimage3d_valid_operation_diff_level"); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, texture); + var uint8 = new Uint8Array(32); + var level1 = 0; + var level2 = 1; + var width = 2; + var height = 2; + var depth = 2; + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8); + gl.generateMipmap(gl.TEXTURE_3D); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, level1, 0); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + gl.copyTexSubImage3D(gl.TEXTURE_3D, level2, 0, 0, 0, 0, 0, width/2, height/2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed."); + } else { + testFailed("framebuffer not complete"); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + gl.deleteTexture(texture); +}; + +function copytexsubimage3d_valid_operation_diff_layer() { + debug(""); + debug("Testing copytexsubimage3d_valid_operation_diff_layer"); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, texture); + var uint8 = new Uint8Array(32); + var layer1 = 0; + var layer2 = 1; + var width = 2; + var height = 2; + var depth = 2; + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint8); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, 0, layer1); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer2, 0, 0, width, height); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed."); + } else { + testFailed("framebuffer not complete"); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + gl.deleteTexture(texture); +} + +function copytexsubimage3d_texture_wrongly_initialized() { + debug(""); + debug("Testing copytexsubimage3d_texture_wrongly_initialized"); + var texture = []; + texture[0] = gl.createTexture(); + texture[1] = gl.createTexture(); + var layer = 0; + var width = 2; + var height = 2; + var depth = 2; + gl.bindTexture(gl.TEXTURE_2D, texture[0]); + var uint = new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + gl.bindTexture(gl.TEXTURE_3D, texture[1]); + gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, width, height, depth); + gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, 0, 0, layer, 0, 0, width, height); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture[1], 0, layer); + var bytes = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, bytes); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readpixel should succeed."); + for (var x = 0; x < width * height * 4; x++) { + if (bytes[x] != uint[x]) { + testFailed("byte comparison failure, byte at "+ x + " was " + bytes[x] + + ", should be " + uint[x]); + break; + } + } + } else { + testFailed("framebuffer not complete"); + } + + gl.bindTexture(gl.TEXTURE_2D, null); + gl.bindTexture(gl.TEXTURE_3D, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + gl.deleteTexture(texture[0]); + gl.deleteTexture(texture[1]); +}; + +function copytexsubimage3d_out_of_bounds_test_helper(xx, yy, copyWidth, copyHeight) { + var texture = []; + texture[0] = gl.createTexture(); + texture[1] = gl.createTexture(); + var layer = 0; + var width = 2; + var height = 2; + var depth = 2; + var width2 = 4; + var height2 = 4; + var xoffset = 0; + var yoffset = 0; + var uint = new Uint8Array(width * height * 4); + for (var i = 0; i < uint.length; i++) { + uint[i] = 0x01; + } + var uint2 = new Uint8Array(width2 * height2 * depth * 4); + for (var i = 0; i < uint2.length; i++) { + uint2[i] = 0xFF; + } + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + + gl.bindTexture(gl.TEXTURE_2D, texture[0]); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture[0], 0); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + gl.bindTexture(gl.TEXTURE_3D, texture[1]); + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, width2, height2, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, uint2); + gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, xoffset, yoffset, layer, xx, yy, copyWidth, copyHeight); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "using copyTexSubImage3D: x = " + xx + ", y = " + yy + " width = " + copyWidth + ", height = " + copyHeight); + + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture[1], 0, layer); + var bytes = new Uint8Array(width2 * height2 * 4); + gl.readPixels(0, 0, width2, height2, gl.RGBA, gl.UNSIGNED_BYTE, bytes); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readpixel should succeed."); + + var sourceX = new Object(); + var sourceY = new Object(); + Clip(xx, copyWidth, width, sourceX); + Clip(yy, copyHeight, height, sourceY); + var destX = sourceX.start - xx + xoffset; + var rangeX = sourceX.range; + var destY = sourceY.start - yy + yoffset; + var rangeY = sourceY.range; + for (var y = 0; y < height2; y++) { + for (var x = 0; x < width2 * 4; x++) { + var current = y * height2 * 4 + x; + // pixels copied from read framebuffer should be 0x01 + if (x >= destX * 4 && x < (destX + rangeX) * 4 && y >= destY && y < destY + rangeY) { + if (bytes[current] != 0x01) { + testFailed("byte comparison failure, byte at "+ (current) + " was " + + bytes[current] +", should be 1"); + break; + } + // pixels out-of-bounds should be untouched + } else { + if (bytes[current] != 0xFF) { + testFailed("byte comparison failure, byte at "+ (current) + " was " + + bytes[current] + ", should be 255"); + break; + } + } + } + // Test failed; abort + if (x < width2 * 4) { + break; + } + } + } else { + testFailed("framebuffer not complete"); + } + + gl.bindTexture(gl.TEXTURE_2D, null); + gl.bindTexture(gl.TEXTURE_3D, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + gl.deleteTexture(texture[0]); + gl.deleteTexture(texture[1]); +} + +function copytexsubimage3d_out_of_bounds() { + debug(""); + debug("Test pixels outside of read framebuffer for CopyTexSubImage3D"); + + for(var i=0; i < testlist.length; i++) { + copytexsubimage3d_out_of_bounds_test_helper(testlist[i][0], testlist[i][1], testlist[i][2], testlist[i][3]); + } +}; + +/** + * This array defines some copy areas for CopyTexSubImage3D. + * A copy area is defined by x coordinate, y coordinate, copyWidth and copyHeight. + * the source read framebuffer is (0, 0, 2, 2). + */ +var testlist = [ + [-1, -1, 4, 4], + + [0, 0, 3, 3], + [-1, -1, 3, 3], + [-1, 0, 3, 3], + [0, -1, 3, 3], + + [0, 0, 2, 3], + [0, 0, 3, 2], + [-1, 0, 3, 2], + [0, -1, 2, 3], + + [-2, -2, 3, 3], + [-2, 1, 3, 3], + [1, -2, 3, 3], + [1, 1, 3, 3], + + [2 , 2 ,3, 3] +]; + + +function Clip(start, range, sourceRange, target) { + if (start < 0) { + range += start; + start = 0; + } + var end = start + range; + if(end > sourceRange) { + range -= end - sourceRange; + } + target.start = start; + target.range = range; +} + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + copytexsubimage3d_invalid_operation_feedbackloops(); + copytexsubimage3d_valid_operation_diff_level(); + copytexsubimage3d_valid_operation_diff_layer(); + copytexsubimage3d_texture_wrongly_initialized(); + copytexsubimage3d_out_of_bounds(); +} + +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image.html new file mode 100644 index 000000000..f01da1238 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/copy-texture-image.html @@ -0,0 +1,248 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL CopyTexImage 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="64" height="64"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +var wtu = WebGLTestUtils; +description("This test verifies the functionality of copyTexImage2D."); +debug(""); + +var gl = wtu.create3DContext("example", undefined, 2); + +function enumToString(value) { + return wtu.glEnumToString(gl, value); +} + +function checkFramebuffer(expected) { + var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (expected.indexOf(actual) < 0) { + var msg = "checkFramebufferStatus expects ["; + for (var index = 0; index < expected.length; ++index) { + msg += wtu.glEnumToString(gl, expected[index]); + if (index + 1 < expected.length) + msg += ", "; + } + msg += "], was " + wtu.glEnumToString(gl, actual); + testFailed(msg); + } else { + var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) + + " as expected"; + testPassed(msg); + } +} + +var testInternalformat = function () { + var goodByteFormats = [ + "RGB", + "RGBA", + "LUMINANCE_ALPHA", + "LUMINANCE", + "ALPHA", + "R8", + "RG8", + "RGB8", + "RGBA8", + ]; + var goodByteFormatsWithUnmatchedComponentSizes = [ + "RGB565", + "RGBA4", + "RGB5_A1", + "RGB10_A2", + ]; + var goodSRGBFormats = [ + "SRGB8", + "SRGB8_ALPHA8", + ]; + var goodIntFormats = [ + "R32I", + "RG32I", + "RGBA32I", + ]; + var goodIntFormatsWithUnmatchedComponentSizes = [ + "R8I", + "R16I", + "RG8I", + "RG16I", + "RGBA8I", + "RGBA16I", + ]; + var goodUnsignedIntFormats = [ + "R32UI", + "RG32UI", + "RGBA32UI", + ]; + var goodUnsignedIntFormatsWithUnmatchedComponentSizes = [ + "R8UI", + "R16UI", + "RG8UI", + "RG16UI", + "RGB10_A2UI", + "RGBA8UI", + "RGBA16UI", + ]; + var badByteFormats = [ + "R8_SNORM", + "RG8_SNORM", + "RGB8_SNORM", + "RGBA8_SNORM", + ]; + var badIntFormats = [ + "RGB8I", + "RGB16I", + "RGB32I", + ]; + var badUnsingedIntFormats = [ + "RGB8UI", + "RGB16UI", + "RGB32UI", + ]; + var badFloatFormats = [ + "R16F", + "R32F", + "RG16F", + "RG32F", + "R11F_G11F_B10F", + "RGB9_E5", + "RGB16F", + "RGB32F", + "RGBA16F", + "RGBA32F", + ]; + var badDepthStencilFormats = [ + "DEPTH_COMPONENT16", + "DEPTH_COMPONENT24", + "DEPTH_COMPONENT32F", + "DEPTH24_STENCIL8", + ]; + + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + function testFormat(internalformat, srcTexFormatsTypes, fboAttachmentType, expected, msg) { + var fbo = gl.createFramebuffer(); + var srcTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, srcTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, srcTexFormatsTypes.internalformat, 64, 64, 0, srcTexFormatsTypes.format, srcTexFormatsTypes.type, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, fboAttachmentType, gl.TEXTURE_2D, srcTexture, 0); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl[internalformat], 0, 0, 64, 64, 0); + wtu.glErrorShouldBe(gl, expected, msg + enumToString(gl[internalformat])); + + gl.deleteTexture(srcTexture); + gl.deleteFramebuffer(fbo); + } + + goodByteFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA, format: gl.RGBA, type: gl.UNSIGNED_BYTE }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat "); + srcTexFormatsTypes = { internalformat: gl.RGBA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat "); + }); + goodByteFormatsWithUnmatchedComponentSizes.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION, + "copyTexImage2D should fail for good internalformat with unmatched component sizes "); + }); + goodSRGBFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.SRGB8_ALPHA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat "); + }); + goodIntFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA32I, format: gl.RGBA_INTEGER, type: gl.INT }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat "); + }); + goodIntFormatsWithUnmatchedComponentSizes.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA32I, format: gl.RGBA_INTEGER, type: gl.INT }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION, + "copyTexImage2D should fail for good internalformat with unmatched component sizes "); + }); + goodUnsignedIntFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA32UI, format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.NO_ERROR, "copyTexImage2D should succeed for good internalformat "); + }); + goodUnsignedIntFormatsWithUnmatchedComponentSizes.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA32UI, format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_OPERATION, + "copyTexImage2D should fail for good internalformat with unmatched component sizes "); + }); + + badByteFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for bad internalformat "); + }); + badIntFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA32I, format: gl.RGBA_INTEGER, type: gl.INT }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for bad internalformat "); + }); + badUnsingedIntFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.RGBA32UI, format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT }; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for bad internalformat "); + }); + badFloatFormats.forEach(function(internalformat) { + if (gl.getExtension("EXT_color_buffer_float")) { + var srcTexFormatsTypes = { internalformat: gl.RGBA32F, format: gl.RGBA, type: gl.FLOAT}; + testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for bad internalformat "); + } + }); + badDepthStencilFormats.forEach(function(internalformat) { + var srcTexFormatsTypes = { internalformat: gl.DEPTH24_STENCIL8, format: gl.DEPTH_STENCIL, type: gl.UNSIGNED_INT_24_8}; + testFormat(internalformat, srcTexFormatsTypes, gl.DEPTH_STENCIL_ATTACHMENT, gl.INVALID_ENUM, "copyTexImage2D should fail for bad internalformat "); + }); + + gl.deleteTexture(texture); +} + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + testInternalformat(); +} + +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/gl-get-tex-parameter.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/gl-get-tex-parameter.html new file mode 100644 index 000000000..691fb4e6a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/gl-get-tex-parameter.html @@ -0,0 +1,48 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL getTexParameter 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="4" height="4" style="width: 40px; height: 30px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +var contextVersion = 2; +</script> +<script src="../../../js/tests/gl-get-tex-parameter.js"></script> +<script src="../../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-specification-order-bug.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-specification-order-bug.html new file mode 100644 index 000000000..5720a07d9 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-specification-order-bug.html @@ -0,0 +1,190 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Integer Cubemap Texture Specification Order Bug 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 id="vs" type="x-shader/x-vertex">#version 300 es + precision highp float; + in vec4 a_position; + void main(){ + gl_Position = a_position; + } +</script> +<script id="fs" type="x-shader/x-fragment">#version 300 es + precision highp float; + // This program samples both textures at varying Lod and exposes + // both of them, the regular on top, and the weird on the bottom. + // On the NVIDIA driver the top is both green and red while the bottom + // is only green. This is a driver bug because both textures should be + // exactly the same. + // I think that because of our level specification order weirdness, the + // driver gets confused as to which levels are complete and thinks only + // level 0 is complete. Then when sampling the texture it clamps the sampling + // to only level 0, resulting in green for all Lod values. + layout(location = 0) out vec4 fragColor; + uniform highp isamplerCube texRegular; + uniform highp isamplerCube texWeird; + void main() { + vec2 fragPos = gl_FragCoord.xy / vec2(128.0, 128.0); + float lod = (fragPos.x - 0.5) * 10.0 + 0.5; + + ivec4 colorRegular = textureLod(texRegular, vec3(1.0, 0.0, 0.0), lod); + ivec4 colorWeird = textureLod(texWeird, vec3(1.0, 0.0, 0.0), lod); + + if (fragPos.y > 0.51) { + fragColor = vec4(vec2(colorRegular.rg), 0.0, 1.0); + } else if (fragPos.y < 0.49){ + fragColor = vec4(vec2(colorWeird.rg), 0.0, 1.0); + } else { + fragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + } +</script> +<script> +"use strict"; + +var wtu = WebGLTestUtils; + +description("Test for a driver bug when specifying integer cubemaps in weird order"); + +var gl = wtu.create3DContext("example", undefined, 2); + +function createTextureCube(layers, maxLevel) { + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); + + layers.forEach(function(layer) { + var level = layer.level; + var face = layer.face; + var color = layer.color; + + var levelSize = 1 << (maxLevel - level); + + var backingBuffer = new ArrayBuffer(levelSize * levelSize * 2); + new Int16Array(backingBuffer).fill(color); + gl.texImage2D(face + gl.TEXTURE_CUBE_MAP_POSITIVE_X, level, gl.RG8I, levelSize, levelSize, 0, gl.RG_INTEGER, gl.BYTE, new Int8Array(backingBuffer)); + }); + + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + return texture; +} + +function test() { + var kMaxLevel = 4; + var kBlack = 0x0000; + var kGreen = 0x7F00; + var kRed = 0x007F; + + // Create two integer cubemaps with green on level 0 and red on the others. + + // The "regular" cube map is filled in a sensible manner. + var regularLayers = []; + for (var level = 0; level <= kMaxLevel; level ++) { + for (var face = 0; face < 6; face ++) { + if (level == 0) { + regularLayers.push({level: level, face: face, color: kGreen}); + } else { + regularLayers.push({level: level, face: face, color: kRed}); + } + } + } + + // The "weird" cube map has all its >= 1 levels filled, then the first level, + // then the >= 1 levels again but for one face. This replicates what the + // Chromium command buffer "cubemap completeness" workaround is doing. + var weirdLayers = []; + for (var level = 1; level <= kMaxLevel; level ++) { + for (var face = 0; face < 5; face ++) { + weirdLayers.push({level: level, face: face, color: kBlack}); + } + weirdLayers.push({level: level, face: 5, color: kRed}); + } + for (var level = 0; level <= kMaxLevel; level ++) { + for (var face = 0; face < 6; face ++) { + if (level == 0) { + weirdLayers.push({level: level, face: face, color: kGreen}); + } else { + if (face != 5) { + weirdLayers.push({level: level, face: face, color: kRed}); + } + } + } + } + + var regularTex = createTextureCube(regularLayers, kMaxLevel); + var weirdTex = createTextureCube(weirdLayers, kMaxLevel); + + // At this point both textures should be the same. + + var sampleProgram = wtu.setupProgram(gl, ["vs", "fs"], ["a_position"]); + var regularLocation = gl.getUniformLocation(sampleProgram, "texRegular"); + var weirdLocation = gl.getUniformLocation(sampleProgram, "texWeird"); + + wtu.setupQuad(gl, gl.getAttribLocation(sampleProgram, "a_position")); + + gl.clearColor(0.0, 0.0, 0.0, 0.0); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, regularTex); + gl.activeTexture(gl.TEXTURE0 + 1); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, weirdTex); + + gl.uniform1i(regularLocation, 0); + gl.uniform1i(weirdLocation, 1); + + wtu.drawUnitQuad(gl); + + wtu.checkCanvasRect(gl, 96, 32, 1, 1, [255, 0, 0, 255], "should be green"); + wtu.checkCanvasRect(gl, 96, 96, 1, 1, [255, 0, 0, 255], "should be green"); + wtu.checkCanvasRect(gl, 32, 32, 1, 1, [0, 255, 0, 255], "should be red"); + wtu.checkCanvasRect(gl, 32, 96, 1, 1, [0, 255, 0, 255], "should be red"); +} + +test(); + +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/textures/misc/integer-cubemap-texture-sampling.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-texture-sampling.html new file mode 100644 index 000000000..95b3541c6 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/integer-cubemap-texture-sampling.html @@ -0,0 +1,190 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Integer Cubemap Texture Sampling 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 src="../../../js/tests/tex-image-and-sub-image-utils.js"></script> +</head> +<body> +<canvas id="example" width="128" height="128"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +var wtu = WebGLTestUtils; +var tiu = TexImageUtils; + +description("Verify sampling works fine with integer cubemap textures"); +debug("https://github.com/KhronosGroup/WebGL/issues/1819"); + +var gl = wtu.create3DContext("example", undefined, 2); + +var testCases = [ + { internalFormat: "R8UI", format: "RED_INTEGER", type: "UNSIGNED_BYTE" }, + { internalFormat: "RG8UI", format: "RG_INTEGER", type: "UNSIGNED_BYTE" }, + { internalFormat: "RGB8UI", format: "RGB_INTEGER", type: "UNSIGNED_BYTE" }, + { internalFormat: "RGBA8UI", format: "RGBA_INTEGER", type: "UNSIGNED_BYTE" }, +]; + +function setupData(internalFormat, size) { + var numComponents = 0; + switch (gl[internalFormat]) { + case gl.R8UI: + numComponents = 1; + break; + case gl.RG8UI: + numComponents = 2; + break; + case gl.RGB8UI: + numComponents = 3; + break; + case gl.RGBA8UI: + numComponents = 4; + break; + } + if (numComponents == 0) { + testFailed("This should never be reached"); + return null; + } + var data = new Uint8Array(numComponents * size * size); + for (var ii = 0; ii < size * size; ++ii) { + // Set all pixels to RED. + data[ii * numComponents] = 255; + if (numComponents > 1) + data[ii * numComponents + 1] = 0; + if (numComponents > 2) + data[ii * numComponents + 2] = 0; + if (numComponents > 3) + data[ii * numComponents + 3] = 255; + } + return data; +} + +function checkIntegerTextureValues(internalFormat, size) { + var buffer = new Uint32Array(4 * size * size); + gl.readPixels(0, 0, size, size, gl.RGBA_INTEGER, gl.UNSIGNED_INT, buffer); + for (var y = 0; y < size; ++y) { + for (var x = 0; x < size; ++x) { + var index = (y * size + x) * 4; + if (buffer[index] != 255 || buffer[index + 1] != 0 || buffer[index + 2] != 0) { + testFailed("At (" + x + ", " + y + "), expected 255,0,0,255, was " + + [buffer[index], buffer[index + 1], buffer[index + 2], buffer[index + 3]]); + return; + } + } + } + testPassed("All pixels are as expected"); +} + +function runOneTest(internalFormat, format, type, size) { + debug(""); + debug("Testing internalformat = " + internalFormat + ", format = " + format + ", type = " + type + ", size = " + size); + + gl.clearColor(1, 1, 0, 1); + gl.clearDepth(1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); + + var targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + var data = setupData(internalFormat, size); + for (var tt = 0; tt < targets.length; ++tt) { + gl.texImage2D(targets[tt], 0, gl[internalFormat], size, size, 0, gl[format], gl[type], data); + } + + debug("1) Reading back texture data"); + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + for (var tt = 0; tt < targets.length; ++tt) { + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, targets[tt], tex, 0); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + checkIntegerTextureValues(internalFormat, size); + } + } + gl.deleteFramebuffer(fbo); + + debug("2) Rendering with texture"); + var program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + var loc = gl.getUniformLocation(program, "face"); + for (var tt = 0; tt < targets.length; ++tt) { + gl.uniform1i(loc, targets[tt]); + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]); + wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [255, 0, 0, 255], "Should be red"); + } + gl.deleteProgram(program); + gl.deleteTexture(tex); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL errors"); + + var m = wtu.makeImageFromCanvas(gl.canvas); + document.getElementById("console").appendChild(m); + document.getElementById("console").appendChild(document.createElement("hr")); +} + +function runTests() { + for (var ii = 0; ii < testCases.length; ++ii) { + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 2); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 4); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 8); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 16); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 32); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 64); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 65); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 127); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 128); + runOneTest(testCases[ii].internalFormat, testCases[ii].format, testCases[ii].type, 129); + } +} + +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/textures/misc/mipmap-fbo.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/mipmap-fbo.html new file mode 100644 index 000000000..efd8bc8a6 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/mipmap-fbo.html @@ -0,0 +1,71 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Test if mipmap incomplete textures can be used as FBO attachments</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="24" height="24"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +var wtu = WebGLTestUtils; +description(); + +var gl = wtu.create3DContext("example", undefined, 2); + +var testIncompleteMipmapInFBO = function () { + // Create a texture that's not mipmap complete. + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + // Framebuffer should be incomplete for incomplete texture. + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 1); + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); +} + +testIncompleteMipmapInFBO(); + +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-size-limit.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-size-limit.html new file mode 100644 index 000000000..8e69f92eb --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-3d-size-limit.html @@ -0,0 +1,184 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL FramebufferTextureLayer 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> +<canvas id="canvas" width="2" height="2"> </canvas> + +<script> +"use strict"; +var wtu = WebGLTestUtils; +var gl; +var canvas = document.getElementById("canvas"); + +function numLevelsFromSize(size) { + var levels = 0; + while ((size >> levels) > 0) { + ++levels; + } + return levels; +} + +function enumToString(value) { + return wtu.glEnumToString(gl, value); +} + +function test3DTextureDimensions() { + debug(""); + debug("Checking 3D texture dimensions."); + + var tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + var maxTexSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE); + var maxLevels = numLevelsFromSize(maxTexSize); + + gl.texImage3D(gl.TEXTURE_3D, + 0, // level + gl.RGBA, // internalFormat + 1, // width + 1, // height + -1, // depth + 0, // border + gl.RGBA, // format + gl.UNSIGNED_BYTE, // type + null); // data + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "texImage3D should fail for dimension out of range."); + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, maxTexSize + 1, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "texImage3D should fail for dimension out of range."); + + for (var i = 0; i < maxLevels; ++i) { + var size = 1 << i; + var level = maxLevels - i - 1; + var badSize = size * 2; + + gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, size, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed."); + gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 1, size, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed."); + gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 1, 1, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed."); + gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, badSize, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texImage3D should fail for dimension out of range."); + gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 2, badSize, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texImage3D should fail for dimension out of range."); + gl.texImage3D(gl.TEXTURE_3D, level, gl.RGBA, 2, 2, badSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texImage3D should fail for dimension out of range."); + } + + // Clean up + gl.deleteTexture(tex3d); +} + +function test3DTexturePixelSize() { + debug(""); + debug("Checking pixel data array is big enough for request."); + + var tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + var tests = [ + { + internalformat: gl.RGBA, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + size: 4, + dataType: Uint8Array + }, + { + internalformat: gl.R8, + format: gl.RED, + type: gl.UNSIGNED_BYTE, + size: 1, + dataType: Uint8Array + }, + { + internalformat: gl.RGB565, + format: gl.RGB, + type: gl.UNSIGNED_SHORT_5_6_5, + size: 1, + dataType: Uint16Array + }, + { + internalformat: gl.RGBA32I, + format: gl.RGBA_INTEGER, + type: gl.INT, + size: 4, + dataType: Int32Array + }, + { + internalformat: gl.RGBA32F, + format: gl.RGBA, + type: gl.FLOAT, + size: 4, + dataType: Float32Array + }, + ]; + + tests.forEach(function(test) { + debug(""); + debug("Testing internalformat " + enumToString(test.internalformat) + + ", format " + enumToString(test.format) + + ", type " + enumToString(test.type)); + + var pixels = new test.dataType(256 * 256 * 4 * test.size); + gl.texImage3D(gl.TEXTURE_3D, 0, test.internalformat, 256, 256, 256, 0, test.format, test.type, pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "ArrayBufferView not big enough for request by texImage3D."); + gl.texImage3D(gl.TEXTURE_3D, 0, test.internalformat, 256, 256, 4, 0, test.format, test.type, pixels); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "ArrayBufferView big enough for request by texImage3D."); + pixels = new test.dataType(256 * 256 * 1 * test.size); + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 256, 256, 2, test.format, test.type, pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "ArrayBufferView not big enough for request by texSubImage3D."); + }); + + gl.deleteTexture(tex3d); +} + +description("This tests size limits of 3D textures."); + +shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)"); + +test3DTextureDimensions(); +test3DTexturePixelSize(); + +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/textures/misc/tex-image-and-sub-image-with-array-buffer-view-sub-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-and-sub-image-with-array-buffer-view-sub-source.html new file mode 100644 index 000000000..b4c7bdf3f --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-and-sub-image-with-array-buffer-view-sub-source.html @@ -0,0 +1,218 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../../resources/js-test-style.css"/> +<script src="../../../js/js-test-pre.js"></script> +<script src="../../../js/webgl-test-utils.js"></script> +<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script> +</head> +<body> +<canvas id="example" width="2" height="2"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description('Verifies tex{Sub}Image{2|3}D code paths taking partial ArrayBufferView'); + +var wtu = WebGLTestUtils; +var tiu = TexImageUtils; + +function createSource(width, height, depth, viewType, offset) { + var size = width * height * depth * 4; // RGBA + var buf = new window[viewType](size + offset); + for (var ii = 0; ii < size; ++ii) { + if (viewType == "Float32Array") + buf[ii + offset] = ii / 255.0; + else + buf[ii + offset] = ii; + } + return buf; +} + +function comparePixels(ref, refOffset, data, tol) { + for (var ii = 0; ii < data.length; ++ii) { + // Skip alpha due to shader's handling of alpha values. + if (ii % 4 == 3) + continue; + var src = ref[ii + refOffset]; + if (ref instanceof Float32Array) + src *= 255; + if (Math.abs(src - data[ii]) > tol) { + testFailed("Element " + ii + ": expected " + src + ", got " + data[ii]); + return; + } + } + return testPassed("texture data uploaded correctly"); +} + +function run2DTest(gl, test, width, height, srcOffset, tol) { + debug(""); + debug("Tesing tex{Sub}Image2D with sub source: internalformat = " + test.internalformat + + ", format = " + test.format + ", type = " + test.type); + + var program = tiu.setupTexturedQuad(gl, test.internalformat); + if (!program) { + testFailed("Failed to set up program"); + return; + } + + var buf = createSource(width, height, 1, test.viewType, srcOffset); + + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + 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); + gl.texImage2D(gl.TEXTURE_2D, 0, gl[test.internalformat], width, height, 0, + gl[test.format], gl[test.type], buf, srcOffset + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large"); + gl.texImage2D(gl.TEXTURE_2D, 0, gl[test.internalformat], width, height, 0, + gl[test.format], gl[test.type], buf, srcOffset); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D succeeds with correct buffer and srcOffset"); + + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + var readBuf = new Uint8Array(width * height * 4); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error"); + var tol = 0.5; + comparePixels(buf, srcOffset, readBuf, tol); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl[test.internalformat], width, height, 0, + gl[test.format], gl[test.type], null); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl[test.format], gl[test.type], + buf, srcOffset + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large"); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl[test.format], gl[test.type], + buf, srcOffset); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D succeeds with correct buffer and srcOffset"); + + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error"); + comparePixels(buf, srcOffset, readBuf, tol); + + gl.deleteTexture(texture); + gl.deleteProgram(program); +} + +function run3DTest(gl, test, width, height, srcOffset, tol) { + debug(""); + debug("Tesing tex{Sub}Image3D with sub source: internalformat = " + test.internalformat + + ", format = " + test.format + ", type = " + test.type); + + var program = tiu.setupTexturedQuadWith3D(gl, test.internalformat); + if (!program) { + testFailed("Failed to set up program"); + return; + } + + var depth = 1; + var buf = createSource(width, height, depth, test.viewType, srcOffset); + + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, texture); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage3D(gl.TEXTURE_3D, 0, gl[test.internalformat], width, height, depth, 0, + gl[test.format], gl[test.type], buf, srcOffset + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large"); + gl.texImage3D(gl.TEXTURE_3D, 0, gl[test.internalformat], width, height, depth, 0, + gl[test.format], gl[test.type], buf, srcOffset); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D succeeds with correct buffer and srcOffset"); + + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + var readBuf = new Uint8Array(width * height * 4); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error"); + var tol = 0.5; + comparePixels(buf, srcOffset, readBuf, tol); + + gl.texImage3D(gl.TEXTURE_3D, 0, gl[test.internalformat], width, height, depth, 0, + gl[test.format], gl[test.type], null); + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl[test.format], gl[test.type], + buf, srcOffset + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "srcOffset too large"); + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, width, height, depth, gl[test.format], gl[test.type], + buf, srcOffset); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D succeeds with correct buffer and srcOffset"); + + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error"); + comparePixels(buf, srcOffset, readBuf, tol); + + gl.deleteTexture(texture); + gl.deleteProgram(program); +} + +var gl = wtu.create3DContext("example", undefined, 2); +if (!gl) { + testFailed("Fail to get a WebGL context"); +} else { + var testCases = [ + { internalformat: 'RGBA8', format: 'RGBA', type: 'UNSIGNED_BYTE', + viewType: 'Uint8Array', }, + { internalformat: 'RGBA8I', format: 'RGBA_INTEGER', type: 'BYTE', + viewType: 'Int8Array', }, + { internalformat: 'RGBA16UI', format: 'RGBA_INTEGER', type: 'UNSIGNED_SHORT', + viewType: 'Uint16Array', }, + { internalformat: 'RGBA16I', format: 'RGBA_INTEGER', type: 'SHORT', + viewType: 'Int16Array', }, + { internalformat: 'RGBA32UI', format: 'RGBA_INTEGER', type: 'UNSIGNED_INT', + viewType: 'Uint32Array', }, + { internalformat: 'RGBA32I', format: 'RGBA_INTEGER', type: 'INT', + viewType: 'Int32Array', }, + { internalformat: 'RGBA32F', format: 'RGBA', type: 'FLOAT', + viewType: 'Float32Array', }, + ]; + + var srcOffset = 3; + var tol = 0.5; + + for (var idx = 0; idx < testCases.length; ++idx) { + run2DTest(gl, testCases[idx], gl.drawingBufferWidth, gl.drawingBufferHeight, srcOffset, tol); + run3DTest(gl, testCases[idx], gl.drawingBufferWidth, gl.drawingBufferHeight, srcOffset, tol); + } +} + +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html new file mode 100644 index 000000000..8f2968063 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html @@ -0,0 +1,149 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../../resources/js-test-style.css"/> +<script src="../../../js/js-test-pre.js"></script> +<script src="../../../js/webgl-test-utils.js"></script> +</head> +<body> +<canvas id="c" width="16" height="16"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description('Tests texImage2D with invalid internalformat/format/type combinations from various dom elements'); + +debug("<a href='https://www.khronos.org/registry/webgl/specs/latest/2.0/#TEXTURE_TYPES_FORMATS_FROM_DOM_ELEMENTS_TABLE'>Valid internalformat/format/type combinations</a>"); +debug(""); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("c", undefined, 2); + +var doTexImage = function(domElement) { + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2, gl.RGBA, gl.UNSIGNED_INT_2_10_10_10_REV, domElement); + wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM, gl.INVALID_OPERATION], "TexImage2D taking RGB10_A2/RGBA/UNSIGNED_INT_2_10_10_10_REV should fail"); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG8, gl.RG, gl.FLOAT, domElement); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "TexImage2D taking RG8/RG/FLOAT should fail"); + gl.deleteTexture(tex); +} + +var createCanvas2DContext = function(width, height) { + var canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + var ctx = canvas.getContext("2d"); + ctx.fillRect(0, 0, width, height); + return ctx; +}; + +var testImage = function(test) { + debug("HTMLImageElement"); + var img = wtu.makeImage(test.src, function() { + doTexImage(img); + setTimeout(runNextTest, 0); + }); +} + +var testVideo = function(test) { + debug("HTMLVideoElement (" + test.videoType + ")"); + var video = wtu.makeVideo(test.src); + if(!video.canPlayType(test.videoType).replace(/no/, '')) { + debug(test.videoType + " unsupported"); + setTimeout(runNextTest, 0); + return; + } + wtu.startPlayingAndWaitForVideo(video, function() { + doTexImage(video); + setTimeout(runNextTest, 0); + }); +} + +var testCanvas = function(test) { + var ctx = createCanvas2DContext(test.width, test.height); + debug("HTMLCanvasElement"); + doTexImage(ctx.canvas); + setTimeout(runNextTest, 0); +} + +var testImageData = function(test) { + var ctx = createCanvas2DContext(test.width, test.height); + var imageData = ctx.getImageData(0, 0, test.width, test.height); + debug("ImageData"); + doTexImage(imageData); + setTimeout(runNextTest, 0); +} + +var testImageBitmap = function(test) { + debug("ImageBitmap"); + if(!window.createImageBitmap || !window.ImageBitmap) { + debug("ImageBitmap isn't supported"); + setTimeout(runNextTest, 0); + return; + } + var ctx = createCanvas2DContext(test.width, test.height); + createImageBitmap(ctx.canvas, 0, 0, test.width, test.height).then(function(imageBitmap) { + doTexImage(imageBitmap); + setTimeout(runNextTest, 0); + }, function() { + debug("createImageBitmap was rejected"); + setTimeout(runNextTest, 0); + }); +} + +var tests = [ + { type: "canvas", width: 64, height: 64, run: testCanvas }, + { type: "image", src: "../../../resources/red-green.png", run: testImage }, + { type: "ImageBitmap",width: 64, height: 64, run: testImageBitmap }, + { type: "ImageData", width: 64, height: 64, run: testImageData }, + { type: "video", src: "../../../resources/red-green.mp4", videoType: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', run: testVideo }, + { type: "video", src: "../../../resources/red-green.webmvp9.webm", videoType: 'video/webm; codecs="vp9"', run: testVideo }, + { type: "video", src: "../../../resources/red-green.webmvp8.webm", videoType: 'video/webm; codecs="vp8, vorbis"', run: testVideo }, + { type: "video", src: "../../../resources/red-green.theora.ogv", videoType: 'video/ogg; codecs="theora, vorbis"', run: testVideo }, +]; + +var testIndex = 0; +var runNextTest = function() { + if (testIndex < tests.length) { + debug(""); + var test = tests[testIndex]; + ++testIndex; + test.run(test); + } else { + finishTest(); + } +}; + +runNextTest(); + +</script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args.html new file mode 100644 index 000000000..8b60624be --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-bad-args.html @@ -0,0 +1,76 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../../resources/js-test-style.css"/> +<script src="../../../js/js-test-pre.js"></script> +<script src="../../../js/webgl-test-utils.js"></script> +</head> +<body> +<canvas id="c" width="16" height="16"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description('Tests texImage2D with invalid internalformat/format/type combinations'); +debug("This is a regression test for <a href='https://bugs.chromium.org/p/chromium/issues/detail?id=656889'>Chromium Issue 656889</a>"); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("c", null, 2); +var ext = null; +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); +} + +var doTexImage = function(test) { + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texImage2D(gl.TEXTURE_2D, 0, test.internalformat, 64, 64, 0, test.format, test.type, null); + wtu.glErrorShouldBe(gl, test.errors, "TexImage2D taking " + wtu.glEnumToString(gl, test.internalformat) + "/" + + wtu.glEnumToString(gl, test.format) + "/" + wtu.glEnumToString(gl, test.type)); + gl.deleteTexture(tex); +} + +var tests = [ + { internalformat: gl.RGBA, format: gl.RGBA, type: gl.UNSIGNED_BYTE, errors: [gl.NO_ERROR] }, + { internalformat: gl.RGBA, format: gl.RGBA, type: gl.FLOAT, errors: [gl.INVALID_OPERATION] }, + { internalformat: gl.RGBA, format: gl.RGBA, type: gl.HALF_FLOAT, errors: [gl.INVALID_OPERATION] }, + { internalformat: gl.LUMINANCE, format: gl.LUMINANCE, type: gl.FLOAT, errors: [gl.INVALID_OPERATION] }, + { internalformat: gl.LUMINANCE_ALPHA, format: gl.LUMINANCE_ALPHA, type: gl.HALF_FLOAT, errors: [gl.INVALID_OPERATION] }, +]; + +tests.forEach(doTexImage); + +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-different-data-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-different-data-source.html new file mode 100644 index 000000000..70b8d50c0 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-image-with-different-data-source.html @@ -0,0 +1,72 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../../resources/js-test-style.css"/> +<script src="../../../js/js-test-pre.js"></script> +<script src="../../../js/webgl-test-utils.js"></script> +</head> +<body> +<canvas id="canvas1" width="16" height="16"></canvas> +<canvas id="canvas2" width="16" height="16"></canvas> +<canvas id="c" width="16" height="16"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description('Tests texImage2D with different data source'); + +var wtu = WebGLTestUtils; +var c = document.getElementById("c"); +var gl = wtu.create3DContext("canvas1", undefined, 2); +var tex = gl.createTexture(); + +// Do TexImage2D taking a canvas source first. +gl.bindTexture(gl.TEXTURE_2D, tex); +gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE, c); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TexImage2D taking a canvas source should succeed"); +gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2, 16, 16, 0, gl.RGBA, gl.UNSIGNED_INT_2_10_10_10_REV, null); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Teximage2D taking a null array buffer should succeed"); +gl.deleteTexture(tex); + +// Do TexImage2D taking an array buffer first. +gl = wtu.create3DContext("canvas2", undefined, 2); +tex = gl.createTexture(); +gl.bindTexture(gl.TEXTURE_2D, tex); +gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2, 16, 16, 0, gl.RGBA, gl.UNSIGNED_INT_2_10_10_10_REV, null); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Teximage2D taking a null array buffer should succeed"); +gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2, gl.RGBA, gl.UNSIGNED_INT_2_10_10_10_REV, c); +wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "TexImage2D taking RGB10_A2 internalformat and a canvas source should fail"); +gl.deleteTexture(tex); + +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-input-validation.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-input-validation.html new file mode 100644 index 000000000..32ac7cc1a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-input-validation.html @@ -0,0 +1,45 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../../resources/js-test-style.css"/> +<script src="../../../js/js-test-pre.js"></script> +<script src="../../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<script> +var contextVersion = 2; +</script> +<script src="../../../js/tests/tex-input-validation.js"></script> +<script src="../../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-mipmap-levels.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-mipmap-levels.html new file mode 100644 index 000000000..17920ea02 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-mipmap-levels.html @@ -0,0 +1,280 @@ +<!-- + +/* +** Copyright (c) 2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL2 Non-Power of 2 texture 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="2" height="2" style="width: 2px; height: 2px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> +uniform vec4 uMult; +attribute vec4 vPosition; +attribute vec2 texCoord0; +varying vec2 texCoord; +void main() +{ + gl_Position = vPosition * uMult; + texCoord = texCoord0; +} +</script> + +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; +uniform sampler2D tex; +varying vec2 texCoord; +void main() +{ + gl_FragColor = texture2D(tex, texCoord); +} +</script> + +<script id="vshader_texsize" type="x-shader/x-vertex">#version 300 es +in vec4 vPosition; +void main() +{ + gl_Position = vPosition; +} +</script> + +<script id="fshader_texsize_2d" type="x-shader/x-fragment">#version 300 es + +precision mediump float; +uniform sampler2D tex; +uniform int lod; +uniform ivec2 texSize; +out vec4 fragColor; +void main() +{ + fragColor = (textureSize(tex, lod) == texSize ? vec4(255, 0, 0, 255) : vec4(0, 0, 0, 255)); +} +</script> + +<script id="fshader_texsize_3d" type="x-shader/x-fragment">#version 300 es +precision mediump float; +uniform highp sampler3D tex; +uniform int lod; +uniform ivec3 texSize; +out vec4 fragColor; +void main() +{ + fragColor = (textureSize(tex, lod) == texSize ? vec4(255, 0, 0, 255) : vec4(0, 0, 0, 255)); +} +</script> + + +<script> +"use strict"; +description(document.title); +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("example", undefined, 2); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + +(function() { + debug(""); + debug("test mipmap level ranges"); + var tex = gl.createTexture(); + wtu.setupUnitQuad(gl, 0, 1); + var program = wtu.setupProgram( + gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]); + + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.BLEND); + gl.uniform1i(gl.getUniformLocation(program, "tex"), 0); + + var multLoc = gl.getUniformLocation(program, "uMult"); + gl.uniform4f(multLoc, 1, 1, 1, 1); + + // Test that filling partial levels is enough for mipmapping. + gl.bindTexture(gl.TEXTURE_2D, tex); + wtu.fillTexture(gl, tex, 8, 8, [255, 0, 0, 255], 2, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(8x8, level=2) should succeed"); + wtu.fillTexture(gl, tex, 4, 4, [0, 255, 0, 255], 3, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(4x4, level=3) should succeed"); + wtu.fillTexture(gl, tex, 2, 2, [0, 0, 255, 255], 4, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(2x2, level=4) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 4); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAX_LEVEL) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAG_FILTER) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MIN_FILTER) should succeed"); + wtu.clearAndDrawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed"); + wtu.checkCanvas(gl, [0, 0, 255, 255], "should draw with [0, 0, 255, 255]"); + + // Test that generateMipmap works with partial levels. + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed"); + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [255, 0, 0, 255], "should draw with [255, 0, 0, 255]"); + gl.deleteTexture(tex); + + // Test incompleteless for partial levels. + tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + wtu.fillTexture(gl, tex, 8, 8, [255, 0, 0, 255], 2, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(8x8, level=2) should succeed"); + wtu.fillTexture(gl, tex, 4, 4, [255, 0, 0, 255], 3, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(4x4, level=3) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 4); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAX_LEVEL) should succeed"); + wtu.clearAndDrawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed"); + wtu.checkCanvas(gl, [0, 0, 0, 255], "incomplete texture should draw with [0, 0, 0, 255]"); + gl.deleteTexture(tex); + + // Test base level texture isn't specified. + tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + wtu.fillTexture(gl, tex, 8, 8, [255, 0, 0, 255], 2, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(8x8, level=2) should succeed"); + wtu.fillTexture(gl, tex, 4, 4, [255, 0, 0, 255], 3, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(4x4, level=3) should succeed"); + wtu.fillTexture(gl, tex, 2, 2, [0, 0, 255, 255], 4, gl.RGBA, gl.UNSIGNED_BYTE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fillTexture(2x2, level=4) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed"); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail if base level texture is not specified"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 2); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed"); + gl.deleteTexture(tex); + + // Test 3D texture. + var tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + gl.texImage3D( gl.TEXTURE_3D, 0, gl.RGBA, 8, 8, 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 8 * 4)); + gl.generateMipmap(gl.TEXTURE_3D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed"); + gl.texSubImage3D(gl.TEXTURE_3D, 1, 0, 0, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4 * 4 * 4 * 4)); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed"); + gl.deleteTexture(tex3d); + + // Test 2D array texture. + var tex2dArray = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex2dArray); + gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, 8, 8, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 4 * 4)); + gl.generateMipmap(gl.TEXTURE_2D_ARRAY); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed"); + gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 1, 0, 0, 0, 4, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4 * 4 * 4 * 4)); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed"); + gl.deleteTexture(tex2dArray); + + // Test sized internal format should be both color-renderable and texture-filterable + tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed for zero-size texture"); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 8, 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 4)); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed"); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8UI, 8, 8, 0, gl.RGBA_INTEGER, gl.UNSIGNED_BYTE, new Uint8Array(8 * 8 * 4)); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail for non-texture-filterable format"); + if (gl.getExtension('EXT_color_buffer_float')) { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 8, 8, 0, gl.RGBA, gl.FLOAT, new Float32Array(8 * 8 * 4)); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "generateMipmap should fail for float texture"); + } + if (gl.getExtension('EXT_color_buffer_float') && gl.getExtension('OES_texture_float_linear')) { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 0, 0, 0, gl.RGBA, gl.FLOAT, null); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed for zero-size texture"); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, 8, 8, 0, gl.RGBA, gl.FLOAT, new Float32Array(8 * 8 * 4)); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed"); + } + gl.deleteTexture(tex); + + // Test textureSize should work correctly with non-zero base level for texStorage2D + var program = wtu.setupProgram( + gl, ['vshader_texsize', 'fshader_texsize_2d'], ['vPosition'], [0]); + + gl.uniform1i(gl.getUniformLocation(program, "tex"), 0); + gl.uniform1i(gl.getUniformLocation(program, "lod"), 1); + gl.uniform2i(gl.getUniformLocation(program, "texSize"), 7, 4); + tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAG_FILTER) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MIN_FILTER) should succeed"); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed"); + gl.texStorage2D(gl.TEXTURE_2D, 4, gl.RGBA8, 31, 17); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage2D should succeed"); + wtu.clearAndDrawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed"); + wtu.checkCanvas(gl, [255, 0, 0, 255], "should draw with [255, 0, 0, 255]"); + gl.deleteTexture(tex); + + // Test textureSize should work correctly with non-zero base level for texStorage3D + var program = wtu.setupProgram( + gl, ['vshader_texsize', 'fshader_texsize_3d'], ['vPosition'], [0]); + + gl.uniform1i(gl.getUniformLocation(program, "tex"), 0); + gl.uniform1i(gl.getUniformLocation(program, "lod"), 1); + gl.uniform3i(gl.getUniformLocation(program, "texSize"), 8, 4, 2); + tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MAG_FILTER) should succeed"); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_MIN_FILTER) should succeed"); + gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_BASE_LEVEL, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texParameter(TEXTURE_BASE_LEVEL) should succeed"); + gl.texStorage3D(gl.TEXTURE_3D, 4, gl.RGBA8, 32, 16, 8); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage3D should succeed"); + wtu.clearAndDrawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "clearAndDrawQuad should succeed"); + wtu.checkCanvas(gl, [255, 0, 0, 255], "should draw with [255, 0, 0, 255]"); + gl.deleteTexture(tex3d); + +})(); + +var successfullyParsed = true; + +</script> +<script src="../../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-new-formats.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-new-formats.html new file mode 100644 index 000000000..8c5fba975 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-new-formats.html @@ -0,0 +1,586 @@ +<!-- + +/* +** Copyright (c) 2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Conformance test for WebGL2 texture image formats specification</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> +"use strict"; +description("This test verifies that texture image specification entry points " + + "accept new formats introduced in WebGL2, and accept sized internalformats."); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var vao = null; + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + runTexFormatsTest(); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +function enumToString(value) { + return wtu.glEnumToString(gl, value); +} + +function runTexFormatsTest() +{ + // texFormats is Table 3.2 and Table 3.3 from the OpenGL ES 3.0.4 spec. + var texFormats = [ + { + sizedformat: "RGBA8", + unsizedformat: "RGBA", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RGB5_A1", + unsizedformat: "RGBA", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RGBA4", + unsizedformat: "RGBA", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "SRGB8_ALPHA8", + unsizedformat: "RGBA", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RGBA8_SNORM", + unsizedformat: "RGBA", + type: "BYTE", + }, + { + sizedformat: "RGBA4", + unsizedformat: "RGBA", + type: "UNSIGNED_SHORT_4_4_4_4", + }, + { + sizedformat: "RGB5_A1", + unsizedformat: "RGBA", + type: "UNSIGNED_SHORT_5_5_5_1", + }, + { + sizedformat: "RGB10_A2", + unsizedformat: "RGBA", + type: "UNSIGNED_INT_2_10_10_10_REV", + }, + { + sizedformat: "RGB5_A1", + unsizedformat: "RGBA", + type: "UNSIGNED_INT_2_10_10_10_REV", + }, + { + sizedformat: "RGBA16F", + unsizedformat: "RGBA", + type: "HALF_FLOAT", + }, + { + sizedformat: "RGBA32F", + unsizedformat: "RGBA", + type: "FLOAT", + }, + { + sizedformat: "RGBA16F", + unsizedformat: "RGBA", + type: "FLOAT", + }, + { + sizedformat: "RGBA8UI", + unsizedformat: "RGBA_INTEGER", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RGBA8I", + unsizedformat: "RGBA_INTEGER", + type: "BYTE", + }, + { + sizedformat: "RGBA16UI", + unsizedformat: "RGBA_INTEGER", + type: "UNSIGNED_SHORT", + }, + { + sizedformat: "RGBA16I", + unsizedformat: "RGBA_INTEGER", + type: "SHORT", + }, + { + sizedformat: "RGBA32UI", + unsizedformat: "RGBA_INTEGER", + type: "UNSIGNED_INT", + }, + { + sizedformat: "RGBA32I", + unsizedformat: "RGBA_INTEGER", + type: "INT", + }, + { + sizedformat: "RGB10_A2UI", + unsizedformat: "RGBA_INTEGER", + type: "UNSIGNED_INT_2_10_10_10_REV", + }, + { + sizedformat: "RGB8", + unsizedformat: "RGB", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RGB565", + unsizedformat: "RGB", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "SRGB8", + unsizedformat: "RGB", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RGB8_SNORM", + unsizedformat: "RGB", + type: "BYTE", + }, + { + sizedformat: "RGB565", + unsizedformat: "RGB", + type: "UNSIGNED_SHORT_5_6_5", + }, + { + sizedformat: "R11F_G11F_B10F", + unsizedformat: "RGB", + type: "UNSIGNED_INT_10F_11F_11F_REV", + }, + { + sizedformat: "RGB9_E5", + unsizedformat: "RGB", + type: "UNSIGNED_INT_5_9_9_9_REV", + }, + { + sizedformat: "RGB16F", + unsizedformat: "RGB", + type: "HALF_FLOAT", + }, + { + sizedformat: "R11F_G11F_B10F", + unsizedformat: "RGB", + type: "HALF_FLOAT", + }, + { + sizedformat: "RGB9_E5", + unsizedformat: "RGB", + type: "HALF_FLOAT", + }, + { + sizedformat: "RGB32F", + unsizedformat: "RGB", + type: "FLOAT", + }, + { + sizedformat: "RGB16F", + unsizedformat: "RGB", + type: "FLOAT", + }, + { + sizedformat: "R11F_G11F_B10F", + unsizedformat: "RGB", + type: "FLOAT", + }, + { + sizedformat: "RGB9_E5", + unsizedformat: "RGB", + type: "FLOAT", + }, + { + sizedformat: "RGB8UI", + unsizedformat: "RGB_INTEGER", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RGB8I", + unsizedformat: "RGB_INTEGER", + type: "BYTE", + }, + { + sizedformat: "RGB16UI", + unsizedformat: "RGB_INTEGER", + type: "UNSIGNED_SHORT", + }, + { + sizedformat: "RGB16I", + unsizedformat: "RGB_INTEGER", + type: "SHORT", + }, + { + sizedformat: "RGB32UI", + unsizedformat: "RGB_INTEGER", + type: "UNSIGNED_INT", + }, + { + sizedformat: "RGB32I", + unsizedformat: "RGB_INTEGER", + type: "INT", + }, + { + sizedformat: "RG8", + unsizedformat: "RG", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RG8_SNORM", + unsizedformat: "RG", + type: "BYTE", + }, + { + sizedformat: "RG16F", + unsizedformat: "RG", + type: "HALF_FLOAT", + }, + { + sizedformat: "RG32F", + unsizedformat: "RG", + type: "FLOAT", + }, + { + sizedformat: "RG16F", + unsizedformat: "RG", + type: "FLOAT", + }, + { + sizedformat: "RG8UI", + unsizedformat: "RG_INTEGER", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "RG8I", + unsizedformat: "RG_INTEGER", + type: "BYTE", + }, + { + sizedformat: "RG16UI", + unsizedformat: "RG_INTEGER", + type: "UNSIGNED_SHORT", + }, + { + sizedformat: "RG16I", + unsizedformat: "RG_INTEGER", + type: "SHORT", + }, + { + sizedformat: "RG32UI", + unsizedformat: "RG_INTEGER", + type: "UNSIGNED_INT", + }, + { + sizedformat: "RG32I", + unsizedformat: "RG_INTEGER", + type: "INT", + }, + { + sizedformat: "R8", + unsizedformat: "RED", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "R8_SNORM", + unsizedformat: "RED", + type: "BYTE", + }, + { + sizedformat: "R16F", + unsizedformat: "RED", + type: "HALF_FLOAT", + }, + { + sizedformat: "R32F", + unsizedformat: "RED", + type: "FLOAT", + }, + { + sizedformat: "R16F", + unsizedformat: "RED", + type: "FLOAT", + }, + { + sizedformat: "R8UI", + unsizedformat: "RED_INTEGER", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: "R8I", + unsizedformat: "RED_INTEGER", + type: "BYTE", + }, + { + sizedformat: "R16UI", + unsizedformat: "RED_INTEGER", + type: "UNSIGNED_SHORT", + }, + { + sizedformat: "R16I", + unsizedformat: "RED_INTEGER", + type: "SHORT", + }, + { + sizedformat: "R32UI", + unsizedformat: "RED_INTEGER", + type: "UNSIGNED_INT", + }, + { + sizedformat: "R32I", + unsizedformat: "RED_INTEGER", + type: "INT", + }, + { + sizedformat: "DEPTH_COMPONENT16", + unsizedformat: "DEPTH_COMPONENT", + type: "UNSIGNED_SHORT", + }, + { + sizedformat: "DEPTH_COMPONENT24", + unsizedformat: "DEPTH_COMPONENT", + type: "UNSIGNED_INT", + }, + { + sizedformat: "DEPTH_COMPONENT16", + unsizedformat: "DEPTH_COMPONENT", + type: "UNSIGNED_INT", + }, + { + sizedformat: "DEPTH_COMPONENT32F", + unsizedformat: "DEPTH_COMPONENT", + type: "FLOAT", + }, + { + sizedformat: "DEPTH24_STENCIL8", + unsizedformat: "DEPTH_STENCIL", + type: "UNSIGNED_INT_24_8", + }, + // No good typed array type for this format, just allow this format when pixel is null. + { + sizedformat: "DEPTH32F_STENCIL8", + unsizedformat: "DEPTH_STENCIL", + type: "FLOAT_32_UNSIGNED_INT_24_8_REV", + }, + // internalFormat of texImage2D may be unsized format according Table 3.3 in OpenGL ES 3.0.4 spec. + { + sizedformat: undefined, + unsizedformat: "RGBA", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: undefined, + unsizedformat: "RGBA", + type: "UNSIGNED_SHORT_4_4_4_4", + }, + { + sizedformat: undefined, + unsizedformat: "RGBA", + type: "UNSIGNED_SHORT_5_5_5_1", + }, + { + sizedformat: undefined, + unsizedformat: "RGB", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: undefined, + unsizedformat: "RGB", + type: "UNSIGNED_SHORT_5_6_5", + }, + { + sizedformat: undefined, + unsizedformat: "LUMINANCE_ALPHA", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: undefined, + unsizedformat: "LUMINANCE", + type: "UNSIGNED_BYTE", + }, + { + sizedformat: undefined, + unsizedformat: "ALPHA", + type: "UNSIGNED_BYTE", + }, + ]; + + texFormats.forEach(function(texformat){ + debug(""); + debug("Testing sized format " + texformat.sizedformat + + ", unsized format " + texformat.unsizedformat + + ", type " + texformat.type); + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + var sizedformat = gl[texformat.sizedformat]; + var unsizedformat = gl[texformat.unsizedformat]; + var type = gl[texformat.type]; + + // prepare some good data to feed texImage2D and friends for this type + var data; + switch(type) { + case gl.UNSIGNED_BYTE: + data = new Uint8Array(4); + break; + case gl.BYTE: + data = new Int8Array(4); + break; + case gl.UNSIGNED_SHORT: + case gl.UNSIGNED_SHORT_4_4_4_4: + case gl.UNSIGNED_SHORT_5_5_5_1: + case gl.UNSIGNED_SHORT_5_6_5: + case gl.HALF_FLOAT: + data = new Uint16Array(4); + break; + case gl.SHORT: + data = new Int16Array(4); + break; + case gl.UNSIGNED_INT: + case gl.UNSIGNED_INT_5_9_9_9_REV: + case gl.UNSIGNED_INT_10F_11F_11F_REV: + case gl.UNSIGNED_INT_2_10_10_10_REV: + case gl.UNSIGNED_INT_24_8: + data = new Uint32Array(4); + break; + case gl.INT: + data = new Int32Array(4); + break; + case gl.FLOAT: + data = new Float32Array(4); + break; + case gl.FLOAT_32_UNSIGNED_INT_24_8_REV: + data = null; + } + + // prepare some bad data that doesn't fit this type + var baddata = (data instanceof Float32Array) + ? new Uint8Array(4) + : new Float32Array(4); + + // test texImage2D with unsized internalformat + if (!sizedformat) { + gl.texImage2D(gl.TEXTURE_2D, 0, unsizedformat, 1, 1, 0, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D should succeed with unsized internalformat"); + gl.texImage2D(gl.TEXTURE_2D, 0, unsizedformat, 1, 1, 0, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D should fail with unsized internalformat and data of wrong type"); + } else { + // test texImage2D with sized internalformat + gl.texImage2D(gl.TEXTURE_2D, 0, sizedformat, 1, 1, 0, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D should succeed with sized internalformat"); + gl.texImage2D(gl.TEXTURE_2D, 0, sizedformat, 1, 1, 0, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D should fail with sized internalformat and data of wrong type"); + } + + // test texSubImage2D + if (gl.FLOAT_32_UNSIGNED_INT_24_8_REV != type) { + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed"); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage2D should fail with data of wrong type"); + } + + // test texStorage2D + if (sizedformat) { + gl.texStorage2D(gl.TEXTURE_2D, 1, sizedformat, 1, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage2D should succeed"); + if (gl.FLOAT_32_UNSIGNED_INT_24_8_REV != type) { + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed on immutable-format texture"); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage2D should fail on immutable-format texture with data of wrong type"); + } + } + + // Test a 3D texture. + // Formats containing a depth component can't be used for 3D textures. + var isdepthformat = + unsizedformat == gl.DEPTH_COMPONENT || + unsizedformat == gl.DEPTH_STENCIL; + if (!isdepthformat) { + var tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + + // test texImage3D with unsized internalformat + if (!sizedformat) { + gl.texImage3D(gl.TEXTURE_3D, 0, unsizedformat, 1, 1, 1, 0, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed with unsized internalformat"); + gl.texImage3D(gl.TEXTURE_3D, 0, unsizedformat, 1, 1, 1, 0, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D should fail with unsized internalformat and data of wrong type"); + } else { + // test texImage3D with sized internalformat + gl.texImage3D(gl.TEXTURE_3D, 0, sizedformat, 1, 1, 1, 0, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D should succeed with sized internalformat"); + gl.texImage3D(gl.TEXTURE_3D, 0, sizedformat, 1, 1, 1, 0, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage3D should fail with sized internalformat and data of wrong type"); + } + + // test texSubImage3D + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed"); + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D should fail with data of wrong type"); + + if (sizedformat) { + gl.texStorage3D(gl.TEXTURE_3D, 1, sizedformat, 1, 1, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage3D should succeed"); + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed on immutable-format texture"); + gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 1, 1, 1, unsizedformat, type, baddata); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D should fail on immutable-format texture with data of wrong type"); + } + } + }); +} + +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/textures/misc/tex-srgb-mipmap.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-srgb-mipmap.html new file mode 100644 index 000000000..e7f2cbbdd --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-srgb-mipmap.html @@ -0,0 +1,227 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL texture mipmap 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="4" height="4" style="width: 16px; height: 16px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> +uniform vec4 uMult; +attribute vec4 vPosition; +attribute vec2 texCoord0; +varying vec2 texCoord; +void main() +{ + gl_Position = vPosition * uMult; + texCoord = texCoord0; +} +</script> + +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; +uniform sampler2D tex; +varying vec2 texCoord; +void main() +{ + gl_FragColor = texture2D(tex, texCoord); +} +</script> +<script> +"use strict"; +var canvas; +var wtu = WebGLTestUtils; + +function generateMipmap() +{ + description("Generate mipmaps for sRGB texture"); + + canvas = document.getElementById("example"); + var gl = wtu.create3DContext(canvas); + + wtu.setupUnitQuad(gl, 0, 1); + var program = wtu.setupProgram( + gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]); + + gl.disable(gl.DEPTH_TEST); + gl.disable(gl.BLEND); + + var colors = { + blank: [0, 0, 0, 0], + srgba: [0, 63, 127, 255], + }; + + var texLoc = gl.getUniformLocation(program, "tex"); + gl.uniform1i(texLoc, 0); + var multLoc = gl.getUniformLocation(program, "uMult"); + + var width = 128; + var height = 128; + canvas.width = width; + canvas.height = height; + gl.viewport(0, 0, width, height); + + var srgbTex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, srgbTex); + gl.uniform4f(multLoc, 1, 1, 1, 1); + // Set full texture as srgba color first. + wtu.fillTexture(gl, srgbTex, width, height, colors['srgba'], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.SRGB8_ALPHA8); + // Set up-left region of the texture as red color. + // In order to make sure bi-linear interpolation operates on different colors, red region + // is 1 pixel smaller than a quarter of the full texture on each side. + var redWidth = width / 2 - 1; + var redHeight = height / 2 - 1; + var buf = new Uint8Array(redWidth * redHeight * 4); + for (var i = 0; i < redWidth * redHeight; i++) { + buf[4 * i + 0] = 255; + buf[4 * i + 1] = 0; + buf[4 * i + 2] = 0; + buf[4 * i + 3] = 255; + } + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf); + gl.generateMipmap(gl.TEXTURE_2D); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); + + // Decode the srgba texture to a linear texture which will be used as reference. + var linearTex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, linearTex); + wtu.fillTexture(gl, linearTex, width, height, wtu.sRGBToLinear(colors['srgba']), 0, gl.RGBA, gl.UNSIGNED_BYTE); + // Set up-left region of the texture as red color. + // In order to make sure bi-linear interpolation operates on different colors, red region + // is 1 pixel smaller than a quarter of the full texture on each side. + for (var i = 0; i < redWidth * redHeight; i++) { + buf[4 * i + 0] = 255; + buf[4 * i + 1] = 0; + buf[4 * i + 2] = 0; + buf[4 * i + 3] = 255; + } + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf); + gl.generateMipmap(gl.TEXTURE_2D); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); + + // Change canvas to a small size. + width = 64; + height = 64; + canvas.width = width; + canvas.height = height; + gl.viewport(0, 0, width, height); + + // Draw with srgb texture and linear texture respectively. + gl.bindTexture(gl.TEXTURE_2D, srgbTex); + wtu.clearAndDrawUnitQuad(gl); + var result = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, result); + gl.bindTexture(gl.TEXTURE_2D, linearTex); + wtu.clearAndDrawUnitQuad(gl); + var reference = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, reference); + + gl.deleteTexture(srgbTex); + gl.deleteTexture(linearTex); + + var tolerance = 7; + var diff = new Uint8Array(width * height * 4); + var failed = compare(result, reference, tolerance, diff); + if (failed) { + testFailed("Generate wrong mipmaps for sRGB texture."); + displayDiff(result, reference, diff, width, height); + } else { + testPassed("Generate correct mipmaps for sRGB texture."); + } + + function compare(cmp, ref, tolerance, diff) { + if (cmp.length != ref.length) { + testFailed("invalid pixel size."); + } + + var count = 0; + for (var i = 0; i < cmp.length; i++) { + diff[i * 4] = 0; + diff[i * 4 + 1] = 255; + diff[i * 4 + 2] = 0; + diff[i * 4 + 3] = 255; + if (Math.abs(cmp[i * 4] - ref[i * 4]) > tolerance || + Math.abs(cmp[i * 4 + 1] - ref[i * 4 + 1]) > tolerance || + Math.abs(cmp[i * 4 + 2] - ref[i * 4 + 2]) > tolerance || + Math.abs(cmp[i * 4 + 3] - ref[i * 4 + 3]) > tolerance) { + debug("Pixel " + i + ": expected (" + + [ref[i * 4], ref[i * 4 + 1], ref[i * 4 + 2], ref[i * 4 + 3]] + "), got (" + + [cmp[i * 4], cmp[i * 4 + 1], cmp[i * 4 + 2], cmp[i * 4 + 3]] + ")"); + count++; + diff[i * 4] = 255; + diff[i * 4 + 1] = 0; + } + } + + return count; + } + + function displayDiff(cmp, ref, diff, width, height) { + var div = document.createElement("div"); + + var cmpImg = createImage(cmp, width, height); + var refImg = createImage(ref, width, height); + var diffImg = createImage(diff, width, height); + wtu.insertImage(div, "Reference", refImg); + wtu.insertImage(div, "Result", cmpImg); + wtu.insertImage(div, "Difference", diffImg); + + var console = document.getElementById("console"); + console.appendChild(div); + } + + function createImage(buf, width, height) { + var canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + var ctx = canvas.getContext("2d"); + var imgData = ctx.getImageData(0, 0, width, height); + + for (var i = 0; i < buf.length; i++) + imgData.data[i] = buf[i]; + ctx.putImageData(imgData, 0, 0); + var img = wtu.makeImageFromCanvas(canvas); + return img; + } +} + +generateMipmap(); +var successfullyParsed = true; +</script> +<script src="../../../js/js-test-post.js"></script> + +</body> +</html> + diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-2d.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-2d.html new file mode 100644 index 000000000..e4c3c436a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-2d.html @@ -0,0 +1,294 @@ +<!-- + +/* +** Copyright (c) 2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>texStorage2D 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> +<canvas id="canvas" width="64" height="64"> </canvas> +<div id="console"></div> + + +<script> +"use strict"; +description("This test verifies the functionality of texStorage2D."); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var vao = null; + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + runTexStorage2DTest(); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +function enumToString(value) { + return wtu.glEnumToString(gl, value); +} + +function runTexStorage2DTest() +{ + var texStorage2DTestCases = [ + { + target: gl.TEXTURE_2D, + mipmap: false, + sizedformat: gl.RGBA8, + unsizedformat: gl.RGBA, + type: gl.UNSIGNED_BYTE, + alpha: true, + redpixel: new Uint8Array([0xff, 0x00, 0x00, 0x00]), + }, + { + target: gl.TEXTURE_2D, + mipmap: true, + sizedformat: gl.R11F_G11F_B10F, + unsizedformat: gl.RGB, + type: gl.UNSIGNED_INT_10F_11F_11F_REV, + alpha: false, + // Red is unsigned floating point with 5 exponent bits followed by 6 mantissa bits. + // The effective value is 2^(exponent - 15) * (1 + mantissa / 64) + // See OpenGL ES 3.0.3 spec, section 2.1.3 + // Here we want to encode the value 1.0, which we achieve with a zero mantissa + // and an exponent of 15. + redpixel: new Uint32Array([15<<6]), + }, + { + target: gl.TEXTURE_2D, + mipmap: true, + sizedformat: gl.RGBA32F, + unsizedformat: gl.RGBA, + type: gl.FLOAT, + alpha: true, + redpixel: new Float32Array([1, 0, 0, 0]), + }, + { + target: gl.TEXTURE_CUBE_MAP, + mipmap: true, + sizedformat: gl.RGBA8, + unsizedformat: gl.RGBA, + type: gl.UNSIGNED_BYTE, + alpha: true, + redpixel: new Uint8Array([0xff, 0x00, 0x00, 0x00]), + }, + { + target: gl.TEXTURE_CUBE_MAP, + mipmap: false, + sizedformat: gl.RGB8, + unsizedformat: gl.RGB, + type: gl.UNSIGNED_BYTE, + alpha: false, + redpixel: new Uint8Array([0xff, 0x00, 0x00]), + }, + { + target: gl.TEXTURE_CUBE_MAP, + mipmap: true, + sizedformat: gl.RGB10_A2UI, + unsizedformat: gl.UNSIGNED_INT_2_10_10_10_REV, // type enum, bad as format + }, + { + target: gl.TEXTURE_CUBE_MAP, + mipmap: false, + sizedformat: gl.R11F_G11F_B10F, + unsizedformat: gl.RGB, + } + ]; + + texStorage2DTestCases.forEach(function(testcase){ + var target = testcase.target; + var imageTargets; + + if (target == gl.TEXTURE_2D) { + imageTargets = [ gl.TEXTURE_2D ]; + } else { + imageTargets = [ gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ]; + } + + var tex = gl.createTexture(); + gl.bindTexture(target, tex); + var texsize = 4; + var levels = testcase.mipmap + ? Math.floor(Math.log(texsize) / Math.log(2)) + 1 + : 1; + + debug(""); + debug("Testing texStorage2D with target " + enumToString(target) + ", " + + (testcase.mipmap ? "mipmap" : "no mipmap") + ", " + + "internalformat: " + enumToString(testcase.sizedformat)); + + gl.texStorage2D(target, levels, testcase.sizedformat, + 0, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for zero width"); + gl.texStorage2D(target, levels, testcase.sizedformat, + texsize, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for zero height"); + gl.texStorage2D(target, levels, testcase.sizedformat, + texsize, -texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for negative height"); + gl.texStorage2D(target, 0, testcase.sizedformat, + texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage2D should fail for zero levels"); + gl.texStorage2D(target, + Math.ceil(Math.log(texsize) / Math.log(2)) + 2, + testcase.sizedformat, + texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage2D should fail for too many levels"); + gl.texStorage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, levels, testcase.sizedformat, + texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage2D should fail for bad target TEXTURE_CUBE_MAP_NEGATIVE_X"); + + gl.bindTexture(target, null); + gl.texStorage2D(target, levels, testcase.sizedformat, + texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage2D should fail when no texture is bound"); + gl.bindTexture(target, tex); + + // texStorage2D should only accept sized internalformats + gl.texStorage2D(target, levels, testcase.unsizedformat, + texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage2D should fail for bad internalformat " + enumToString(testcase.unsizedformat)); + + // OK, now let's finally do the successfull texStorage2D call + gl.texStorage2D(target, levels, testcase.sizedformat, + texsize, texsize); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage2D should succeed with a good sized internalformat"); + + // check TEXTURE_IMMUTABLE_FORMAT + var immutable = gl.getTexParameter(target, gl.TEXTURE_IMMUTABLE_FORMAT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getTexParameter should succeed with TEXTURE_IMMUTABLE_FORMAT"); + assertMsg(immutable != 0, "getTexParameter with TEXTURE_IMMUTABLE_FORMAT should not return 0"); + + // check operations disallowed on immutable texture + gl.texImage2D(imageTargets[0], 0, gl.RGBA, texsize, texsize, 0, + gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texImage2D should fail on immutable texture"); + var s3tc = gl.getExtension("WEBGL_compressed_texture_s3tc"); + // FIXME - should eventually use a compressed format that's core in WebGL2, but + // I wanted something that I can run in Firefox today, which doesn't support the new formats yet. + if (s3tc) { + gl.compressedTexImage2D(imageTargets[0], 0, s3tc.COMPRESSED_RGBA_S3TC_DXT3_EXT, + texsize, texsize, 0, + new Uint8Array(texsize * texsize)); + } + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexImage2D should fail on immutable texture"); + gl.copyTexImage2D(imageTargets[0], 0, gl.RGBA, 0, 0, texsize, texsize, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "copyTexImage2D should fail on immutable texture"); + + if ('redpixel' in testcase) { + // At this point, the texture images have only been defined by + // texStorage2D, which per spec should be equivalent to having + // defined texture images with null data, which should sample as RGBA 0,0,0,0. + gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, + testcase.mipmap ? gl.NEAREST_MIPMAP_NEAREST : gl.NEAREST); + if (testcase.type == gl.FLOAT) { + gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + } + + // Now upload some red texture data + var s = texsize; + var pixels; + if (testcase.redpixel instanceof Uint8Array) { + pixels = new Uint8Array(texsize * texsize * testcase.redpixel.length); + } else if (testcase.redpixel instanceof Uint16Array) { + pixels = new Uint16Array(texsize * texsize * testcase.redpixel.length); + } else if (testcase.redpixel instanceof Uint32Array) { + pixels = new Uint32Array(texsize * texsize * testcase.redpixel.length); + } else if (testcase.redpixel instanceof Float32Array) { + pixels = new Float32Array(texsize * texsize * testcase.redpixel.length); + } + for (var i = 0; i < texsize * texsize; i++) { + for (var j = 0; j < testcase.redpixel.length; j++) { + pixels[i * testcase.redpixel.length + j] = testcase.redpixel[j]; + } + } + + if (target == gl.TEXTURE_2D) { + wtu.setupTexturedQuad(gl); + } else if (target == gl.TEXTURE_CUBE_MAP) { + wtu.setupTexturedQuadWithCubeMap(gl); + } + + wtu.clearAndDrawUnitQuad(gl); + var alpha = testcase.alpha ? 0 : 255; + wtu.checkCanvas(gl, [0, 0, 0, alpha], "texture should sample as uninitialized texture after texStorage2D"); + + if (target == gl.TEXTURE_2D) { + for (var l = 0; l < levels; l++) { + gl.texSubImage2D(gl.TEXTURE_2D, + l, 0, 0, + s, s, + testcase.unsizedformat, testcase.type, + pixels); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed on immutable texture as long as the format is compatible"); + s /= 2; + } + } else if (target == gl.TEXTURE_CUBE_MAP) { + for (var l = 0; l < levels; l++) { + for (var f = 0; f < 6; f++) { + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + f, + l, 0, 0, + s, s, + testcase.unsizedformat, testcase.type, + pixels); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed on immutable texture as long as the format is compatible"); + } + s /= 2; + } + } + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [255, 0, 0, alpha], "texture should sample as red after uploading red pixels with texSubImage2D"); + } + }); +} + +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/textures/misc/tex-storage-and-subimage-3d.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-and-subimage-3d.html new file mode 100644 index 000000000..8588d5b7b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-and-subimage-3d.html @@ -0,0 +1,234 @@ +<!-- + +/* +** Copyright (c) 2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>texStorage3D and texSubImage3D 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> +<canvas id="canvas" width="64" height="64"> </canvas> +<div id="console"></div> + + +<script> +"use strict"; +description("This test verifies the functionality of texStorage3D and texSubImage3D."); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var vao = null; + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + runTexStorageAndSubImage3DTest(); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +function enumToString(value) { + return wtu.glEnumToString(gl, value); +} + +function runTexStorageAndSubImage3DTest() +{ + var texStorage3DTestCases = [ + { + target: gl.TEXTURE_3D, + mipmap: false, + sizedformat: gl.RGBA8, + unsizedformat: gl.RGBA, + type: gl.UNSIGNED_BYTE, + alpha: true, + redpixel: new Uint8Array([0xff, 0x00, 0x00, 0x00]), + }, + { + target: gl.TEXTURE_3D, + mipmap: true, + sizedformat: gl.R11F_G11F_B10F, + unsizedformat: gl.RGB, + type: gl.UNSIGNED_INT_10F_11F_11F_REV, + alpha: false, + // Red is unsigned floating point with 5 exponent bits followed by 6 mantissa bits. + // The effective value is 2^(exponent - 15) * (1 + mantissa / 64) + // See OpenGL ES 3.0.3 spec, section 2.1.3 + // Here we want to encode the value 1.0, which we achieve with a zero mantissa + // and an exponent of 15. + redpixel: new Uint32Array([15<<6]), + }, + { + target: gl.TEXTURE_3D, + mipmap: true, + sizedformat: gl.RGBA32F, + unsizedformat: gl.RGBA, + type: gl.FLOAT, + alpha: true, + redpixel: new Float32Array([1, 0, 0, 0]), + }, + ]; + + texStorage3DTestCases.forEach(function(testcase){ + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex); + var texsize = 4; + var levels = testcase.mipmap + ? Math.floor(Math.log(texsize) / Math.log(2)) + 1 + : 1; + + debug(""); + debug("Testing texStorage3D with " + + (testcase.mipmap ? "mipmap" : "no mipmap") + ", " + + "internalformat: " + enumToString(testcase.sizedformat)); + + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat, + 0, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero width"); + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat, + texsize, 0, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero height"); + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat, + texsize, texsize, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero depth"); + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat, + texsize, -texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for negative height"); + gl.texStorage3D(gl.TEXTURE_3D, 0, testcase.sizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texStorage3D should fail for zero levels"); + if (testcase.mipmap) { + gl.texStorage3D(gl.TEXTURE_3D, + levels + 1, + testcase.sizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage3D should fail for too many levels"); + } + gl.texStorage3D(gl.TEXTURE_2D, + levels, + testcase.sizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage3D should fail for target TEXTURE_2D"); + gl.texStorage3D(gl.TEXTURE_CUBE_MAP, + levels, + testcase.sizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage3D should fail for target TEXTURE_CUBE_MAP"); + gl.bindTexture(gl.TEXTURE_3D, null); + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage3D should fail when no texture is bound"); + gl.bindTexture(gl.TEXTURE_3D, tex); + + // texStorage3D should only accept sized internalformats + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.unsizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "texStorage3D should fail for bad internalformat " + enumToString(testcase.unsizedformat)); + + var pixels; + var number_of_pixels = texsize * texsize * texsize; + if (testcase.redpixel instanceof Uint8Array) { + pixels = new Uint8Array(number_of_pixels * testcase.redpixel.length); + } else if (testcase.redpixel instanceof Uint16Array) { + pixels = new Uint16Array(number_of_pixels * testcase.redpixel.length); + } else if (testcase.redpixel instanceof Uint32Array) { + pixels = new Uint32Array(number_of_pixels * testcase.redpixel.length); + } else if (testcase.redpixel instanceof Float32Array) { + pixels = new Float32Array(number_of_pixels * testcase.redpixel.length); + } + for (var i = 0; i < number_of_pixels; i++) { + for (var j = 0; j < testcase.redpixel.length; j++) { + pixels[i * testcase.redpixel.length + j] = testcase.redpixel[j]; + } + } + + gl.texSubImage3D(gl.TEXTURE_2D, + 0, 0, 0, 0, + texsize, texsize, texsize, + testcase.unsizedformat, testcase.type, + pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, + "texSubImage3D should generate INVALID_ENUM if passed TEXTURE_2D target"); + gl.texSubImage3D(gl.TEXTURE_3D, + 0, 0, 0, 0, + texsize, texsize, texsize, + testcase.unsizedformat, testcase.type, + pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "texSubImage3D should fail if texStorage3D has not succeeded"); + + // OK, now let's finally do the successfull texStorage3D call + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texStorage3D should succeed with a good sized internalformat"); + + // Subsequent texStorage3D calls should fail, even identical ones. + gl.texStorage3D(gl.TEXTURE_3D, levels, testcase.sizedformat, + texsize, texsize, texsize); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texStorage3D should fail on immutable-format texture"); + + var s = texsize; + for (var l = 0; l < levels; l++) { + gl.texSubImage3D(gl.TEXTURE_3D, + l, 0, 0, 0, + s, s, s, + testcase.unsizedformat, testcase.type, + pixels); + s /= 2; + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D should succeed on immutable texture as long as the format is compatible"); + } + gl.texSubImage3D(gl.TEXTURE_3D, + levels, 0, 0, 0, + texsize, texsize, texsize, + testcase.unsizedformat, testcase.type, + pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "texSubImage3D should fail for too-high level"); + gl.texSubImage3D(gl.TEXTURE_3D, + 0, 1, 0, 0, + texsize, texsize, texsize, + testcase.unsizedformat, testcase.type, + pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "texSubImage3D should fail for dimension out of range"); + }); +} + +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/textures/misc/tex-storage-compressed-formats.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-compressed-formats.html new file mode 100644 index 000000000..4f4295f10 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-storage-compressed-formats.html @@ -0,0 +1,124 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Conformance test for WebGL2 texStorage2D and texStorage3D with compressed format</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> +"use strict"; +description("This test verifies that texStorage2D and texStorage3D " + + "accept compressed internalformats."); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var WEBGL_compressed_texture_etc = gl.getExtension("WEBGL_compressed_texture_etc"); +var vao = null; + +if (!gl) { + testFailed("WebGL context does not exist"); +} else if (!WEBGL_compressed_texture_etc) { + testPassed("No WEBGL_compressed_texture_etc support -- this is legal"); +} else { + testPassed("WebGL context exists"); + + runTexCompressedFormatsTest(); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +function enumToString(value) { + return wtu.glEnumToString(gl, value); +} + +function runTexCompressedFormatsTest() +{ + // These compressed formats are in Table 3.19 from the OpenGL ES 3.0.4 spec. + var texCompressedFormats = [ + WEBGL_compressed_texture_etc.COMPRESSED_R11_EAC, + WEBGL_compressed_texture_etc.COMPRESSED_SIGNED_R11_EAC, + WEBGL_compressed_texture_etc.COMPRESSED_RG11_EAC, + WEBGL_compressed_texture_etc.COMPRESSED_SIGNED_RG11_EAC, + WEBGL_compressed_texture_etc.COMPRESSED_RGB8_ETC2, + WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_ETC2, + WEBGL_compressed_texture_etc.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + WEBGL_compressed_texture_etc.COMPRESSED_RGBA8_ETC2_EAC, + WEBGL_compressed_texture_etc.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + ]; + + texCompressedFormats.forEach(function(internalformat){ + // Test a 2D texture. + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texStorage2D(gl.TEXTURE_2D, 1, internalformat, 1, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "texStorage2D should succeed for " + enumToString(internalformat)); + gl.deleteTexture(tex); + + // GLES 3.0.4 p147: + // "If internalformat is an ETC2/EAC format, CompressedTexImage3D will generate an + // INVALID_OPERATION error if target is not TEXTURE_2D_ARRAY." + + // Test the 3D texture targets. + var tex3d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + gl.texStorage3D(gl.TEXTURE_3D, 1, internalformat, 1, 1, 1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "texStorage3D(TEXTURE_3D) should fail for " + enumToString(internalformat)); + gl.deleteTexture(tex3d); + + var tex2dArr = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex2dArr); + gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, internalformat, 1, 1, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "texStorage3D(TEXTURE_2D_ARRAY) should succeed for " + enumToString(internalformat)); + gl.deleteTexture(tex2dArr); + }); +} + +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/textures/misc/tex-unpack-params.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params.html new file mode 100644 index 000000000..73c0958d0 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params.html @@ -0,0 +1,612 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL2 texture unpack parameters 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="4" height="4"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +var wtu = WebGLTestUtils; +var __verbose__ = false; + +// Some drivers (for example, NVIDIA Linux) incorrectly require padding for +// the last row. The below flag is only for testing convenience. Browsers should +// work around the bug. +var __apply_alignment_workaround__ = false; + +function setupArrayBuffer(size, initData) { + var array = new Uint8Array(size); + if (initData) { + for (var ii = 0; ii < size; ++ii) { + array[ii] = ii % 255; + } + } + return array; +} + +function calculatePaddingBytes(bytesPerPixel, alignment, width) { + var padding = 0; + switch (alignment) { + case 1: + case 2: + case 4: + case 8: + padding = (bytesPerPixel * width) % alignment; + if (padding > 0) + padding = alignment - padding; + return padding; + default: + testFailed("should not reach here"); + return; + } +} + +function computeImageSizes2D(width, height, testCase) { + // Assume RGB8/UNSIGNED_BYTE + var bytesPerPixel = 3; + var actualWidth = testCase.rowLength == 0 ? width : testCase.rowLength; + var padding = calculatePaddingBytes(bytesPerPixel, testCase.alignment, actualWidth); + var bytesPerRow = actualWidth * bytesPerPixel + padding; + var bytesLastRow = bytesPerPixel * width; + var size = bytesPerRow * (height - 1) + bytesLastRow; + var skipSize = 0; + if (testCase.skipPixels > 0) + skipSize += bytesPerPixel * testCase.skipPixels; + if (testCase.skipRows > 0) + skipSize += bytesPerRow * testCase.skipRows; + return {size: size, + bytesPerRow: bytesPerRow, + bytesLastRow: bytesLastRow, + padding: padding, + skipSize: skipSize, + totalSize: size + skipSize}; +} + +function computeImageSizes3D(width, height, depth, testCase) { + // Assume RGB8/UNSIGNED_BYTE + var bytesPerPixel = 3; + var actualWidth = testCase.rowLength == 0 ? width : testCase.rowLength; + var actualHeight = testCase.imageHeight == 0 ? height : testCase.imageHeight; + var padding = calculatePaddingBytes(bytesPerPixel, testCase.alignment, actualWidth); + var bytesPerRow = actualWidth * bytesPerPixel + padding; + var bytesLastRow = bytesPerPixel * width; + var bytesPerImage = bytesPerRow * actualHeight; + var bytesLastImage = bytesPerRow * (height - 1) + bytesLastRow; + var size = bytesPerImage * (depth - 1) + bytesLastImage; + var skipSize = 0; + if (testCase.skipPixels > 0) + skipSize += bytesPerPixel * testCase.skipPixels; + if (testCase.skipRows > 0) + skipSize += bytesPerRow * testCase.skipRows; + if (testCase.skipImages > 0) + skipSize += bytesPerImage * testCase.skipImages; + return {size: size, + bytesPerRow: bytesPerRow, + bytesLastRow: bytesLastRow, + bytesPerImage: bytesPerImage, + bytesLastImage: bytesLastImage, + padding: padding, + skipSize: skipSize, + totalSize: size + skipSize}; +} + +function copyData(srcData, srcIndex, dstData, dstIndex, size) { + for (var ii = 0; ii < size; ++ii) + dstData[dstIndex + ii] = srcData[srcIndex + ii]; +} + +function unpackPixels(srcData, width, height, depth, imageSizes) { + var bytesPerPixel = 3; + var unpackedSize = width * height * depth * bytesPerPixel; + var dstData = setupArrayBuffer(unpackedSize, false); + var srcIndex = imageSizes.skipSize; + var dstIndex = 0; + for (var z = 0; z < depth; ++z) { + var srcIndexPerImage = srcIndex; + for (var y = 0; y < height; ++y) { + copyData(srcData, srcIndexPerImage, dstData, dstIndex, width * 3); + srcIndexPerImage += imageSizes.bytesPerRow; + dstIndex += width * 3; + } + if (depth > 1) + srcIndex += imageSizes.bytesPerImage; + } + return dstData; +} + +function getPixelsFromTexture2D(gl, tex, xoffset, yoffset, width, height) { + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); + var bytesPerReadbackPixel = 4; + var readbackBuffer = setupArrayBuffer(width * height * bytesPerReadbackPixel, false); + gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readbackBuffer); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "read back texture pixels should succeed"); + var bytesPerPixel = 3; + var buffer = setupArrayBuffer(width * height * bytesPerPixel, false); + var srcIndex = 0; + var dstIndex = 0; + for (var y = 0; y < height; ++y) { + for (var x = 0; x < width; ++x) { + buffer[dstIndex++] = readbackBuffer[srcIndex++]; // R + buffer[dstIndex++] = readbackBuffer[srcIndex++]; // G + buffer[dstIndex++] = readbackBuffer[srcIndex++]; // B + srcIndex++; // A + } + } + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + return buffer; +} + +function getPixelsFromTexture3D(gl, tex, xoffset, yoffset, zoffset, width, height, depth) { + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + var bytesPerReadbackPixel = 4; + var readbackBuffer = setupArrayBuffer(width * height * bytesPerReadbackPixel, false); + var bytesPerPixel = 3; + var buffer = setupArrayBuffer(width * height * depth * bytesPerPixel, false); + var dstIndex = 0; + for (var zz = 0; zz < depth; ++zz) { + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, zz + zoffset); + gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readbackBuffer); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "read back texture pixels should succeed"); + var srcIndex = 0; + for (var y = 0; y < height; ++y) { + for (var x = 0; x < width; ++x) { + buffer[dstIndex++] = readbackBuffer[srcIndex++]; // R + buffer[dstIndex++] = readbackBuffer[srcIndex++]; // G + buffer[dstIndex++] = readbackBuffer[srcIndex++]; // B + srcIndex++; // A + } + } + } + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); + return buffer; +} + +function comparePixels(buffer1, buffer2) { + if (buffer1.length != buffer2.length || buffer1.length % 3 != 0) { + testFailed("compare pixels: invalid buffer size"); + return; + } + var count = 0; + for (var ii = 0; ii < buffer1.length / 3; ++ii) { + if (buffer1[ii * 3] != buffer2[ii * 3] || + buffer1[ii * 3 + 1] != buffer2[ii * 3 + 1] || + buffer1[ii * 3 + 2] != buffer2[ii * 3 + 2]) { + if (__verbose__) { + debug("Pixel " + ii + ": expected (" + + [buffer1[ii * 3], buffer1[ii * 3 + 1], buffer1[ii * 3 + 2]] + "), got (" + + [buffer2[ii * 3], buffer2[ii * 3 + 1], buffer2[ii * 3 + 2]] + ")"); + } + count++; + } + } + if (count > 0) { + testFailed("compare pixels: " + count + " pixels differ"); + } else { + testPassed("compare pixels: as expected"); + } +} + +function runTestIteration2D(gl, testCase, useUnpackBuffer) { + debug(""); + debug("Texture upload from " + (useUnpackBuffer ? "unpack buffer" : "client data") + + " : alignment = " + testCase.alignment + ", rowLength = " + testCase.rowLength + + ", skipPixels = " + testCase.skipPixels + ", skipRows = " + testCase.skipRows); + debug("TexImage2D : size = (" + testCase.width + ", " + testCase.height + ")"); + gl.pixelStorei(gl.UNPACK_ALIGNMENT, testCase.alignment); + gl.pixelStorei(gl.UNPACK_ROW_LENGTH, testCase.rowLength); + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, testCase.skipPixels); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, testCase.skipRows); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up pixel store parameters should succeed"); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + var imageSizes = computeImageSizes2D(testCase.width, testCase.height, testCase); + var bufferSize = imageSizes.totalSize; + var buffer = null; + var array; + + // Verify buffer with less than enough size will fail. + if (useUnpackBuffer) { + buffer = gl.createBuffer(); + gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer); + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0, + gl.RGB, gl.UNSIGNED_BYTE, 0); + } else { + array = setupArrayBuffer(bufferSize - 1, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0, + gl.RGB, gl.UNSIGNED_BYTE, array); + } + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small"); + + if (__apply_alignment_workaround__) + bufferSize += imageSizes.padding; + array = setupArrayBuffer(bufferSize, true); + if (useUnpackBuffer) { + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW); + } + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0, + gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array); + if (testCase.validUnpackParams2D) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D with correct buffer size should succeed"); + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination"); + if (!useUnpackBuffer) { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0, + gl.RGB, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "unpack param constraints do not apply if no data are uploaded."); + } + return; + } + + var buffer1 = unpackPixels(array, testCase.width, testCase.height, 1, imageSizes); + var buffer2 = getPixelsFromTexture2D(gl, tex, 0, 0, testCase.width, testCase.height); + comparePixels(buffer1, buffer2); + + var subWidth = testCase.width - testCase.xoffset; + var subHeight = testCase.height - testCase.yoffset; + debug("TexSubImage2D : offset = (" + testCase.xoffset + ", " + testCase.yoffset + + "), size = (" + subWidth + ", " + subHeight + ")"); + imageSizes = computeImageSizes2D(subWidth, subHeight, testCase); + bufferSize = imageSizes.totalSize; + + if (useUnpackBuffer) { + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW); + gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset, + subWidth, subHeight, gl.RGB, gl.UNSIGNED_BYTE, 0); + } else { + array = setupArrayBuffer(bufferSize - 1, false); + gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset, + subWidth, subHeight, gl.RGB, gl.UNSIGNED_BYTE, array); + } + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small"); + + if (__apply_alignment_workaround__) + bufferSize += imageSizes.padding; + array = setupArrayBuffer(bufferSize, true); + if (useUnpackBuffer) { + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW); + } + gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset, subWidth, subHeight, + gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array); + if (testCase.validUnpackParamsForSub2D) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D with correct buffer size should succeed"); + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination"); + return; + } + + var buffer1 = unpackPixels(array, subWidth, subHeight, 1, imageSizes); + var buffer2 = getPixelsFromTexture2D( + gl, tex, testCase.xoffset, testCase.yoffset, subWidth, subHeight); + comparePixels(buffer1, buffer2); + + if (buffer) { + gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null); + gl.deleteBuffer(buffer); + } + gl.bindTexture(gl.TEXTURE_2D, null); + gl.deleteTexture(tex); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error"); +} + +function runTestIteration3D(gl, testCase, useUnpackBuffer) { + debug(""); + debug("Texture upload from " + (useUnpackBuffer ? "unpack buffer" : "client data") + + " : alignment = " + testCase.alignment + ", rowLength = " + testCase.rowLength + + ", imageHeight = " + testCase.imageHeight + ", skipPixels = " + testCase.skipPixels + + ", skipRows = " + testCase.skipRows + ", skipImages = " + testCase.skipImages); + debug("TexImage3D : size = (" + testCase.width + ", " + testCase.height + ", " + testCase.depth + ")"); + gl.pixelStorei(gl.UNPACK_ALIGNMENT, testCase.alignment); + gl.pixelStorei(gl.UNPACK_ROW_LENGTH, testCase.rowLength); + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, testCase.imageHeight); + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, testCase.skipPixels); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, testCase.skipRows); + gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, testCase.skipImages); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up pixel store parameters should succeed"); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_3D, tex); + + var imageSizes = computeImageSizes3D(testCase.width, testCase.height, testCase.depth, testCase); + var buffer = null; + var array; + var bufferSize = imageSizes.totalSize; + + // Verify buffer with less than enough size will fail. + if (useUnpackBuffer) { + buffer = gl.createBuffer(); + gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer); + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW); + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0, + gl.RGB, gl.UNSIGNED_BYTE, 0); + } else { + array = setupArrayBuffer(bufferSize - 1, false); + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0, + gl.RGB, gl.UNSIGNED_BYTE, array); + } + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small"); + + if (__apply_alignment_workaround__) + bufferSize += imageSizes.padding; + array = setupArrayBuffer(bufferSize, true); + if (useUnpackBuffer) { + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW); + } + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0, + gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array); + if (testCase.validUnpackParams3D) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D with correct buffer size should succeed"); + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination"); + if (!useUnpackBuffer) { + gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0, + gl.RGB, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "unpack param constraints do not apply if no data are uploaded."); + } + return; + } + + var buffer1 = unpackPixels(array, testCase.width, testCase.height, testCase.depth, imageSizes); + var buffer2 = getPixelsFromTexture3D( + gl, tex, 0, 0, 0, testCase.width, testCase.height, testCase.depth); + comparePixels(buffer1, buffer2); + + var subWidth = testCase.width - testCase.xoffset; + var subHeight = testCase.height - testCase.yoffset; + var subDepth = testCase.depth - testCase.zoffset; + debug("TexSubImage3D : offset = (" + testCase.xoffset + ", " + testCase.yoffset + ", " + + testCase.zoffset + "), size = (" + subWidth + ", " + subHeight + ", " + subDepth + ")"); + imageSizes = computeImageSizes3D(subWidth, subHeight, subDepth, testCase); + bufferSize = imageSizes.totalSize; + + if (useUnpackBuffer) { + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW); + gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset, + subWidth, subHeight, subDepth, gl.RGB, gl.UNSIGNED_BYTE, 0); + } else { + array = setupArrayBuffer(bufferSize - 1, false); + gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset, + subWidth, subHeight, subDepth, gl.RGB, gl.UNSIGNED_BYTE, array); + } + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small"); + + if (__apply_alignment_workaround__) + bufferSize += imageSizes.padding; + array = setupArrayBuffer(bufferSize, true); + if (useUnpackBuffer) { + gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW); + } + gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset, + subWidth, subHeight, subDepth, + gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array); + if (testCase.validUnpackParamsForSub3D) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D with correct buffer size should succeed"); + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination"); + return; + } + + buffer1 = unpackPixels(array, subWidth, subHeight, subDepth, imageSizes); + buffer2 = getPixelsFromTexture3D(gl, tex, testCase.xoffset, testCase.yoffset, testCase.zoffset, + subWidth, subHeight, subDepth); + comparePixels(buffer1, buffer2); + + if (buffer) { + gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null); + gl.deleteBuffer(buffer); + } + gl.bindTexture(gl.TEXTURE_3D, null); + gl.deleteTexture(tex); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error"); +} + +function runTests() { + var gl = wtu.create3DContext("example", undefined, 2); + if (!gl) { + testFailed("Fail to get a WebGL context"); + return; + } + + // For 2D cases, depth, zoffset, imageHeight, skipImages are ignored. + var testCases = [ + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 1, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 5, height: 7, depth: 4, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 2, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 6, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 4, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 5, height: 8, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 8, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + + // ROW_LENGTH == width + { width: 10, height: 9, depth: 2, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 4, rowLength: 10, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + + // ROW_LENGTH < width + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 1, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 2, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 4, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 8, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: false, validUnpackParams3D: false }, + + // ROW_LENGTH > width + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 1, rowLength: 6, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 2, rowLength: 7, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 4, rowLength: 8, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 5, height: 7, depth: 5, xoffset: 2, yoffset: 3, zoffset: 2, + alignment: 8, rowLength: 9, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + + // IMAGE_HEIGHT == height + { width: 6, height: 7, depth: 4, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 8, rowLength: 0, imageHeight: 7, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + + // IMAGE_HEIGHT < height + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 1, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 2, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 4, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 8, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: false }, + + // IMAGE_HEIGHT > height + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 1, rowLength: 0, imageHeight: 8, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 6, height: 7, depth: 3, xoffset: 2, yoffset: 2, zoffset: 1, + alignment: 2, rowLength: 0, imageHeight: 9, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 7, height: 7, depth: 3, xoffset: 2, yoffset: 4, zoffset: 1, + alignment: 4, rowLength: 0, imageHeight: 10, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + { width: 8, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 8, rowLength: 0, imageHeight: 11, skipPixels: 0, skipRows: 0, skipImages: 0, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: true, validUnpackParamsForSub3D: true }, + + // SKIP parameters + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 1, rowLength: 0, imageHeight: 0, skipPixels: 10, skipRows: 0, skipImages: 0, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 2, rowLength: 0, imageHeight: 0, skipPixels: 2, skipRows: 8, skipImages: 0, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 4, rowLength: 0, imageHeight: 0, skipPixels: 3, skipRows: 5, skipImages: 1, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 8, rowLength: 0, imageHeight: 0, skipPixels: 7, skipRows: 0, skipImages: 2, + validUnpackParams2D: false, validUnpackParams3D: false }, + + // all mixed. + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 1, rowLength: 6, imageHeight: 6, skipPixels: 3, skipRows: 5, skipImages: 1, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 2, rowLength: 4, imageHeight: 8, skipPixels: 7, skipRows: 2, skipImages: 2, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1, + alignment: 4, rowLength: 10, imageHeight: 2, skipPixels: 0, skipRows: 3, skipImages: 1, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: false }, + { width: 1, height: 1, depth: 1, xoffset: 0, yoffset: 0, zoffset: 0, + alignment: 2, rowLength: 3, imageHeight: 2, skipPixels: 3, skipRows: 5, skipImages: 1, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 17, height: 6, depth: 4, xoffset: 12, yoffset: 3, zoffset: 2, + alignment: 2, rowLength: 4, imageHeight: 8, skipPixels: 1, skipRows: 4, skipImages: 2, + validUnpackParams2D: false, validUnpackParams3D: false }, + { width: 8, height: 17, depth: 3, xoffset: 2, yoffset: 13, zoffset: 1, + alignment: 4, rowLength: 9, imageHeight: 2, skipPixels: 0, skipRows: 3, skipImages: 1, + validUnpackParams2D: true, validUnpackParamsForSub2D: true, + validUnpackParams3D: false }, + ]; + + // Upload textures from client data + var useUnpackBuffer = false; + for (var ii = 0; ii < testCases.length; ++ii) { + var testCase = testCases[ii]; + runTestIteration2D(gl, testCase, useUnpackBuffer); + runTestIteration3D(gl, testCase, useUnpackBuffer); + } + + // Upload textures from unpack buffer + useUnpackBuffer = true; + for (var ii = 0; ii < testCases.length; ++ii) { + var testCase = testCases[ii]; + runTestIteration2D(gl, testCase, useUnpackBuffer); + runTestIteration3D(gl, testCase, useUnpackBuffer); + } +} + +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/textures/misc/texel-fetch-undefined.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texel-fetch-undefined.html new file mode 100644 index 000000000..7f176b573 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texel-fetch-undefined.html @@ -0,0 +1,104 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL texel fetch test.</title> +<link rel="stylesheet" href="../../../resources/js-test-style.css"/> +<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/> +<script src="../../../js/js-test-pre.js"></script> +<script src="../../../js/webgl-test-utils.js"></script> +<script src="../../../js/glsl-conformance-test.js"></script> +</head> +<body> +<canvas id="c" width="256" height="256"></canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vertex-shader" type="x-shader/x-vertex">#version 300 es + precision highp float; + in vec4 aPosition; + + void main() { + gl_Position = aPosition; + } +</script> +<script id="fragment-shader" type="x-shader/x-fragment">#version 300 es + precision mediump float; + uniform sampler2D uSampler; + uniform ivec2 uTestPos; + + out vec4 my_FragColor; + void main() { + my_FragColor = texelFetch(uSampler, uTestPos, 0); + } +</script> +<script> +"use strict"; +description("This test makes sure that texelFetch works to the WebGL 2.0 spec when retrieving a texel outside of the texture's size."); + +var wtu = WebGLTestUtils; +var textureSize = 24; + +var gl = wtu.create3DContext('c', undefined, 2); + +function testFetchAt(x, y, expectedColor) { + debug(""); + debug("Test fetching a texel of the texture at x = " + x +", y = " + y); + gl.uniform2i(uTestPos, x, y); + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, expectedColor); +} + +var program = wtu.setupProgram(gl, ["vertex-shader", "fragment-shader"]); +var aPosition = gl.getAttribLocation(program, "aPosition"); +var uTestPos = gl.getUniformLocation(program, "uTestPos"); + +debug('Creating a texture with size ' + textureSize + '*' + textureSize); +var tex = gl.createTexture(); +gl.bindTexture(gl.TEXTURE_2D, tex); +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); +wtu.fillTexture(gl, tex, textureSize, textureSize, [0, 255, 0, 255]); + +wtu.setupUnitQuad(gl, aPosition); + +testFetchAt(0, 0, [0, 255, 0, 255]); +testFetchAt(textureSize - 1, textureSize - 1, [0, 255, 0, 255]); +testFetchAt(textureSize, 0, [0, 0, 0, 0]); +testFetchAt(0, textureSize, [0, 0, 0, 0]); +testFetchAt(-1, 0, [0, 0, 0, 0]); +testFetchAt(0, -1, [0, 0, 0, 0]); +testFetchAt(-1, 1, [0, 0, 0, 0]); + +finishTest(); +</script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texture-npot.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texture-npot.html new file mode 100644 index 000000000..19ae44b19 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/texture-npot.html @@ -0,0 +1,181 @@ +<!-- + +/* +** Copyright (c) 2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL2 Non-Power of 2 texture 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="5" height="3" style="width: 40px; height: 30px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex"> +attribute vec4 vPosition; +attribute vec2 texCoord0; +varying vec2 texCoord; +void main() +{ + gl_Position = vPosition; + texCoord = texCoord0; +} +</script> + +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; +uniform samplerCube tex; +varying vec2 texCoord; +void main() +{ + gl_FragColor = textureCube(tex, normalize(vec3(texCoord, 1))); +} +</script> +<script> +"use strict"; +description(document.title); +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("example", undefined, 2); +var program = wtu.setupTexturedQuad(gl); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + +var tests = [ + { format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + color: [192, 0, 128, 64], + expected: [192, 0, 128, 64], + tolerance: 0, + }, + { format: gl.RGB, + type: gl.UNSIGNED_BYTE, + color: [192, 0, 128], + expected: [192, 0, 128, 255], + tolerance: 0, + }, + { format: gl.LUMINANCE, + type: gl.UNSIGNED_BYTE, + color: [192], + expected: [192, 192, 192, 255], + tolerance: 0, + }, + { format: gl.ALPHA, + type: gl.UNSIGNED_BYTE, + color: [64], + expected: [0, 0, 0, 64], + tolerance: 0, + }, + { format: gl.LUMINANCE_ALPHA, + type: gl.UNSIGNED_BYTE, + color: [192, 64], + expected: [192, 192, 192, 64], + tolerance: 0, + }, +]; + +tests.forEach(function(test) { + debug(""); + debug("test " + wtu.glEnumToString(gl, test.format) + "/" + wtu.glEnumToString(gl, test.type)); + var tex = gl.createTexture(); + + // Check that an NPOT texture not on level 0 does not generate INVALID_VALUE + wtu.fillTexture(gl, tex, 5, 3, test.color, 1, test.format, test.type); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "gl.texImage2D with NPOT texture with level > 0 should succeed"); + + // Check that an NPOT texture on level 0 succeeds + wtu.fillTexture(gl, tex, 5, 3, test.color, 0, test.format, test.type); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "gl.texImage2D with NPOT texture at level 0 should succeed"); + + // Check that generateMipmap succeeds on NPOT + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "gl.generateMipmap with NPOT texture should succeed"); + + // Check that nothing is drawn if filtering is not correct for NPOT + 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.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas( + gl, test.expected, + "NPOT texture with TEXTURE_WRAP set to REPEAT should draw"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + + 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_MIPMAP_LINEAR); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas( + gl, test.expected, + "NPOT texture with TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas( + gl, test.expected, + "NPOT texture with TEXTURE_MIN_FILTER set to LINEAR should draw."); + + gl.copyTexImage2D(gl.TEXTURE_2D, 1, test.format, 0, 0, 5, 3, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "copyTexImage2D with NPOT texture with level > 0 should succeed."); + + // Check that generateMipmap for an POT texture succeeds + wtu.fillTexture(gl, tex, 2, 2, test.color, 0, test.format); + gl.generateMipmap(gl.TEXTURE_2D); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "gl.texImage2D and gl.generateMipmap with POT texture at level 0 should succeed"); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas( + gl, test.expected, + "POT texture with TEXTURE_MIN_FILTER set to LINEAR_MIPMAP_LINEAR should draw."); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); +}); + +var successfullyParsed = true; + +</script> +<script src="../../../js/js-test-post.js"></script> + +</body> +</html> + |