content/canvas/test/webgl-conformance/conformance/extensions/webgl-compressed-texture-s3tc.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/canvas/test/webgl-conformance/conformance/extensions/webgl-compressed-texture-s3tc.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,614 @@
     1.4 +<!--
     1.5 +Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.6 +Use of this source code is governed by a BSD-style license that can be
     1.7 +found in the LICENSE file.
     1.8 + -->
     1.9 +<!DOCTYPE html>
    1.10 +<html>
    1.11 +<head>
    1.12 +<meta charset="utf-8">
    1.13 +<link rel="stylesheet" href="../../resources/js-test-style.css"/>
    1.14 +<script src="../../resources/js-test-pre.js"></script>
    1.15 +<script src="../resources/webgl-test.js"></script>
    1.16 +<script src="../resources/webgl-test-utils.js"></script>
    1.17 +<title>WebGL WEBGL_compressed_texture_s3tc Conformance Tests</title>
    1.18 +<style>
    1.19 +img {
    1.20 + border: 1px solid black;
    1.21 + margin-right: 1em;
    1.22 +}
    1.23 +.testimages {
    1.24 +}
    1.25 +
    1.26 +.testimages br {
    1.27 +  clear: both;
    1.28 +}
    1.29 +
    1.30 +.testimages > div {
    1.31 +  float: left;
    1.32 +  margin: 1em;
    1.33 +}
    1.34 +</style>
    1.35 +</head>
    1.36 +<body>
    1.37 +<div id="description"></div>
    1.38 +<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
    1.39 +<div id="console"></div>
    1.40 +<script>
    1.41 +description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc extension, if it is available.");
    1.42 +
    1.43 +debug("");
    1.44 +
    1.45 +var img_4x4_rgba_raw = new Uint8Array([
    1.46 +    0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,
    1.47 +]);
    1.48 +var img_4x4_rgb_dxt1 = new Uint8Array([
    1.49 +    0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,
    1.50 +]);
    1.51 +var img_4x4_rgba_dxt1 = new Uint8Array([
    1.52 +    0xe0,0x07,0x00,0xf8,0x13,0x10,0x15,0x00,
    1.53 +]);
    1.54 +var img_4x4_rgba_dxt3 = new Uint8Array([
    1.55 +    0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
    1.56 +]);
    1.57 +var img_4x4_rgba_dxt5 = new Uint8Array([
    1.58 +    0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
    1.59 +]);
    1.60 +var img_8x8_rgba_raw = new Uint8Array([
    1.61 +    0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x69,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,
    1.62 +]);
    1.63 +var img_8x8_rgb_dxt1 = new Uint8Array([
    1.64 +    0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x40,0x55,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
    1.65 +]);
    1.66 +var img_8x8_rgba_dxt1 = new Uint8Array([
    1.67 +    0xe0,0x07,0x00,0xf8,0x13,0x13,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x43,0x57,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
    1.68 +]);
    1.69 +var img_8x8_rgba_dxt3 = new Uint8Array([
    1.70 +    0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
    1.71 +]);
    1.72 +var img_8x8_rgba_dxt5 = new Uint8Array([
    1.73 +    0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
    1.74 +]);
    1.75 +
    1.76 +var wtu = WebGLTestUtils;
    1.77 +var canvas = document.getElementById("canvas");
    1.78 +var gl = wtu.create3DContext(canvas, {antialias: false});
    1.79 +var program = wtu.setupTexturedQuad(gl);
    1.80 +var ext = null;
    1.81 +var vao = null;
    1.82 +var validFormats = {
    1.83 +    COMPRESSED_RGB_S3TC_DXT1_EXT        : 0x83F0,
    1.84 +    COMPRESSED_RGBA_S3TC_DXT1_EXT       : 0x83F1,
    1.85 +    COMPRESSED_RGBA_S3TC_DXT3_EXT       : 0x83F2,
    1.86 +    COMPRESSED_RGBA_S3TC_DXT5_EXT       : 0x83F3,
    1.87 +};
    1.88 +var name;
    1.89 +var supportedFormats;
    1.90 +
    1.91 +if (!gl) {
    1.92 +    testFailed("WebGL context does not exist");
    1.93 +} else {
    1.94 +    testPassed("WebGL context exists");
    1.95 +
    1.96 +    // Run tests with extension disabled
    1.97 +    runTestDisabled();
    1.98 +
    1.99 +    // Query the extension and store globally so shouldBe can access it
   1.100 +    ext = gl.getExtension("WEBGL_compressed_texture_s3tc");
   1.101 +    if (!ext) {
   1.102 +        ext = gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");
   1.103 +    }
   1.104 +    if (!ext) {
   1.105 +        testPassed("No WEBGL_compressed_texture_s3tc support -- this is legal");
   1.106 +        runSupportedTest(false);
   1.107 +    } else {
   1.108 +        testPassed("Successfully enabled WEBGL_compressed_texture_s3tc extension");
   1.109 +
   1.110 +        runSupportedTest(true);
   1.111 +        runTestExtension();
   1.112 +    }
   1.113 +}
   1.114 +
   1.115 +function runSupportedTest(extensionEnabled) {
   1.116 +    var supported = gl.getSupportedExtensions();
   1.117 +    if (supported.indexOf("WEBGL_compressed_texture_s3tc") >= 0 ||
   1.118 +        supported.indexOf("WEBKIT_WEBGL_compressed_texture_s3tc") >= 0) {
   1.119 +        if (extensionEnabled) {
   1.120 +            testPassed("WEBGL_compressed_texture_s3tc listed as supported and getExtension succeeded");
   1.121 +        } else {
   1.122 +            testFailed("WEBGL_compressed_texture_s3tc listed as supported but getExtension failed");
   1.123 +        }
   1.124 +    } else {
   1.125 +        if (extensionEnabled) {
   1.126 +            testFailed("WEBGL_compressed_texture_s3tc not listed as supported but getExtension succeeded");
   1.127 +        } else {
   1.128 +            testPassed("WEBGL_compressed_texture_s3tc not listed as supported and getExtension failed -- this is legal");
   1.129 +        }
   1.130 +    }
   1.131 +}
   1.132 +
   1.133 +
   1.134 +function runTestDisabled() {
   1.135 +    debug("Testing binding enum with extension disabled");
   1.136 +
   1.137 +    shouldBe('gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)', '[]');
   1.138 +}
   1.139 +
   1.140 +function formatExists(format, supportedFormats) {
   1.141 +    for (var ii = 0; ii < supportedFormats.length; ++ii) {
   1.142 +        if (format == supportedFormats[ii]) {
   1.143 +            testPassed("supported format " + formatToString(format) + " is exists");
   1.144 +            return;
   1.145 +        }
   1.146 +    }
   1.147 +    testFailed("supported format " + formatToString(format) + " does not exist");
   1.148 +}
   1.149 +
   1.150 +function formatToString(format) {
   1.151 +    for (var p in ext) {
   1.152 +        if (ext[p] == format) {
   1.153 +            return p;
   1.154 +        }
   1.155 +    }
   1.156 +    return "0x" + format.toString(16);
   1.157 +}
   1.158 +
   1.159 +function runTestExtension() {
   1.160 +    debug("Testing WEBGL_compressed_texture_s3tc");
   1.161 +
   1.162 +    // check that all format enums exist.
   1.163 +    for (name in validFormats) {
   1.164 +        var expected = "0x" + validFormats[name].toString(16);
   1.165 +        var actual = "ext['" + name + "']";
   1.166 +        shouldBe(actual, expected);
   1.167 +    }
   1.168 +
   1.169 +    supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
   1.170 +    // There should be exactly 4 formats
   1.171 +    shouldBe("supportedFormats.length", "4");
   1.172 +
   1.173 +    // check that all 4 formats exist
   1.174 +    for (var name in validFormats.length) {
   1.175 +        formatExists(validFormats[name], supportedFormats);
   1.176 +    }
   1.177 +
   1.178 +    // Test each format
   1.179 +    testDXT1_RGB();
   1.180 +    testDXT1_RGBA();
   1.181 +    testDXT3_RGBA();
   1.182 +    testDXT5_RGBA();
   1.183 +}
   1.184 +
   1.185 +function testDXT1_RGB() {
   1.186 +    var tests = [
   1.187 +        {   width: 4,
   1.188 +            height: 4,
   1.189 +            channels: 3,
   1.190 +            data: img_4x4_rgb_dxt1,
   1.191 +            format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
   1.192 +        },
   1.193 +        {   width: 8,
   1.194 +            height: 8,
   1.195 +            channels: 3,
   1.196 +            data: img_8x8_rgb_dxt1,
   1.197 +            format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
   1.198 +        }
   1.199 +    ];
   1.200 +    testDXTTextures(tests);
   1.201 +}
   1.202 +
   1.203 +function testDXT1_RGBA() {
   1.204 +    var tests = [
   1.205 +        {   width: 4,
   1.206 +            height: 4,
   1.207 +            channels: 4,
   1.208 +            data: img_4x4_rgba_dxt1,
   1.209 +            format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
   1.210 +        },
   1.211 +        {   width: 8,
   1.212 +            height: 8,
   1.213 +            channels: 4,
   1.214 +            data: img_8x8_rgba_dxt1,
   1.215 +            format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
   1.216 +        }
   1.217 +    ];
   1.218 +    testDXTTextures(tests);
   1.219 +}
   1.220 +
   1.221 +function testDXT3_RGBA() {
   1.222 +    var tests = [
   1.223 +        {   width: 4,
   1.224 +            height: 4,
   1.225 +            channels: 4,
   1.226 +            data: img_4x4_rgba_dxt3,
   1.227 +            format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
   1.228 +        },
   1.229 +        {   width: 8,
   1.230 +            height: 8,
   1.231 +            channels: 4,
   1.232 +            data: img_8x8_rgba_dxt3,
   1.233 +            format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
   1.234 +        }
   1.235 +    ];
   1.236 +    testDXTTextures(tests);
   1.237 +}
   1.238 +
   1.239 +function testDXT5_RGBA() {
   1.240 +    var tests = [
   1.241 +        {   width: 4,
   1.242 +            height: 4,
   1.243 +            channels: 4,
   1.244 +            data: img_4x4_rgba_dxt5,
   1.245 +            format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
   1.246 +        },
   1.247 +        {   width: 8,
   1.248 +            height: 8,
   1.249 +            channels: 4,
   1.250 +            data: img_8x8_rgba_dxt5,
   1.251 +            format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
   1.252 +        }
   1.253 +    ];
   1.254 +    testDXTTextures(tests);
   1.255 +}
   1.256 +
   1.257 +function testDXTTextures(tests) {
   1.258 +    debug("<hr/>");
   1.259 +    for (var ii = 0; ii < tests.length; ++ii) {
   1.260 +        testDXTTexture(tests[ii]);
   1.261 +    }
   1.262 +}
   1.263 +
   1.264 +function uncompressDXTBlock(
   1.265 +    destBuffer, destX, destY, destWidth, src, srcOffset, format) {
   1.266 +    function make565(src, offset) {
   1.267 +        return src[offset + 0] + src[offset + 1] * 256;
   1.268 +    }
   1.269 +    function make8888From565(c) {
   1.270 +        return [
   1.271 +                Math.floor(((c >> 11) & 0x1F) * 255 / 31),
   1.272 +                Math.floor(((c >>    5) & 0x3F) * 255 / 63),
   1.273 +                Math.floor(((c >>    0) & 0x1F) * 255 / 31),
   1.274 +                255
   1.275 +            ];
   1.276 +    }
   1.277 +    function mix(mult, c0, c1, div) {
   1.278 +        var r = [];
   1.279 +        for (var ii = 0; ii < c0.length; ++ii) {
   1.280 +            r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div);
   1.281 +        }
   1.282 +        return r;
   1.283 +    }
   1.284 +    var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
   1.285 +                 format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
   1.286 +    var colorOffset = srcOffset + (isDXT1 ? 0 : 8);
   1.287 +    var color0 = make565(src, colorOffset + 0);
   1.288 +    var color1 = make565(src, colorOffset + 2);
   1.289 +    var c0gtc1 = color0 > color1 || !isDXT1;
   1.290 +    var rgba0 = make8888From565(color0);
   1.291 +    var rgba1 = make8888From565(color1);
   1.292 +    var colors = [
   1.293 +            rgba0,
   1.294 +            rgba1,
   1.295 +            c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
   1.296 +            c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
   1.297 +        ];
   1.298 +
   1.299 +    // yea I know there is a lot of math in this inner loop.
   1.300 +    // so sue me.
   1.301 +    for (var yy = 0; yy < 4; ++yy) {
   1.302 +        var pixels = src[colorOffset + 4 + yy];
   1.303 +        for (var xx = 0; xx < 4; ++xx) {
   1.304 +            var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
   1.305 +            var code = (pixels >> (xx * 2)) & 0x3;
   1.306 +            var srcColor = colors[code];
   1.307 +            var alpha;
   1.308 +            switch (format) {
   1.309 +            case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
   1.310 +                alpha = 255;
   1.311 +                break;
   1.312 +            case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
   1.313 +                alpha = (code == 3 && !c0gtc1) ? 0 : 255;
   1.314 +                break;
   1.315 +            case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
   1.316 +                {
   1.317 +                    var alpha0 = src[srcOffset + yy * 2 + Math.floor(xx / 2)];
   1.318 +                    var alpha1 = (alpha0 >> ((xx % 2) * 4)) & 0xF;
   1.319 +                    alpha = alpha1 | (alpha1 << 4);
   1.320 +                }
   1.321 +                break;
   1.322 +            case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
   1.323 +                {
   1.324 +                    var alpha0 = src[srcOffset + 0];
   1.325 +                    var alpha1 = src[srcOffset + 1];
   1.326 +                    var alphaOff = Math.floor(yy / 2) * 3 + 2;
   1.327 +                    var alphaBits =
   1.328 +                         src[srcOffset + alphaOff + 0] +
   1.329 +                         src[srcOffset + alphaOff + 1] * 256 +
   1.330 +                         src[srcOffset + alphaOff + 2] * 65536;
   1.331 +                    var alphaShift = (yy % 2) * 12 + xx * 3;
   1.332 +                    var alphaCode = (alphaBits >> alphaShift) & 0x7;
   1.333 +                    if (alpha0 > alpha1) {
   1.334 +                        switch (alphaCode) {
   1.335 +                        case 0:
   1.336 +                            alpha = alpha0;
   1.337 +                            break;
   1.338 +                        case 1:
   1.339 +                            alpha = alpha1;
   1.340 +                            break;
   1.341 +                        default:
   1.342 +                            alpha = ((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7;
   1.343 +                            break;
   1.344 +                        }
   1.345 +                    } else {
   1.346 +                        switch (alphaCode) {
   1.347 +                        case 0:
   1.348 +                            alpha = alpha0;
   1.349 +                            break;
   1.350 +                        case 1:
   1.351 +                            alpha = alpha1;
   1.352 +                            break;
   1.353 +                        case 6:
   1.354 +                            alpha = 0;
   1.355 +                            break;
   1.356 +                        case 7:
   1.357 +                            alpha = 255;
   1.358 +                            break;
   1.359 +                        default:
   1.360 +                            alpha = ((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5;
   1.361 +                            break;
   1.362 +                        }
   1.363 +                    }
   1.364 +                }
   1.365 +                break;
   1.366 +            default:
   1.367 +                throw "bad format";
   1.368 +            }
   1.369 +            destBuffer[dstOff + 0] = srcColor[0];
   1.370 +            destBuffer[dstOff + 1] = srcColor[1];
   1.371 +            destBuffer[dstOff + 2] = srcColor[2];
   1.372 +            destBuffer[dstOff + 3] = alpha;
   1.373 +        }
   1.374 +    }
   1.375 +}
   1.376 +
   1.377 +function getBlockSize(format) {
   1.378 +  var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
   1.379 +               format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
   1.380 +  return isDXT1 ? 8 : 16;
   1.381 +}
   1.382 +
   1.383 +function uncompressDXT(width, height, data, format) {
   1.384 +    if (width % 4 || height % 4) throw "bad width or height";
   1.385 +
   1.386 +    var dest = new Uint8Array(width * height * 4);
   1.387 +    var blocksAcross = width / 4;
   1.388 +    var blocksDown = height / 4;
   1.389 +    var blockSize = getBlockSize(format);
   1.390 +    for (var yy = 0; yy < blocksDown; ++yy) {
   1.391 +        for (var xx = 0; xx < blocksAcross; ++xx) {
   1.392 +            uncompressDXTBlock(
   1.393 +                dest, xx * 4, yy * 4, width, data,
   1.394 +                (yy * blocksAcross + xx) * blockSize, format);
   1.395 +        }
   1.396 +    }
   1.397 +    return dest;
   1.398 +}
   1.399 +
   1.400 +function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) {
   1.401 +  var bytesPerLine = width * 4;
   1.402 +  var srcOffset = srcX * 4 + srcY * stride;
   1.403 +  var dstOffset = dstX * 4 + dstY * stride;
   1.404 +  for (; height > 0; --height) {
   1.405 +    for (var ii = 0; ii < bytesPerLine; ++ii) {
   1.406 +      data[dstOffset + ii] = data[srcOffset + ii];
   1.407 +    }
   1.408 +    srcOffset += stride;
   1.409 +    dstOffset += stride;
   1.410 +  }
   1.411 +}
   1.412 +
   1.413 +function testDXTTexture(test) {
   1.414 +    var data = new Uint8Array(test.data);
   1.415 +    var width = test.width;
   1.416 +    var height = test.height;
   1.417 +    var format = test.format;
   1.418 +
   1.419 +    var uncompressedData = uncompressDXT(width, height, data, format);
   1.420 +
   1.421 +    canvas.width = width;
   1.422 +    canvas.height = height;
   1.423 +    gl.viewport(0, 0, width, height);
   1.424 +    debug("testing " + formatToString(format) + " " + width + "x" + height);
   1.425 +    var tex = gl.createTexture();
   1.426 +    gl.bindTexture(gl.TEXTURE_2D, tex);
   1.427 +    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   1.428 +    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   1.429 +    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   1.430 +    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
   1.431 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
   1.432 +    glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
   1.433 +    wtu.drawQuad(gl);
   1.434 +    compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
   1.435 +
   1.436 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
   1.437 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
   1.438 +
   1.439 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
   1.440 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.441 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
   1.442 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.443 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
   1.444 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.445 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
   1.446 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.447 +
   1.448 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
   1.449 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.450 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
   1.451 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.452 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
   1.453 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.454 +    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
   1.455 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.456 +
   1.457 +    if (width == 4) {
   1.458 +      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
   1.459 +      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   1.460 +      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
   1.461 +      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   1.462 +    }
   1.463 +    if (height == 4) {
   1.464 +      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
   1.465 +      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   1.466 +      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
   1.467 +      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   1.468 +    }
   1.469 +
   1.470 +    // pick a wrong format that uses the same amount of data.
   1.471 +    var wrongFormat;
   1.472 +    switch (format) {
   1.473 +    case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
   1.474 +      wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
   1.475 +      break;
   1.476 +    case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
   1.477 +      wrongFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT;
   1.478 +      break;
   1.479 +    case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
   1.480 +      wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
   1.481 +      break;
   1.482 +    case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
   1.483 +      wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
   1.484 +      break;
   1.485 +    }
   1.486 +
   1.487 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data);
   1.488 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match");
   1.489 +
   1.490 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data);
   1.491 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.492 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data);
   1.493 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.494 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data);
   1.495 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.496 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data);
   1.497 +    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   1.498 +
   1.499 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data);
   1.500 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.501 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
   1.502 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.503 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data);
   1.504 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.505 +    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
   1.506 +    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
   1.507 +
   1.508 +    var subData = new Uint8Array(data.buffer, 0, getBlockSize(format));
   1.509 +
   1.510 +    if (width == 8 && height == 8) {
   1.511 +        gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData);
   1.512 +        glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
   1.513 +        gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData);
   1.514 +        glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
   1.515 +    }
   1.516 +
   1.517 +    var stride = width * 4;
   1.518 +    for (var yoff = 0; yoff < height; yoff += 4) {
   1.519 +        for (var xoff = 0; xoff < width; xoff += 4) {
   1.520 +            copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride);
   1.521 +            gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData);
   1.522 +            glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
   1.523 +            wtu.drawQuad(gl);
   1.524 +            compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
   1.525 +        }
   1.526 +    }
   1.527 +}
   1.528 +
   1.529 +function insertImg(element, caption, img) {
   1.530 +    var div = document.createElement("div");
   1.531 +    div.appendChild(img);
   1.532 +    var label = document.createElement("div");
   1.533 +    label.appendChild(document.createTextNode(caption));
   1.534 +    div.appendChild(label);
   1.535 +    element.appendChild(div);
   1.536 +}
   1.537 +
   1.538 +function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
   1.539 +    var scale = 8;
   1.540 +    var c = document.createElement("canvas");
   1.541 +    c.width = imageWidth * scale;
   1.542 +    c.height = imageHeight * scale;
   1.543 +    var ctx = c.getContext("2d");
   1.544 +    for (var yy = 0; yy < imageWidth; ++yy) {
   1.545 +        for (var xx = 0; xx < imageHeight; ++xx) {
   1.546 +            var offset = (yy * dataWidth + xx) * 4;
   1.547 +            ctx.fillStyle = "rgba(" +
   1.548 +                    data[offset + 0] + "," +
   1.549 +                    data[offset + 1] + "," +
   1.550 +                    data[offset + 2] + "," +
   1.551 +                    (alpha ? data[offset + 3] / 255 : 1) + ")";
   1.552 +            ctx.fillRect(xx * scale, yy * scale, scale, scale);
   1.553 +        }
   1.554 +    }
   1.555 +    var img = document.createElement("img");
   1.556 +    img.src = c.toDataURL();
   1.557 +    return img;
   1.558 +}
   1.559 +function compareRect(
   1.560 +        actualWidth, actualHeight, actualChannels,
   1.561 +        dataWidth, dataHeight, expectedData,
   1.562 +        testData, testFormat) {
   1.563 +    var actual = new Uint8Array(actualWidth * actualHeight * 4);
   1.564 +    gl.readPixels(
   1.565 +            0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
   1.566 +
   1.567 +    var div = document.createElement("div");
   1.568 +    div.className = "testimages";
   1.569 +    insertImg(div, "expected", makeImage(
   1.570 +            actualWidth, actualHeight, dataWidth, expectedData,
   1.571 +            actualChannels == 4));
   1.572 +    insertImg(div, "actual", makeImage(
   1.573 +            actualWidth, actualHeight, actualWidth, actual,
   1.574 +            actualChannels == 4));
   1.575 +    div.appendChild(document.createElement('br'));
   1.576 +    document.getElementById("console").appendChild(div);
   1.577 +
   1.578 +    var failed = false;
   1.579 +    for (var yy = 0; yy < actualHeight; ++yy) {
   1.580 +        for (var xx = 0; xx < actualWidth; ++xx) {
   1.581 +            var actualOffset = (yy * actualWidth + xx) * 4;
   1.582 +            var expectedOffset = (yy * dataWidth + xx) * 4;
   1.583 +            var expected = [
   1.584 +                    expectedData[expectedOffset + 0],
   1.585 +                    expectedData[expectedOffset + 1],
   1.586 +                    expectedData[expectedOffset + 2],
   1.587 +                    (actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
   1.588 +            ];
   1.589 +            for (var jj = 0; jj < 4; ++jj) {
   1.590 +                if (actual[actualOffset + jj] != expected[jj]) {
   1.591 +                    failed = true;
   1.592 +                    var was = actual[actualOffset + 0].toString();
   1.593 +                    for (j = 1; j < 4; ++j) {
   1.594 +                        was += "," + actual[actualOffset + j];
   1.595 +                    }
   1.596 +                    testFailed('at (' + xx + ', ' + yy +
   1.597 +                                         ') expected: ' + expected + ' was ' + was);
   1.598 +                }
   1.599 +            }
   1.600 +        }
   1.601 +    }
   1.602 +    if (!failed) {
   1.603 +        testPassed("texture rendered correctly");
   1.604 +    }
   1.605 +}
   1.606 +
   1.607 +function testPVRTCTextures() {
   1.608 +    testFailed("PVRTC test not yet implemented");
   1.609 +}
   1.610 +
   1.611 +debug("");
   1.612 +successfullyParsed = true;
   1.613 +</script>
   1.614 +<script>finishTest();</script>
   1.615 +
   1.616 +</body>
   1.617 +</html>

mercurial