summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-mochitest/test_webgl_compressed_texture_es3.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-mochitest/test_webgl_compressed_texture_es3.html')
-rw-r--r--dom/canvas/test/webgl-mochitest/test_webgl_compressed_texture_es3.html751
1 files changed, 751 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-mochitest/test_webgl_compressed_texture_es3.html b/dom/canvas/test/webgl-mochitest/test_webgl_compressed_texture_es3.html
new file mode 100644
index 0000000000..d40bd1dc7f
--- /dev/null
+++ b/dom/canvas/test/webgl-mochitest/test_webgl_compressed_texture_es3.html
@@ -0,0 +1,751 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<script src="webgl-util.js"></script>
+<script src="es3-data.js"></script>
+<title>WebGL test: test WEBGL_compressed_texture_etc extension</title>
+<style>
+img {
+ border: 1px solid black;
+ margin-right: 1em;
+}
+.testimages {
+}
+
+.testimages br {
+ clear: both;
+}
+
+.testimages > div {
+ float: left;
+ margin: 1em;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="8" height="8"></canvas>
+<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 sampler2D tex;
+ varying vec2 texCoord;
+ void main() {
+ gl_FragData[0] = texture2D(tex, texCoord);
+ }
+</script>
+<script id="fshader-r" type="x-shader/x-fragment">
+ precision mediump float;
+ uniform sampler2D tex;
+ varying vec2 texCoord;
+ void main() {
+ vec4 pixel = (texture2D(tex, texCoord));
+ pixel.r = (pixel.r + 1.0) / 2.0;
+ gl_FragData[0] = pixel;
+ }
+</script>
+<script id="fshader-rg" type="x-shader/x-fragment">
+ precision mediump float;
+ uniform sampler2D tex;
+ varying vec2 texCoord;
+ void main() {
+ vec4 pixel = (texture2D(tex, texCoord));
+ pixel.rg = (pixel.rg + 1.0) / 2.0;
+ gl_FragData[0] = pixel;
+ }
+</script>
+<script>
+"use strict";
+var ext = null;
+var vao = null;
+var gl = null;
+var validFormats = {
+ COMPRESSED_R11_EAC : 0x9270,
+ COMPRESSED_SIGNED_R11_EAC : 0x9271,
+ COMPRESSED_RG11_EAC : 0x9272,
+ COMPRESSED_SIGNED_RG11_EAC : 0x9273,
+ COMPRESSED_RGB8_ETC2 : 0x9274,
+ COMPRESSED_SRGB8_ETC2 : 0x9275,
+ COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9276,
+ COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9277,
+ COMPRESSED_RGBA8_ETC2_EAC : 0x9278,
+ COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : 0x9279,
+};
+
+function setupUnitQuad() {
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0, 1.0, 0.0,
+ -1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, 1.0, 0.0,
+ -1.0, -1.0, 0.0,
+ 1.0, -1.0, 0.0]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var vertexObject = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ 1.0, 1.0,
+ 0.0, 1.0,
+ 0.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 0.0,
+ 1.0, 0.0]), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+}
+
+function runTest() {
+ gl = canvas.getContext('webgl', {antialias: false});
+ if (!gl) {
+ ok(false, "WebGL context does not exist");
+ } else {
+ ok(true, "WebGL context exists");
+ setupUnitQuad();
+
+ // Run tests with extension disabled
+ runTestDisabled();
+
+ // Query the extension and store globally so shouldBe can access it
+ ext = gl.getExtension("WEBGL_compressed_texture_etc");
+ if (!ext) {
+ ok(true, "No WEBGL_compressed_texture_etc support -- this is legal");
+ runSupportedTest(false);
+ } else {
+ ok(true, "Successfully enabled WEBGL_compressed_texture_etc extension");
+
+ runSupportedTest(true);
+ runTestExtension();
+ }
+ }
+ SimpleTest.finish();
+}
+
+function runSupportedTest(extensionEnabled) {
+ var supported = gl.getSupportedExtensions();
+ if (supported.includes("WEBGL_compressed_texture_etc")) {
+ if (extensionEnabled) {
+ ok(true, "WEBGL_compressed_texture_etc listed as supported and getExtension succeeded");
+ } else {
+ ok(false, "WEBGL_compressed_texture_etc listed as supported but getExtension failed");
+ }
+ } else {
+ if (extensionEnabled) {
+ ok(false, "WEBGL_compressed_texture_etc not listed as supported but getExtension succeeded");
+ } else {
+ ok(true, "WEBGL_compressed_texture_etc not listed as supported and getExtension failed -- this is legal");
+ }
+ }
+}
+
+function runTestDisabled() {
+ is(gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS).length, 0,
+ "Should be no compressed texture formats");
+}
+
+function formatExists(format, supportedFormats) {
+ for (var ii = 0; ii < supportedFormats.length; ++ii) {
+ if (format == supportedFormats[ii]) {
+ ok(true, "supported format " + formatToString(format) + " is exists");
+ return;
+ }
+ }
+ ok(false, "supported format " + formatToString(format) + " does not exist");
+}
+
+function formatToString(format) {
+ for (var p in ext) {
+ if (ext[p] == format) {
+ return p;
+ }
+ }
+ return "0x" + format.toString(16);
+}
+
+function runTestExtension() {
+ // check that all format enums exist.
+ for (let name in validFormats) {
+ is(ext[name], validFormats[name], "format is match");
+ }
+
+ let supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
+ // There should be exactly 10 formats
+ is(supportedFormats.length, 10, "Should be exactly 10 formats");
+
+ // check that all 10 formats exist
+ for (let name in validFormats.length) {
+ formatExists(validFormats[name], supportedFormats);
+ }
+
+ // Test each format
+ testETC2_RGB();
+}
+
+function testETC2_RGB() {
+ var tests = [
+ {
+ width: 4,
+ height: 4,
+ channels: 1,
+ data: img_4x4_r11_eac,
+ format: ext.COMPRESSED_R11_EAC
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 1,
+ data: img_4x4_signed_r11_eac,
+ format: ext.COMPRESSED_SIGNED_R11_EAC
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 2,
+ data: img_4x4_rg11_eac,
+ format: ext.COMPRESSED_RG11_EAC
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 2,
+ data: img_4x4_signed_rg11_eac,
+ format: ext.COMPRESSED_SIGNED_RG11_EAC
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 3,
+ data: img_4x4_rgb_etc2,
+ format: ext.COMPRESSED_RGB8_ETC2
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 3,
+ data: img_4x4_rgb_etc2,
+ format: ext.COMPRESSED_SRGB8_ETC2
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgb_punchthrough_etc2,
+ format: ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgb_punchthrough_etc2,
+ format: ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_etc2,
+ format: ext.COMPRESSED_RGBA8_ETC2_EAC
+ },
+ {
+ width: 4,
+ height: 4,
+ channels: 4,
+ data: img_4x4_rgba_etc2,
+ format: ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 1,
+ data: img_8x8_r11_eac,
+ format: ext.COMPRESSED_R11_EAC
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 1,
+ data: img_8x8_signed_r11_eac,
+ format: ext.COMPRESSED_SIGNED_R11_EAC
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 2,
+ data: img_8x8_rg11_eac,
+ format: ext.COMPRESSED_RG11_EAC
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 2,
+ data: img_8x8_signed_rg11_eac,
+ format: ext.COMPRESSED_SIGNED_RG11_EAC
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 3,
+ data: img_8x8_rgb_etc2,
+ format: ext.COMPRESSED_RGB8_ETC2
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 3,
+ data: img_8x8_rgb_etc2,
+ format: ext.COMPRESSED_SRGB8_ETC2
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgb_punchthrough_etc2,
+ format: ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgb_punchthrough_etc2,
+ format: ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_etc2,
+ format: ext.COMPRESSED_RGBA8_ETC2_EAC
+ },
+ {
+ width: 8,
+ height: 8,
+ channels: 4,
+ data: img_8x8_rgba_etc2,
+ format: ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 1,
+ data: img_32x32_r11_eac,
+ format: ext.COMPRESSED_R11_EAC
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 1,
+ data: img_32x32_signed_r11_eac,
+ format: ext.COMPRESSED_SIGNED_R11_EAC
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 2,
+ data: img_32x32_rg11_eac,
+ format: ext.COMPRESSED_RG11_EAC
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 2,
+ data: img_32x32_signed_rg11_eac,
+ format: ext.COMPRESSED_SIGNED_RG11_EAC
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 3,
+ data: img_32x32_rgb_etc2,
+ format: ext.COMPRESSED_RGB8_ETC2
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 3,
+ data: img_32x32_rgb_etc2,
+ format: ext.COMPRESSED_SRGB8_ETC2
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 4,
+ data: img_32x32_rgb_punchthrough_etc2,
+ format: ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 4,
+ data: img_32x32_rgb_punchthrough_etc2,
+ format: ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 4,
+ data: img_32x32_rgba_etc2,
+ format: ext.COMPRESSED_RGBA8_ETC2_EAC
+ },
+ {
+ width: 32,
+ height: 32,
+ channels: 4,
+ data: img_32x32_rgba_etc2,
+ format: ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ },
+ ];
+ testETCTextures(tests);
+}
+
+function testETCTextures(tests) {
+ for (var ii = 0; ii < tests.length; ++ii) {
+ testETCTexture(tests[ii]);
+ }
+}
+
+/* Return the size of block in bytes */
+function getBlockSize(format) {
+ switch (format) {
+ case ext.COMPRESSED_R11_EAC:
+ case ext.COMPRESSED_SIGNED_R11_EAC:
+ case ext.COMPRESSED_RGB8_ETC2:
+ case ext.COMPRESSED_SRGB8_ETC2:
+ case ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ return 8;
+ case ext.COMPRESSED_RG11_EAC:
+ case ext.COMPRESSED_SIGNED_RG11_EAC:
+ case ext.COMPRESSED_RGBA8_ETC2_EAC:
+ case ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ return 16
+ }
+}
+
+function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) {
+ var bytesPerLine = width * 4;
+ var srcOffset = srcX * 4 + srcY * stride;
+ var dstOffset = dstX * 4 + dstY * stride;
+ for (var jj = height; jj > 0; --jj) {
+ for (var ii = 0; ii < bytesPerLine; ++ii) {
+ data[dstOffset + ii] = data[srcOffset + ii];
+ }
+ srcOffset += stride;
+ dstOffset += stride;
+ }
+}
+
+function testETCTexture(test) {
+ var data = new Uint8Array(test.data.compressed);
+ var width = test.width;
+ var height = test.height;
+ var format = test.format;
+
+ var uncompressedData = new Uint8Array(test.data.decompressed);
+ var glErrorShouldBe = (glInner, glError, msg) => {
+ msg = msg || "";
+ var err = glInner.getError();
+ var getGLErrorAsString = error => {
+ if (error === glInner.NO_ERROR) {
+ return "NO_ERROR";
+ }
+ for (let name in glInner) {
+ if (glInner[name] === error) {
+ return name;
+ }
+ }
+ return error.toString();
+ }
+
+ if (err != glError) {
+ ok(false, "getError expected: " + getGLErrorAsString(glError) +
+ ". Was " + getGLErrorAsString(err) + " : " + msg);
+ } else {
+ ok(true, "getError was expected value: " +
+ getGLErrorAsString(glError) + " : " + msg);
+ }
+ };
+
+ canvas.width = width;
+ canvas.height = height;
+ gl.viewport(0, 0, width, height);
+
+ 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);
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ gl.generateMipmap(gl.TEXTURE_2D);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
+ if (format == ext.COMPRESSED_SIGNED_R11_EAC) {
+ var program = WebGLUtil.createProgramByIds(gl, 'vshader', 'fshader-r');
+ } else if (format == ext.COMPRESSED_SIGNED_RG11_EAC) {
+ var program = WebGLUtil.createProgramByIds(gl, 'vshader', 'fshader-rg');
+ } else {
+ var program = WebGLUtil.createProgramByIds(gl, 'vshader', 'fshader');
+ }
+ gl.bindAttribLocation(program, 0, 'vPosition');
+ gl.bindAttribLocation(program, 1, 'texCoord0');
+ gl.useProgram(program);
+
+ gl.clearColor(1.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
+
+ if (width == 4) {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ }
+ if (height == 4) {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+ }
+
+ // pick a wrong format that uses the same amount of data.
+ var wrongFormat;
+ switch (format) {
+ case ext.COMPRESSED_R11_EAC:
+ wrongFormat = ext.COMPRESSED_SIGNED_R11_EAC;
+ break;
+ case ext.COMPRESSED_SIGNED_R11_EAC:
+ wrongFormat = ext.COMPRESSED_R11_EAC;
+ break;
+ case ext.COMPRESSED_RG11_EAC:
+ wrongFormat = ext.COMPRESSED_SIGNED_RG11_EAC;
+ break;
+ case ext.COMPRESSED_SIGNED_RG11_EAC:
+ wrongFormat = ext.COMPRESSED_RG11_EAC;
+ break;
+ case ext.COMPRESSED_RGB8_ETC2:
+ wrongFormat = ext.COMPRESSED_SRGB8_ETC2;
+ break;
+ case ext.COMPRESSED_SRGB8_ETC2:
+ wrongFormat = ext.COMPRESSED_RGB8_ETC2;
+ break;
+ case ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ wrongFormat = ext.COMPRESSED_RGB8_ETC2;
+ break;
+ case ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ wrongFormat = ext.COMPRESSED_RGB8_ETC2;
+ break;
+ case ext.COMPRESSED_RGBA8_ETC2_EAC:
+ wrongFormat = ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
+ break;
+ case ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ wrongFormat = ext.COMPRESSED_RGBA8_ETC2_EAC;
+ break;
+ }
+
+ // Restore original texture.
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match");
+
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data);
+ glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+ glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+ var subData = new Uint8Array(data.buffer, 0, getBlockSize(format));
+
+ if (width == 8 && height == 8) {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData);
+ glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+ }
+
+ if (width < 32 && height < 32) {
+ var stride = width * 4;
+ for (var yoff = 0; yoff < height; yoff += 4) {
+ for (var xoff = 0; xoff < width; xoff += 4) {
+ copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride);
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData);
+ glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+ gl.clearColor(1.0, 1.0, 1.0, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+ compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
+ }
+ }
+ }
+}
+
+function insertImg(element, caption, img) {
+ var div = document.createElement("div");
+ div.appendChild(img);
+ var label = document.createElement("div");
+ label.appendChild(document.createTextNode(caption));
+ div.appendChild(label);
+ element.appendChild(div);
+}
+
+function convertToSRGB(val) {
+ var norm = val / 255.0;
+ var res = 0;
+ if (norm <= 0.04045) {
+ res = norm / 12.92;
+ } else {
+ res = Math.pow(((norm + 0.055)/1.055), 2.4);
+ }
+
+ return res * 255.0;
+}
+
+function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
+ var scale = 8;
+ var c = document.createElement("canvas");
+ c.width = imageWidth * scale;
+ c.height = imageHeight * scale;
+ var ctx = c.getContext("2d");
+ for (var yy = 0; yy < imageHeight; ++yy) {
+ for (var xx = 0; xx < imageWidth; ++xx) {
+ var offset = (yy * dataWidth + xx) * 4;
+ ctx.fillStyle = "rgba(" +
+ data[offset + 0] + "," +
+ data[offset + 1] + "," +
+ data[offset + 2] + "," +
+ (alpha ? data[offset + 3] / 255 : 1) + ")";
+ ctx.fillRect(xx * scale, yy * scale, scale, scale);
+ }
+ }
+ var img = document.createElement("img");
+ img.src = c.toDataURL();
+ return img;
+}
+
+function compareRect(actualWidth, actualHeight, actualChannels,
+ dataWidth, dataHeight, expectedData,
+ testData, testFormat)
+{
+ var actual = new Uint8Array(actualWidth * actualHeight * 4);
+ gl.readPixels(
+ 0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ var hasAlpha = actualChannels == 4;
+ var imgExpected = makeImage(actualWidth, actualHeight, dataWidth, expectedData, hasAlpha);
+ var imgActual = makeImage(actualWidth, actualHeight, actualWidth, actual, hasAlpha);
+ insertImg(div, "expected", imgExpected);
+ insertImg(div, "actual", imgActual);
+ div.appendChild(document.createElement('br'));
+ document.getElementById("console").appendChild(div);
+
+ var failed = false;
+ for (var yy = 0; yy < actualHeight; ++yy) {
+ for (var xx = 0; xx < actualWidth; ++xx) {
+ var actualOffset = (yy * actualWidth + xx) * 4;
+ var expectedOffset = (yy * dataWidth + xx) * 4;
+ var expected = expectedData.slice(expectedOffset, expectedOffset + 4);
+
+ var maxDiffPixel = 0;
+ switch (testFormat) {
+ case ext.COMPRESSED_SRGB8_ETC2:
+ case ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+
+ // Alpha shouldn't do conversion.
+ for (var i = 0; i < 3; ++i) {
+ expected[i] = convertToSRGB(expected[i]);
+ }
+ //fallthrough
+ case ext.COMPRESSED_R11_EAC:
+ case ext.COMPRESSED_RG11_EAC:
+ case ext.COMPRESSED_SIGNED_R11_EAC:
+ case ext.COMPRESSED_SIGNED_RG11_EAC:
+ // Due to floating round error, we need fuzzy test here.
+ var maxDiffPixel = 1;
+ break;
+ default:
+ var maxDiffPixel = 0;
+ break;
+ }
+
+ for (var channel = 0; channel < actualChannels; ++channel) {
+ var diff = Math.abs(expected[channel] - actual[actualOffset + channel]);
+
+ if (diff > maxDiffPixel) {
+ failed = true;
+ var was = actual.slice(actualOffset, actualOffset + 4).join();
+ ok(false, 'at (' + xx + ', ' + yy +
+ ') expected: ' + expected.join() + ' was ' + was);
+ break;
+ }
+ }
+ }
+ }
+ if (!failed) {
+ ok(true, "texture rendered correctly");
+ }
+}
+
+var prefArrArr = [
+ ['webgl.enable-draft-extensions', true],
+];
+var prefEnv = {'set': prefArrArr};
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv(prefEnv, runTest);
+</script>
+</body>
+</html>