<!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_es3 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, }; var name; var supportedFormats; 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 = WebGLUtil.getWebGL("canvas", false, {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_es3"); if (!ext) { ok(true, "No WEBGL_compressed_texture_es3 support -- this is legal"); runSupportedTest(false); } else { ok(true, "Successfully enabled WEBGL_compressed_texture_es3 extension"); runSupportedTest(true); runTestExtension(); } } SimpleTest.finish(); } function runSupportedTest(extensionEnabled) { var supported = gl.getSupportedExtensions(); if (supported.indexOf("WEBGL_compressed_texture_es3") >= 0) { if (extensionEnabled) { ok(true, "WEBGL_compressed_texture_es3 listed as supported and getExtension succeeded"); } else { ok(false, "WEBGL_compressed_texture_es3 listed as supported but getExtension failed"); } } else { if (extensionEnabled) { ok(false, "WEBGL_compressed_texture_es3 not listed as supported but getExtension succeeded"); } else { ok(true, "WEBGL_compressed_texture_es3 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 (name in validFormats) { is(ext[name], validFormats[name], "format is match"); } 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 (var 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 = (gl, glError, msg) => { msg = msg || ""; var err = gl.getError(); var getGLErrorAsString = err => { if (err === gl.NO_ERROR) { return "NO_ERROR"; } for (var name in gl) { if (gl[name] === err) { return name; } } return err.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>