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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 <!--
     3 /*
     4 ** Copyright (c) 2012 The Khronos Group Inc.
     5 **
     6 ** Permission is hereby granted, free of charge, to any person obtaining a
     7 ** copy of this software and/or associated documentation files (the
     8 ** "Materials"), to deal in the Materials without restriction, including
     9 ** without limitation the rights to use, copy, modify, merge, publish,
    10 ** distribute, sublicense, and/or sell copies of the Materials, and to
    11 ** permit persons to whom the Materials are furnished to do so, subject to
    12 ** the following conditions:
    13 **
    14 ** The above copyright notice and this permission notice shall be included
    15 ** in all copies or substantial portions of the Materials.
    16 **
    17 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    18 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    19 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    20 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    21 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    22 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    23 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    24 */
    26 -->
    28 <!DOCTYPE html>
    29 <html>
    30 <head>
    31 <meta charset="utf-8">
    32 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
    33 <script src="../../resources/js-test-pre.js"></script>
    34 <script src="../resources/webgl-test.js"></script>
    35 <script src="../resources/webgl-test-utils.js"></script>
    36 <title>WebGL WEBGL_compressed_texture_etc1 Conformance Tests</title>
    37 <style>
    38 img {
    39  border: 1px solid black;
    40  margin-right: 1em;
    41 }
    42 .testimages {
    43 }
    45 .testimages br {
    46   clear: both;
    47 }
    49 .testimages > div {
    50   float: left;
    51   margin: 1em;
    52 }
    53 </style>
    54 </head>
    55 <body>
    56 <div id="description"></div>
    57 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
    58 <div id="console"></div>
    59 <script>
    60 "use strict";
    61 description("This test verifies the functionality of the WEBGL_compressed_texture_etc1 extension, if it is available.");
    63 debug("");
    65 var img_4x4_rgb_etc1 = new Uint8Array([
    66     0x00, 0xc0, 0x00, 0xff, 0x07, 0x45, 0x07, 0x45
    67 ]);
    68 var img_8x8_rgb_etc1 = new Uint8Array([
    69     0x00, 0xff, 0x55, 0xfc, 0xff, 0xff, 0x07, 0x45,
    70     0x11, 0x11, 0xff, 0xfc, 0xf8, 0xba, 0x07, 0x45,
    71     0xee, 0x00, 0xee, 0xfc, 0x07, 0x45, 0x07, 0x45,
    72     0x00, 0x90, 0xf8, 0x92, 0x07, 0x45, 0xff, 0xff,
    73 ]);
    75 var wtu = WebGLTestUtils;
    76 var canvas = document.getElementById("canvas");
    77 var gl = wtu.create3DContext(canvas, {antialias: false});
    78 var program = wtu.setupTexturedQuad(gl);
    79 var ext = null;
    80 var vao = null;
    81 var validFormats = {
    82     COMPRESSED_RGB_ETC1_WEBGL : 0x8D64
    83 };
    84 var name;
    85 var supportedFormats;
    87 if (!gl) {
    88     testFailed("WebGL context does not exist");
    89 } else {
    90     testPassed("WebGL context exists");
    92     // Run tests with extension disabled
    93     runTestDisabled();
    95     // Query the extension and store globally so shouldBe can access it
    96     ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_etc1");
    97     if (!ext) {
    98         testPassed("No WEBGL_compressed_texture_etc1 support -- this is legal");
    99         runSupportedTest(false);
   100     } else {
   101         testPassed("Successfully enabled WEBGL_compressed_texture_etc1 extension");
   103         runSupportedTest(true);
   104         runTestExtension();
   105     }
   106 }
   108 function runSupportedTest(extensionEnabled) {
   109     var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_etc1");
   110     if (name !== undefined) {
   111         if (extensionEnabled) {
   112             testPassed("WEBGL_compressed_texture_etc1 listed as supported and getExtension succeeded");
   113         } else {
   114             testFailed("WEBGL_compressed_texture_etc1 listed as supported but getExtension failed");
   115         }
   116     } else {
   117         if (extensionEnabled) {
   118             testFailed("WEBGL_compressed_texture_etc1 not listed as supported but getExtension succeeded");
   119         } else {
   120             testPassed("WEBGL_compressed_texture_etc1 not listed as supported and getExtension failed -- this is legal");
   121         }
   122     }
   123 }
   126 function runTestDisabled() {
   127     debug("Testing binding enum with extension disabled");
   129     shouldBe('gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)', '[]');
   130 }
   132 function formatExists(format, supportedFormats) {
   133     for (var ii = 0; ii < supportedFormats.length; ++ii) {
   134         if (format == supportedFormats[ii]) {
   135             testPassed("supported format " + formatToString(format) + " is exists");
   136             return;
   137         }
   138     }
   139     testFailed("supported format " + formatToString(format) + " does not exist");
   140 }
   142 function formatToString(format) {
   143     for (var p in ext) {
   144         if (ext[p] == format) {
   145             return p;
   146         }
   147     }
   148     return "0x" + format.toString(16);
   149 }
   151 function runTestExtension() {
   152     debug("Testing WEBGL_compressed_texture_etc1");
   154     // check that all format enums exist.
   155     for (name in validFormats) {
   156         var expected = "0x" + validFormats[name].toString(16);
   157         var actual = "ext['" + name + "']";
   158         shouldBe(actual, expected);
   159     }
   161     supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
   162     // There should be exactly 4 formats
   163     shouldBe("supportedFormats.length", "1");
   165     // check that all 4 formats exist
   166     for (var name in validFormats.length) {
   167         formatExists(validFormats[name], supportedFormats);
   168     }
   170     // Test each format
   171     testETC1_RGB();
   172 }
   174 function testETC1_RGB() {
   175     var tests = [
   176         {   width: 4,
   177             height: 4,
   178             channels: 3,
   179             data: img_4x4_rgb_etc1,
   180             format: ext.COMPRESSED_RGB_ETC1_WEBGL
   181         },
   182         {   width: 8,
   183             height: 8,
   184             channels: 3,
   185             data: img_8x8_rgb_etc1,
   186             format: ext.COMPRESSED_RGB_ETC1_WEBGL
   187         }
   188     ];
   189     testETCTextures(tests);
   190 }
   192 function testETCTextures(tests) {
   193     for (var ii = 0; ii < tests.length; ++ii) {
   194         debug("<hr/>");
   195         testETCTexture(tests[ii]);
   196     }
   197 }
   199 function offset_color(c, o) {
   200     return [
   201         Math.min(Math.max(0, c[0] + o), 255),
   202         Math.min(Math.max(0, c[1] + o), 255),
   203         Math.min(Math.max(0, c[2] + o), 255),
   204         c[3]
   205     ];
   206 }
   208 function uncompressETC1Block(destBuffer, destX, destY, destWidth, src) {
   209     'use strict';
   210     var xx, yy, basecols;
   211     var _deltatable = [ 0, 1, 2, 3, -4, -3, -2, -1 ];
   212     var _modtable = [
   213         [ 2,    8,  -2,   -8 ],
   214         [ 5,   17,  -5,  -17 ],
   215         [ 9,   29,  -9,  -29 ],
   216         [ 13,  42, -13,  -42 ],
   217         [ 18,  60, -18,  -60 ],
   218         [ 24,  80, -24,  -80 ],
   219         [ 33, 106, -33, -106 ],
   220         [ 47, 183, -47, -183 ]
   221     ];
   222     var _sl = [
   223         0x00, 0x01, 0x04, 0x05,
   224         0x10, 0x11, 0x14, 0x15,
   225         0x40, 0x41, 0x44, 0x45,
   226         0x50, 0x51, 0x54, 0x55
   227     ];
   228     var _sh = [
   229         0x00, 0x02, 0x08, 0x0a,
   230         0x20, 0x22, 0x28, 0x2a,
   231         0x80, 0x82, 0x88, 0x8a,
   232         0xa0, 0xa2, 0xa8, 0xaa
   233     ];
   235     function extend_4to8bits(r, g, b) {
   236         return [
   237             (r & 0xf0) | ((r >> 4) & 0x0f),
   238             (g & 0xf0) | ((g >> 4) & 0x0f),
   239             (b & 0xf0) | ((b >> 4) & 0x0f),
   240             255
   241         ];
   242     }
   244     function extend_5to8bits(r, g, b) {
   245         return [
   246             (r & 0xf8) | ((r >> 5) & 0x07),
   247             (g & 0xf8) | ((g >> 5) & 0x07),
   248             (b & 0xf8) | ((b >> 5) & 0x07),
   249             255
   250         ];
   251     }
   253     function base_colors(src, mode) {
   254         var col_1, col_2, didx, d;
   255         if (mode === 'I') {
   256             col_1 = extend_4to8bits(src[0], src[1], src[2]);
   257             col_2 = extend_4to8bits(src[0] << 4, src[1] << 4, src[2] << 4);
   258             return [ col_1, col_2 ];
   259         }
   261         if (mode === 'D') {
   262             col_1 = extend_5to8bits(src[0], src[1], src[2]);
   263             col_2 = extend_5to8bits(src[0] + 8 * _deltatable[(src[0] & 0x7)],
   264                                     src[1] + 8 * _deltatable[(src[1] & 0x7)],
   265                                     src[2] + 8 * _deltatable[(src[2] & 0x7)]);
   266             return [ col_1, col_2 ];
   267         }
   269         return [];
   270     }
   272     function mode(src) {
   273         return (src[3] & 0x2) ? 'D' : 'I';
   274     }
   276     function flip(src) {
   277         return (src[3] & 0x1) === 0x1;
   278     }
   280     function subblock_modtable(src, sb) {
   281         var shift = (sb ? 2 : 5);
   282         var idx = (src[3] >> shift) & 0x7;
   283         return _modtable[idx];
   284     }
   286     function interleave_table_indices(src) {
   287         var result =
   288                 (_sl[src[7]         & 0xf] | _sh[src[5]        & 0xf]) |
   289                 ((_sl[(src[7] >> 4) & 0xf] | _sh[(src[5] >> 4) & 0xf]) << 8) |
   290                 ((_sl[src[6]        & 0xf] | _sh[src[4]        & 0xf]) << 16) |
   291                 ((_sl[(src[6] >> 4) & 0xf] | _sh[(src[4] >> 4) & 0xf]) << 24);
   292         return result;
   293     }
   295     function subblock(n, flip) {
   296         var mask = flip ? 0x2 : 0x8;
   297         return (n & mask) ? 1 : 0;
   298     }
   300     var m = mode(src);
   301     basecols = base_colors(src, m);
   303     var alpha = 255;
   304     var flipbit = flip(src);
   305     var table_indices = interleave_table_indices(src);
   307     var n = 0;
   308     for (xx = 0; xx < 4; ++xx) {
   309         for (yy = 0; yy < 4; ++yy) {
   310             var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
   312             var sb = subblock(n, flipbit);
   313             var mod = subblock_modtable(src, sb);
   314             var offset = mod[(table_indices & 0x3)];
   315             var col = offset_color(basecols[sb], offset);
   317             destBuffer[dstOff]     = col[0];
   318             destBuffer[dstOff + 1] = col[1];
   319             destBuffer[dstOff + 2] = col[2];
   320             destBuffer[dstOff + 3] = alpha;
   321             table_indices >>= 2;
   322             n++;
   323         }
   324     }
   325 }
   327 function uncompressETC1(width, height, data, format) {
   328     if (width % 4 || height % 4) throw "bad width or height";
   330     var dest = new Uint8Array(width * height * 4);
   331     var blocksAcross = width / 4;
   332     var blocksDown = height / 4;
   333     var blockSize = 8;
   334     for (var yy = 0; yy < blocksDown; ++yy) {
   335         for (var xx = 0; xx < blocksAcross; ++xx) {
   336             var srcOffset = (yy * blocksAcross + xx) * blockSize;
   337             var srcblk = data.subarray(srcOffset, srcOffset + blockSize);
   338             uncompressETC1Block(dest, xx * 4, yy * 4, width, srcblk);
   339         }
   340     }
   341     return dest;
   342 }
   344 function testETCTexture(test) {
   345     var data = new Uint8Array(test.data);
   346     var width = test.width;
   347     var height = test.height;
   348     var format = test.format;
   350     var uncompressedData = uncompressETC1(width, height, data, format);
   352     canvas.width = width;
   353     canvas.height = height;
   354     gl.viewport(0, 0, width, height);
   355     debug("testing " + formatToString(format) + " " + width + "x" + height);
   357     var tex = gl.createTexture();
   358     gl.bindTexture(gl.TEXTURE_2D, tex);
   359     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   360     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   361     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   362     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
   363     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
   364     glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
   365     gl.generateMipmap(gl.TEXTURE_2D);
   366     glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
   367     wtu.clearAndDrawUnitQuad(gl);
   368     compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
   370     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
   371     glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
   373     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
   374     glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   375     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
   376     glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   377     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
   378     glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   379     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
   380     glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
   382     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
   383     glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
   384     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
   385     glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
   386     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
   387     glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
   388     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
   389     glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported");
   391     if (width == 4) {
   392       gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
   393       glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   394       gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
   395       glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   396     }
   397     if (height == 4) {
   398       gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
   399       glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   400       gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
   401       glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
   402     }
   404     // Reupload the complete texture before SubImage tests.
   405     gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
   406     glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
   408     /* OES_compressed_ETC1_RGB8_texture:
   409      *   INVALID_OPERATION is generated by CompressedTexSubImage2D,
   410      *   TexSubImage2D, or CopyTexSubImage2D if the texture image
   411      *   <level> bound to <target> has internal format ETC1_RGB8_OES.
   412      */
   413     gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
   414     glErrorShouldBe(gl, gl.INVALID_OPERATION, "ETC1 should not support compressedTexSubImage2D.");
   415 }
   417 function insertImg(element, caption, img) {
   418     var div = document.createElement("div");
   419     div.appendChild(img);
   420     var label = document.createElement("div");
   421     label.appendChild(document.createTextNode(caption));
   422     div.appendChild(label);
   423     element.appendChild(div);
   424 }
   426 function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
   427     var scale = 8;
   428     var c = document.createElement("canvas");
   429     c.width = imageWidth * scale;
   430     c.height = imageHeight * scale;
   431     var ctx = c.getContext("2d");
   432     for (var yy = 0; yy < imageHeight; ++yy) {
   433         for (var xx = 0; xx < imageWidth; ++xx) {
   434             var offset = (yy * dataWidth + xx) * 4;
   435             ctx.fillStyle = "rgba(" +
   436                     data[offset + 0] + "," +
   437                     data[offset + 1] + "," +
   438                     data[offset + 2] + "," +
   439                     (alpha ? data[offset + 3] / 255 : 1) + ")";
   440             ctx.fillRect(xx * scale, yy * scale, scale, scale);
   441         }
   442     }
   443     var img = document.createElement("img");
   444     img.src = c.toDataURL();
   445     return img;
   446 }
   448 function compareRect(actualWidth, actualHeight, actualChannels,
   449                      dataWidth, dataHeight, expectedData,
   450                      testData, testFormat)
   451 {
   452     var actual = new Uint8Array(actualWidth * actualHeight * 4);
   453     gl.readPixels(0, 0, actualWidth, actualHeight,
   454                   gl.RGBA, gl.UNSIGNED_BYTE, actual);
   456     var div = document.createElement("div");
   457     div.className = "testimages";
   458     insertImg(div, "expected", makeImage(
   459             actualWidth, actualHeight, dataWidth, expectedData,
   460             actualChannels == 4));
   461     insertImg(div, "actual", makeImage(
   462             actualWidth, actualHeight, actualWidth, actual,
   463             actualChannels == 4));
   464     div.appendChild(document.createElement('br'));
   465     document.getElementById("console").appendChild(div);
   467     var failed = false;
   468     for (var yy = 0; yy < actualHeight; ++yy) {
   469         for (var xx = 0; xx < actualWidth; ++xx) {
   470             var actualOffset = (yy * actualWidth + xx) * 4;
   471             var expectedOffset = (yy * dataWidth + xx) * 4;
   472             var expected = [
   473                     expectedData[expectedOffset + 0],
   474                     expectedData[expectedOffset + 1],
   475                     expectedData[expectedOffset + 2],
   476                     (actualChannels == 3 ? 255
   477                                          : expectedData[expectedOffset + 3])
   478             ];
   480             if (actual[actualOffset + 0] != expected[0] ||
   481                 actual[actualOffset + 1] != expected[1] ||
   482                 actual[actualOffset + 2] != expected[2] ||
   483                 actual[actualOffset + 3] != expected[3])
   484             {
   485                 failed = true;
   486                 var was = actual[actualOffset + 0].toString();
   487                 for (var j = 1; j < 4; ++j) {
   488                     was += "," + actual[actualOffset + j];
   489                 }
   490                 testFailed('at (' + xx + ', ' + yy +
   491                            ') expected: ' + expected + ' was ' + was);
   492             }
   493         }
   494     }
   495     if (!failed) {
   496         testPassed("texture rendered correctly");
   497     }
   498 }
   500 debug("");
   501 var successfullyParsed = true;
   502 </script>
   503 <script>finishTest();</script>
   505 </body>
   506 </html>

mercurial