tor-browser

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

glsTextureTestUtil.js (122947B)


      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 'use strict';
     22 goog.provide('modules.shared.glsTextureTestUtil');
     23 goog.require('framework.common.tcuImageCompare');
     24 goog.require('framework.common.tcuPixelFormat');
     25 goog.require('framework.common.tcuRGBA');
     26 goog.require('framework.common.tcuStringTemplate');
     27 goog.require('framework.common.tcuSurface');
     28 goog.require('framework.common.tcuTexLookupVerifier');
     29 goog.require('framework.common.tcuTexCompareVerifier');
     30 goog.require('framework.common.tcuTexture');
     31 goog.require('framework.delibs.debase.deMath');
     32 goog.require('framework.opengl.gluDrawUtil');
     33 goog.require('framework.opengl.gluShaderUtil');
     34 goog.require('framework.opengl.gluShaderProgram');
     35 goog.require('framework.delibs.debase.deRandom');
     36 
     37 goog.scope(function() {
     38 var tcuTexLookupVerifier = framework.common.tcuTexLookupVerifier;
     39 var tcuTexCompareVerifier = framework.common.tcuTexCompareVerifier;
     40 var glsTextureTestUtil = modules.shared.glsTextureTestUtil;
     41 var gluDrawUtil = framework.opengl.gluDrawUtil;
     42 var gluShaderProgram = framework.opengl.gluShaderProgram;
     43 var tcuTexture = framework.common.tcuTexture;
     44 var tcuSurface = framework.common.tcuSurface;
     45 var gluShaderUtil = framework.opengl.gluShaderUtil;
     46 var tcuStringTemplate = framework.common.tcuStringTemplate;
     47 var deMath = framework.delibs.debase.deMath;
     48 var tcuImageCompare = framework.common.tcuImageCompare;
     49 var tcuPixelFormat = framework.common.tcuPixelFormat;
     50 var tcuRGBA = framework.common.tcuRGBA;
     51 var deRandom = framework.delibs.debase.deRandom;
     52 
     53 var DE_ASSERT = function(x) {
     54    if (!x)
     55        throw new Error('Assert failed');
     56 };
     57 
     58 var MIN_SUBPIXEL_BITS = 4;
     59 
     60 /**
     61 * @enum
     62 */
     63 glsTextureTestUtil.textureType = {
     64    TEXTURETYPE_2D: 0,
     65    TEXTURETYPE_CUBE: 1,
     66    TEXTURETYPE_2D_ARRAY: 2,
     67    TEXTURETYPE_3D: 3,
     68    TEXTURETYPE_CUBE_ARRAY: 4,
     69    TEXTURETYPE_1D: 5,
     70    TEXTURETYPE_1D_ARRAY: 6,
     71    TEXTURETYPE_BUFFER: 7
     72 };
     73 
     74 /**
     75 * @enum
     76 */
     77 glsTextureTestUtil.samplerType = {
     78    SAMPLERTYPE_FLOAT: 0,
     79    SAMPLERTYPE_INT: 1,
     80    SAMPLERTYPE_UINT: 2,
     81    SAMPLERTYPE_SHADOW: 3,
     82 
     83    SAMPLERTYPE_FETCH_FLOAT: 4,
     84    SAMPLERTYPE_FETCH_INT: 5,
     85    SAMPLERTYPE_FETCH_UINT: 6
     86 };
     87 
     88 /**
     89 * @param {tcuTexture.TextureFormat} format
     90 * @return {glsTextureTestUtil.samplerType}
     91 */
     92 glsTextureTestUtil.getSamplerType = function(format) {
     93    if (format == null)
     94        throw new Error('Missing format information');
     95 
     96    switch (format.type) {
     97        case tcuTexture.ChannelType.SIGNED_INT8:
     98        case tcuTexture.ChannelType.SIGNED_INT16:
     99        case tcuTexture.ChannelType.SIGNED_INT32:
    100            return glsTextureTestUtil.samplerType.SAMPLERTYPE_INT;
    101 
    102        case tcuTexture.ChannelType.UNSIGNED_INT8:
    103        case tcuTexture.ChannelType.UNSIGNED_INT32:
    104        case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV:
    105            return glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT;
    106 
    107        // Texture formats used in depth/stencil textures.
    108        case tcuTexture.ChannelType.UNSIGNED_INT16:
    109        case tcuTexture.ChannelType.UNSIGNED_INT_24_8:
    110            return (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS) ? glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT : glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT;
    111 
    112        default:
    113            return glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT;
    114    }
    115 };
    116 
    117 /**
    118 * @constructor
    119 * @param {HTMLElement} canvas
    120 * @param {number} preferredWidth
    121 * @param {number} preferredHeight
    122 * @param {number=} seed
    123 */
    124 glsTextureTestUtil.RandomViewport = function(canvas, preferredWidth, preferredHeight, seed) {
    125    this.width = Math.min(canvas.width, preferredWidth);
    126    this.height = Math.min(canvas.height, preferredHeight);
    127 
    128    if (typeof seed === 'undefined')
    129        seed = preferredWidth + preferredHeight;
    130 
    131    var rnd = new deRandom.Random(seed);
    132    this.x = rnd.getInt(0, canvas.width - this.width);
    133    this.y = rnd.getInt(0, canvas.height - this.height);
    134 };
    135 
    136 /**
    137 * @constructor
    138 * @param {glsTextureTestUtil.textureType} texType
    139 */
    140 glsTextureTestUtil.RenderParams = function(texType) {
    141    this.flags = {
    142        projected: false,
    143        use_bias: false,
    144        log_programs: false,
    145        log_uniforms: false
    146    };
    147    this.texType = texType;
    148    this.w = [1, 1, 1, 1];
    149    this.bias = 0;
    150    this.ref = 0;
    151    this.colorScale = [1, 1, 1, 1];
    152    this.colorBias = [0, 0, 0, 0];
    153    this.samplerType = glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT;
    154 };
    155 
    156 /**
    157 * @enum
    158 */
    159 glsTextureTestUtil.lodMode = {
    160    EXACT: 0, //!< Ideal lod computation.
    161    MIN_BOUND: 1, //!< Use estimation range minimum bound.
    162    MAX_BOUND: 2 //!< Use estimation range maximum bound.
    163 
    164 };
    165 
    166 /**
    167 * @constructor
    168 * @extends {glsTextureTestUtil.RenderParams}
    169 * @param {glsTextureTestUtil.textureType} texType
    170 * @param {tcuTexture.Sampler=} sampler
    171 * @param {glsTextureTestUtil.lodMode=} lodMode_
    172 */
    173 glsTextureTestUtil.ReferenceParams = function(texType, sampler, lodMode_) {
    174    glsTextureTestUtil.RenderParams.call(this, texType);
    175    if (sampler)
    176        this.sampler = sampler;
    177    if (lodMode_)
    178        this.lodMode = lodMode_;
    179    else
    180        this.lodMode = glsTextureTestUtil.lodMode.EXACT;
    181    this.minLod = -1000;
    182    this.maxLod = 1000;
    183    this.baseLevel = 0;
    184    this.maxLevel = 1000;
    185 };
    186 
    187 glsTextureTestUtil.ReferenceParams.prototype = Object.create(glsTextureTestUtil.RenderParams.prototype);
    188 
    189 /** Copy constructor */
    190 glsTextureTestUtil.ReferenceParams.prototype.constructor = glsTextureTestUtil.ReferenceParams;
    191 
    192 /**
    193 * @param {Array<number>} bottomLeft
    194 * @param {Array<number>} topRight
    195 * @return {Array<number>}
    196 */
    197 glsTextureTestUtil.computeQuadTexCoord2D = function(bottomLeft, topRight) {
    198    var dst = [];
    199    dst.length = 4 * 2;
    200 
    201    dst[0] = bottomLeft[0]; dst[1] = bottomLeft[1];
    202    dst[2] = bottomLeft[0]; dst[3] = topRight[1];
    203    dst[4] = topRight[0]; dst[5] = bottomLeft[1];
    204    dst[6] = topRight[0]; dst[7] = topRight[1];
    205 
    206    return dst;
    207 };
    208 
    209 /**
    210 * @param {tcuTexture.CubeFace} face
    211 * @return {Array<number>}
    212 */
    213 glsTextureTestUtil.computeQuadTexCoordCube = function(face) {
    214    var texCoordNegX = [
    215        -1, 1, -1,
    216        -1, -1, -1,
    217        -1, 1, 1,
    218        -1, -1, 1
    219    ];
    220    var texCoordPosX = [
    221        +1, 1, 1,
    222        +1, -1, 1,
    223        +1, 1, -1,
    224        +1, -1, -1
    225    ];
    226    var texCoordNegY = [
    227        -1, -1, 1,
    228        -1, -1, -1,
    229         1, -1, 1,
    230         1, -1, -1
    231    ];
    232    var texCoordPosY = [
    233        -1, +1, -1,
    234        -1, +1, 1,
    235         1, +1, -1,
    236         1, +1, 1
    237    ];
    238    var texCoordNegZ = [
    239         1, 1, -1,
    240         1, -1, -1,
    241        -1, 1, -1,
    242        -1, -1, -1
    243    ];
    244    var texCoordPosZ = [
    245        -1, 1, +1,
    246        -1, -1, +1,
    247         1, 1, +1,
    248         1, -1, +1
    249    ];
    250 
    251    switch (face) {
    252        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: return texCoordNegX;
    253        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: return texCoordPosX;
    254        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: return texCoordNegY;
    255        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: return texCoordPosY;
    256        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: return texCoordNegZ;
    257        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: return texCoordPosZ;
    258    }
    259    throw new Error('Unrecognized face ' + face);
    260 };
    261 
    262 /**
    263 * @param {tcuTexture.CubeFace} face
    264 * @param {Array<number>} bottomLeft
    265 * @param {Array<number>} topRight
    266 * @return {Array<number>}
    267 */
    268 glsTextureTestUtil.computeQuadTexCoordCubeFace = function(face, bottomLeft, topRight) {
    269    var dst = [];
    270    /** @type {number} */ var sRow = 0;
    271    /** @type {number} */ var tRow = 0;
    272    /** @type {number} */ var mRow = 0;
    273    /** @type {number} */ var sSign = 1.0;
    274    /** @type {number} */ var tSign = 1.0;
    275    /** @type {number} */ var mSign = 1.0;
    276 
    277    switch (face) {
    278        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0; tSign = -1.0; break;
    279        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1; sSign = -1.0; tSign = -1.0; break;
    280        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0; tSign = -1.0; break;
    281        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2; break;
    282        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0; sSign = -1.0; tSign = -1.0; break;
    283        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1; tSign = -1.0; break;
    284        default:
    285            throw new Error('Invalid cube face specified.');
    286    }
    287 
    288    dst[0 + mRow] = mSign;
    289    dst[3 + mRow] = mSign;
    290    dst[6 + mRow] = mSign;
    291    dst[9 + mRow] = mSign;
    292 
    293    dst[0 + sRow] = sSign * bottomLeft[0];
    294    dst[3 + sRow] = sSign * bottomLeft[0];
    295    dst[6 + sRow] = sSign * topRight[0];
    296    dst[9 + sRow] = sSign * topRight[0];
    297 
    298    dst[0 + tRow] = tSign * bottomLeft[1];
    299    dst[3 + tRow] = tSign * topRight[1];
    300    dst[6 + tRow] = tSign * bottomLeft[1];
    301    dst[9 + tRow] = tSign * topRight[1];
    302 
    303    return dst;
    304 };
    305 
    306 /**
    307 * @param {number} layerNdx
    308 * @param {Array<number>} bottomLeft
    309 * @param {Array<number>} topRight
    310 * @return {Array<number>}
    311 */
    312 glsTextureTestUtil.computeQuadTexCoord2DArray = function(layerNdx, bottomLeft, topRight) {
    313    var dst = [];
    314    dst.length = 4 * 3;
    315 
    316    dst[0] = bottomLeft[0]; dst[1] = bottomLeft[1]; dst[2] = layerNdx;
    317    dst[3] = bottomLeft[0]; dst[4] = topRight[1]; dst[5] = layerNdx;
    318    dst[6] = topRight[0]; dst[7] = bottomLeft[1]; dst[8] = layerNdx;
    319    dst[9] = topRight[0]; dst[10] = topRight[1]; dst[11] = layerNdx;
    320 
    321    return dst;
    322 };
    323 
    324 /**
    325 * @param {Array<number>} a
    326 * @param {Array<number>} b
    327 * @param {Array<number>} c
    328 * @return {Array<number>} a + (b - a) * c
    329 */
    330 glsTextureTestUtil.selectCoords = function(a, b, c) {
    331    var x1 = deMath.subtract(b, a);
    332    var x2 = deMath.multiply(x1, c);
    333    var x3 = deMath.add(a, x2);
    334    return x3;
    335 };
    336 
    337 /**
    338 * @param {Array<number>} p0
    339 * @param {Array<number>} p1
    340 * @param {Array<number>} dirSwz
    341 * @return {Array<number>}
    342 */
    343 glsTextureTestUtil.computeQuadTexCoord3D = function(p0, p1, dirSwz) {
    344    var dst = [];
    345    dst.length = 4 * 3;
    346 
    347    var f0 = deMath.swizzle(([0, 0, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
    348    var f1 = deMath.swizzle(([0, 1, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
    349    var f2 = deMath.swizzle(([1, 0, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
    350    var f3 = deMath.swizzle(([1, 1, 0]), [dirSwz[0], dirSwz[1], dirSwz[2]]);
    351 
    352    var v0 = glsTextureTestUtil.selectCoords(p0, p1, f0);
    353    var v1 = glsTextureTestUtil.selectCoords(p0, p1, f1);
    354    var v2 = glsTextureTestUtil.selectCoords(p0, p1, f2);
    355    var v3 = glsTextureTestUtil.selectCoords(p0, p1, f3);
    356 
    357    dst[0] = v0[0]; dst[1] = v0[1]; dst[2] = v0[2];
    358    dst[3] = v1[0]; dst[4] = v1[1]; dst[5] = v1[2];
    359    dst[6] = v2[0]; dst[7] = v2[1]; dst[8] = v2[2];
    360    dst[9] = v3[0]; dst[10] = v3[1]; dst[11] = v3[2];
    361 
    362    return dst;
    363 };
    364 
    365 /**
    366 * @enum
    367 */
    368 glsTextureTestUtil.programType = {
    369    PROGRAM_2D_FLOAT: 0,
    370    PROGRAM_2D_INT: 1,
    371    PROGRAM_2D_UINT: 2,
    372    PROGRAM_2D_SHADOW: 3,
    373 
    374    PROGRAM_2D_FLOAT_BIAS: 4,
    375    PROGRAM_2D_INT_BIAS: 5,
    376    PROGRAM_2D_UINT_BIAS: 6,
    377    PROGRAM_2D_SHADOW_BIAS: 7,
    378 
    379    PROGRAM_1D_FLOAT: 8,
    380    PROGRAM_1D_INT: 9,
    381    PROGRAM_1D_UINT: 10,
    382    PROGRAM_1D_SHADOW: 11,
    383 
    384    PROGRAM_1D_FLOAT_BIAS: 12,
    385    PROGRAM_1D_INT_BIAS: 13,
    386    PROGRAM_1D_UINT_BIAS: 14,
    387    PROGRAM_1D_SHADOW_BIAS: 15,
    388 
    389    PROGRAM_CUBE_FLOAT: 16,
    390    PROGRAM_CUBE_INT: 17,
    391    PROGRAM_CUBE_UINT: 18,
    392    PROGRAM_CUBE_SHADOW: 19,
    393 
    394    PROGRAM_CUBE_FLOAT_BIAS: 20,
    395    PROGRAM_CUBE_INT_BIAS: 21,
    396    PROGRAM_CUBE_UINT_BIAS: 22,
    397    PROGRAM_CUBE_SHADOW_BIAS: 23,
    398 
    399    PROGRAM_1D_ARRAY_FLOAT: 24,
    400    PROGRAM_1D_ARRAY_INT: 25,
    401    PROGRAM_1D_ARRAY_UINT: 26,
    402    PROGRAM_1D_ARRAY_SHADOW: 27,
    403 
    404    PROGRAM_2D_ARRAY_FLOAT: 28,
    405    PROGRAM_2D_ARRAY_INT: 29,
    406    PROGRAM_2D_ARRAY_UINT: 30,
    407    PROGRAM_2D_ARRAY_SHADOW: 31,
    408 
    409    PROGRAM_3D_FLOAT: 32,
    410    PROGRAM_3D_INT: 33,
    411    PROGRAM_3D_UINT: 34,
    412 
    413    PROGRAM_3D_FLOAT_BIAS: 35,
    414    PROGRAM_3D_INT_BIAS: 36,
    415    PROGRAM_3D_UINT_BIAS: 37,
    416 
    417    PROGRAM_CUBE_ARRAY_FLOAT: 38,
    418    PROGRAM_CUBE_ARRAY_INT: 39,
    419    PROGRAM_CUBE_ARRAY_UINT: 40,
    420    PROGRAM_CUBE_ARRAY_SHADOW: 41,
    421 
    422    PROGRAM_BUFFER_FLOAT: 42,
    423    PROGRAM_BUFFER_INT: 43,
    424    PROGRAM_BUFFER_UINT: 44
    425 };
    426 
    427 /**
    428 * @constructor
    429 * @param {string} version GL version
    430 * @param {gluShaderUtil.precision} precision
    431 */
    432 glsTextureTestUtil.ProgramLibrary = function(version, precision) {
    433    this.m_glslVersion = version;
    434    this.m_texCoordPrecision = precision;
    435 };
    436 
    437 /**
    438 * @param {glsTextureTestUtil.programType} program
    439 * @return {gluShaderProgram.ShaderProgram}
    440 */
    441 glsTextureTestUtil.ProgramLibrary.prototype.getProgram = function(program) {
    442    /* TODO: Implement */
    443    // if (m_programs.find(program) != m_programs.end())
    444    //     return m_programs[program]; // Return from cache.
    445 
    446    var vertShaderTemplate =
    447        '${VTX_HEADER}' +
    448        '${VTX_IN} highp vec4 a_position;\n' +
    449        '${VTX_IN} ${PRECISION} ${TEXCOORD_TYPE} a_texCoord;\n' +
    450        '${VTX_OUT} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n' +
    451        '\n' +
    452        'void main (void)\n' +
    453        ' {\n' +
    454        ' gl_Position = a_position;\n' +
    455        ' v_texCoord = a_texCoord;\n' +
    456        '}\n';
    457    var fragShaderTemplate =
    458        '${FRAG_HEADER}' +
    459        '${FRAG_IN} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n' +
    460        'uniform ${PRECISION} float u_bias;\n' +
    461        'uniform ${PRECISION} float u_ref;\n' +
    462        'uniform ${PRECISION} vec4 u_colorScale;\n' +
    463        'uniform ${PRECISION} vec4 u_colorBias;\n' +
    464        'uniform ${PRECISION} ${SAMPLER_TYPE} u_sampler;\n' +
    465        '\n' +
    466        'void main (void)\n' +
    467        ' {\n' +
    468        ' ${FRAG_COLOR} = ${LOOKUP} * u_colorScale + u_colorBias;\n' +
    469        '}\n';
    470 
    471    var params = [];
    472 
    473    var isCube = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT, glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS);
    474    var isArray = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW) ||
    475                            deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW);
    476 
    477    var is1D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS) ||
    478                            deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW) ||
    479                            deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT, glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT);
    480 
    481    var is2D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS) ||
    482                            deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW);
    483 
    484    var is3D = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_3D_FLOAT, glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS);
    485    var isCubeArray = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT, glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW);
    486    var isBuffer = deMath.deInRange32(program, glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT, glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT);
    487 
    488    if (this.m_glslVersion === '100 es') {
    489        params['FRAG_HEADER'] = '';
    490        params['VTX_HEADER'] = '';
    491        params['VTX_IN'] = 'attribute';
    492        params['VTX_OUT'] = 'varying';
    493        params['FRAG_IN'] = 'varying';
    494        params['FRAG_COLOR'] = 'gl_FragColor';
    495    } else if (this.m_glslVersion === '300 es' || this.m_glslVersion === '310 es' || this.m_glslVersion === '330 es') {
    496        var ext = null;
    497 
    498        // if (isCubeArray && glu::glslVersionIsES(m_glslVersion))
    499        //     ext = "gl.EXT_texture_cube_map_array";
    500        // else if (isBuffer && glu::glslVersionIsES(m_glslVersion))
    501        //     ext = "gl.EXT_texture_buffer";
    502 
    503        var extension = '';
    504        if (ext)
    505            extension = '\n#extension ' + ext + ' : require';
    506 
    507        params['FRAG_HEADER'] = '#version ' + this.m_glslVersion + extension + '\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
    508        params['VTX_HEADER'] = '#version ' + this.m_glslVersion + '\n';
    509        params['VTX_IN'] = 'in';
    510        params['VTX_OUT'] = 'out';
    511        params['FRAG_IN'] = 'in';
    512        params['FRAG_COLOR'] = 'dEQP_FragColor';
    513    } else
    514        throw new Error('Unsupported version: ' + this.m_glslVersion);
    515 
    516    params['PRECISION'] = gluShaderUtil.getPrecisionName(this.m_texCoordPrecision);
    517 
    518    if (isCubeArray)
    519        params['TEXCOORD_TYPE'] = 'vec4';
    520    else if (isCube || (is2D && isArray) || is3D)
    521        params['TEXCOORD_TYPE'] = 'vec3';
    522    else if ((is1D && isArray) || is2D)
    523        params['TEXCOORD_TYPE'] = 'vec2';
    524    else if (is1D)
    525        params['TEXCOORD_TYPE'] = 'float';
    526    else
    527        DE_ASSERT(false);
    528 
    529    var sampler = null;
    530    var lookup = null;
    531 
    532    if (this.m_glslVersion === '300 es' || this.m_glslVersion === '310 es' || this.m_glslVersion === '330 es') {
    533        switch (program) {
    534            case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT: sampler = 'sampler2D'; lookup = 'texture(u_sampler, v_texCoord)'; break;
    535            case glsTextureTestUtil.programType.PROGRAM_2D_INT: sampler = 'isampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    536            case glsTextureTestUtil.programType.PROGRAM_2D_UINT: sampler = 'usampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    537            case glsTextureTestUtil.programType.PROGRAM_2D_SHADOW: sampler = 'sampler2DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
    538            case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS: sampler = 'sampler2D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
    539            case glsTextureTestUtil.programType.PROGRAM_2D_INT_BIAS: sampler = 'isampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    540            case glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS: sampler = 'usampler2D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    541            case glsTextureTestUtil.programType.PROGRAM_2D_SHADOW_BIAS: sampler = 'sampler2DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break;
    542            case glsTextureTestUtil.programType.PROGRAM_1D_FLOAT: sampler = 'sampler1D'; lookup = 'texture(u_sampler, v_texCoord)'; break;
    543            case glsTextureTestUtil.programType.PROGRAM_1D_INT: sampler = 'isampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    544            case glsTextureTestUtil.programType.PROGRAM_1D_UINT: sampler = 'usampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    545            case glsTextureTestUtil.programType.PROGRAM_1D_SHADOW: sampler = 'sampler1DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
    546            case glsTextureTestUtil.programType.PROGRAM_1D_FLOAT_BIAS: sampler = 'sampler1D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
    547            case glsTextureTestUtil.programType.PROGRAM_1D_INT_BIAS: sampler = 'isampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    548            case glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS: sampler = 'usampler1D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    549            case glsTextureTestUtil.programType.PROGRAM_1D_SHADOW_BIAS: sampler = 'sampler1DShadow'; lookup = 'vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break;
    550            case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT: sampler = 'samplerCube'; lookup = 'texture(u_sampler, v_texCoord)'; break;
    551            case glsTextureTestUtil.programType.PROGRAM_CUBE_INT: sampler = 'isamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    552            case glsTextureTestUtil.programType.PROGRAM_CUBE_UINT: sampler = 'usamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    553            case glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW: sampler = 'samplerCubeShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
    554            case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS: sampler = 'samplerCube'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
    555            case glsTextureTestUtil.programType.PROGRAM_CUBE_INT_BIAS: sampler = 'isamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    556            case glsTextureTestUtil.programType.PROGRAM_CUBE_UINT_BIAS: sampler = 'usamplerCube'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    557            case glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS: sampler = 'samplerCubeShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)'; break;
    558            case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT: sampler = 'sampler2DArray'; lookup = 'texture(u_sampler, v_texCoord)'; break;
    559            case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_INT: sampler = 'isampler2DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    560            case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_UINT: sampler = 'usampler2DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    561            case glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW: sampler = 'sampler2DArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
    562            case glsTextureTestUtil.programType.PROGRAM_3D_FLOAT: sampler = 'sampler3D'; lookup = 'texture(u_sampler, v_texCoord)'; break;
    563            case glsTextureTestUtil.programType.PROGRAM_3D_INT: sampler = 'isampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    564            case glsTextureTestUtil.programType.PROGRAM_3D_UINT: sampler = ' usampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    565            case glsTextureTestUtil.programType.PROGRAM_3D_FLOAT_BIAS: sampler = 'sampler3D'; lookup = 'texture(u_sampler, v_texCoord, u_bias)'; break;
    566            case glsTextureTestUtil.programType.PROGRAM_3D_INT_BIAS: sampler = 'isampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    567            case glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS: sampler = ' usampler3D'; lookup = 'vec4(texture(u_sampler, v_texCoord, u_bias))'; break;
    568            case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT: sampler = 'samplerCubeArray'; lookup = 'texture(u_sampler, v_texCoord)'; break;
    569            case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_INT: sampler = 'isamplerCubeArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    570            case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_UINT: sampler = 'usamplerCubeArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    571            case glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW: sampler = 'samplerCubeArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
    572            case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT: sampler = 'sampler1DArray'; lookup = 'texture(u_sampler, v_texCoord)'; break;
    573            case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_INT: sampler = 'isampler1DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    574            case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_UINT: sampler = 'usampler1DArray'; lookup = 'vec4(texture(u_sampler, v_texCoord))'; break;
    575            case glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW: sampler = 'sampler1DArrayShadow'; lookup = 'vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)'; break;
    576            case glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT: sampler = 'samplerBuffer'; lookup = 'texelFetch(u_sampler, int(v_texCoord))'; break;
    577            case glsTextureTestUtil.programType.PROGRAM_BUFFER_INT: sampler = 'isamplerBuffer'; lookup = 'vec4(texelFetch(u_sampler, int(v_texCoord)))'; break;
    578            case glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT: sampler = 'usamplerBuffer'; lookup = 'vec4(texelFetch(u_sampler, int(v_texCoord)))'; break;
    579            default:
    580                DE_ASSERT(false);
    581        }
    582    } else if (this.m_glslVersion === '100 es') {
    583        sampler = isCube ? 'samplerCube' : 'sampler2D';
    584 
    585        switch (program) {
    586            case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT: lookup = 'texture2D(u_sampler, v_texCoord)'; break;
    587            case glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS: lookup = 'texture2D(u_sampler, v_texCoord, u_bias)'; break;
    588            case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT: lookup = 'textureCube(u_sampler, v_texCoord)'; break;
    589            case glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS: lookup = 'textureCube(u_sampler, v_texCoord, u_bias)'; break;
    590            default:
    591                DE_ASSERT(false);
    592        }
    593    } else
    594        DE_ASSERT(!'Unsupported version');
    595 
    596    params['SAMPLER_TYPE'] = sampler;
    597    params['LOOKUP'] = lookup;
    598 
    599    var vertSrc = tcuStringTemplate.specialize(vertShaderTemplate, params);
    600    var fragSrc = tcuStringTemplate.specialize(fragShaderTemplate, params);
    601    var progObj = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertSrc, fragSrc));
    602    // if (!progObj.isOk()) {
    603    //     // log << *progObj;
    604    //     testFailedOptions("Failed to create shader", true);
    605    // }
    606 
    607    // try
    608    // {
    609    //     m_programs[program] = progObj;
    610    // }
    611    // catch (...)
    612    // {
    613    //     delete progObj;
    614    //     throw;
    615    // }
    616 
    617    return progObj;
    618 };
    619 
    620 // public:
    621 //                                             glsTextureTestUtil.ProgramLibrary (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision);
    622 //                                             ~glsTextureTestUtil.ProgramLibrary (void);
    623 
    624 //     glu::ShaderProgram*                        getProgram (Program program);
    625 //     void clear (void);
    626 
    627 // private:
    628 //                                             glsTextureTestUtil.ProgramLibrary (const glsTextureTestUtil.ProgramLibrary& other);
    629 //     glsTextureTestUtil.ProgramLibrary& operator= (const glsTextureTestUtil.ProgramLibrary& other);
    630 
    631 //     const glu::RenderContext& m_context;
    632 //     tcu::TestContext& m_testCtx;
    633 //     glu::GLSLVersion m_glslVersion;
    634 //     glu::Precision m_texCoordPrecision;
    635 //     std::map<Program, glu::ShaderProgram*> m_programs;
    636 // };
    637 
    638 /**
    639 * @constructor
    640 * @param {string} version GL version
    641 * @param {gluShaderUtil.precision} precision
    642 */
    643 glsTextureTestUtil.TextureRenderer = function(version, precision) {
    644    this.m_programLibrary = new glsTextureTestUtil.ProgramLibrary(version, precision);
    645 };
    646 
    647 /**
    648 * @param {tcuPixelFormat.PixelFormat} format
    649 * @return {Array<boolean>}
    650 */
    651 glsTextureTestUtil.getCompareMask = function(format) {
    652    return [
    653        format.redBits > 0,
    654        format.greenBits > 0,
    655        format.blueBits > 0,
    656        format.alphaBits > 0
    657    ];
    658 };
    659 
    660 /**
    661 * @param {tcuPixelFormat.PixelFormat} format
    662 * @return {Array<number>}
    663 */
    664 glsTextureTestUtil.getBitsVec = function(format) {
    665    return [
    666        format.redBits,
    667        format.greenBits,
    668        format.blueBits,
    669        format.alphaBits
    670    ];
    671 };
    672 
    673 /**
    674 * @param {number} texUnit
    675 * @param {Array<number>} texCoord
    676 * @param {glsTextureTestUtil.RenderParams} params
    677 */
    678 glsTextureTestUtil.TextureRenderer.prototype.renderQuad = function(texUnit, texCoord, params) {
    679    var wCoord = params.flags.projected ? params.w : [1, 1, 1, 1];
    680    var useBias = params.flags.use_bias;
    681    var logUniforms = params.flags.log_uniforms;
    682 
    683    // Render quad with texture.
    684    var position = [
    685        -1 * wCoord[0], -1 * wCoord[0], 0, wCoord[0],
    686        -1 * wCoord[1], +1 * wCoord[1], 0, wCoord[1],
    687        +1 * wCoord[2], -1 * wCoord[2], 0, wCoord[2],
    688        +1 * wCoord[3], +1 * wCoord[3], 0, wCoord[3]
    689    ];
    690    /** @const */ var indices = [0, 1, 2, 2, 1, 3];
    691 
    692    /** @type {?glsTextureTestUtil.programType} */ var progSpec = null;
    693    var numComps = 0;
    694    if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_2D) {
    695        numComps = 2;
    696 
    697        switch (params.samplerType) {
    698            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_FLOAT; break;
    699            case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_INT; break;
    700            case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_UINT; break;
    701            case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_2D_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_2D_SHADOW; break;
    702            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    703        }
    704    } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_1D) {
    705        numComps = 1;
    706 
    707        switch (params.samplerType) {
    708            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_FLOAT; break;
    709            case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_INT; break;
    710            case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_UINT; break;
    711            case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_1D_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_1D_SHADOW; break;
    712            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    713        }
    714    } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_CUBE) {
    715        numComps = 3;
    716 
    717        switch (params.samplerType) {
    718            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_FLOAT; break;
    719            case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_INT; break;
    720            case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_UINT; break;
    721            case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW_BIAS : glsTextureTestUtil.programType.PROGRAM_CUBE_SHADOW; break;
    722            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    723        }
    724    } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_3D) {
    725        numComps = 3;
    726 
    727        switch (params.samplerType) {
    728            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_FLOAT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_FLOAT; break;
    729            case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_INT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_INT; break;
    730            case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = useBias ? glsTextureTestUtil.programType.PROGRAM_3D_UINT_BIAS : glsTextureTestUtil.programType.PROGRAM_3D_UINT; break;
    731            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    732        }
    733    } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_2D_ARRAY) {
    734        DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
    735 
    736        numComps = 3;
    737 
    738        switch (params.samplerType) {
    739            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_FLOAT; break;
    740            case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_INT; break;
    741            case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_UINT; break;
    742            case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_2D_ARRAY_SHADOW; break;
    743            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    744        }
    745    } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_CUBE_ARRAY) {
    746        DE_ASSERT(!useBias);
    747 
    748        numComps = 4;
    749 
    750        switch (params.samplerType) {
    751            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_FLOAT; break;
    752            case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_INT; break;
    753            case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_UINT; break;
    754            case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_CUBE_ARRAY_SHADOW; break;
    755            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    756        }
    757    } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_1D_ARRAY) {
    758        DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
    759 
    760        numComps = 2;
    761 
    762        switch (params.samplerType) {
    763            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_FLOAT; break;
    764            case glsTextureTestUtil.samplerType.SAMPLERTYPE_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_INT; break;
    765            case glsTextureTestUtil.samplerType.SAMPLERTYPE_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_UINT; break;
    766            case glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW: progSpec = glsTextureTestUtil.programType.PROGRAM_1D_ARRAY_SHADOW; break;
    767            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    768        }
    769    } else if (params.texType == glsTextureTestUtil.textureType.TEXTURETYPE_BUFFER) {
    770        numComps = 1;
    771 
    772        switch (params.samplerType) {
    773            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_FLOAT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_FLOAT; break;
    774            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_INT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_INT; break;
    775            case glsTextureTestUtil.samplerType.SAMPLERTYPE_FETCH_UINT: progSpec = glsTextureTestUtil.programType.PROGRAM_BUFFER_UINT; break;
    776            default: throw new Error('Unrecognized sampler type:' + params.samplerType);
    777        }
    778    } else
    779       throw new Error('Unrecognized texture type:' + params.texType);
    780 
    781    if (progSpec === null)
    782        throw new Error('Could not find program specification');
    783 
    784    var program = this.m_programLibrary.getProgram(progSpec);
    785 
    786    // \todo [2012-09-26 pyry] Move to glsTextureTestUtil.ProgramLibrary and log unique programs only(?)
    787    /* TODO: Port logging
    788    if (params.flags.log_programs)
    789        log << *program;
    790    */
    791 
    792    // Program and uniforms.
    793    var prog = program.getProgram();
    794    gl.useProgram(prog);
    795 
    796    var loc = gl.getUniformLocation(prog, 'u_sampler');
    797    gl.uniform1i(loc, texUnit);
    798    // if (logUniforms)
    799    //     log << TestLog::Message << "u_sampler = " << texUnit << TestLog::EndMessage;
    800 
    801    if (useBias) {
    802        gl.uniform1f(gl.getUniformLocation(prog, 'u_bias'), params.bias);
    803        // if (logUniforms)
    804        //     log << TestLog::Message << "u_bias = " << params.bias << TestLog::EndMessage;
    805    }
    806 
    807    if (params.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW) {
    808        gl.uniform1f(gl.getUniformLocation(prog, 'u_ref'), params.ref);
    809        // if (logUniforms)
    810        //     log << TestLog::Message << "u_ref = " << params.ref << TestLog::EndMessage;
    811    }
    812 
    813    gl.uniform4fv(gl.getUniformLocation(prog, 'u_colorScale'), params.colorScale);
    814    gl.uniform4fv(gl.getUniformLocation(prog, 'u_colorBias'), params.colorBias);
    815 
    816    // if (logUniforms)
    817    // {
    818    //     log << TestLog::Message << "u_colorScale = " << params.colorScale << TestLog::EndMessage;
    819    //     log << TestLog::Message << "u_colorBias = " << params.colorBias << TestLog::EndMessage;
    820    // }
    821    var vertexArrays = [];
    822 
    823    var posLoc = gl.getAttribLocation(prog, 'a_position');
    824    if (posLoc === -1) {
    825        testFailedOptions("no location found for attribute 'a_position'", true);
    826    }
    827    var texLoc = gl.getAttribLocation(prog, 'a_texCoord');
    828    if (texLoc === -1) {
    829        testFailedOptions("no location found for attribute 'a_texCoord'", true);
    830    }
    831 
    832    vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, posLoc, 4, 4, position));
    833    vertexArrays.push(new gluDrawUtil.VertexArrayBinding(gl.FLOAT, texLoc, numComps, 4, texCoord));
    834    gluDrawUtil.draw(gl, prog, vertexArrays, gluDrawUtil.triangles(indices));
    835 };
    836 
    837 // public:
    838 //                                 glsTextureTestUtil.TextureRenderer (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision);
    839 //                                 ~glsTextureTestUtil.TextureRenderer (void);
    840 
    841 //     void clear (void); //!< Frees allocated resources. Destructor will call clear() as well.
    842 
    843 //     void renderQuad (int texUnit, const float* texCoord, TextureType texType);
    844 //     void renderQuad (int texUnit, const float* texCoord, const glsTextureTestUtil.RenderParams& params);
    845 
    846 // private:
    847 //                                 glsTextureTestUtil.TextureRenderer (const glsTextureTestUtil.TextureRenderer& other);
    848 //     glsTextureTestUtil.TextureRenderer& operator= (const glsTextureTestUtil.TextureRenderer& other);
    849 
    850 //     const glu::RenderContext& m_renderCtx;
    851 //     tcu::TestContext& m_testCtx;
    852 //     glsTextureTestUtil.ProgramLibrary m_programLibrary;
    853 // };
    854 
    855 /**
    856 * @constructor
    857 * @param {tcuSurface.Surface} surface
    858 * @param {tcuPixelFormat.PixelFormat=} colorFmt
    859 * @param {number=} x
    860 * @param {number=} y
    861 * @param {number=} width
    862 * @param {number=} height
    863 */
    864 glsTextureTestUtil.SurfaceAccess = function(surface, colorFmt, x, y, width, height) {
    865    this.m_surface = surface;
    866    this.colorMask = undefined; /*TODO*/
    867    this.m_x = x || 0;
    868    this.m_y = y || 0;
    869    this.m_width = width || surface.getWidth();
    870    this.m_height = height || surface.getHeight();
    871 };
    872 
    873 /** @return {number} */
    874 glsTextureTestUtil.SurfaceAccess.prototype.getWidth = function() { return this.m_width; };
    875 /** @return {number} */
    876 glsTextureTestUtil.SurfaceAccess.prototype.getHeight = function() { return this.m_height; };
    877 
    878 /**
    879 * @param {Array<number>} color
    880 * @param {number} x
    881 * @param {number} y
    882 */
    883 glsTextureTestUtil.SurfaceAccess.prototype.setPixel = function(color, x, y) {
    884    /* TODO: Apply color mask */
    885    var c = color;
    886    for (var i = 0; i < c.length; i++)
    887        c[i] = deMath.clamp(Math.round(color[i] * 255), 0, 255);
    888    this.m_surface.setPixel(x, y, c);
    889 };
    890 
    891 /**
    892 * @param {glsTextureTestUtil.lodMode} mode
    893 * @param {number} dudx
    894 * @param {number} dvdx
    895 * @param {number} dwdx
    896 * @param {number} dudy
    897 * @param {number} dvdy
    898 * @param {number} dwdy
    899 * @return {number}
    900 */
    901 glsTextureTestUtil.computeLodFromDerivates3D = function(mode, dudx, dvdx, dwdx, dudy, dvdy, dwdy) {
    902    var p = 0;
    903    switch (mode) {
    904        case glsTextureTestUtil.lodMode.EXACT:
    905            p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx + dwdx * dwdx), Math.sqrt(dudy * dudy + dvdy * dvdy + dwdy * dwdy));
    906            break;
    907 
    908        case glsTextureTestUtil.lodMode.MIN_BOUND:
    909        case glsTextureTestUtil.lodMode.MAX_BOUND: {
    910            var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
    911            var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
    912            var mw = Math.max(Math.abs(dwdx), Math.abs(dwdy));
    913 
    914            p = (mode == glsTextureTestUtil.lodMode.MIN_BOUND) ? Math.max(mu, mv, mw) : mu + mv + mw;
    915            break;
    916        }
    917 
    918        default:
    919            DE_ASSERT(false);
    920    }
    921 
    922    // Native dEQP uses 32-bit numbers. So here 64-bit floating numbers should be transformed into 32-bit ones to ensure the correctness of the result.
    923    return deMath.toFloat32(Math.log(p)) * deMath.INV_LOG_2_FLOAT32;
    924 };
    925 
    926 /**
    927 * @param {glsTextureTestUtil.lodMode} mode
    928 * @param {Array<number>} dstSize
    929 * @param {Array<number>} srcSize
    930 * @param {Array<number>} sq
    931 * @param {Array<number>} tq
    932 * @param {Array<number>=} rq
    933 * @return {number}
    934 */
    935 glsTextureTestUtil.computeNonProjectedTriLod = function(mode, dstSize, srcSize, sq, tq, rq) {
    936    var dux = (sq[2] - sq[0]) * srcSize[0];
    937    var duy = (sq[1] - sq[0]) * srcSize[0];
    938    var dvx = (tq[2] - tq[0]) * srcSize[1];
    939    var dvy = (tq[1] - tq[0]) * srcSize[1];
    940    var dwx = 0;
    941    var dwy = 0;
    942    if (rq) {
    943        dwx = (rq[2] - rq[0]) * srcSize[2];
    944        dwy = (rq[1] - rq[0]) * srcSize[2];
    945    }
    946    var dx = dstSize[0];
    947    var dy = dstSize[1];
    948 
    949    return glsTextureTestUtil.computeLodFromDerivates3D(mode, dux / dx, dvx / dx, dwx / dx, duy / dy, dvy / dy, dwy / dy);
    950 };
    951 
    952 /**
    953 * @param {Array<number>} v
    954 * @param {number} x
    955 * @param {number} y
    956 * @return {number}
    957 */
    958 glsTextureTestUtil.triangleInterpolate = function(v, x, y) {
    959    return v[0] + (v[2] - v[0]) * x + (v[1] - v[0]) * y;
    960 };
    961 
    962 /**
    963 * @param {Array<number>} s
    964 * @param {Array<number>} w
    965 * @param {number} wx
    966 * @param {number} width
    967 * @param {number} ny
    968 * @return {number}
    969 */
    970 glsTextureTestUtil.triDerivateX = function(s, w, wx, width, ny) {
    971    var d = w[1] * w[2] * (width * (ny - 1) + wx) - w[0] * (w[2] * width * ny + w[1] * wx);
    972    return (w[0] * w[1] * w[2] * width * (w[1] * (s[0] - s[2]) * (ny - 1) + ny * (w[2] * (s[1] - s[0]) + w[0] * (s[2] - s[1])))) / (d * d);
    973 };
    974 
    975 /**
    976 * @param {Array<number>} s
    977 * @param {Array<number>} w
    978 * @param {number} wy
    979 * @param {number} height
    980 * @param {number} nx
    981 * @return {number}
    982 */
    983 glsTextureTestUtil.triDerivateY = function(s, w, wy, height, nx) {
    984    var d = w[1] * w[2] * (height * (nx - 1) + wy) - w[0] * (w[1] * height * nx + w[2] * wy);
    985    return (w[0] * w[1] * w[2] * height * (w[2] * (s[0] - s[1]) * (nx - 1) + nx * (w[0] * (s[1] - s[2]) + w[1] * (s[2] - s[0])))) / (d * d);
    986 };
    987 
    988 /**
    989 * @param {(tcuTexture.Texture2DView|tcuTexture.Texture2DArrayView|tcuTexture.TextureCubeView)} src
    990 * @param {glsTextureTestUtil.ReferenceParams} params
    991 * @param {Array<number>} texCoord Texture coordinates
    992 * @param {number} lod
    993 * @return {Array<number>} sample
    994 */
    995 glsTextureTestUtil.execSample = function(src, params, texCoord, lod) {
    996    if (params.samplerType == glsTextureTestUtil.samplerType.SAMPLERTYPE_SHADOW)
    997        return [src.sampleCompare(params.sampler, params.ref, texCoord, lod), 0, 0, 1];
    998    else
    999        return src.sample(params.sampler, texCoord, lod);
   1000 };
   1001 
   1002 /**
   1003 * @param {Array<number>} pixel
   1004 * @param {Array<number>} scale
   1005 * @param {Array<number>} bias
   1006 */
   1007 glsTextureTestUtil.applyScaleAndBias = function(pixel, scale, bias) {
   1008    pixel[0] = pixel[0] * scale[0] + bias[0];
   1009    pixel[1] = pixel[1] * scale[1] + bias[1];
   1010    pixel[2] = pixel[2] * scale[2] + bias[2];
   1011    pixel[3] = pixel[3] * scale[3] + bias[3];
   1012 };
   1013 
   1014 /**
   1015 * @param {Array<number>} pixel
   1016 * @param {Array<number>} scale
   1017 * @param {Array<number>} bias
   1018 */
   1019 glsTextureTestUtil.deapplyScaleAndBias = function(pixel, scale, bias) {
   1020    pixel[0] = (pixel[0] - bias[0]) / scale[0];
   1021    pixel[1] = (pixel[1] - bias[1]) / scale[1];
   1022    pixel[2] = (pixel[2] - bias[2]) / scale[2];
   1023    pixel[3] = (pixel[3] - bias[3]) / scale[3];
   1024 };
   1025 
   1026 /**
   1027 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1028 * @param {tcuTexture.Texture2DView} src
   1029 * @param {Array<number>} sq
   1030 * @param {Array<number>} tq
   1031 * @param {glsTextureTestUtil.ReferenceParams} params
   1032 */
   1033 glsTextureTestUtil.sampleTextureProjected2D = function(dst, src, sq, tq, params) {
   1034    /** @type {number} */ var lodBias = params.flags.use_bias ? params.bias : 0.0;
   1035    /** @type {number} */ var dstW = dst.getWidth();
   1036    /** @type {number} */ var dstH = dst.getHeight();
   1037 
   1038    /** @type {Array<number>} */ var uq = deMath.scale(sq, src.getWidth());
   1039    /** @type {Array<number>} */ var vq = deMath.scale(tq, src.getHeight());
   1040 
   1041    /** @type {Array<Array<number>>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1042    /** @type {Array<Array<number>>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1043    /** @type {Array<Array<number>>} */ var triU = [deMath.swizzle(uq, [0, 1, 2]), deMath.swizzle(uq, [3, 2, 1])];
   1044    /** @type {Array<Array<number>>} */ var triV = [deMath.swizzle(vq, [0, 1, 2]), deMath.swizzle(vq, [3, 2, 1])];
   1045    /** @type {Array<Array<number>>} */ var triW = [deMath.swizzle(params.w, [0, 1, 2]), deMath.swizzle(params.w, [3, 2, 1])];
   1046 
   1047    for (var py = 0; py < dst.getHeight(); py++) {
   1048        for (var px = 0; px < dst.getWidth(); px++) {
   1049            /** @type {number} */ var wx = px + 0.5;
   1050            /** @type {number} */ var wy = py + 0.5;
   1051            /** @type {number} */ var nx = wx / dstW;
   1052            /** @type {number} */ var ny = wy / dstH;
   1053 
   1054            /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0;
   1055            /** @type {number} */ var triWx = triNdx ? dstW - wx : wx;
   1056            /** @type {number} */ var triWy = triNdx ? dstH - wy : wy;
   1057            /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx;
   1058            /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny;
   1059 
   1060            /** @type {number} */ var s = glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
   1061            /** @type {number} */ var t = glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy);
   1062            /** @type {number} */ var lod = glsTextureTestUtil.computeProjectedTriLod2D(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triWx, triWy, dst.getWidth(), dst.getHeight()) + lodBias;
   1063 
   1064            var pixel = glsTextureTestUtil.execSample(src, params, [s, t], lod);
   1065            glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
   1066            dst.setPixel(pixel, px, py);
   1067        }
   1068    }
   1069 };
   1070 
   1071 /**
   1072 * @param {glsTextureTestUtil.lodMode} mode
   1073 * @param {Array<number>} u
   1074 * @param {Array<number>} v
   1075 * @param {Array<number>} projection
   1076 * @param {number} wx
   1077 * @param {number} wy
   1078 * @param {number} width
   1079 * @param {number} height
   1080 * @return {number}
   1081 */
   1082 glsTextureTestUtil.computeProjectedTriLod2D = function(mode, u, v, projection, wx, wy, width, height) {
   1083    // Exact derivatives.
   1084    /** @type {number} */ var dudx = glsTextureTestUtil.triDerivateX(u, projection, wx, width, wy / height);
   1085    /** @type {number} */ var dvdx = glsTextureTestUtil.triDerivateX(v, projection, wx, width, wy / height);
   1086    /** @type {number} */ var dudy = glsTextureTestUtil.triDerivateY(u, projection, wy, height, wx / width);
   1087    /** @type {number} */ var dvdy = glsTextureTestUtil.triDerivateY(v, projection, wy, height, wx / width);
   1088 
   1089    return glsTextureTestUtil.computeLodFromDerivates2D(mode, dudx, dvdx, dudy, dvdy);
   1090 };
   1091 
   1092 /**
   1093 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1094 * @param {tcuTexture.Texture2DView} src
   1095 * @param {Array<number>} sq
   1096 * @param {Array<number>} tq
   1097 * @param {glsTextureTestUtil.ReferenceParams} params
   1098 */
   1099 glsTextureTestUtil.sampleTextureNonProjected2D = function(dst, src, sq, tq, params) {
   1100    var lodBias = params.flags.use_bias ? params.bias : 0;
   1101 
   1102    var dstSize = [dst.getWidth(), dst.getHeight()];
   1103    var srcSize = [src.getWidth(), src.getHeight()];
   1104 
   1105    // Coordinates and lod per triangle.
   1106    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1107    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1108    var triLod = [deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias), params.minLod, params.maxLod),
   1109                    deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias), params.minLod, params.maxLod)];
   1110 
   1111 
   1112    for (var y = 0; y < dst.getHeight(); y++) {
   1113        for (var x = 0; x < dst.getWidth(); x++) {
   1114            var yf = (y + 0.5) / dst.getHeight();
   1115            var xf = (x + 0.5) / dst.getWidth();
   1116 
   1117            var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule.
   1118            var triX = triNdx ? 1 - xf : xf;
   1119            var triY = triNdx ? 1 - yf : yf;
   1120 
   1121            var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY);
   1122            var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY);
   1123            var lod = triLod[triNdx];
   1124 
   1125            var pixel = glsTextureTestUtil.execSample(src, params, [s, t], lod);
   1126            glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
   1127            dst.setPixel(pixel, x, y);
   1128        }
   1129    }
   1130 };
   1131 
   1132 /**
   1133 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1134 * @param {tcuTexture.Texture2DArrayView} src
   1135 * @param {Array<number>} sq
   1136 * @param {Array<number>} tq
   1137 * @param {Array<number>} rq
   1138 * @param {glsTextureTestUtil.ReferenceParams} params
   1139 */
   1140 glsTextureTestUtil.sampleTextureNonProjected2DArray = function(dst, src, sq, tq, rq, params) {
   1141    var lodBias = (params.flags.use_bias) ? params.bias : 0;
   1142 
   1143    var dstSize = [dst.getWidth(), dst.getHeight()];
   1144    var srcSize = [src.getWidth(), src.getHeight()];
   1145 
   1146    // Coordinates and lod per triangle.
   1147    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1148    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1149    var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   1150    var triLod = [glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias,
   1151                                glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias];
   1152 
   1153    for (var y = 0; y < dst.getHeight(); y++) {
   1154        for (var x = 0; x < dst.getWidth(); x++) {
   1155            var yf = (y + 0.5) / dst.getHeight();
   1156            var xf = (x + 0.5) / dst.getWidth();
   1157 
   1158            var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule.
   1159            var triX = triNdx ? 1 - xf : xf;
   1160            var triY = triNdx ? 1 - yf : yf;
   1161 
   1162            var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY);
   1163            var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY);
   1164            var r = glsTextureTestUtil.triangleInterpolate(triR[triNdx], triX, triY);
   1165            var lod = triLod[triNdx];
   1166 
   1167            var pixel = glsTextureTestUtil.execSample(src, params, [s, t, r], lod);
   1168            glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
   1169            dst.setPixel(pixel, x, y);
   1170        }
   1171    }
   1172 };
   1173 
   1174 /**
   1175 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1176 * @param {tcuTexture.Texture2DView} src
   1177 * @param {Array<number>} texCoord
   1178 * @param {glsTextureTestUtil.ReferenceParams} params
   1179 */
   1180 glsTextureTestUtil.sampleTexture2D = function(dst, src, texCoord, params) {
   1181    var view = src.getSubView(params.baseLevel, params.maxLevel);
   1182    var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]];
   1183    var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]];
   1184 
   1185    if (params.flags.projected)
   1186        glsTextureTestUtil.sampleTextureProjected2D(dst, view, sq, tq, params);
   1187    else
   1188        glsTextureTestUtil.sampleTextureNonProjected2D(dst, view, sq, tq, params);
   1189 };
   1190 
   1191 /**
   1192 * @param {glsTextureTestUtil.lodMode} mode
   1193 * @param {number} dudx
   1194 * @param {number} dvdx
   1195 * @param {number} dudy
   1196 * @param {number} dvdy
   1197 * @return {number}
   1198 */
   1199 glsTextureTestUtil.computeLodFromDerivates2D = function(mode, dudx, dvdx, dudy, dvdy) {
   1200    var p = 0;
   1201    switch (mode) {
   1202        case glsTextureTestUtil.lodMode.EXACT:
   1203            p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx), Math.sqrt(dudy * dudy + dvdy * dvdy));
   1204            break;
   1205 
   1206        case glsTextureTestUtil.lodMode.MIN_BOUND:
   1207        case glsTextureTestUtil.lodMode.MAX_BOUND: {
   1208            var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
   1209            var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
   1210 
   1211            p = (mode == glsTextureTestUtil.lodMode.MIN_BOUND) ? Math.max(mu, mv) : mu + mv;
   1212            break;
   1213        }
   1214 
   1215        default:
   1216            throw new Error('Unrecognized mode:' + mode);
   1217    }
   1218 
   1219    // Native dEQP uses 32-bit numbers. So here 64-bit floating numbers should be transformed into 32-bit ones to ensure the correctness of the result.
   1220    return deMath.toFloat32(Math.log(p)) * deMath.INV_LOG_2_FLOAT32;
   1221 };
   1222 
   1223 /**
   1224 * @param {glsTextureTestUtil.lodMode} lodModeParm
   1225 * @param {Array<number>} coord
   1226 * @param {Array<number>} coordDx
   1227 * @param {Array<number>} coordDy
   1228 * @param {number} faceSize
   1229 * @return {number}
   1230 */
   1231 glsTextureTestUtil.computeCubeLodFromDerivates = function(lodModeParm, coord, coordDx, coordDy, faceSize) {
   1232    var face = tcuTexture.selectCubeFace(coord);
   1233    var maNdx = 0;
   1234    var sNdx = 0;
   1235    var tNdx = 0;
   1236 
   1237    // \note Derivate signs don't matter when computing lod
   1238    switch (face) {
   1239        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X:
   1240        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break;
   1241        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y:
   1242        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break;
   1243        case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z:
   1244        case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break;
   1245        default:
   1246            throw new Error('Unrecognized face ' + face);
   1247    } {
   1248        var sc = coord[sNdx];
   1249        var tc = coord[tNdx];
   1250        var ma = Math.abs(coord[maNdx]);
   1251        var scdx = coordDx[sNdx];
   1252        var tcdx = coordDx[tNdx];
   1253        var madx = Math.abs(coordDx[maNdx]);
   1254        var scdy = coordDy[sNdx];
   1255        var tcdy = coordDy[tNdx];
   1256        var mady = Math.abs(coordDy[maNdx]);
   1257        var dudx = faceSize * 0.5 * (scdx * ma - sc * madx) / (ma * ma);
   1258        var dvdx = faceSize * 0.5 * (tcdx * ma - tc * madx) / (ma * ma);
   1259        var dudy = faceSize * 0.5 * (scdy * ma - sc * mady) / (ma * ma);
   1260        var dvdy = faceSize * 0.5 * (tcdy * ma - tc * mady) / (ma * ma);
   1261        return glsTextureTestUtil.computeLodFromDerivates2D(lodModeParm, dudx, dvdx, dudy, dvdy);
   1262    }
   1263 };
   1264 
   1265 /**
   1266 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1267 * @param {tcuTexture.TextureCubeView} src
   1268 * @param {Array<number>} sq
   1269 * @param {Array<number>} tq
   1270 * @param {Array<number>} rq
   1271 * @param {glsTextureTestUtil.ReferenceParams} params
   1272 */
   1273 glsTextureTestUtil.sampleTextureCube_str = function(dst, src, sq, tq, rq, params) {
   1274    var dstSize = [dst.getWidth(), dst.getHeight()];
   1275    var dstW = dstSize[0];
   1276    var dstH = dstSize[1];
   1277    var srcSize = src.getSize();
   1278 
   1279    // Coordinates per triangle.
   1280    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1281    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1282    var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   1283    var triW = [deMath.swizzle(params.w, [0, 1, 2]), deMath.swizzle(params.w, [3, 2, 1])];
   1284 
   1285    var lodBias = (params.flags.use_bias ? params.bias : 0);
   1286 
   1287    for (var py = 0; py < dst.getHeight(); py++) {
   1288        for (var px = 0; px < dst.getWidth(); px++) {
   1289            var wx = px + 0.5;
   1290            var wy = py + 0.5;
   1291            var nx = wx / dstW;
   1292            var ny = wy / dstH;
   1293            var triNdx = nx + ny >= 1 ? 1 : 0;
   1294            var triNx = triNdx ? 1 - nx : nx;
   1295            var triNy = triNdx ? 1 - ny : ny;
   1296 
   1297            var coord = [glsTextureTestUtil.triangleInterpolate(triS[triNdx], triNx, triNy),
   1298                                         glsTextureTestUtil.triangleInterpolate(triT[triNdx], triNx, triNy),
   1299                                         glsTextureTestUtil.triangleInterpolate(triR[triNdx], triNx, triNy)];
   1300            var coordDx = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
   1301                                         glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
   1302                                         glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)];
   1303            var coordDy = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
   1304                                         glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
   1305                                         glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)];
   1306 
   1307            var lod = deMath.clamp((glsTextureTestUtil.computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, srcSize) + lodBias), params.minLod, params.maxLod);
   1308 
   1309            var pixel = glsTextureTestUtil.execSample(src, params, coord, lod);
   1310            glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
   1311            dst.setPixel(pixel, px, py);
   1312        }
   1313    }
   1314 };
   1315 
   1316 /**
   1317 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1318 * @param {tcuTexture.TextureCubeView} src
   1319 * @param {Array<number>} texCoord
   1320 * @param {glsTextureTestUtil.ReferenceParams} params
   1321 */
   1322 glsTextureTestUtil.sampleTextureCube = function(dst, src, texCoord, params) {
   1323    /*const tcu::TextureCubeView*/ var view = src.getSubView(params.baseLevel, params.maxLevel);
   1324    var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   1325    var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   1326    var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   1327 
   1328    glsTextureTestUtil.sampleTextureCube_str(dst, view, sq, tq, rq, params);
   1329 };
   1330 
   1331 /**
   1332 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1333 * @param {tcuTexture.Texture2DArrayView} src
   1334 * @param {Array<number>} texCoord
   1335 * @param {glsTextureTestUtil.ReferenceParams} params
   1336 */
   1337 glsTextureTestUtil.sampleTexture2DArray = function(dst, src, texCoord, params) {
   1338    var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   1339    var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   1340    var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   1341 
   1342    DE_ASSERT(!(params.flags.projected)); // \todo [2012-02-17 pyry] Support projected lookups.
   1343    glsTextureTestUtil.sampleTextureNonProjected2DArray(dst, src, sq, tq, rq, params);
   1344 };
   1345 
   1346 /**
   1347 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1348 * @param {tcuTexture.Texture3DView} src
   1349 * @param {Array<number>} sq
   1350 * @param {Array<number>} tq
   1351 * @param {Array<number>} rq
   1352 * @param {glsTextureTestUtil.ReferenceParams} params
   1353 */
   1354 glsTextureTestUtil.sampleTextureNonProjected3D = function(dst, src, sq, tq, rq, params) {
   1355    var lodBias = params.flags.use_bias ? params.bias : 0;
   1356 
   1357    var dstSize = [dst.getWidth(), dst.getHeight()];
   1358    var srcSize = [src.getWidth(), src.getHeight(), src.getDepth()];
   1359 
   1360    // Coordinates and lod per triangle.
   1361    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1362    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1363    var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   1364    var triLod = [deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias), params.minLod, params.maxLod),
   1365                  deMath.clamp((glsTextureTestUtil.computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias), params.minLod, params.maxLod)];
   1366 
   1367    for (var y = 0; y < dst.getHeight(); y++) {
   1368        for (var x = 0; x < dst.getWidth(); x++) {
   1369            var yf = (y + 0.5) / dst.getHeight();
   1370            var xf = (x + 0.5) / dst.getWidth();
   1371 
   1372            var triNdx = xf + yf >= 1 ? 1 : 0; // Top left fill rule.
   1373            var triX = triNdx ? 1 - xf : xf;
   1374            var triY = triNdx ? 1 - yf : yf;
   1375 
   1376            var s = glsTextureTestUtil.triangleInterpolate(triS[triNdx], triX, triY);
   1377            var t = glsTextureTestUtil.triangleInterpolate(triT[triNdx], triX, triY);
   1378            var r = glsTextureTestUtil.triangleInterpolate(triR[triNdx], triX, triY);
   1379            var lod = triLod[triNdx];
   1380 
   1381            var pixel = src.sample(params.sampler, [s, t, r], lod);
   1382            glsTextureTestUtil.applyScaleAndBias(pixel, params.colorScale, params.colorBias);
   1383            dst.setPixel(pixel, x, y);
   1384        }
   1385    }
   1386 };
   1387 
   1388 /**
   1389 * @param {glsTextureTestUtil.SurfaceAccess} dst
   1390 * @param {tcuTexture.Texture3DView} src
   1391 * @param {Array<number>} texCoord
   1392 * @param {glsTextureTestUtil.ReferenceParams} params
   1393 */
   1394 glsTextureTestUtil.sampleTexture3D = function(dst, src, texCoord, params) {
   1395    /*const tcu::TextureCubeView*/ var view = src.getSubView(params.baseLevel, params.maxLevel);
   1396    var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   1397    var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   1398    var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   1399 
   1400    glsTextureTestUtil.sampleTextureNonProjected3D(dst, view, sq, tq, rq, params);
   1401 };
   1402 
   1403 /**
   1404 * @param {tcuSurface.Surface} reference
   1405 * @param {tcuSurface.Surface} rendered
   1406 * @param {Array<number>} threshold
   1407 * @param {Array< Array<number> >} skipPixels
   1408 *
   1409 * @return {boolean}
   1410 */
   1411 glsTextureTestUtil.compareImages = function(reference, rendered, threshold, skipPixels) {
   1412    return tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', reference, rendered, threshold, undefined /*tcu::COMPARE_LOG_RESULT*/, skipPixels);
   1413 };
   1414 
   1415 /**
   1416 * @param {tcuTexture.ConstPixelBufferAccess} result
   1417 * @param {tcuTexture.Texture2DView} src
   1418 * @param {Array<number>} texCoord
   1419 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   1420 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   1421 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   1422 * @param {tcuPixelFormat.PixelFormat} pixelFormat
   1423 * @return {boolean}
   1424 */
   1425 glsTextureTestUtil.verifyTexture2DResult = function(result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat) {
   1426    DE_ASSERT(deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask));
   1427    /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
   1428    /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
   1429    /** @type {number} */ var numFailedPixels;
   1430 
   1431    /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
   1432 
   1433    glsTextureTestUtil.sampleTexture2D(surface, src, texCoord, sampleParams);
   1434    numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff2D(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec/*, testCtx.getWatchDog()*/);
   1435 
   1436    if (numFailedPixels > 0)
   1437        tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
   1438 
   1439    return numFailedPixels == 0;
   1440 };
   1441 
   1442 /**
   1443 * @param {tcuTexture.ConstPixelBufferAccess} result
   1444 * @param {tcuTexture.ConstPixelBufferAccess} reference
   1445 * @param {tcuTexture.PixelBufferAccess} errorMask
   1446 * @param {tcuTexture.Texture2DView} src
   1447 * @param {Array<number>} texCoord
   1448 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   1449 * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
   1450 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   1451 * @param {Array<number>} nonShadowThreshold
   1452 * @return {number}
   1453 */
   1454 glsTextureTestUtil.computeTextureCompareDiff2D = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) {
   1455    DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
   1456    DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
   1457 
   1458    var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]];
   1459    var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]];
   1460 
   1461    var dstSize = [result.getWidth(), result.getHeight()];
   1462    var dstW = dstSize[0];
   1463    var dstH = dstSize[1];
   1464    var srcSize = [src.getWidth(), src.getHeight()];
   1465 
   1466    // Coordinates and lod per triangle.
   1467    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1468    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1469    var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
   1470 
   1471    var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0];
   1472    var numFailed = 0;
   1473 
   1474    var lodOffsets = [
   1475        [-1, 0],
   1476        [1, 0],
   1477        [0, -1],
   1478        [0, 1]
   1479    ];
   1480 
   1481    /** @type {Array<number>} */ var green = [0, 255, 0, 255];
   1482    errorMask.clear(green);
   1483 
   1484    /** @type {Array<number>} */ var red = [];
   1485    for (var py = 0; py < result.getHeight(); py++) {
   1486        for (var px = 0; px < result.getWidth(); px++) {
   1487            /** @type {Array<number>} */
   1488            var resPix = result.getPixel(px, py);
   1489            /** @type {Array<number>} */
   1490            var refPix = reference.getPixel(px, py);
   1491 
   1492            if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(refPix, [1, 2, 3]), deMath.swizzle(resPix, [1, 2, 3])), nonShadowThreshold))) {
   1493                red = [255, 0, 0, 255];
   1494                errorMask.setPixel(red, px, py);
   1495                numFailed += 1;
   1496                continue;
   1497            }
   1498 
   1499            if (resPix[0] != refPix[0]) {
   1500                var wx = px + 0.5;
   1501                var wy = py + 0.5;
   1502                var nx = wx / dstW;
   1503                var ny = wy / dstH;
   1504 
   1505                var triNdx = nx + ny >= 1.0 ? 1 : 0;
   1506                var triWx = triNdx ? dstW - wx : wx;
   1507                var triWy = triNdx ? dstH - wy : wy;
   1508                var triNx = triNdx ? 1.0 - nx : nx;
   1509                var triNy = triNdx ? 1.0 - ny : ny;
   1510 
   1511                var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
   1512                             glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)];
   1513                var coordDx = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
   1514                                            glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
   1515                var coordDy = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
   1516                                            glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
   1517 
   1518                var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
   1519 
   1520                // Compute lod bounds across lodOffsets range.
   1521                for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
   1522                    var wxo = triWx + lodOffsets[lodOffsNdx][0];
   1523                    var wyo = triWy + lodOffsets[lodOffsNdx][1];
   1524                    var nxo = wxo / dstW;
   1525                    var nyo = wyo / dstH;
   1526 
   1527                    var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
   1528                                  glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)];
   1529                    var coordDxo = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
   1530                                                 glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize);
   1531                    var coordDyo = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
   1532                                                 glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize);
   1533                    var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
   1534 
   1535                    lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
   1536                    lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
   1537                }
   1538 
   1539                var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
   1540                var isOk = tcuTexCompareVerifier.isTexCompareResultValid2D(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]);
   1541 
   1542                if (!isOk) {
   1543                    red = [255, 0, 0, 255];
   1544                    errorMask.setPixel(red, px, py);
   1545                    numFailed += 1;
   1546                }
   1547            }
   1548        }
   1549    }
   1550 
   1551    return numFailed;
   1552 };
   1553 
   1554 /**
   1555 * @param {tcuTexture.ConstPixelBufferAccess} result
   1556 * @param {tcuTexture.Texture3DView} src
   1557 * @param {Array<number>} texCoord
   1558 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   1559 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   1560 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   1561 * @param {tcuPixelFormat.PixelFormat} pixelFormat
   1562 * @return {boolean}
   1563 */
   1564 glsTextureTestUtil.verifyTexture3DResult = function(
   1565    result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat
   1566 ) {
   1567    /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
   1568    /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
   1569    var numFailedPixels = 0;
   1570 
   1571    assertMsgOptions(
   1572        deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask),
   1573        'Compare color masks do not match', false, true
   1574    );
   1575 
   1576    /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
   1577    glsTextureTestUtil.sampleTexture3D(surface, src, texCoord, sampleParams);
   1578    numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff3D(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec);
   1579 
   1580    if (numFailedPixels > 0)
   1581        tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
   1582 
   1583    return numFailedPixels == 0;
   1584 };
   1585 
   1586 /**
   1587 * @param {tcuTexture.ConstPixelBufferAccess} result
   1588 * @param {tcuTexture.ConstPixelBufferAccess} reference
   1589 * @param {tcuTexture.PixelBufferAccess} errorMask
   1590 * @param {tcuTexture.Texture3DView} baseView
   1591 * @param {Array<number>} texCoord
   1592 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   1593 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   1594 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   1595 * @return {number}
   1596 */
   1597 glsTextureTestUtil.computeTextureLookupDiff3D = function(
   1598    result, reference, errorMask, baseView, texCoord,
   1599    sampleParams, lookupPrec, lodPrec
   1600 ) {
   1601    assertMsgOptions(
   1602        result.getWidth() == reference.getWidth() &&
   1603        result.getHeight() == reference.getHeight(),
   1604        'Result and reference images are not the same size', false, true
   1605    );
   1606    assertMsgOptions(
   1607        result.getWidth() == errorMask.getWidth() &&
   1608        result.getHeight() == errorMask.getHeight(),
   1609        'Result and error mask images are not the same size', false, true
   1610    );
   1611 
   1612    /** @type {tcuTexture.Texture3DView} */
   1613    var src = baseView.getSubView(
   1614        sampleParams.baseLevel, sampleParams.maxLevel
   1615    );
   1616 
   1617    var sq =
   1618        [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   1619    var tq =
   1620        [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   1621    var rq =
   1622        [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   1623 
   1624    var dstSize = [result.getWidth(), result.getHeight()];
   1625    var dstW = dstSize[0];
   1626    var dstH = dstSize[1];
   1627    var srcSize = [src.getWidth(), src.getHeight(), src.getDepth()];
   1628 
   1629    // Coordinates and lod per triangle.
   1630    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1631    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1632    var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   1633    var triW = [
   1634        deMath.swizzle(sampleParams.w, [0, 1, 2]),
   1635        deMath.swizzle(sampleParams.w, [3, 2, 1])
   1636    ];
   1637 
   1638    var lodBias = sampleParams.flags.useBias ? sampleParams.bias : 0.0;
   1639 
   1640    var posEps = 1.0 / ((1 << MIN_SUBPIXEL_BITS) + 1);
   1641 
   1642    var numFailed = 0;
   1643 
   1644    var lodOffsets = [
   1645        [-1, 0],
   1646        [+1, 0],
   1647        [0, -1],
   1648        [0, +1]
   1649    ];
   1650 
   1651    var green = [0, 255, 0, 255];
   1652    errorMask.clear(new tcuRGBA.RGBA(green).toVec());
   1653 
   1654    for (var py = 0; py < result.getHeight(); py++) {
   1655        // Ugly hack, validation can take way too long at the moment.
   1656        /*TODO: if (watchDog)
   1657            qpWatchDog_touch(watchDog);*/
   1658 
   1659        for (var px = 0; px < result.getWidth(); px++) {
   1660            /** @type {Array<number>} */
   1661            var resPix = result.getPixel(px, py);
   1662            glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
   1663            /** @type {Array<number>} */
   1664            var refPix = reference.getPixel(px, py);
   1665            glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
   1666 
   1667            // Try comparison to ideal reference first,
   1668            // and if that fails use slower verificator.
   1669            if (!deMath.boolAll(deMath.lessThanEqual(
   1670                deMath.absDiff(resPix, refPix),
   1671                lookupPrec.colorThreshold))
   1672            ) {
   1673                /** @type {number} */ var wx = px + 0.5;
   1674                /** @type {number} */ var wy = py + 0.5;
   1675                /** @type {number} */ var nx = wx / dstW;
   1676                /** @type {number} */ var ny = wy / dstH;
   1677 
   1678                /** @type {boolean} */ var tri0 = nx + ny - posEps <= 1.0;
   1679                /** @type {boolean} */ var tri1 = nx + ny + posEps >= 1.0;
   1680 
   1681                var isOk = false;
   1682 
   1683                assertMsgOptions(
   1684                    tri0 || tri1,
   1685                    'Pixel should belong at least to one triangle',
   1686                    false, true
   1687                );
   1688 
   1689                // Pixel can belong to either of the triangles
   1690                // if it lies close enough to the edge.
   1691                for (var triNdx = (tri0 ? 0 : 1);
   1692                    triNdx <= (tri1 ? 1 : 0);
   1693                    triNdx++) {
   1694                    var triWx = triNdx ? dstW - wx : wx;
   1695                    var triWy = triNdx ? dstH - wy : wy;
   1696                    var triNx = triNdx ? 1.0 - nx : nx;
   1697                    var triNy = triNdx ? 1.0 - ny : ny;
   1698 
   1699                    var coord = [
   1700                        glsTextureTestUtil.projectedTriInterpolate(
   1701                            triS[triNdx], triW[triNdx], triNx, triNy
   1702                        ),
   1703                        glsTextureTestUtil.projectedTriInterpolate(
   1704                            triT[triNdx], triW[triNdx], triNx, triNy
   1705                        ),
   1706                        glsTextureTestUtil.projectedTriInterpolate(
   1707                            triR[triNdx], triW[triNdx], triNx, triNy
   1708                        )
   1709                    ];
   1710                    var coordDx = deMath.multiply([
   1711                        glsTextureTestUtil.triDerivateX(
   1712                            triS[triNdx], triW[triNdx], wx, dstW, triNy
   1713                        ),
   1714                        glsTextureTestUtil.triDerivateX(
   1715                            triT[triNdx], triW[triNdx], wx, dstW, triNy
   1716                        ),
   1717                        glsTextureTestUtil.triDerivateX(
   1718                            triR[triNdx], triW[triNdx], wx, dstW, triNy
   1719                        )
   1720                    ], srcSize);
   1721                    var coordDy = deMath.multiply([
   1722                        glsTextureTestUtil.triDerivateY(
   1723                            triS[triNdx], triW[triNdx], wy, dstH, triNx
   1724                        ),
   1725                        glsTextureTestUtil.triDerivateY(
   1726                            triT[triNdx], triW[triNdx], wy, dstH, triNx
   1727                        ),
   1728                        glsTextureTestUtil.triDerivateY(
   1729                            triR[triNdx], triW[triNdx], wy, dstH, triNx
   1730                        )
   1731                    ], srcSize);
   1732 
   1733                    var lodBounds =
   1734                        tcuTexLookupVerifier.computeLodBoundsFromDerivates(
   1735                            coordDx[0], coordDx[1], coordDx[2],
   1736                            coordDy[0], coordDy[1], coordDy[2], lodPrec
   1737                        );
   1738 
   1739                    // Compute lod bounds across lodOffsets range.
   1740                    for (var lodOffsNdx = 0;
   1741                        lodOffsNdx < lodOffsets.length;
   1742                        lodOffsNdx++) {
   1743                        var wxo = triWx + lodOffsets[lodOffsNdx][0];
   1744                        var wyo = triWy + lodOffsets[lodOffsNdx][1];
   1745                        var nxo = wxo / dstW;
   1746                        var nyo = wyo / dstH;
   1747 
   1748                        var coordO = [
   1749                            glsTextureTestUtil.projectedTriInterpolate(
   1750                                triS[triNdx], triW[triNdx], nxo, nyo
   1751                            ),
   1752                            glsTextureTestUtil.projectedTriInterpolate(
   1753                                triT[triNdx], triW[triNdx], nxo, nyo
   1754                            ),
   1755                            glsTextureTestUtil.projectedTriInterpolate(
   1756                                triR[triNdx], triW[triNdx], nxo, nyo
   1757                            )
   1758                        ];
   1759                        var coordDxo = deMath.multiply([
   1760                            glsTextureTestUtil.triDerivateX(
   1761                                triS[triNdx], triW[triNdx], wxo, dstW, nyo
   1762                            ),
   1763                            glsTextureTestUtil.triDerivateX(
   1764                                triT[triNdx], triW[triNdx], wxo, dstW, nyo
   1765                            ),
   1766                            glsTextureTestUtil.triDerivateX(
   1767                                triR[triNdx], triW[triNdx], wxo, dstW, nyo
   1768                            )
   1769                        ], srcSize);
   1770                        var coordDyo = deMath.multiply([
   1771                            glsTextureTestUtil.triDerivateY(
   1772                                triS[triNdx], triW[triNdx], wyo, dstH, nxo
   1773                            ),
   1774                            glsTextureTestUtil.triDerivateY(
   1775                                triT[triNdx], triW[triNdx], wyo, dstH, nxo
   1776                            ),
   1777                            glsTextureTestUtil.triDerivateY(
   1778                                triR[triNdx], triW[triNdx], wyo, dstH, nxo
   1779                            )
   1780                        ], srcSize);
   1781                        var lodO =
   1782                            tcuTexLookupVerifier.computeLodBoundsFromDerivates(
   1783                                coordDxo[0], coordDxo[1], coordDxo[2],
   1784                                coordDyo[0], coordDyo[1], coordDyo[2], lodPrec
   1785                            );
   1786 
   1787                        lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
   1788                        lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
   1789                    }
   1790 
   1791                    var clampedLod = tcuTexLookupVerifier.clampLodBounds(
   1792                        deMath.addScalar(lodBounds, lodBias),
   1793                        [sampleParams.minLod, sampleParams.maxLod],
   1794                        lodPrec
   1795                    );
   1796 
   1797                    if (
   1798                        tcuTexLookupVerifier.isLookupResultValid(
   1799                            src, sampleParams.sampler, lookupPrec,
   1800                            coord, clampedLod, resPix
   1801                        )
   1802                    ) {
   1803                        isOk = true;
   1804                        break;
   1805                    }
   1806                }
   1807 
   1808                if (!isOk) {
   1809                    var red = [255, 0, 0, 255];
   1810                    errorMask.setPixel(new tcuRGBA.RGBA(red).toVec(), px, py);
   1811                    numFailed += 1;
   1812                }
   1813            }
   1814        }
   1815    }
   1816 
   1817    return numFailed;
   1818 };
   1819 
   1820 /**
   1821 * @param {tcuTexture.ConstPixelBufferAccess} result
   1822 * @param {tcuTexture.TextureCubeView} src
   1823 * @param {Array<number>} texCoord
   1824 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   1825 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   1826 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   1827 * @param {tcuPixelFormat.PixelFormat} pixelFormat
   1828 * @return {boolean}
   1829 */
   1830 glsTextureTestUtil.verifyTextureCubeResult = function(
   1831    result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat
   1832 ) {
   1833    /** @type {tcuSurface.Surface} */
   1834    var reference = new tcuSurface.Surface(
   1835        result.getWidth(), result.getHeight()
   1836    );
   1837    /** @type {tcuSurface.Surface} */
   1838    var errorMask = new tcuSurface.Surface(
   1839        result.getWidth(), result.getHeight()
   1840    );
   1841    /** @type {number} */ var numFailedPixels = 0;
   1842 
   1843    assertMsgOptions(
   1844        deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask),
   1845        'Compare color masks do not match', false, true
   1846    );
   1847 
   1848    /** @type {glsTextureTestUtil.SurfaceAccess} */
   1849    var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
   1850 
   1851    glsTextureTestUtil.sampleTextureCube(
   1852        surface, src, texCoord, sampleParams
   1853    );
   1854 
   1855    numFailedPixels = glsTextureTestUtil.computeTextureLookupDiffCube(
   1856        result, reference.getAccess(), errorMask.getAccess(),
   1857        src, texCoord, sampleParams, lookupPrec, lodPrec
   1858        /*, testCtx.getWatchDog()*/
   1859    );
   1860 
   1861    if (numFailedPixels > 0)
   1862        tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
   1863 
   1864    return numFailedPixels == 0;
   1865 };
   1866 
   1867 /**
   1868 * @param {tcuTexture.ConstPixelBufferAccess} result
   1869 * @param {tcuTexture.ConstPixelBufferAccess} reference
   1870 * @param {tcuTexture.PixelBufferAccess} errorMask
   1871 * @param {tcuTexture.TextureCubeView} baseView
   1872 * @param {Array<number>} texCoord
   1873 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   1874 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   1875 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   1876 * @return {number}
   1877 */
   1878 glsTextureTestUtil.computeTextureLookupDiffCube = function(
   1879    result, reference, errorMask, baseView, texCoord,
   1880    sampleParams, lookupPrec, lodPrec
   1881 ) {
   1882    assertMsgOptions(
   1883        result.getWidth() == reference.getWidth() &&
   1884        result.getHeight() == reference.getHeight(),
   1885        'Result and reference images are not the same size', false, true
   1886    );
   1887    assertMsgOptions(
   1888        result.getWidth() == errorMask.getWidth() &&
   1889        result.getHeight() == errorMask.getHeight(),
   1890        'Result and error mask images are not the same size', false, true
   1891    );
   1892 
   1893    /** @type {tcuTexture.TextureCubeView} */
   1894    var src = baseView.getSubView(
   1895        sampleParams.baseLevel, sampleParams.maxLevel
   1896    );
   1897 
   1898    var sq =
   1899        [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   1900    var tq =
   1901        [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   1902    var rq =
   1903        [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   1904 
   1905    var dstSize = [result.getWidth(), result.getHeight()];
   1906    var dstW = dstSize[0];
   1907    var dstH = dstSize[1];
   1908    var srcSize = [src.getSize(), src.getSize()];
   1909 
   1910    // Coordinates and lod per triangle.
   1911    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   1912    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   1913    var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   1914    var triW = [
   1915        deMath.swizzle(sampleParams.w, [0, 1, 2]),
   1916        deMath.swizzle(sampleParams.w, [3, 2, 1])
   1917    ];
   1918 
   1919    var lodBias = sampleParams.flags.useBias ? sampleParams.bias : 0.0;
   1920 
   1921    var posEps = 1.0 / ((1 << MIN_SUBPIXEL_BITS) + 1);
   1922 
   1923    var numFailed = 0;
   1924 
   1925    var lodOffsets = [
   1926        [-1, 0],
   1927        [+1, 0],
   1928        [0, -1],
   1929        [0, +1],
   1930 
   1931        // \note Not strictly allowed by spec,
   1932        // but implementations do this in practice.
   1933        [-1, -1],
   1934        [-1, 1],
   1935        [1, -1],
   1936        [1, 1]
   1937    ];
   1938 
   1939    var green = [0, 255, 0, 255];
   1940    errorMask.clear(new tcuRGBA.RGBA(green).toVec());
   1941 
   1942    for (var py = 0; py < result.getHeight(); py++) {
   1943        // Ugly hack, validation can take way too long at the moment.
   1944        /*TODO: if (watchDog)
   1945            qpWatchDog_touch(watchDog);*/
   1946 
   1947        for (var px = 0; px < result.getWidth(); px++) {
   1948            /** @type {Array<number>} */
   1949            var resPix = result.getPixel(px, py);
   1950            glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
   1951            /** @type {Array<number>} */
   1952            var refPix = reference.getPixel(px, py);
   1953            glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
   1954 
   1955            // Try comparison to ideal reference first,
   1956            // and if that fails use slower verificator.
   1957            if (!deMath.boolAll(deMath.lessThanEqual(
   1958                deMath.absDiff(resPix, refPix),
   1959                lookupPrec.colorThreshold))
   1960            ) {
   1961                /** @type {number} */ var wx = px + 0.5;
   1962                /** @type {number} */ var wy = py + 0.5;
   1963                /** @type {number} */ var nx = wx / dstW;
   1964                /** @type {number} */ var ny = wy / dstH;
   1965 
   1966                /** @type {boolean} */ var tri0 = nx + ny - posEps <= 1.0;
   1967                /** @type {boolean} */ var tri1 = nx + ny + posEps >= 1.0;
   1968 
   1969                var isOk = false;
   1970 
   1971                assertMsgOptions(
   1972                    tri0 || tri1,
   1973                    'Pixel should belong at least to one triangle',
   1974                    false, true
   1975                );
   1976 
   1977                // Pixel can belong to either of the triangles
   1978                // if it lies close enough to the edge.
   1979                for (var triNdx = (tri0 ? 0 : 1);
   1980                    triNdx <= (tri1 ? 1 : 0);
   1981                    triNdx++) {
   1982                    var triWx = triNdx ? dstW - wx : wx;
   1983                    var triWy = triNdx ? dstH - wy : wy;
   1984                    var triNx = triNdx ? 1.0 - nx : nx;
   1985                    var triNy = triNdx ? 1.0 - ny : ny;
   1986 
   1987                    var coord = [
   1988                        glsTextureTestUtil.projectedTriInterpolate(
   1989                            triS[triNdx], triW[triNdx], triNx, triNy
   1990                        ),
   1991                        glsTextureTestUtil.projectedTriInterpolate(
   1992                            triT[triNdx], triW[triNdx], triNx, triNy
   1993                        ),
   1994                        glsTextureTestUtil.projectedTriInterpolate(
   1995                            triR[triNdx], triW[triNdx], triNx, triNy
   1996                        )
   1997                    ];
   1998                    var coordDx = [
   1999                        glsTextureTestUtil.triDerivateX(
   2000                            triS[triNdx], triW[triNdx], wx, dstW, triNy
   2001                        ),
   2002                        glsTextureTestUtil.triDerivateX(
   2003                            triT[triNdx], triW[triNdx], wx, dstW, triNy
   2004                        ),
   2005                        glsTextureTestUtil.triDerivateX(
   2006                            triR[triNdx], triW[triNdx], wx, dstW, triNy
   2007                        )
   2008                    ];
   2009                    var coordDy = [
   2010                        glsTextureTestUtil.triDerivateY(
   2011                            triS[triNdx], triW[triNdx], wy, dstH, triNx
   2012                        ),
   2013                        glsTextureTestUtil.triDerivateY(
   2014                            triT[triNdx], triW[triNdx], wy, dstH, triNx
   2015                        ),
   2016                        glsTextureTestUtil.triDerivateY(
   2017                            triR[triNdx], triW[triNdx], wy, dstH, triNx
   2018                        )
   2019                    ];
   2020 
   2021                    var lodBounds =
   2022                        tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(
   2023                            coord, coordDx, coordDy, src.getSize(), lodPrec
   2024                        );
   2025 
   2026                    // Compute lod bounds across lodOffsets range.
   2027                    for (var lodOffsNdx = 0;
   2028                        lodOffsNdx < lodOffsets.length;
   2029                        lodOffsNdx++) {
   2030                        var wxo = triWx + lodOffsets[lodOffsNdx][0];
   2031                        var wyo = triWy + lodOffsets[lodOffsNdx][1];
   2032                        var nxo = wxo / dstW;
   2033                        var nyo = wyo / dstH;
   2034 
   2035                        var coordO = [
   2036                            glsTextureTestUtil.projectedTriInterpolate(
   2037                                triS[triNdx], triW[triNdx], nxo, nyo
   2038                            ),
   2039                            glsTextureTestUtil.projectedTriInterpolate(
   2040                                triT[triNdx], triW[triNdx], nxo, nyo
   2041                            ),
   2042                            glsTextureTestUtil.projectedTriInterpolate(
   2043                                triR[triNdx], triW[triNdx], nxo, nyo
   2044                            )
   2045                        ];
   2046                        var coordDxo = [
   2047                            glsTextureTestUtil.triDerivateX(
   2048                                triS[triNdx], triW[triNdx], wxo, dstW, nyo
   2049                            ),
   2050                            glsTextureTestUtil.triDerivateX(
   2051                                triT[triNdx], triW[triNdx], wxo, dstW, nyo
   2052                            ),
   2053                            glsTextureTestUtil.triDerivateX(
   2054                                triR[triNdx], triW[triNdx], wxo, dstW, nyo
   2055                            )
   2056                        ];
   2057                        var coordDyo = [
   2058                            glsTextureTestUtil.triDerivateY(
   2059                                triS[triNdx], triW[triNdx], wyo, dstH, nxo
   2060                            ),
   2061                            glsTextureTestUtil.triDerivateY(
   2062                                triT[triNdx], triW[triNdx], wyo, dstH, nxo
   2063                            ),
   2064                            glsTextureTestUtil.triDerivateY(
   2065                                triR[triNdx], triW[triNdx], wyo, dstH, nxo
   2066                            )
   2067                        ];
   2068                        var lodO =
   2069                            tcuTexLookupVerifier.
   2070                            computeCubeLodBoundsFromDerivates(
   2071                                coordO, coordDxo, coordDyo,
   2072                                src.getSize(), lodPrec
   2073                            );
   2074 
   2075                        lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
   2076                        lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
   2077                    }
   2078 
   2079                    var clampedLod = tcuTexLookupVerifier.clampLodBounds(
   2080                        deMath.addScalar(lodBounds, lodBias),
   2081                        [sampleParams.minLod, sampleParams.maxLod],
   2082                        lodPrec
   2083                    );
   2084 
   2085                    if (tcuTexLookupVerifier.
   2086                        isLookupResultValid_TextureCubeView(
   2087                            src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix
   2088                        )
   2089                    ) {
   2090                        isOk = true;
   2091                        break;
   2092                    }
   2093                }
   2094 
   2095                if (!isOk) {
   2096                    var red = [255, 0, 0, 255];
   2097                    errorMask.setPixel(new tcuRGBA.RGBA(red).toVec(), px, py);
   2098                    numFailed += 1;
   2099                }
   2100            }
   2101        }
   2102    }
   2103 
   2104    return numFailed;
   2105 };
   2106 
   2107 /**
   2108 * @param {tcuTexture.ConstPixelBufferAccess} result
   2109 * @param {tcuTexture.Texture2DArrayView} src
   2110 * @param {Array<number>} texCoord
   2111 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   2112 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   2113 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   2114 * @param {tcuPixelFormat.PixelFormat} pixelFormat
   2115 * @return {boolean}
   2116 */
   2117 glsTextureTestUtil.verifyTexture2DArrayResult = function(result, src, texCoord, sampleParams, lookupPrec, lodPrec, pixelFormat) {
   2118    DE_ASSERT(deMath.equal(glsTextureTestUtil.getCompareMask(pixelFormat), lookupPrec.colorMask));
   2119    /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(result.getWidth(), result.getHeight());
   2120    /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
   2121    /** @type {number} */ var numFailedPixels;
   2122 
   2123    /** @type {glsTextureTestUtil.SurfaceAccess} */ var surface = new glsTextureTestUtil.SurfaceAccess(reference, pixelFormat);
   2124 
   2125    glsTextureTestUtil.sampleTexture2DArray(surface, src, texCoord, sampleParams);
   2126    numFailedPixels = glsTextureTestUtil.computeTextureLookupDiff2DArray(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec/*, testCtx.getWatchDog()*/);
   2127 
   2128    if (numFailedPixels > 0)
   2129        tcuImageCompare.displayImages(result, reference.getAccess(), errorMask.getAccess());
   2130 
   2131    return numFailedPixels == 0;
   2132 };
   2133 
   2134 /**
   2135 * @param {tcuTexture.ConstPixelBufferAccess} result
   2136 * @param {tcuTexture.ConstPixelBufferAccess} reference
   2137 * @param {tcuTexture.PixelBufferAccess} errorMask
   2138 * @param {tcuTexture.Texture2DArrayView} src
   2139 * @param {Array<number>} texCoord
   2140 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   2141 * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
   2142 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   2143 * @param {Array<number>} nonShadowThreshold
   2144 * @return {number}
   2145 */
   2146 glsTextureTestUtil.computeTextureCompareDiff2DArray = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) {
   2147    DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
   2148    DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
   2149 
   2150    var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   2151    var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   2152    var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   2153 
   2154    var dstSize = [result.getWidth(), result.getHeight()];
   2155    var dstW = dstSize[0];
   2156    var dstH = dstSize[1];
   2157    var srcSize = [src.getWidth(), src.getHeight()];
   2158 
   2159    // Coordinates and lod per triangle.
   2160    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   2161    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   2162    var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   2163    var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
   2164 
   2165    var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0];
   2166    var numFailed = 0;
   2167 
   2168    var lodOffsets = [
   2169        [-1, 0],
   2170        [1, 0],
   2171        [0, -1],
   2172        [0, 1]
   2173    ];
   2174 
   2175    /** @type {Array<number>} */ var green = [0, 255, 0, 255];
   2176    errorMask.clear(green);
   2177 
   2178    /** @type {Array<number>} */ var red = [];
   2179    for (var py = 0; py < result.getHeight(); py++) {
   2180        for (var px = 0; px < result.getWidth(); px++) {
   2181            /** @type {Array<number>} */
   2182            var resPix = result.getPixel(px, py);
   2183            /** @type {Array<number>} */
   2184            var refPix = reference.getPixel(px, py);
   2185 
   2186            if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(refPix, [1, 2, 3]), deMath.swizzle(resPix, [1, 2, 3])), nonShadowThreshold))) {
   2187                red = [255, 0, 0, 255];
   2188                errorMask.setPixel(red, px, py);
   2189                numFailed += 1;
   2190                continue;
   2191            }
   2192 
   2193            if (resPix[0] != refPix[0]) {
   2194                var wx = px + 0.5;
   2195                var wy = py + 0.5;
   2196                var nx = wx / dstW;
   2197                var ny = wy / dstH;
   2198 
   2199                var triNdx = nx + ny >= 1.0 ? 1 : 0;
   2200                var triWx = triNdx ? dstW - wx : wx;
   2201                var triWy = triNdx ? dstH - wy : wy;
   2202                var triNx = triNdx ? 1.0 - nx : nx;
   2203                var triNy = triNdx ? 1.0 - ny : ny;
   2204 
   2205                var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
   2206                             glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
   2207                             glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)];
   2208                var coordDx = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
   2209                               glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
   2210                var coordDy = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
   2211                               glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
   2212 
   2213                var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
   2214 
   2215                // Compute lod bounds across lodOffsets range.
   2216                for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
   2217                    var wxo = triWx + lodOffsets[lodOffsNdx][0];
   2218                    var wyo = triWy + lodOffsets[lodOffsNdx][1];
   2219                    var nxo = wxo / dstW;
   2220                    var nyo = wyo / dstH;
   2221 
   2222                    var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
   2223                                  glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)];
   2224                    var coordDxo = deMath.multiply([glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
   2225                                                 glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize);
   2226                    var coordDyo = deMath.multiply([glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
   2227                                                 glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize);
   2228                    var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
   2229 
   2230                    lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
   2231                    lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
   2232                }
   2233 
   2234                var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
   2235                var isOk = tcuTexCompareVerifier.isTexCompareResultValid2DArray(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]);
   2236 
   2237                if (!isOk) {
   2238                    red = [255, 0, 0, 255];
   2239                    errorMask.setPixel(red, px, py);
   2240                    numFailed += 1;
   2241                }
   2242            }
   2243        }
   2244    }
   2245 
   2246    return numFailed;
   2247 };
   2248 
   2249 /**
   2250 * @param {tcuTexture.ConstPixelBufferAccess} result
   2251 * @param {tcuTexture.ConstPixelBufferAccess} reference
   2252 * @param {tcuTexture.PixelBufferAccess} errorMask
   2253 * @param {tcuTexture.TextureCubeView} src
   2254 * @param {Array<number>} texCoord
   2255 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   2256 * @param {tcuTexCompareVerifier.TexComparePrecision} comparePrec
   2257 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   2258 * @param {Array<number>} nonShadowThreshold
   2259 * @return {number}
   2260 */
   2261 glsTextureTestUtil.computeTextureCompareDiffCube = function(result, reference, errorMask, src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold) {
   2262    DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
   2263    DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
   2264 
   2265    var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   2266    var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   2267    var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   2268 
   2269    var dstSize = [result.getWidth(), result.getHeight()];
   2270    var dstW = dstSize[0];
   2271    var dstH = dstSize[1];
   2272    var srcSize = src.getSize();
   2273 
   2274    // Coordinates per triangle.
   2275    var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   2276    var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   2277    var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   2278    var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
   2279 
   2280    var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0, 0];
   2281    var numFailed = 0;
   2282 
   2283    var lodOffsets = [
   2284        [-1, 0],
   2285        [1, 0],
   2286        [0, -1],
   2287        [0, 1]
   2288    ];
   2289 
   2290    /** @type {Array<number>} */ var green = [0, 255, 0, 255];
   2291    errorMask.clear(new tcuRGBA.RGBA(green).toVec());
   2292 
   2293    /** @type {Array<number>} */ var red = [];
   2294    for (var py = 0; py < result.getHeight(); py++) {
   2295        for (var px = 0; px < result.getWidth(); px++) {
   2296            /** @type {Array<number>} */
   2297            var resPix = result.getPixel(px, py);
   2298            /** @type {Array<number>} */
   2299            var refPix = reference.getPixel(px, py);
   2300 
   2301            if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(deMath.swizzle(resPix, [1, 2, 3]), deMath.swizzle(refPix, [1, 2, 3])), nonShadowThreshold))) {
   2302                red = [255, 0, 0, 255];
   2303                errorMask.setPixel(red, px, py);
   2304                numFailed += 1;
   2305                continue;
   2306            }
   2307 
   2308            if (resPix[0] != refPix[0]) {
   2309                var wx = px + 0.5;
   2310                var wy = py + 0.5;
   2311                var nx = wx / dstW;
   2312                var ny = wy / dstH;
   2313 
   2314                var triNdx = nx + ny >= 1.0 ? 1 : 0;
   2315                var triWx = triNdx ? dstW - wx : wx;
   2316                var triWy = triNdx ? dstH - wy : wy;
   2317                var triNx = triNdx ? 1.0 - nx : nx;
   2318                var triNy = triNdx ? 1.0 - ny : ny;
   2319 
   2320                var coord = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
   2321                             glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
   2322                             glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)];
   2323                var coordDx = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
   2324                               glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
   2325                               glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)];
   2326                var coordDy = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
   2327                               glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
   2328                               glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)];
   2329 
   2330                var lodBounds = tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
   2331 
   2332                // Compute lod bounds across lodOffsets range.
   2333                for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
   2334                    var wxo = triWx + lodOffsets[lodOffsNdx][0];
   2335                    var wyo = triWy + lodOffsets[lodOffsNdx][1];
   2336                    var nxo = wxo / dstW;
   2337                    var nyo = wyo / dstH;
   2338 
   2339                    var coordO = [glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
   2340                                  glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
   2341                                  glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)];
   2342                    var coordDxo = [glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
   2343                                    glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
   2344                                    glsTextureTestUtil.triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)];
   2345                    var coordDyo = [glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
   2346                                    glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
   2347                                    glsTextureTestUtil.triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)];
   2348                    var lodO = tcuTexLookupVerifier.computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
   2349 
   2350                    lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
   2351                    lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
   2352                }
   2353 
   2354                var clampedLod = tcuTexLookupVerifier.clampLodBounds(deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
   2355                var isOk = tcuTexCompareVerifier.isTexCompareResultValidCube(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix[0]);
   2356 
   2357                if (!isOk) {
   2358                    red = [255, 0, 0, 255];
   2359                    errorMask.setPixel(red, px, py);
   2360                    numFailed += 1;
   2361                }
   2362            }
   2363        }
   2364    }
   2365 
   2366    return numFailed;
   2367 };
   2368 
   2369 /**
   2370 * @param {Array<number>} s
   2371 * @param {Array<number>} w
   2372 * @param {number} nx
   2373 * @param {number} ny
   2374 * @return {number}
   2375 */
   2376 glsTextureTestUtil.projectedTriInterpolate = function(s, w, nx, ny) {
   2377    return (s[0] * (1.0 - nx - ny) / w[0] + s[1] * ny / w[1] + s[2] * nx / w[2]) / ((1.0 - nx - ny) / w[0] + ny / w[1] + nx / w[2]);
   2378 };
   2379 
   2380 /**
   2381 * @param {tcuTexture.ConstPixelBufferAccess} result
   2382 * @param {tcuTexture.ConstPixelBufferAccess} reference
   2383 * @param {tcuTexture.PixelBufferAccess} errorMask
   2384 * @param {tcuTexture.Texture2DView} baseView
   2385 * @param {Array<number>} texCoord
   2386 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   2387 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   2388 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   2389 * @param {*=} watchDog - TODO: ??
   2390 * @return {number}
   2391 */
   2392 glsTextureTestUtil.computeTextureLookupDiff2D = function(result, reference, errorMask, baseView, texCoord, sampleParams, lookupPrec, lodPrec, watchDog) {
   2393    DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
   2394    DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
   2395 
   2396    /** @type {tcuTexture.Texture2DView} */ var src = baseView.getSubView(sampleParams.baseLevel, sampleParams.maxLevel);
   2397 
   2398    /** @type {Array<number>} */ var sq = [texCoord[0 + 0], texCoord[2 + 0], texCoord[4 + 0], texCoord[6 + 0]];
   2399    /** @type {Array<number>} */ var tq = [texCoord[0 + 1], texCoord[2 + 1], texCoord[4 + 1], texCoord[6 + 1]];
   2400 
   2401    /** @type {Array<number>} */ var dstSize = [result.getWidth(), result.getHeight()];
   2402    /** @type {number} */ var dstW = dstSize[0];
   2403    /** @type {number} */ var dstH = dstSize[1];
   2404    /** @type {Array<number>} */ var srcSize = [src.getWidth(), src.getHeight()];
   2405 
   2406    // Coordinates and lod per triangle.
   2407    /** @type {Array<Array<number>>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   2408    /** @type {Array<Array<number>>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   2409    /** @type {Array<Array<number>>} */ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
   2410 
   2411    /** @type {Array<number>} */ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0.0, 0.0];
   2412 
   2413    /** @type {number} */ var numFailed = 0;
   2414 
   2415    /** @type {Array<Array<number>>} */ var lodOffsets = [
   2416        [-1, 0],
   2417        [1, 0],
   2418        [0, -1],
   2419        [0, 1]
   2420    ];
   2421 
   2422    /** @type {Array<number>} */ var green = [0, 255, 0, 255];
   2423    errorMask.clear(new tcuRGBA.RGBA(green).toVec());
   2424 
   2425    for (var py = 0; py < result.getHeight(); py++) {
   2426        // Ugly hack, validation can take way too long at the moment.
   2427 
   2428        // TODO:are we implementing qpWatchDog? skipping in the meantime
   2429        // if (watchDog)
   2430        //     qpWatchDog_touch(watchDog);
   2431 
   2432        for (var px = 0; px < result.getWidth(); px++) {
   2433            /** @type {Array<number>} */
   2434            var resPix = result.getPixel(px, py);
   2435            glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
   2436            /** @type {Array<number>} */
   2437            var refPix = reference.getPixel(px, py);
   2438            glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
   2439 
   2440            // Try comparison to ideal reference first, and if that fails use slower verificator.
   2441            if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold))) {
   2442                /** @type {number} */ var wx = px + 0.5;
   2443                /** @type {number} */ var wy = py + 0.5;
   2444                /** @type {number} */ var nx = wx / dstW;
   2445                /** @type {number} */ var ny = wy / dstH;
   2446 
   2447                /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0;
   2448                /** @type {number} */ var triWx = triNdx ? dstW - wx : wx;
   2449                /** @type {number} */ var triWy = triNdx ? dstH - wy : wy;
   2450                /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx;
   2451                /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny;
   2452 
   2453                /** @type {Array<number>} */ var coord = [
   2454                    glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
   2455                    glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)
   2456                ];
   2457                /** @type {Array<number>} */ var coordDx = deMath.multiply([
   2458                    glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
   2459                    glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
   2460                /** @type {Array<number>} */ var coordDy = deMath.multiply([
   2461                    glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
   2462                    glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
   2463 
   2464                /** @type {Array<number>} */
   2465                var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
   2466 
   2467                // Compute lod bounds across lodOffsets range.
   2468                for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
   2469                    /** @type {number} */ var wxo = triWx + lodOffsets[lodOffsNdx][0];
   2470                    /** @type {number} */ var wyo = triWy + lodOffsets[lodOffsNdx][1];
   2471                    /** @type {number} */ var nxo = wxo / dstW;
   2472                    /** @type {number} */ var nyo = wyo / dstH;
   2473 
   2474                    /** @type {Array<number>} */ var coordO = [
   2475                        glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
   2476                        glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo)];
   2477                    /** @type {Array<number>} */ var coordDxo = deMath.multiply([
   2478                        glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
   2479                        glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize);
   2480                    /** @type {Array<number>} */ var coordDyo = deMath.multiply([
   2481                        glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
   2482                        glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize);
   2483                    /** @type {Array<number>} */
   2484                    var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
   2485 
   2486                    lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
   2487                    lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
   2488                }
   2489 
   2490                /** @type {Array<number>} */ var clampedLod = tcuTexLookupVerifier.clampLodBounds(
   2491                    deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
   2492                /** @type {boolean} */
   2493                var isOk = tcuTexLookupVerifier.isLookupResultValid_Texture2DView(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
   2494 
   2495                if (!isOk) {
   2496                    /** @type {tcuRGBA.RGBA} */ var red = tcuRGBA.newRGBAComponents(255, 0, 0, 255);
   2497                    errorMask.setPixel(red.toVec(), px, py);
   2498                    numFailed += 1;
   2499                }
   2500            }
   2501        }
   2502    }
   2503 
   2504    return numFailed;
   2505 };
   2506 
   2507 // Verifies texture lookup results and returns number of failed pixels.
   2508 
   2509 /**
   2510 * @param {tcuTexture.ConstPixelBufferAccess} result
   2511 * @param {tcuTexture.ConstPixelBufferAccess} reference
   2512 * @param {tcuTexture.PixelBufferAccess} errorMask
   2513 * @param {tcuTexture.Texture2DArrayView} src
   2514 * @param {Array<number>} texCoord
   2515 * @param {glsTextureTestUtil.ReferenceParams} sampleParams
   2516 * @param {tcuTexLookupVerifier.LookupPrecision} lookupPrec
   2517 * @param {tcuTexLookupVerifier.LodPrecision} lodPrec
   2518 * @param {*=} watchDog - TODO: ??
   2519 * @return {number}
   2520 */
   2521 glsTextureTestUtil.computeTextureLookupDiff2DArray = function(result, reference, errorMask, src, texCoord, sampleParams, lookupPrec, lodPrec, watchDog) {
   2522    DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
   2523    DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
   2524 
   2525    /** @type {Array<number>} */ var sq = [texCoord[0 + 0], texCoord[3 + 0], texCoord[6 + 0], texCoord[9 + 0]];
   2526    /** @type {Array<number>} */ var tq = [texCoord[0 + 1], texCoord[3 + 1], texCoord[6 + 1], texCoord[9 + 1]];
   2527    /** @type {Array<number>} */ var rq = [texCoord[0 + 2], texCoord[3 + 2], texCoord[6 + 2], texCoord[9 + 2]];
   2528 
   2529    /** @type {Array<number>} */ var dstSize = [result.getWidth(), result.getHeight()];
   2530    /** @type {number} */ var dstW = dstSize[0];
   2531    /** @type {number} */ var dstH = dstSize[1];
   2532    /** @type {Array<number>} */ var srcSize = [src.getWidth(), src.getHeight()];
   2533 
   2534    // Coordinates and lod per triangle.
   2535    /** @type {Array<Array<number>>} */ var triS = [deMath.swizzle(sq, [0, 1, 2]), deMath.swizzle(sq, [3, 2, 1])];
   2536    /** @type {Array<Array<number>>} */ var triT = [deMath.swizzle(tq, [0, 1, 2]), deMath.swizzle(tq, [3, 2, 1])];
   2537    /** @type {Array<Array<number>>} */ var triR = [deMath.swizzle(rq, [0, 1, 2]), deMath.swizzle(rq, [3, 2, 1])];
   2538    /** @type {Array<Array<number>>} */ var triW = [deMath.swizzle(sampleParams.w, [0, 1, 2]), deMath.swizzle(sampleParams.w, [3, 2, 1])];
   2539 
   2540    /** @type {Array<number>} */ var lodBias = sampleParams.flags.use_bias ? [sampleParams.bias, sampleParams.bias] : [0.0, 0.0];
   2541 
   2542    /** @type {number} */ var numFailed = 0;
   2543 
   2544    /** @type {Array<Array<number>>} */ var lodOffsets = [
   2545        [-1, 0],
   2546        [1, 0],
   2547        [0, -1],
   2548        [0, 1]
   2549    ];
   2550 
   2551    /** @type {Array<number>} */ var green = [0, 255, 0, 255];
   2552    errorMask.clear(new tcuRGBA.RGBA(green).toVec());
   2553 
   2554    for (var py = 0; py < result.getHeight(); py++) {
   2555        // Ugly hack, validation can take way too long at the moment.
   2556 
   2557        // TODO:are we implementing qpWatchDog? skipping in the meantime
   2558        // if (watchDog)
   2559        //     qpWatchDog_touch(watchDog);
   2560 
   2561        for (var px = 0; px < result.getWidth(); px++) {
   2562            /** @type {Array<number>} */
   2563            var resPix = result.getPixel(px, py);
   2564            glsTextureTestUtil.deapplyScaleAndBias(resPix, sampleParams.colorScale, sampleParams.colorBias);
   2565            /** @type {Array<number>} */
   2566            var refPix = reference.getPixel(px, py);
   2567            glsTextureTestUtil.deapplyScaleAndBias(refPix, sampleParams.colorScale, sampleParams.colorBias);
   2568 
   2569 
   2570            // Try comparison to ideal reference first, and if that fails use slower verificator.
   2571            if (!deMath.boolAll(deMath.lessThanEqual(deMath.absDiff(resPix, refPix), lookupPrec.colorThreshold))) {
   2572                /** @type {number} */ var wx = px + 0.5;
   2573                /** @type {number} */ var wy = py + 0.5;
   2574                /** @type {number} */ var nx = wx / dstW;
   2575                /** @type {number} */ var ny = wy / dstH;
   2576 
   2577                /** @type {number} */ var triNdx = nx + ny >= 1.0 ? 1 : 0;
   2578                /** @type {number} */ var triWx = triNdx ? dstW - wx : wx;
   2579                /** @type {number} */ var triWy = triNdx ? dstH - wy : wy;
   2580                /** @type {number} */ var triNx = triNdx ? 1.0 - nx : nx;
   2581                /** @type {number} */ var triNy = triNdx ? 1.0 - ny : ny;
   2582 
   2583                /** @type {Array<number>} */ var coord = [
   2584                    glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
   2585                    glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
   2586                    glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)
   2587                ];
   2588                /** @type {Array<number>} */ var coordDx = deMath.multiply([
   2589                    glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
   2590                    glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)], srcSize);
   2591                /** @type {Array<number>} */ var coordDy = deMath.multiply([
   2592                    glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
   2593                    glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)], srcSize);
   2594 
   2595                /** @type {Array<number>} */
   2596                var lodBounds = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDx[0], coordDx[1], coordDy[0], coordDy[1], lodPrec);
   2597 
   2598                // Compute lod bounds across lodOffsets range.
   2599                for (var lodOffsNdx = 0; lodOffsNdx < lodOffsets.length; lodOffsNdx++) {
   2600                    /** @type {number} */ var wxo = triWx + lodOffsets[lodOffsNdx][0];
   2601                    /** @type {number} */ var wyo = triWy + lodOffsets[lodOffsNdx][1];
   2602                    /** @type {number} */ var nxo = wxo / dstW;
   2603                    /** @type {number} */ var nyo = wyo / dstH;
   2604 
   2605                    /** @type {Array<number>} */ var coordO = [
   2606                        glsTextureTestUtil.projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
   2607                        glsTextureTestUtil.projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
   2608                        glsTextureTestUtil.projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)
   2609                    ];
   2610                    /** @type {Array<number>} */ var coordDxo = deMath.multiply([
   2611                        glsTextureTestUtil.triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
   2612                        glsTextureTestUtil.triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)], srcSize
   2613                    );
   2614                    /** @type {Array<number>} */ var coordDyo = deMath.multiply([
   2615                        glsTextureTestUtil.triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
   2616                        glsTextureTestUtil.triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)], srcSize
   2617                    );
   2618                    /** @type {Array<number>} */
   2619                    var lodO = tcuTexLookupVerifier.computeLodBoundsFromDerivatesUV(coordDxo[0], coordDxo[1], coordDyo[0], coordDyo[1], lodPrec);
   2620 
   2621                    lodBounds[0] = Math.min(lodBounds[0], lodO[0]);
   2622                    lodBounds[1] = Math.max(lodBounds[1], lodO[1]);
   2623                }
   2624 
   2625                /** @type {Array<number>} */ var clampedLod = tcuTexLookupVerifier.clampLodBounds(
   2626                    deMath.add(lodBounds, lodBias), [sampleParams.minLod, sampleParams.maxLod], lodPrec);
   2627                /** @type {boolean} */
   2628                var isOk = tcuTexLookupVerifier.isLookupResultValid_Texture2DArrayView(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
   2629 
   2630                if (!isOk) {
   2631                    /** @type {tcuRGBA.RGBA} */ var red = tcuRGBA.newRGBAComponents(255, 0, 0, 255);
   2632                    errorMask.setPixel(red.toVec(), px, py);
   2633                    numFailed += 1;
   2634                }
   2635            }
   2636        }
   2637    }
   2638 
   2639    return numFailed;
   2640 };
   2641 
   2642 });