diff options
Diffstat (limited to '')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html new file mode 100644 index 0000000000..4befe35c93 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/misc/uninitialized-test-2.html @@ -0,0 +1,583 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL 2 Uninitialized GL Resources Tests</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="2" height="2"> </canvas> +<script> +"use strict"; +description("Tests to check user code cannot access uninitialized data from GL resources."); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("canvas", undefined, 2); +if (!gl) + testFailed("Context created."); +else + testPassed("Context created."); + +// This is the maximum size that will end up being allocated with the tests +// currently written as they are. It could need to be increased later. +var scratchBuffer = new ArrayBuffer(1024 * 1024 * 8 * 4); +function zeroArrayBuffer(arr) { + for (var i = 0; i < arr.length; ++i) { + arr[i] = 0; + } +} +function getUint32Array(length) { + var arr = new Uint32Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} +function getInt32Array(length) { + var arr = new Int32Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} +function getUint8Array(length) { + var arr = new Uint8Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} +function getInt8Array(length) { + var arr = new Int8Array(scratchBuffer, 0, length); + zeroArrayBuffer(arr); + return arr; +} + +function setupTexture(target, texWidth, texHeight, texDepth) { + var is3d = (target == gl.TEXTURE_3D || target == gl.TEXTURE_2D_ARRAY); + var texture = gl.createTexture(); + gl.bindTexture(target, texture); + if (is3d) { + gl.texImage3D(target, 0, gl.RGBA8, texWidth, texHeight, texDepth, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } else if (target == gl.TEXTURE_2D) { + gl.texImage2D(target, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } else { + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA8, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + } + + // this can be quite undeterministic so to improve odds of seeing uninitialized data write bits + // into tex then delete texture then re-create one with same characteristics (driver will likely reuse mem) + // with this trick on r59046 WebKit/OSX I get FAIL 100% of the time instead of ~15% of the time. + + var badData = getUint8Array(texWidth * texHeight * texDepth * 4); + for (var i = 0; i < badData.length; ++i) + badData[i] = i % 255; + + if (is3d) { + gl.texSubImage3D(target, 0, 0, 0, 0, texWidth, texHeight, texDepth, gl.RGBA, gl.UNSIGNED_BYTE, badData); + } else if (target == gl.TEXTURE_2D) { + gl.texSubImage2D(target, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + } else { + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, badData); + } + gl.finish(); // make sure it has been uploaded + + gl.deleteTexture(texture); + gl.finish(); // make sure it has been deleted + + var texture = gl.createTexture(); + gl.bindTexture(target, texture); + return texture; +} + +function checkNonZeroPixels(texture, target, format, type, texWidth, texHeight, level, layer, exceptions) { + var tol = 2; + var is3d = (target == gl.TEXTURE_3D || target == gl.TEXTURE_2D_ARRAY); + switch (target) { + case gl.TEXTURE_CUBE_MAP_POSITIVE_X: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_X: + case gl.TEXTURE_CUBE_MAP_POSITIVE_Y: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: + case gl.TEXTURE_CUBE_MAP_POSITIVE_Z: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: + gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); + break; + default: + gl.bindTexture(target, null); + break; + } + var fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + if (is3d) { + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, level, layer); + } else { + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, texture, level); + } + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); + + var data; + switch (type) { + case gl.UNSIGNED_INT: + data = getUint32Array(texWidth * texHeight * 4); + break; + case gl.INT: + data = getInt32Array(texWidth * texHeight * 4); + break; + case gl.UNSIGNED_BYTE: + default: + data = getUint8Array(texWidth * texHeight * 4); + break; + } + gl.readPixels(0, 0, texWidth, texHeight, format, type, data); + + var k = 0; + var failed_exceptions = 0; + for (var y = 0; y < texHeight; ++y) { + for (var x = 0; x < texWidth; ++x) { + var index = (y * texWidth + x) * 4; + var is_exception = false; + for (var ii = 0; ii < exceptions.length; ++ii) { + if (exceptions[ii].x == x && exceptions[ii].y == y) { + is_exception = true; + if (Math.abs(data[index] - exceptions[ii].r) > tol || + Math.abs(data[index + 1] - exceptions[ii].g) > tol || + Math.abs(data[index + 2] - exceptions[ii].b) > tol || + Math.abs(data[index + 3] - exceptions[ii].a) > tol) { + failed_exceptions++; + } + } + } + if (is_exception) + continue; + for (var i = 0; i < 4; ++i) { + if (data[index + i] != 0) { + k++; + } + } + } + } + var info = "Level = " + level; + if (is3d) + info += ", layer = " + layer; + info += " : "; + if (k) { + testFailed(info + "found " + k + " non-zero elements"); + } else { + testPassed(info + "all data initialized"); + } + if (exceptions.length > 0) { + if (failed_exceptions) { + testFailed(info + "found " + failed_exceptions + " elements incorrectly overwritten"); + } else { + testPassed(info + "all initialized elements stay untouched"); + } + } +} + +function testTexImage3D() { + + var max_3d_texture_size = Math.min(gl.getParameter(gl.MAX_3D_TEXTURE_SIZE), 1024); + + var test_cases = [ + // TEXTURE_3D + RGBA8 + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [ { x: 0, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [ { x: 0, y: 128, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [], + }, + + // TEXTURE_3D + RGBA8UI + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [ { x: 0, y: 255, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [ { x: 128, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [], + }, + + // TEXTURE_3D + RGBA8I + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [ { x: 128, y: 255, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 256, // minimum MAX_3D_TEXTURE_SIZE is 256 + height: 256, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [ { x: 128, y: 128, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_3D", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: max_3d_texture_size, + height: max_3d_texture_size, + depth: 4, + exceptions: [], + }, + + // TEXTURE_2D_ARRAY + RGBA8 + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 1024, + height: 1024, + depth: 8, + exceptions: [ { x: 1023, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 1024, + height: 1024, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [ { x: 63, y: 32, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8", + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_BYTE, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [], + }, + + // TEXTURE_2D_ARRAY + RGBA8UI + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [ { x: 1023, y: 1023, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [ { x: 0, y: 0, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8UI", + format: gl.RGBA_INTEGER, + type: gl.UNSIGNED_BYTE, + read_type: gl.UNSIGNED_INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [], + }, + + // TEXTURE_2D_ARRAY + RGBA8I + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [ { x: 512, y: 1023, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 1024, + height: 1024, + depth: 8, + exceptions: [], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [ { x: 63, y: 32, r: 108, g: 72, b: 36, a: 9 } ], + }, + { + target: "TEXTURE_2D_ARRAY", + internal_format: "RGBA8I", + format: gl.RGBA_INTEGER, + type: gl.BYTE, + read_type: gl.INT, + width: 64, + height: 64, + depth: 256, // minimum MAX_ARRAY_TEXTURE_LAYERS is 256 + exceptions: [], + }, + + // If more tests are added here, make sure to increase the size of + // scratchBuffer above, if needed. + ]; + + for (var ii = 0; ii < test_cases.length; ++ii) { + debug(""); + var test = test_cases[ii]; + debug("TexImage3D with target = " + test.target + ", internal_format = " + test.internal_format + + ", width = " + test.width + ", height = " + test.height + ", depth = " + test.depth); + var tex = setupTexture(gl[test.target], test.width, test.height, test.depth); + gl.texImage3D(gl[test.target], 0, gl[test.internal_format], test.width, test.height, test.depth, 0, test.format, test.type, null); + for (var jj = 0; jj < test.exceptions.length; ++jj) { + var exception = test.exceptions[jj]; + var data; + switch (test.type) { + case gl.BYTE: + data = getInt8Array(4 * test.depth); + break; + case gl.UNSIGNED_BYTE: + data = getUint8Array(4 * test.depth); + break; + default: + assert(false); + } + for (var pixel = 0; pixel < test.depth; ++pixel) { + data[pixel * 4] = exception.r; + data[pixel * 4 + 1] = exception.g; + data[pixel * 4 + 2] = exception.b; + data[pixel * 4 + 3] = exception.a; + } + gl.texSubImage3D(gl[test.target], 0, exception.x, exception.y, 0, 1, 1, test.depth, test.format, test.type, data); + } + for (var layer = 0; layer < test.depth; ++layer) + checkNonZeroPixels(tex, gl[test.target], test.format, test.read_type, test.width, test.height, 0, layer, test.exceptions); + gl.deleteTexture(tex); + gl.finish(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + } +} + +function testTexStorage2D() { + var targets = [ "TEXTURE_2D", "TEXTURE_CUBE_MAP" ]; + var width = 512; + var height = 512; + var levels = 5; + + for (var ii = 0; ii < targets.length; ++ii) { + debug(""); + debug("Reading an uninitialized texture (texStorage2D) should succeed with all bytes set to 0 : target = " + targets[ii]); + var tex = setupTexture(gl[targets[ii]], width, height, 1); + gl.texStorage2D(gl[targets[ii]], levels, gl.RGBA8, width, height); + for (var level = 0; level < levels; ++level) { + if (gl[targets[ii]] == gl.TEXTURE_2D) { + checkNonZeroPixels(tex, gl[targets[ii]], gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + } else { + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_X, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_POSITIVE_Z, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + checkNonZeroPixels(tex, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, gl.RGBA, gl.UNSIGNED_BYTE, width, height, level, 0, []); + } + } + gl.deleteTexture(tex); + gl.finish(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + } +} + +function testTexStorage3D() { + var targets = [ "TEXTURE_3D", "TEXTURE_2D_ARRAY" ]; + var internal_formats = [ "RGBA8", "RGBA8UI", "RGBA8I" ]; + var formats = [ gl.RGBA, gl.RGBA_INTEGER, gl.RGBA_INTEGER ]; + var read_types = [ gl.UNSIGNED_BYTE, gl.UNSIGNED_INT, gl.INT ]; + var width = 256; // minimum MAX_3D_TEXTURE_SIZE is 256 + var height = 256; // minimum MAX_3D_TEXTURE_SIZE is 256 + var depth = 8; + var levels = 5; + + for (var ii = 0; ii < targets.length; ++ii) { + debug(""); + debug("Reading an uninitialized texture (texStorage3D) should succeed with all bytes set to 0 : target = " + targets[ii]); + for (var jj = 0; jj < internal_formats.length; ++jj) { + debug(""); + debug("Internal format : " + internal_formats[jj]); + var tex = setupTexture(gl[targets[ii]], width, height, depth); + gl.texStorage3D(gl[targets[ii]], levels, gl[internal_formats[jj]], width, height, depth); + var level_depth = depth; + for (var level = 0; level < levels; ++level) { + for (var layer = 0; layer < level_depth; ++layer) { + checkNonZeroPixels(tex, gl[targets[ii]], formats[jj], read_types[jj], width, height, level, layer, []); + } + if (gl[targets[ii]] == gl.TEXTURE_3D) + level_depth = Math.max(1, level_depth >> 1); + } + gl.deleteTexture(tex); + gl.finish(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + } + } +} + +testTexImage3D(); +testTexStorage2D(); +testTexStorage3D(); + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> + |