diff options
Diffstat (limited to '')
4 files changed, 787 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance/reading/00_test_list.txt new file mode 100644 index 0000000000..8651fbd83f --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/00_test_list.txt @@ -0,0 +1,3 @@ +--min-version 1.0.4 fbo-remains-unchanged-after-read-pixels.html +read-pixels-pack-alignment.html +read-pixels-test.html diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/fbo-remains-unchanged-after-read-pixels.html b/dom/canvas/test/webgl-conf/checkout/conformance/reading/fbo-remains-unchanged-after-read-pixels.html new file mode 100644 index 0000000000..00e8dcd9a0 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/fbo-remains-unchanged-after-read-pixels.html @@ -0,0 +1,105 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="4" height="4"></canvas> +<script id="vshader" type="x-shader/x-vertex"> +attribute vec3 a_pos; +attribute vec4 a_color; +varying vec4 v_color; + +void main() +{ + v_color = a_color; + gl_Position = vec4(a_pos.xyz, 1.0); +} +</script> + +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; + +varying vec4 v_color; + +void main() +{ + gl_FragColor = v_color; +} +</script> + +<script> +"use strict"; + +description("when antialias is enabled, verify default fbo pixels would not be changed between two readPixels without drawing operations"); +var wtu = WebGLTestUtils; +var N = 4; + +var vertices = new Float32Array([ + 1.0, 1.0, 0.0, + -1.0, -1.0, 0.0]); +var colors = new Uint8Array([ + 255, 0, 0, 255, + 255, 0, 0, 255]); + +var canvas = document.getElementById('canvas'); +var gl = wtu.create3DContext(canvas, {antialias: true}); + +if (!gl) { + testFailed("context does not exist"); +} else { + testPassed("context exists"); + + var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_pos", "a_color"]); + gl.clearColor(0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + + var colorOffset = vertices.byteLength; + var vbo = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vbo); + gl.bufferData(gl.ARRAY_BUFFER, colorOffset + colors.byteLength, gl.STATIC_DRAW); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices); + gl.bufferSubData(gl.ARRAY_BUFFER, colorOffset, colors); + + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(0); + gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, colorOffset); + gl.enableVertexAttribArray(1); + gl.drawArrays(gl.LINES, 0, vertices.length / 3); + + var result_1 = new Uint8Array(N * N * 4); + var result_2 = new Uint8Array(N * N * 4); + gl.readPixels(0, 0, N, N, gl.RGBA, gl.UNSIGNED_BYTE, result_1); + gl.readPixels(0, 0, N, N, gl.RGBA, gl.UNSIGNED_BYTE, result_2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + var tolerance = 0; + var diff = new Uint8Array(N * N * 4); + var failed = wtu.comparePixels(result_1, result_2, tolerance, diff); + + if (failed) { + testFailed("default fbo pixels had be changed between two readPixels without drawing operations"); + } else { + testPassed("default fbo pixels had not be changed between two readPixels without drawing operations."); + } + + gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.deleteBuffer(vbo); +} + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-pack-alignment.html b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-pack-alignment.html new file mode 100644 index 0000000000..3090284b05 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-pack-alignment.html @@ -0,0 +1,251 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<script id="vshader" type="x-shader/x-vertex"> +attribute vec3 pos; +attribute vec4 colorIn; +varying vec4 color; + +void main() +{ + color = colorIn; + gl_Position = vec4(pos.xyz, 1.0); +} +</script> + +<script id="fshader" type="x-shader/x-fragment"> +precision mediump float; +varying vec4 color; + +void main() +{ + gl_FragColor = color; +} +</script> +</head> +<body> +<canvas id="example" width="32" height="32"></canvas> +<canvas id="example2" width="32" height="32"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +// The below declarations need to be global for "shouldBe" to see them +var wtu = WebGLTestUtils; +var gl = null; +var array = null; +var pixel = [ 0, 0, 0, 0 ]; +var expectedColor = [ 0, 0, 0, 0 ]; + +function calculatePixelBytes(format, type) +{ + var size = 0; + switch (format) { + case gl.ALPHA: + size = 1; + break; + case gl.RGB: + size = 3; + break; + case gl.RGBA: + size = 4; + break; + default: + return -1; + } + switch (type) { + case gl.UNSIGNED_BYTE: + break; + case gl.UNSIGNED_SHORT_5_6_5: + if (format != gl.RGB) + return -1; + size = 2; + break; + case gl.UNSIGNED_SHORT_4_4_4_4: + case gl.UNSIGNED_SHORT_5_5_5_1: + if (format != gl.RGBA) + return -1; + size = 2; + break; + default: + return -1; + } + return size; +} + +function calculatePaddingBytes(bytesPerPixel, packAlignment, width) +{ + var padding = 0; + switch (packAlignment) { + case 1: + case 2: + case 4: + case 8: + padding = (bytesPerPixel * width) % packAlignment; + if (padding > 0) + padding = packAlignment - padding; + break; + default: + return -1; + } + return padding; +} + +function packColor(format, type, r, g, b, a) +{ + // FIXME: not sure if the color packing is correct for UNSIGNED_SHORT_*. + var color = [ 0, 0, 0, 0 ]; + switch (type) { + case gl.UNSIGNED_BYTE: + switch (format) { + case gl.ALPHA: + color[0] = a; + break; + case gl.RGB: + color[0] = r; + color[1] = g; + color[2] = b; + break; + case gl.RGBA: + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = a; + break; + default: + return null; + } + break; + case gl.UNSIGNED_SHORT_5_6_5: + if (format != gl.RGB) + return null; + r >>= 3; + g >>= 2; + b >>= 3; + color[0] = (r << 11) + (g << 5) + b; + break; + case gl.UNSIGNED_SHORT_4_4_4_4: + if (format != gl.RGBA) + return null; + r >>= 4; + g >>= 4; + b >>= 4; + a >>= 4; + color[0] = (r << 12) + (g << 8) + (b << 4) + a; + break; + case gl.UNSIGNED_SHORT_5_5_5_1: + if (format != gl.RGBA) + return null; + r >>= 3; + g >>= 3; + b >>= 3; + a >>= 7; + color[0] = (r << 11) + (g << 6) + (b << 1) + a; + break; + Default: + return null; + } + return color; +} + +function runTestIteration(format, type, packAlignment, width, height) +{ + debug("Testing PACK_ALIGNMENT = " + packAlignment + ", width = " + width + ", height = " + height); + gl.clearColor(1, 0.4, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.pixelStorei(gl.PACK_ALIGNMENT, packAlignment); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + var bytesPerPixel = calculatePixelBytes(format, type); + var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width); + var size = bytesPerPixel * width * height + padding * (height - 1); + if (type != gl.UNSIGNED_BYTE) { + throw "test error: only UNSIGNED_BYTE is valid to ReadPixels"; + } + if (size < 0) + size = 0; + array = new Uint8Array(size); + gl.readPixels(0, 0, width, height, format, type, array); + if (width < 0 || height < 0) { + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + return; + } + + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + if (!array.length) + return; + + // Check the last pixel of the last row. + var bytesPerRow = width * bytesPerPixel + padding; + var pos = bytesPerRow * (height - 1) + (width - 1) * bytesPerPixel; + var numComponents = bytesPerPixel; + for (var i = 0; i < numComponents; ++i) + pixel[i] = array[pos + i]; + for (var i = numComponents; i < 4; ++i) + pixel[i] = 0; + expectedColor = packColor(format, type, 255, 102, 0, 255); + shouldBeNonNull("expectedColor"); + shouldBe("pixel", "expectedColor"); +} + +description('Verify readPixels() works fine with various PACK_ALIGNMENT values.'); + + +debug("<h1>antialias = false</h1>"); +shouldBeNonNull("gl = wtu.create3DContext('example', {antialias: false})") +var formats = [ gl.RGBA ]; +var formatNames = [ "RGBA" ]; +runAllIterations(); +debug("<h1>antialias = true</h1>"); +shouldBeNonNull("gl = wtu.create3DContext('example2', {antialias: true})") +runAllIterations(); + +function runAllIterations() { + shouldBeNonNull("program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn'])"); + + for (var i = 0; i < formats.length; ++i) { + var format = formats[i]; + + debug("Testing format = " + formatNames[i] + " and type = UNSIGNED_BYTE"); + runTestIteration(format, gl.UNSIGNED_BYTE, 1, 1, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 4, 1, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 1, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 4, 2, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 2, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 4, 3, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 3, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 4, 4, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 4, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 1); + runTestIteration(format, gl.UNSIGNED_BYTE, 4, 5, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 6, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 7, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 8, 2); + runTestIteration(format, gl.UNSIGNED_BYTE, 1, 0, 0); + runTestIteration(format, gl.UNSIGNED_BYTE, 2, 0, 0); + runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, 0); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, 0, 0); + runTestIteration(format, gl.UNSIGNED_BYTE, 1, -1, 1); + runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, -1); + runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, -1); + runTestIteration(format, gl.UNSIGNED_BYTE, 8, -1, -1); + } +} +var successfullyParsed = true; + +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-test.html b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-test.html new file mode 100644 index 0000000000..078b436427 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/reading/read-pixels-test.html @@ -0,0 +1,428 @@ +<!-- +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 ReadPixels conformance test.</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/desktop-gl-constants.js"></script> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="example" width="200" height="200" style="width: 20px; height: 20px"></canvas> +<canvas id="example2" width="200" height="200" style="width: 20px; height: 20px"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("Checks that ReadPixels works as expected."); + +var wtu = WebGLTestUtils; +let gl; + +debug("<h1>antialias = false</h1>") +runTest(document.getElementById("example"), false); +debug("<h1>antialias = true</h1>") +runTest(document.getElementById("example2"), true); +finishTest(); + +var actual; +var expected; + +function runTest(canvas, antialias) { + gl = wtu.create3DContext(canvas, {antialias: antialias}); + var contextVersion = wtu.getDefault3DContextVersion(); + + var width = 2; + var height = 2; + var continueTestFunc = continueTestPart1; + + gl.clearColor(1, 1, 1, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + + // Resize the canvas to 2x2. This is an attempt to get stuff in the backbuffer. + // that shouldn't be there. + canvas.addEventListener("webglcontextlost", function(e) { e.preventDefault(); }, false); + canvas.addEventListener("webglcontextrestored", continueTestAfterContextRestored, false); + canvas.width = width; + canvas.height = height; + if (gl.getError() != gl.CONTEXT_LOST_WEBGL) { + continueTestPart1(); + } + + function continueTestAfterContextRestored() { + window.gl = wtu.create3DContext(canvas); + var func = continueTestFunc; + window.continueTestFunc = function() { testFailed("should not be here"); }; + func(); + } + + function continueTestPart1() { + gl.clearColor(0.2, 0.6, 0.4, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + + var innerColor = [51, 153, 102, 255]; // (0.2, 0.6, 0.4, 1) + var outerColor = [19, 72, 0, 198]; // Random color other than [0, 0, 0, 0] + + var tests = [ + { msg: 'in range', checkColor: innerColor, x: 0, y: 0, + oneColor: innerColor, oneX: 0, oneY: 0}, + { msg: 'off top left', checkColor: outerColor, x: -1, y: -1, + oneColor: innerColor, oneX: 1, oneY: 1}, + { msg: 'off bottom right', checkColor: outerColor, x: 1, y: 1, + oneColor: innerColor, oneX: 0, oneY: 0}, + { msg: 'completely off top ', checkColor: outerColor, x: 0, y: -2, + oneColor: outerColor, oneX: 0, oneY: 0}, + { msg: 'completely off bottom', checkColor: outerColor, x: 0, y: 2, + oneColor: outerColor, oneX: 0, oneY: 0}, + { msg: 'completely off left', checkColor: outerColor, x: -2, y: 0, + oneColor: outerColor, oneX: 0, oneY: 0}, + { msg: 'completeley off right', checkColor: outerColor, x: 2, y: 0, + oneColor: outerColor, oneX: 0, oneY: 0} + ]; + + for (var tt = 0; tt < tests.length; ++tt) { + var test = tests[tt]; + debug(""); + debug("checking: " + test.msg); + checkBuffer(test.checkColor, test.x, test.y, + test.oneColor, test.oneX, test.oneY); + } + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors"); + + function checkBuffer(checkColor, x, y, oneColor, oneX, oneY) { + var buf = new Uint8Array(width * height * 4); + // Initialize buf. + for (var ii = 0; ii < width * height; ++ii) { + buf[ii * 4] = outerColor[0]; + buf[ii * 4 + 1] = outerColor[1]; + buf[ii * 4 + 2] = outerColor[2]; + buf[ii * 4 + 3] = outerColor[3]; + } + gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf); + for (var yy = 0; yy < height; ++yy) { + for (var xx = 0; xx < width; ++xx) { + var offset = (yy * width + xx) * 4; + var expectedColors = (oneX == xx && oneY == yy) ? oneColor : checkColor; + var mismatch = false; + for (var cc = 0; cc < 4; ++cc) { + var expectedColor = expectedColors[cc]; + var color = buf[offset + cc]; + var diff = Math.abs(expectedColor - color); + if (diff >= 3) { + mismatch = true; + break; + } + } + assertMsg(!mismatch, + "color pixel at " + xx + ", " + yy + " should be about " + expectedColors + + ", was = " + [buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3]]); + } + } + } + + continueTestPart2(); + } + + function continueTestPart2() { + let neverValidFormats = [gl.DEPTH_COMPONENT, gl.DEPTH_STENCIL, desktopGL.R8, gl.RGBA4]; + let maybeValidFormats = [gl.LUMINANCE, gl.LUMINANCE_ALPHA]; + if (contextVersion < 2) { + // They are valid in WebGL 2 or higher + maybeValidFormats = maybeValidFormats.concat([desktopGL.RED, desktopGL.RG_INTEGER, desktopGL.RGBA_INTEGER]); + } + + let neverValidTypeInfo = [ + {type: desktopGL.UNSIGNED_INT_24_8, dest: new Uint32Array(4)} + ]; + let maybeValidTypeInfo = []; + if (contextVersion < 2) { + // They are valid in WebGL 2 or Higher + maybeValidTypeInfo = maybeValidTypeInfo.concat([ + {type: gl.UNSIGNED_SHORT, dest: new Uint16Array(4)}, + {type: gl.SHORT, dest: new Int16Array(4)}, + {type: gl.BYTE, dest: new Int8Array(4)}, + {type: gl.UNSIGNED_INT, dest: new Uint32Array(4)}, + {type: desktopGL.UNSIGNED_INT_2_10_10_10_REV, dest: new Uint32Array(4)} + ]); + } + + debug(""); + debug("check non-default format or type"); + for (let format of neverValidFormats) { + var buf = new Uint8Array(4); + gl.readPixels(0, 0, 1, 1, format, gl.UNSIGNED_BYTE, buf); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Should not be able to read as " + wtu.glEnumToString(gl, format)); + } + for (let format of maybeValidFormats) { + var buf = new Uint8Array(4); + gl.readPixels(0, 0, 1, 1, format, gl.UNSIGNED_BYTE, buf); + wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "Should not be able to read as " + wtu.glEnumToString(gl, format)); + } + + for (let info of neverValidTypeInfo) { + var type = info.type; + var dest = info.dest; + gl.readPixels(0, 0, 1, 1, gl.RGBA, type, dest); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Should not be able to read as " + wtu.glEnumToString(gl, type)); + } + for (let info of maybeValidTypeInfo) { + var type = info.type; + var dest = info.dest; + gl.readPixels(0, 0, 1, 1, gl.RGBA, type, dest); + wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "Should not be able to read as " + wtu.glEnumToString(gl, type)); + } + + + // - + + const combinations = [ + { + format: gl.RGB, + type: gl.UNSIGNED_SHORT_5_6_5, + dest: new Uint8Array(3), + }, + { + format: gl.RGBA, + type: gl.UNSIGNED_SHORT_5_5_5_1, + dest: new Uint16Array(1), + }, + { + format: gl.RGBA, + type: gl.UNSIGNED_SHORT_4_4_4_4, + dest: new Uint16Array(1), + }, + ]; + + const FORMATS = [ + { + format: gl.RGBA, + channels: 4, + }, { + format: gl.RGB, + channels: 3, + }, { + format: gl.LUMINANCE_ALPHA, + channels: 2, + }, { + format: gl.ALPHA, + channels: 1, + }, { + format: gl.LUMINANCE, + channels: 3, + }, + ]; + if (contextVersion >= 2) { + FORMATS.push( + { + format: gl.RED, + channels: 1, + }, { + format: gl.RG, + channels: 1, + }, { + format: gl.RGBA_INTEGER, + channels: 4, + }, { + format: gl.RGB_INTEGER, + channels: 3, + }, { + format: gl.RG_INTEGER, + channels: 2, + }, { + format: gl.RED_INTEGER, + channels: 1, + } + ); + } + + // - + + const TYPES = [ + { + type: gl.UNSIGNED_BYTE, + ctor: Uint8Array, + }, { + type: gl.BYTE, + ctor: Int8Array, + }, { + type: gl.UNSIGNED_SHORT, + ctor: Uint16Array, + }, { + type: gl.SHORT, + ctor: Int16Array, + }, { + type: gl.UNSIGNED_INT, + ctor: Uint32Array, + }, { + type: gl.INT, + ctor: Int32Array, + }, { + type: gl.FLOAT, + ctor: Float32Array, + } + ]; + + if (contextVersion >= 2) { + TYPES.push( + { + type: gl.HALF_FLOAT, + ctor: Uint16Array, + } + ); + } + + const ext = gl.getExtension('OES_texture_half_float'); + if (ext) { + TYPES.push( + { + type: ext.HALF_FLOAT_OES, + ctor: Uint16Array, + } + ); + } + + for (const t of TYPES) { + for (const f of FORMATS) { + const desc = Object.assign({}, f, t); + desc.dest = new desc.ctor(desc.channels); + combinations.push(desc); + } + } + + // - + + debug(""); + debug("check invalid combinations of format/type"); + + var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT); + var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE); + debug("IMPLEMENTATION_COLOR_READ_FORMAT: " + wtu.glEnumToString(gl, implFormat)); + debug("IMPLEMENTATION_COLOR_READ_TYPE: " + wtu.glEnumToString(gl, implType)); + + for (var tt = 0; tt < combinations.length; ++ tt) { + var info = combinations[tt]; + var format = info.format; + var type = info.type; + var dest = info.dest; + gl.readPixels(0, 0, 1, 1, format, type, dest); + // Only two format/type parameter pairs are accepted. GL_RGBA/GL_UNSIGNED_BYTE is always + // accepted on default readbuffer. The other acceptable pair can be discovered by querying + // GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. + if ((format == gl.RGBA && type == gl.UNSIGNED_BYTE) || (format == implFormat && type == implType)) { + wtu.glErrorShouldBe( + gl, gl.NO_ERROR, + "Should be able to read as " + wtu.glEnumToString(gl, format) + + " / " + wtu.glEnumToString(gl, type)); + } else { + wtu.glErrorShouldBe( + gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], + "Should not be able to read as " + wtu.glEnumToString(gl, format) + + " / " + wtu.glEnumToString(gl, type)); + } + } + + debug(""); + debug("check reading with lots of drawing"); + continueTestFunc = continueTestPart3; + width = 1024; + height = 1024; + canvas.width = width; + canvas.height = height; + if (gl.getError() != gl.CONTEXT_LOST_WEBGL) { + continueTestPart3(); + } + } + + function continueTestPart3() { + gl.viewport(0, 0, 1024, 1024); + var program = wtu.setupTexturedQuad(gl); + var loc = gl.getUniformLocation(program, "tex"); + gl.disable(gl.BLEND); + gl.disable(gl.DEPTH_TEST); + var colors = [[255, 0, 0, 255], [0, 255, 0, 255], [0, 0, 255, 255]]; + var textures = []; + var results = []; + for (var ii = 0; ii < colors.length; ++ii) { + gl.activeTexture(gl.TEXTURE0 + ii); + var tex = gl.createTexture(); + wtu.fillTexture(gl, tex, 1, 1, colors[ii]); + textures.push(tex); + } + for (var ii = 0; ii < colors.length; ++ii) { + for (var jj = 0; jj < 300 + ii + 1; ++jj) { + gl.uniform1i(loc, jj % 3); + gl.drawArrays(gl.TRIANGLES, 0, 6); + } + var buf = new Uint8Array(4); + gl.readPixels(512, 512, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf); + results.push(buf); + for (var kk = 0; kk < 99; ++kk) { + gl.uniform1i(loc, (jj + kk) % 3); + gl.drawArrays(gl.TRIANGLES, 0, 6); + } + } + for (var ii = 0; ii < colors.length; ++ii) { + var buf = results[ii]; + var color = colors[ii]; + actual = [buf[0], buf[1], buf[2], buf[3]]; + expected = [color[0], color[1], color[2], color[3]]; + shouldBe("actual", "expected"); + } + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors"); + + debug(""); + debug("check readback into Uint8ClampedArray"); + continueTestFunc = continueTestPart4; + const kSize = 32; + canvas.width = kSize; + canvas.height = kSize; + if (gl.getError() != gl.CONTEXT_LOST_WEBGL) { + continueTestPart4(); + } + } + + function continueTestPart4() { + const kSize = 32; + gl.viewport(0, 0, kSize, kSize); + gl.clearColor(0.0, 1.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + + var buf = new Uint8ClampedArray(4); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no GL errors reading back into a Uint8ClampedArray"); + if (buf[0] == 0 && buf[1] == 255 && buf[2] == 0 && buf[3] == 255) { + testPassed("Readback into Uint8ClampedArray worked successfully"); + } else { + assertMsg(false, + "color pixel at 0, 0 should be [0, 255, 0, 255], was " + + [buf[0], buf[1], buf[2], buf[3]]); + } + + const validDatas = [ + `new Uint8Array(4)`, + `new Uint8Array(new ArrayBuffer(4))`, + `new Uint8ClampedArray(4)`, + `new Uint8ClampedArray(new ArrayBuffer(4))`, + ]; + if (window.SharedArrayBuffer) { + validDatas.push( + `new Uint8Array(new SharedArrayBuffer(4))`, + `new Uint8ClampedArray(new SharedArrayBuffer(4))` + ); + } + for (const x of validDatas) { + shouldNotThrow(`gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`); + } + } +} +</script> +</body> +</html> |