tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tcuCompressedTexture.js (41508B)


      1 /*-------------------------------------------------------------------------
      2 * drawElements Quality Program OpenGL ES Utilities
      3 * ------------------------------------------------
      4 *
      5 * Copyright 2014 The Android Open Source Project
      6 *
      7 * Licensed under the Apache License, Version 2.0 (the "License");
      8 * you may not use this file except in compliance with the License.
      9 * You may obtain a copy of the License at
     10 *
     11 *      http://www.apache.org/licenses/LICENSE-2.0
     12 *
     13 * Unless required by applicable law or agreed to in writing, software
     14 * distributed under the License is distributed on an "AS IS" BASIS,
     15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16 * See the License for the specific language governing permissions and
     17 * limitations under the License.
     18 *
     19 */
     20 
     21 /*--------------------------------------------------------------------*//*!
     22 * \brief Map tcu::TextureFormat to GL pixel transfer format.
     23 *
     24 * Maps generic texture format description to GL pixel transfer format.
     25 * If no mapping is found, throws tcu::InternalError.
     26 *
     27 * \param texFormat Generic texture format.
     28 * \return GL pixel transfer format.
     29 *//*--------------------------------------------------------------------*/
     30 'use strict';
     31 goog.provide('framework.common.tcuCompressedTexture');
     32 goog.require('framework.common.tcuTexture');
     33 goog.require('framework.delibs.debase.deMath');
     34 
     35 goog.scope(function() {
     36 
     37 var tcuCompressedTexture = framework.common.tcuCompressedTexture;
     38 var tcuTexture = framework.common.tcuTexture;
     39 var deMath = framework.delibs.debase.deMath;
     40 
     41    var DE_ASSERT = function(x) {
     42        if (!x)
     43            throw new Error('Assert failed');
     44    };
     45 
     46 /**
     47 * @enum
     48 */
     49 tcuCompressedTexture.Format = {
     50    ETC1_RGB8: 0,
     51    EAC_R11: 1,
     52    EAC_SIGNED_R11: 2,
     53    EAC_RG11: 3,
     54    EAC_SIGNED_RG11: 4,
     55    ETC2_RGB8: 5,
     56    ETC2_SRGB8: 6,
     57    ETC2_RGB8_PUNCHTHROUGH_ALPHA1: 7,
     58    ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: 8,
     59    ETC2_EAC_RGBA8: 9,
     60    ETC2_EAC_SRGB8_ALPHA8: 10,
     61 
     62    ASTC_4x4_RGBA: 11,
     63    ASTC_5x4_RGBA: 12,
     64    ASTC_5x5_RGBA: 13,
     65    ASTC_6x5_RGBA: 14,
     66    ASTC_6x6_RGBA: 15,
     67    ASTC_8x5_RGBA: 16,
     68    ASTC_8x6_RGBA: 17,
     69    ASTC_8x8_RGBA: 18,
     70    ASTC_10x5_RGBA: 19,
     71    ASTC_10x6_RGBA: 20,
     72    ASTC_10x8_RGBA: 21,
     73    ASTC_10x10_RGBA: 22,
     74    ASTC_12x10_RGBA: 23,
     75    ASTC_12x12_RGBA: 24,
     76    ASTC_4x4_SRGB8_ALPHA8: 25,
     77    ASTC_5x4_SRGB8_ALPHA8: 26,
     78    ASTC_5x5_SRGB8_ALPHA8: 27,
     79    ASTC_6x5_SRGB8_ALPHA8: 28,
     80    ASTC_6x6_SRGB8_ALPHA8: 29,
     81    ASTC_8x5_SRGB8_ALPHA8: 30,
     82    ASTC_8x6_SRGB8_ALPHA8: 31,
     83    ASTC_8x8_SRGB8_ALPHA8: 32,
     84    ASTC_10x5_SRGB8_ALPHA8: 33,
     85    ASTC_10x6_SRGB8_ALPHA8: 34,
     86    ASTC_10x8_SRGB8_ALPHA8: 35,
     87    ASTC_10x10_SRGB8_ALPHA8: 36,
     88    ASTC_12x10_SRGB8_ALPHA8: 37,
     89    ASTC_12x12_SRGB8_ALPHA8: 38
     90 };
     91 
     92 tcuCompressedTexture.divRoundUp = function(a, b) {
     93    return Math.floor(a / b) + ((a % b) ? 1 : 0);
     94 };
     95 
     96 tcuCompressedTexture.isEtcFormat = function(fmt) {
     97    // WebGL2 supports ETC2 and EAC formats
     98    switch (fmt) {
     99        // case tcuCompressedTexture.Format.ETC1_RGB8:
    100        case tcuCompressedTexture.Format.EAC_R11:
    101        case tcuCompressedTexture.Format.EAC_SIGNED_R11:
    102        case tcuCompressedTexture.Format.EAC_RG11:
    103        case tcuCompressedTexture.Format.EAC_SIGNED_RG11:
    104        case tcuCompressedTexture.Format.ETC2_RGB8:
    105        case tcuCompressedTexture.Format.ETC2_SRGB8:
    106        case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
    107        case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
    108        case tcuCompressedTexture.Format.ETC2_EAC_RGBA8:
    109        case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8:
    110            return true;
    111 
    112        default:
    113            return false;
    114    }
    115 };
    116 
    117 tcuCompressedTexture.etcDecompressInternal = function() {
    118 
    119 var ETC2_BLOCK_WIDTH = 4;
    120 var ETC2_BLOCK_HEIGHT = 4;
    121 var ETC2_UNCOMPRESSED_PIXEL_SIZE_A8 = 1;
    122 var ETC2_UNCOMPRESSED_PIXEL_SIZE_R11 = 2;
    123 var ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11 = 4;
    124 var ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8 = 3;
    125 var ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 = 4;
    126 var ETC2_UNCOMPRESSED_BLOCK_SIZE_A8 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
    127 var ETC2_UNCOMPRESSED_BLOCK_SIZE_R11 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
    128 var ETC2_UNCOMPRESSED_BLOCK_SIZE_RG11 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11;
    129 var ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    130 var ETC2_UNCOMPRESSED_BLOCK_SIZE_RGBA8 = ETC2_BLOCK_WIDTH * ETC2_BLOCK_HEIGHT * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
    131 
    132 /**
    133 * @param {ArrayBuffer} src Source ArrayBuffer
    134 * @return {Uint8Array}
    135 */
    136 var get64BitBlock = function(src, blockNdx) {
    137    var block = new Uint8Array(src, blockNdx * 8, 8);
    138    return block;
    139 };
    140 
    141 /**
    142 * @param {ArrayBuffer} src Source ArrayBuffer
    143 * Return the first 64 bits of a 128 bit block.
    144 */
    145 var get128BitBlockStart = function(src, blockNdx) {
    146    return get64BitBlock(src, 2 * blockNdx);
    147 };
    148 
    149 /**
    150 * @param {ArrayBuffer} src Source ArrayBuffer
    151 * Return the last 64 bits of a 128 bit block.
    152 */
    153 var get128BitBlockEnd = function(src, blockNdx) {
    154    return get64BitBlock(src, 2 * blockNdx + 1);
    155 };
    156 
    157 var mask8 = function(src, low, high) {
    158    if (low > 7 || high < 0)
    159        return {
    160            value: 0,
    161            bits: 0
    162        };
    163 
    164    var numBits = high - low + 1;
    165    var mask = (1 << numBits) - 1;
    166 
    167    return {
    168        value: (src >> low) & mask,
    169        bits: numBits
    170    };
    171 };
    172 
    173 var getBits64 = function(src, low, high) {
    174    var result = 0;
    175    var bits = 0;
    176    var lowIndex = low;
    177    var highIndex = high;
    178    for (var i = 7; i >= 0; i--) {
    179        var v = mask8(src[i], Math.max(0, lowIndex), Math.min(7, highIndex));
    180        lowIndex = lowIndex - 8;
    181        highIndex = highIndex - 8;
    182        result = result | (v.value << bits);
    183        bits = v.bits;
    184    }
    185    return result;
    186 };
    187 
    188 var getBit64 = function(src, bit) {
    189    return getBits64(src, bit, bit);
    190 };
    191 
    192 var extendSigned3To8 = function(src) {
    193    var isNeg = (src & (1 << 2)) != 0;
    194    var val = isNeg ? src - 8 : src;
    195    return val;
    196 };
    197 
    198 var extend4To8 = function(src) {
    199    return src * 255 / 15;
    200 };
    201 
    202 var extend5To8 = function(src) {
    203    return src * 255 / 31;
    204 };
    205 
    206 var extend6To8 = function(src) {
    207    return src * 255 / 63;
    208 };
    209 
    210 var extend7To8 = function(src) {
    211    return src * 255 / 127;
    212 };
    213 
    214 var extend11To16 = function(src) {
    215    return src * 32.015144;
    216 };
    217 
    218 var extend11To16WithSign = function(src) {
    219    if (src < 0)
    220        return -extend11To16(-src);
    221    else
    222        return extend11To16(src);
    223 };
    224 
    225 /**
    226 * @param { (Uint16Array|Int16Array) } dst
    227 * @param {Uint8Array} src
    228 * @param {boolean} signedMode
    229 */
    230 var decompressEAC11Block = function(dst, src, signedMode) {
    231    var modifierTable = [
    232        [-3, -6, -9, -15, 2, 5, 8, 14],
    233        [-3, -7, -10, -13, 2, 6, 9, 12],
    234        [-2, -5, -8, -13, 1, 4, 7, 12],
    235        [-2, -4, -6, -13, 1, 3, 5, 12],
    236        [-3, -6, -8, -12, 2, 5, 7, 11],
    237        [-3, -7, -9, -11, 2, 6, 8, 10],
    238        [-4, -7, -8, -11, 3, 6, 7, 10],
    239        [-3, -5, -8, -11, 2, 4, 7, 10],
    240        [-2, -6, -8, -10, 1, 5, 7, 9],
    241        [-2, -5, -8, -10, 1, 4, 7, 9],
    242        [-2, -4, -8, -10, 1, 3, 7, 9],
    243        [-2, -5, -7, -10, 1, 4, 6, 9],
    244        [-3, -4, -7, -10, 2, 3, 6, 9],
    245        [-1, -2, -3, -10, 0, 1, 2, 9],
    246        [-4, -6, -8, -9, 3, 5, 7, 8],
    247        [-3, -5, -7, -9, 2, 4, 6, 8]
    248    ];
    249 
    250    var multiplier = getBits64(src, 52, 55);
    251    var tableNdx = getBits64(src, 48, 51);
    252    var baseCodeword = getBits64(src, 56, 63);
    253 
    254    if (signedMode) {
    255        if (baseCodeword > 127)
    256            baseCodeword -= 256;
    257        if (baseCodeword == -128)
    258            baseCodeword = -127;
    259    }
    260 
    261    var pixelNdx = 0;
    262    for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
    263        for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++) {
    264             var dstOffset = (y * ETC2_BLOCK_WIDTH + x);
    265             var pixelBitNdx = 45 - 3 * pixelNdx;
    266             var modifierNdx = (getBit64(src, pixelBitNdx + 2) << 2) | (getBit64(src, pixelBitNdx + 1) << 1) | getBit64(src, pixelBitNdx);
    267             var modifier = modifierTable[tableNdx][modifierNdx];
    268 
    269            if (signedMode) {
    270                if (multiplier != 0)
    271                    dst[dstOffset] = deMath.clamp(baseCodeword * 8 + multiplier * modifier * 8, -1023, 1023);
    272                else
    273                    dst[dstOffset] = deMath.clamp(baseCodeword * 8 + modifier, -1023, 1023);
    274            } else {
    275                if (multiplier != 0)
    276                    dst[dstOffset] = deMath.clamp(baseCodeword * 8 + 4 + multiplier * modifier * 8, 0, 2047);
    277                else
    278                    dst[dstOffset] = deMath.clamp(baseCodeword * 8 + 4 + modifier, 0, 2047);
    279            }
    280            pixelNdx++;
    281        }
    282    }
    283 };
    284 
    285 var decompressEAC_R11 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src, signedMode) {
    286    /** @const */ var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
    287    /** @const */ var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
    288    var dstPtr;
    289    var dstRowPitch = dst.getRowPitch();
    290    var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
    291    var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_R11);
    292    var uncompressedBlock16;
    293    if (signedMode) {
    294        dstPtr = new Int16Array(dst.m_data);
    295        uncompressedBlock16 = new Int16Array(uncompressedBlockArray);
    296    } else {
    297        dstPtr = new Uint16Array(dst.m_data);
    298        uncompressedBlock16 = new Uint16Array(uncompressedBlockArray);
    299    }
    300 
    301    for (var blockY = 0; blockY < numBlocksY; blockY++) {
    302        for (var blockX = 0; blockX < numBlocksX; blockX++) {
    303            /*const deUint64*/ var compressedBlock = get64BitBlock(src, blockY * numBlocksX + blockX);
    304 
    305            // Decompress.
    306            decompressEAC11Block(uncompressedBlock16, compressedBlock, signedMode);
    307 
    308            // Write to dst.
    309            var baseX = blockX * ETC2_BLOCK_WIDTH;
    310            var baseY = blockY * ETC2_BLOCK_HEIGHT;
    311            for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
    312                for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
    313                    DE_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_R11 == 2);
    314 
    315                    if (signedMode) {
    316                        var srcIndex = y * ETC2_BLOCK_WIDTH + x;
    317                        var dstIndex = (baseY + y) * dstRowPitch / dstPixelSize + baseX + x;
    318 
    319                        dstPtr[dstIndex] = extend11To16WithSign(uncompressedBlock16[srcIndex]);
    320                    } else {
    321                        var srcIndex = y * ETC2_BLOCK_WIDTH + x;
    322                        var dstIndex = (baseY + y) * dstRowPitch / dstPixelSize + baseX + x;
    323 
    324                        dstPtr[dstIndex] = extend11To16(uncompressedBlock16[srcIndex]);
    325                    }
    326                }
    327            }
    328        }
    329    }
    330 };
    331 
    332 var decompressEAC_RG11 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src, signedMode) {
    333    /** @const */ var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
    334    /** @const */ var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
    335    var dstPtr;
    336    var dstRowPitch = dst.getRowPitch();
    337    var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11;
    338    var uncompressedBlockArrayR = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_R11);
    339    var uncompressedBlockArrayG = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_R11);
    340    var uncompressedBlockR16;
    341    var uncompressedBlockG16;
    342    if (signedMode) {
    343        dstPtr = new Int16Array(dst.m_data);
    344        uncompressedBlockR16 = new Int16Array(uncompressedBlockArrayR);
    345        uncompressedBlockG16 = new Int16Array(uncompressedBlockArrayG);
    346    } else {
    347        dstPtr = new Uint16Array(dst.m_data);
    348        uncompressedBlockR16 = new Uint16Array(uncompressedBlockArrayR);
    349        uncompressedBlockG16 = new Uint16Array(uncompressedBlockArrayG);
    350    }
    351 
    352    for (var blockY = 0; blockY < numBlocksY; blockY++) {
    353        for (var blockX = 0; blockX < numBlocksX; blockX++) {
    354            /*const deUint64*/ var compressedBlockR = get128BitBlockStart(src, blockY * numBlocksX + blockX);
    355            /*const deUint64*/ var compressedBlockG = get128BitBlockEnd(src, blockY * numBlocksX + blockX);
    356 
    357            // Decompress.
    358            decompressEAC11Block(uncompressedBlockR16, compressedBlockR, signedMode);
    359            decompressEAC11Block(uncompressedBlockG16, compressedBlockG, signedMode);
    360 
    361            // Write to dst.
    362            var baseX = blockX * ETC2_BLOCK_WIDTH;
    363            var baseY = blockY * ETC2_BLOCK_HEIGHT;
    364            for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
    365                for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
    366                    DE_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11 == 4);
    367 
    368                    if (signedMode) {
    369                        var srcIndex = y * ETC2_BLOCK_WIDTH + x;
    370                        var dstIndex = 2 * ((baseY + y) * dstRowPitch / dstPixelSize + baseX + x);
    371 
    372                        dstPtr[dstIndex] = extend11To16WithSign(uncompressedBlockR16[srcIndex]);
    373                        dstPtr[dstIndex + 1] = extend11To16WithSign(uncompressedBlockG16[srcIndex]);
    374                    } else {
    375                        var srcIndex = y * ETC2_BLOCK_WIDTH + x;
    376                        var dstIndex = 2 * ((baseY + y) * dstRowPitch / dstPixelSize + baseX + x);
    377 
    378                        dstPtr[dstIndex] = extend11To16(uncompressedBlockR16[srcIndex]);
    379                        dstPtr[dstIndex + 1] = extend11To16(uncompressedBlockG16[srcIndex]);
    380                    }
    381                }
    382            }
    383        }
    384    }
    385 };
    386 
    387 // if alphaMode is true, do PUNCHTHROUGH and store alpha to alphaDst; otherwise do ordinary ETC2 RGB8.
    388 /**
    389 * @param {Uint8Array} dst Destination array
    390 * @param {Uint8Array} src Source array
    391 * @param {Uint8Array} alphaDst Optional Alpha output channel
    392 */
    393 var decompressETC2Block = function(dst, src, alphaDst, alphaMode) {
    394    /**
    395     * enum
    396     */
    397    var Etc2Mode = {
    398        MODE_INDIVIDUAL: 0,
    399        MODE_DIFFERENTIAL: 1,
    400        MODE_T: 2,
    401        MODE_H: 3,
    402        MODE_PLANAR: 4
    403    };
    404 
    405    var diffOpaqueBit = getBit64(src, 33);
    406    var selBR = getBits64(src, 59, 63); // 5 bits.
    407    var selBG = getBits64(src, 51, 55);
    408    var selBB = getBits64(src, 43, 47);
    409    var selDR = extendSigned3To8(getBits64(src, 56, 58)); // 3 bits.
    410    var selDG = extendSigned3To8(getBits64(src, 48, 50));
    411    var selDB = extendSigned3To8(getBits64(src, 40, 42));
    412 
    413    var mode;
    414 
    415    if (!alphaMode && diffOpaqueBit == 0)
    416        mode = Etc2Mode.MODE_INDIVIDUAL;
    417    else if (!deMath.deInRange32(selBR + selDR, 0, 31))
    418        mode = Etc2Mode.MODE_T;
    419    else if (!deMath.deInRange32(selBG + selDG, 0, 31))
    420        mode = Etc2Mode.MODE_H;
    421    else if (!deMath.deInRange32(selBB + selDB, 0, 31))
    422        mode = Etc2Mode.MODE_PLANAR;
    423    else
    424        mode = Etc2Mode.MODE_DIFFERENTIAL;
    425 
    426    if (mode == Etc2Mode.MODE_INDIVIDUAL || mode == Etc2Mode.MODE_DIFFERENTIAL) {
    427        // Individual and differential modes have some steps in common, handle them here.
    428        var modifierTable = [
    429        //      00 01 10 11
    430            [2, 8, -2, -8],
    431            [5, 17, -5, -17],
    432            [9, 29, -9, -29],
    433            [13, 42, -13, -42],
    434            [18, 60, -18, -60],
    435            [24, 80, -24, -80],
    436            [33, 106, -33, -106],
    437            [47, 183, -47, -183]
    438        ];
    439 
    440         var flipBit = getBit64(src, 32);
    441         var table = [getBits64(src, 37, 39), getBits64(src, 34, 36)];
    442        var baseR = [];
    443        var baseG = [];
    444        var baseB = [];
    445 
    446        if (mode == Etc2Mode.MODE_INDIVIDUAL) {
    447            // Individual mode, initial values.
    448            baseR[0] = extend4To8(getBits64(src, 60, 63));
    449            baseR[1] = extend4To8(getBits64(src, 56, 59));
    450            baseG[0] = extend4To8(getBits64(src, 52, 55));
    451            baseG[1] = extend4To8(getBits64(src, 48, 51));
    452            baseB[0] = extend4To8(getBits64(src, 44, 47));
    453            baseB[1] = extend4To8(getBits64(src, 40, 43));
    454        } else {
    455            // Differential mode, initial values.
    456            baseR[0] = extend5To8(selBR);
    457            baseG[0] = extend5To8(selBG);
    458            baseB[0] = extend5To8(selBB);
    459 
    460            baseR[1] = extend5To8((selBR + selDR));
    461            baseG[1] = extend5To8((selBG + selDG));
    462            baseB[1] = extend5To8((selBB + selDB));
    463        }
    464 
    465        // Write final pixels for individual or differential mode.
    466        var pixelNdx = 0;
    467        for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
    468            for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++, pixelNdx++) {
    469                 var dstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    470                 var subBlock = ((flipBit ? y : x) >= 2) ? 1 : 0;
    471                 var tableNdx = table[subBlock];
    472                 var modifierNdx = (getBit64(src, 16 + pixelNdx) << 1) | getBit64(src, pixelNdx);
    473                 var alphaDstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
    474 
    475                // If doing PUNCHTHROUGH version (alphaMode), opaque bit may affect colors.
    476                if (alphaMode && diffOpaqueBit == 0 && modifierNdx == 2) {
    477                    dst[dstOffset + 0] = 0;
    478                    dst[dstOffset + 1] = 0;
    479                    dst[dstOffset + 2] = 0;
    480                    alphaDst[alphaDstOffset] = 0;
    481                } else {
    482                    var modifier;
    483 
    484                    // PUNCHTHROUGH version and opaque bit may also affect modifiers.
    485                    if (alphaMode && diffOpaqueBit == 0 && (modifierNdx == 0 || modifierNdx == 2))
    486                        modifier = 0;
    487                    else
    488                        modifier = modifierTable[tableNdx][modifierNdx];
    489 
    490                    dst[dstOffset + 0] = deMath.clamp(baseR[subBlock] + modifier, 0, 255);
    491                    dst[dstOffset + 1] = deMath.clamp(baseG[subBlock] + modifier, 0, 255);
    492                    dst[dstOffset + 2] = deMath.clamp(baseB[subBlock] + modifier, 0, 255);
    493 
    494                    if (alphaMode)
    495                        alphaDst[alphaDstOffset] = 255;
    496                }
    497            }
    498        }
    499    } else if (mode == Etc2Mode.MODE_T || mode == Etc2Mode.MODE_H) {
    500        // T and H modes have some steps in common, handle them here.
    501        var distTable = [3, 6, 11, 16, 23, 32, 41, 64];
    502 
    503        var paintR = [];
    504        var paintG = [];
    505        var paintB = [];
    506 
    507        if (mode == Etc2Mode.MODE_T) {
    508            // T mode, calculate paint values.
    509             var R1a = getBits64(src, 59, 60);
    510             var R1b = getBits64(src, 56, 57);
    511             var G1 = getBits64(src, 52, 55);
    512             var B1 = getBits64(src, 48, 51);
    513             var R2 = getBits64(src, 44, 47);
    514             var G2 = getBits64(src, 40, 43);
    515             var B2 = getBits64(src, 36, 39);
    516             var distNdx = (getBits64(src, 34, 35) << 1) | getBit64(src, 32);
    517             var dist = distTable[distNdx];
    518 
    519            paintR[0] = extend4To8((R1a << 2) | R1b);
    520            paintG[0] = extend4To8(G1);
    521            paintB[0] = extend4To8(B1);
    522            paintR[2] = extend4To8(R2);
    523            paintG[2] = extend4To8(G2);
    524            paintB[2] = extend4To8(B2);
    525            paintR[1] = deMath.clamp(paintR[2] + dist, 0, 255);
    526            paintG[1] = deMath.clamp(paintG[2] + dist, 0, 255);
    527            paintB[1] = deMath.clamp(paintB[2] + dist, 0, 255);
    528            paintR[3] = deMath.clamp(paintR[2] - dist, 0, 255);
    529            paintG[3] = deMath.clamp(paintG[2] - dist, 0, 255);
    530            paintB[3] = deMath.clamp(paintB[2] - dist, 0, 255);
    531        } else {
    532            // H mode, calculate paint values.
    533            var R1 = getBits64(src, 59, 62);
    534            var G1a = getBits64(src, 56, 58);
    535            var G1b = getBit64(src, 52);
    536            var B1a = getBit64(src, 51);
    537            var B1b = getBits64(src, 47, 49);
    538            var R2 = getBits64(src, 43, 46);
    539            var G2 = getBits64(src, 39, 42);
    540            var B2 = getBits64(src, 35, 38);
    541            var baseR = [];
    542            var baseG = [];
    543            var baseB = [];
    544            var baseValue = [];
    545            var distNdx;
    546            var dist;
    547 
    548            baseR[0] = extend4To8(R1);
    549            baseG[0] = extend4To8((G1a << 1) | G1b);
    550            baseB[0] = extend4To8((B1a << 3) | B1b);
    551            baseR[1] = extend4To8(R2);
    552            baseG[1] = extend4To8(G2);
    553            baseB[1] = extend4To8(B2);
    554            baseValue[0] = ((baseR[0]) << 16) | ((baseG[0]) << 8) | baseB[0];
    555            baseValue[1] = ((baseR[1]) << 16) | ((baseG[1]) << 8) | baseB[1];
    556            distNdx = (getBit64(src, 34) << 2) | (getBit64(src, 32) << 1);
    557            if (baseValue[0] >= baseValue[1])
    558                distNdx += 1;
    559            dist = distTable[distNdx];
    560 
    561            paintR[0] = deMath.clamp(baseR[0] + dist, 0, 255);
    562            paintG[0] = deMath.clamp(baseG[0] + dist, 0, 255);
    563            paintB[0] = deMath.clamp(baseB[0] + dist, 0, 255);
    564            paintR[1] = deMath.clamp(baseR[0] - dist, 0, 255);
    565            paintG[1] = deMath.clamp(baseG[0] - dist, 0, 255);
    566            paintB[1] = deMath.clamp(baseB[0] - dist, 0, 255);
    567            paintR[2] = deMath.clamp(baseR[1] + dist, 0, 255);
    568            paintG[2] = deMath.clamp(baseG[1] + dist, 0, 255);
    569            paintB[2] = deMath.clamp(baseB[1] + dist, 0, 255);
    570            paintR[3] = deMath.clamp(baseR[1] - dist, 0, 255);
    571            paintG[3] = deMath.clamp(baseG[1] - dist, 0, 255);
    572            paintB[3] = deMath.clamp(baseB[1] - dist, 0, 255);
    573        }
    574 
    575        // Write final pixels for T or H mode.
    576        var pixelNdx = 0;
    577        for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
    578            for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++, pixelNdx++) {
    579                 var dstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    580                 var paintNdx = (getBit64(src, 16 + pixelNdx) << 1) | getBit64(src, pixelNdx);
    581                 var alphaDstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
    582 
    583                if (alphaMode && diffOpaqueBit == 0 && paintNdx == 2) {
    584                    dst[dstOffset + 0] = 0;
    585                    dst[dstOffset + 1] = 0;
    586                    dst[dstOffset + 2] = 0;
    587                    alphaDst[alphaDstOffset] = 0;
    588                } else {
    589                    dst[dstOffset + 0] = deMath.clamp(paintR[paintNdx], 0, 255);
    590                    dst[dstOffset + 1] = deMath.clamp(paintG[paintNdx], 0, 255);
    591                    dst[dstOffset + 2] = deMath.clamp(paintB[paintNdx], 0, 255);
    592 
    593                    if (alphaMode)
    594                        alphaDst[alphaDstOffset] = 255;
    595                }
    596            }
    597        }
    598    } else {
    599        // Planar mode.
    600        var GO1 = getBit64(src, 56);
    601        var GO2 = getBits64(src, 49, 54);
    602        var BO1 = getBit64(src, 48);
    603        var BO2 = getBits64(src, 43, 44);
    604        var BO3 = getBits64(src, 39, 41);
    605        var RH1 = getBits64(src, 34, 38);
    606        var RH2 = getBit64(src, 32);
    607        var RO = extend6To8(getBits64(src, 57, 62));
    608        var GO = extend7To8((GO1 << 6) | GO2);
    609        var BO = extend6To8((BO1 << 5) | (BO2 << 3) | BO3);
    610        var RH = extend6To8((RH1 << 1) | RH2);
    611        var GH = extend7To8(getBits64(src, 25, 31));
    612        var BH = extend6To8(getBits64(src, 19, 24));
    613        var RV = extend6To8(getBits64(src, 13, 18));
    614        var GV = extend7To8(getBits64(src, 6, 12));
    615        var BV = extend6To8(getBits64(src, 0, 5));
    616 
    617        // Write final pixels for planar mode.
    618        for (var y = 0; y < 4; y++) {
    619            for (var x = 0; x < 4; x++) {
    620                 var dstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    621                 var unclampedR = (x * (RH - RO) + y * (RV - RO) + 4 * RO + 2) / 4;
    622                 var unclampedG = (x * (GH - GO) + y * (GV - GO) + 4 * GO + 2) / 4;
    623                 var unclampedB = (x * (BH - BO) + y * (BV - BO) + 4 * BO + 2) / 4;
    624                 var alphaDstOffset = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
    625 
    626                dst[dstOffset + 0] = deMath.clamp(unclampedR, 0, 255);
    627                dst[dstOffset + 1] = deMath.clamp(unclampedG, 0, 255);
    628                dst[dstOffset + 2] = deMath.clamp(unclampedB, 0, 255);
    629 
    630                if (alphaMode)
    631                    alphaDst[alphaDstOffset] = 255;
    632            }
    633        }
    634    }
    635 };
    636 
    637 var decompressEAC8Block = function(dst, src) {
    638    var modifierTable = [
    639        [-3, -6, -9, -15, 2, 5, 8, 14],
    640        [-3, -7, -10, -13, 2, 6, 9, 12],
    641        [-2, -5, -8, -13, 1, 4, 7, 12],
    642        [-2, -4, -6, -13, 1, 3, 5, 12],
    643        [-3, -6, -8, -12, 2, 5, 7, 11],
    644        [-3, -7, -9, -11, 2, 6, 8, 10],
    645        [-4, -7, -8, -11, 3, 6, 7, 10],
    646        [-3, -5, -8, -11, 2, 4, 7, 10],
    647        [-2, -6, -8, -10, 1, 5, 7, 9],
    648        [-2, -5, -8, -10, 1, 4, 7, 9],
    649        [-2, -4, -8, -10, 1, 3, 7, 9],
    650        [-2, -5, -7, -10, 1, 4, 6, 9],
    651        [-3, -4, -7, -10, 2, 3, 6, 9],
    652        [-1, -2, -3, -10, 0, 1, 2, 9],
    653        [-4, -6, -8, -9, 3, 5, 7, 8],
    654        [-3, -5, -7, -9, 2, 4, 6, 8]
    655    ];
    656 
    657    var baseCodeword = getBits64(src, 56, 63);
    658    var multiplier = getBits64(src, 52, 55);
    659    var tableNdx = getBits64(src, 48, 51);
    660 
    661    var pixelNdx = 0;
    662    for (var x = 0; x < ETC2_BLOCK_WIDTH; x++) {
    663        for (var y = 0; y < ETC2_BLOCK_HEIGHT; y++, pixelNdx++) {
    664            var dstOffset = (y * ETC2_BLOCK_WIDTH + x);
    665            var pixelBitNdx = 45 - 3 * pixelNdx;
    666            var modifierNdx = (getBit64(src, pixelBitNdx + 2) << 2) | (getBit64(src, pixelBitNdx + 1) << 1) | getBit64(src, pixelBitNdx);
    667            var modifier = modifierTable[tableNdx][modifierNdx];
    668 
    669            dst[dstOffset] = deMath.clamp(baseCodeword + multiplier * modifier, 0, 255);
    670        }
    671    }
    672 };
    673 
    674 var decompressETC2 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src) {
    675    var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
    676    var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
    677    var dstPtr = new Uint8Array(dst.m_data);
    678    var dstRowPitch = dst.getRowPitch();
    679    var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    680    var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8);
    681    var uncompressedBlock = new Uint8Array(uncompressedBlockArray);
    682 
    683    for (var blockY = 0; blockY < numBlocksY; blockY++) {
    684        for (var blockX = 0; blockX < numBlocksX; blockX++) {
    685            var compressedBlock = get64BitBlock(src, blockY * numBlocksX + blockX);
    686 
    687            // Decompress.
    688            decompressETC2Block(uncompressedBlock, compressedBlock, null, false);
    689 
    690            // Write to dst.
    691            var baseX = blockX * ETC2_BLOCK_WIDTH;
    692            var baseY = blockY * ETC2_BLOCK_HEIGHT;
    693            for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
    694                for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
    695                    var srcIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    696                    var dstIndex = (baseY + y) * dstRowPitch + (baseX + x) * dstPixelSize;
    697 
    698                    for (var i = 0; i < ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8; i++)
    699                        dstPtr[dstIndex + i] = uncompressedBlock[srcIndex + i];
    700                }
    701            }
    702        }
    703    }
    704 };
    705 
    706 var decompressETC2_EAC_RGBA8 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src) {
    707    var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
    708    var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
    709    var dstPtr = new Uint8Array(dst.m_data);
    710    var dstRowPitch = dst.getRowPitch();
    711    var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
    712    var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8);
    713    var uncompressedBlock = new Uint8Array(uncompressedBlockArray);
    714    var uncompressedBlockAlphaArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_A8);
    715    var uncompressedBlockAlpha = new Uint8Array(uncompressedBlockAlphaArray);
    716 
    717    for (var blockY = 0; blockY < numBlocksY; blockY++) {
    718        for (var blockX = 0; blockX < numBlocksX; blockX++) {
    719            var compressedBlockAlpha = get128BitBlockStart(src, blockY * numBlocksX + blockX);
    720            var compressedBlockRGB = get128BitBlockEnd(src, blockY * numBlocksX + blockX);
    721 
    722            // Decompress.
    723            decompressETC2Block(uncompressedBlock, compressedBlockRGB, null, false);
    724            decompressEAC8Block(uncompressedBlockAlpha, compressedBlockAlpha);
    725 
    726            // Write to dst.
    727            var baseX = blockX * ETC2_BLOCK_WIDTH;
    728            var baseY = blockY * ETC2_BLOCK_HEIGHT;
    729            for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
    730                for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
    731                    var srcIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    732                    var srcAlphaIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
    733                    var dstIndex = (baseY + y) * dstRowPitch + (baseX + x) * dstPixelSize;
    734 
    735                    for (var i = 0; i < ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1; i++)
    736                        dstPtr[dstIndex + i] = uncompressedBlock[srcIndex + i];
    737                    dstPtr[dstIndex + ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1] = uncompressedBlockAlpha[srcAlphaIndex];
    738 
    739                }
    740            }
    741        }
    742    }
    743 };
    744 
    745 var decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1 = function(/*const tcu::PixelBufferAccess&*/ dst, width, height, src) {
    746    var numBlocksX = tcuCompressedTexture.divRoundUp(width, 4);
    747    var numBlocksY = tcuCompressedTexture.divRoundUp(height, 4);
    748    var dstPtr = new Uint8Array(dst.m_data);
    749    var dstRowPitch = dst.getRowPitch();
    750    var dstPixelSize = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
    751    var uncompressedBlockArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8);
    752    var uncompressedBlock = new Uint8Array(uncompressedBlockArray);
    753    var uncompressedBlockAlphaArray = new ArrayBuffer(ETC2_UNCOMPRESSED_BLOCK_SIZE_A8);
    754    var uncompressedBlockAlpha = new Uint8Array(uncompressedBlockAlphaArray);
    755 
    756    for (var blockY = 0; blockY < numBlocksY; blockY++) {
    757        for (var blockX = 0; blockX < numBlocksX; blockX++) {
    758            var compressedBlock = get64BitBlock(src, blockY * numBlocksX + blockX);
    759 
    760            // Decompress.
    761            decompressETC2Block(uncompressedBlock, compressedBlock, uncompressedBlockAlpha, true);
    762 
    763            // Write to dst.
    764            var baseX = blockX * ETC2_BLOCK_WIDTH;
    765            var baseY = blockY * ETC2_BLOCK_HEIGHT;
    766            for (var y = 0; y < Math.min(ETC2_BLOCK_HEIGHT, height - baseY); y++) {
    767                for (var x = 0; x < Math.min(ETC2_BLOCK_WIDTH, width - baseX); x++) {
    768                    var srcIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
    769                    var srcAlphaIndex = (y * ETC2_BLOCK_WIDTH + x) * ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
    770                    var dstIndex = (baseY + y) * dstRowPitch + (baseX + x) * dstPixelSize;
    771 
    772                    for (var i = 0; i < ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1; i++)
    773                        dstPtr[dstIndex + i] = uncompressedBlock[srcIndex + i];
    774                    dstPtr[dstIndex + ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 - 1] = uncompressedBlockAlpha[srcAlphaIndex];
    775 
    776                }
    777            }
    778        }
    779    }
    780 };
    781 
    782 return {
    783    decompressEAC_R11: decompressEAC_R11,
    784    decompressEAC_RG11: decompressEAC_RG11,
    785    decompressETC2: decompressETC2,
    786    decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1: decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1,
    787    decompressETC2_EAC_RGBA8: decompressETC2_EAC_RGBA8
    788 };
    789 
    790 }();
    791 
    792 /**
    793 * @constructor
    794 * @param {tcuCompressedTexture.Format} format
    795 * @param {number} width
    796 * @param {number} height
    797 * @param {number=} depth
    798 */
    799 tcuCompressedTexture.CompressedTexture = function(format, width, height, depth) {
    800    depth = depth === undefined ? 1 : depth;
    801    this.setStorage(format, width, height, depth);
    802    /** @type {Uint8Array} */ this.m_data;
    803 };
    804 
    805 /**
    806 * @return {number}
    807 */
    808 tcuCompressedTexture.CompressedTexture.prototype.getDataSize = function() {
    809     return this.m_data.length;
    810 };
    811 
    812 /**
    813  * @return {Uint8Array}
    814  */
    815 tcuCompressedTexture.CompressedTexture.prototype.getData = function() {
    816      return this.m_data;
    817 };
    818 
    819 /**
    820  * @return {number}
    821  */
    822 tcuCompressedTexture.CompressedTexture.prototype.getWidth = function() {
    823      return this.m_width;
    824 };
    825 
    826 /**
    827  * @return {number}
    828  */
    829 tcuCompressedTexture.CompressedTexture.prototype.getHeight = function() {
    830      return this.m_height;
    831 };
    832 
    833 /**
    834  * @return {tcuCompressedTexture.Format}
    835  */
    836 tcuCompressedTexture.CompressedTexture.prototype.getFormat = function() {
    837      return this.m_format;
    838 };
    839 
    840 tcuCompressedTexture.CompressedTexture.prototype.setStorage = function(format, width, height, depth) {
    841    depth = depth === undefined ? 1 : depth;
    842    this.m_format = format;
    843    this.m_width = width;
    844    this.m_height = height;
    845    this.m_depth = depth;
    846 
    847    if (tcuCompressedTexture.isEtcFormat(this.m_format)) {
    848        DE_ASSERT(this.m_depth == 1);
    849 
    850        var blockSizeMultiplier = 0; // How many 64-bit parts each compressed block contains.
    851 
    852        switch (this.m_format) {
    853            case tcuCompressedTexture.Format.ETC1_RGB8: blockSizeMultiplier = 1; break;
    854            case tcuCompressedTexture.Format.EAC_R11: blockSizeMultiplier = 1; break;
    855            case tcuCompressedTexture.Format.EAC_SIGNED_R11: blockSizeMultiplier = 1; break;
    856            case tcuCompressedTexture.Format.EAC_RG11: blockSizeMultiplier = 2; break;
    857            case tcuCompressedTexture.Format.EAC_SIGNED_RG11: blockSizeMultiplier = 2; break;
    858            case tcuCompressedTexture.Format.ETC2_RGB8: blockSizeMultiplier = 1; break;
    859            case tcuCompressedTexture.Format.ETC2_SRGB8: blockSizeMultiplier = 1; break;
    860            case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1: blockSizeMultiplier = 1; break;
    861            case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: blockSizeMultiplier = 1; break;
    862            case tcuCompressedTexture.Format.ETC2_EAC_RGBA8: blockSizeMultiplier = 2; break;
    863            case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8: blockSizeMultiplier = 2; break;
    864 
    865            default:
    866                throw new Error('Unsupported format ' + format);
    867                break;
    868        }
    869 
    870        this.m_array = new ArrayBuffer(blockSizeMultiplier * 8 * tcuCompressedTexture.divRoundUp(this.m_width, 4) * tcuCompressedTexture.divRoundUp(this.m_height, 4));
    871        this.m_data = new Uint8Array(this.m_array);
    872    }
    873    // else if (isASTCFormat(this.m_format))
    874    // {
    875    //     if (this.m_depth > 1)
    876    //         throw tcu::InternalError("3D ASTC textures not currently supported");
    877 
    878    //     const IVec3 blockSize = getASTCBlockSize(this.m_format);
    879    //     this.m_data.resize(ASTC_BLOCK_SIZE_BYTES * tcuCompressedTexture.divRoundUp(this.m_width, blockSize[0]) * tcuCompressedTexture.divRoundUp(this.m_height, blockSize[1]) * tcuCompressedTexture.divRoundUp(this.m_depth, blockSize[2]));
    880    // }
    881    // else
    882    // {
    883    //     DE_ASSERT(this.m_format == FORMAT_LAST);
    884    //     DE_ASSERT(this.m_width == 0 && this.m_height == 0 && this.m_depth == 0);
    885    //     this.m_data.resize(0);
    886    // }
    887 };
    888 
    889 /*--------------------------------------------------------------------*//*!
    890 * \brief Get uncompressed texture format
    891 *//*--------------------------------------------------------------------*/
    892 tcuCompressedTexture.CompressedTexture.prototype.getUncompressedFormat = function() {
    893    if (tcuCompressedTexture.isEtcFormat(this.m_format)) {
    894        switch (this.m_format) {
    895            case tcuCompressedTexture.Format.ETC1_RGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8);
    896            case tcuCompressedTexture.Format.EAC_R11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.UNORM_INT16);
    897            case tcuCompressedTexture.Format.EAC_SIGNED_R11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.R, tcuTexture.ChannelType.SNORM_INT16);
    898            case tcuCompressedTexture.Format.EAC_RG11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.UNORM_INT16);
    899            case tcuCompressedTexture.Format.EAC_SIGNED_RG11: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT16);
    900            case tcuCompressedTexture.Format.ETC2_RGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB, tcuTexture.ChannelType.UNORM_INT8);
    901            case tcuCompressedTexture.Format.ETC2_SRGB8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGB, tcuTexture.ChannelType.UNORM_INT8);
    902            case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
    903            case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGBA, tcuTexture.ChannelType.UNORM_INT8);
    904            case tcuCompressedTexture.Format.ETC2_EAC_RGBA8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
    905            case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8: return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.sRGBA, tcuTexture.ChannelType.UNORM_INT8);
    906            default:
    907                throw new Error('Unsupported format ' + this.m_format);
    908        }
    909    }
    910    // else if (isASTCFormat(m_format))
    911    // {
    912    //     if (isASTCSRGBFormat(m_format))
    913    //         return TextureFormat(tcuTexture.ChannelType.sRGBA, tcuTexture.ChannelType.UNORM_INT8);
    914    //     else
    915    //         return TextureFormat(tcuTexture.ChannelType.RGBA, tcuTexture.ChannelType.HALF_FLOAT);
    916    // }
    917    // else
    918    // {
    919    //     DE_ASSERT(false);
    920    //     return TextureFormat();
    921    // }
    922 };
    923 
    924 /**
    925 * Decode to uncompressed pixel data
    926 * @param {tcuTexture.PixelBufferAccess} dst Destination buffer
    927 */
    928 tcuCompressedTexture.CompressedTexture.prototype.decompress = function(dst) {
    929    DE_ASSERT(dst.getWidth() == this.m_width && dst.getHeight() == this.m_height && dst.getDepth() == 1);
    930    var format = this.getUncompressedFormat();
    931    if (dst.getFormat().order != format.order || dst.getFormat().type != format.type)
    932        throw new Error('Formats do not match.');
    933 
    934    if (tcuCompressedTexture.isEtcFormat(this.m_format)) {
    935        switch (this.m_format) {
    936            // case tcuCompressedTexture.Format.ETC1_RGB8: decompressETC1 (dst, this.m_width, this.m_height, this.m_data); break;
    937            case tcuCompressedTexture.Format.EAC_R11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_R11(dst, this.m_width, this.m_height, this.m_array, false); break;
    938            case tcuCompressedTexture.Format.EAC_SIGNED_R11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_R11(dst, this.m_width, this.m_height, this.m_array, true); break;
    939            case tcuCompressedTexture.Format.EAC_RG11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_RG11(dst, this.m_width, this.m_height, this.m_array, false); break;
    940            case tcuCompressedTexture.Format.EAC_SIGNED_RG11: tcuCompressedTexture.etcDecompressInternal.decompressEAC_RG11(dst, this.m_width, this.m_height, this.m_array, true); break;
    941            case tcuCompressedTexture.Format.ETC2_RGB8: tcuCompressedTexture.etcDecompressInternal.decompressETC2(dst, this.m_width, this.m_height, this.m_array); break;
    942            case tcuCompressedTexture.Format.ETC2_SRGB8: tcuCompressedTexture.etcDecompressInternal.decompressETC2(dst, this.m_width, this.m_height, this.m_array); break;
    943            case tcuCompressedTexture.Format.ETC2_RGB8_PUNCHTHROUGH_ALPHA1: tcuCompressedTexture.etcDecompressInternal.decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(dst, this.m_width, this.m_height, this.m_array); break;
    944            case tcuCompressedTexture.Format.ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: tcuCompressedTexture.etcDecompressInternal.decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1(dst, this.m_width, this.m_height, this.m_array); break;
    945            case tcuCompressedTexture.Format.ETC2_EAC_RGBA8: tcuCompressedTexture.etcDecompressInternal.decompressETC2_EAC_RGBA8(dst, this.m_width, this.m_height, this.m_array); break;
    946            case tcuCompressedTexture.Format.ETC2_EAC_SRGB8_ALPHA8: tcuCompressedTexture.etcDecompressInternal.decompressETC2_EAC_RGBA8(dst, this.m_width, this.m_height, this.m_array); break;
    947 
    948            default:
    949                throw new Error('Unsupported format ' + this.m_format);
    950                break;
    951        }
    952    }
    953    // else if (isASTCFormat(m_format))
    954    // {
    955    //     const tcu::IVec3 blockSize = getASTCBlockSize(m_format);
    956    //     const bool isSRGBFormat = isASTCSRGBFormat(m_format);
    957 
    958    //     if (blockSize[2] > 1)
    959    //         throw tcu::InternalError("3D ASTC textures not currently supported");
    960 
    961    //     decompressASTC(dst, m_width, m_height, &m_data[0], blockSize[0], blockSize[1], isSRGBFormat, isSRGBFormat || params.isASTCModeLDR);
    962    // } /**/
    963    else
    964        throw new Error('Unsupported format ' + this.m_format);
    965 };
    966 
    967 });