tor-browser

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

es3fUniformApiTests.js (165934B)


      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('functional.gles3.es3fUniformApiTests');
     23 goog.require('framework.common.tcuSurface');
     24 goog.require('framework.common.tcuTestCase');
     25 goog.require('framework.common.tcuTexture');
     26 goog.require('framework.delibs.debase.deMath');
     27 goog.require('framework.delibs.debase.deRandom');
     28 goog.require('framework.delibs.debase.deString');
     29 goog.require('framework.opengl.gluDrawUtil');
     30 goog.require('framework.opengl.gluShaderProgram');
     31 goog.require('framework.opengl.gluShaderUtil');
     32 goog.require('framework.opengl.gluTexture');
     33 goog.require('framework.opengl.gluVarType');
     34 
     35 goog.scope(function() {
     36 
     37    var es3fUniformApiTests = functional.gles3.es3fUniformApiTests;
     38    var gluDrawUtil = framework.opengl.gluDrawUtil;
     39    var gluShaderUtil = framework.opengl.gluShaderUtil;
     40    var gluShaderProgram = framework.opengl.gluShaderProgram;
     41    var gluTexture = framework.opengl.gluTexture;
     42    var gluVarType = framework.opengl.gluVarType;
     43    var tcuTestCase = framework.common.tcuTestCase;
     44    var tcuSurface = framework.common.tcuSurface;
     45    var tcuTexture = framework.common.tcuTexture;
     46    var deMath = framework.delibs.debase.deMath;
     47    var deString = framework.delibs.debase.deString;
     48    var deRandom = framework.delibs.debase.deRandom;
     49 
     50    /** @type {WebGL2RenderingContext} */ var gl;
     51 
     52    /** @typedef {function(gluShaderUtil.DataType): boolean} */
     53    es3fUniformApiTests.dataTypePredicate;
     54 
     55    /** @type {number} */ es3fUniformApiTests.MAX_RENDER_WIDTH = 32;
     56    /** @type {number} */ es3fUniformApiTests.MAX_RENDER_HEIGHT = 32;
     57    /** @type {number} */ es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS = 16;
     58 
     59    /** @type {Array<gluShaderUtil.DataType>} */ es3fUniformApiTests.s_testDataTypes = [
     60    gluShaderUtil.DataType.FLOAT,
     61    gluShaderUtil.DataType.FLOAT_VEC2,
     62    gluShaderUtil.DataType.FLOAT_VEC3,
     63    gluShaderUtil.DataType.FLOAT_VEC4,
     64    gluShaderUtil.DataType.FLOAT_MAT2,
     65    gluShaderUtil.DataType.FLOAT_MAT2X3,
     66    gluShaderUtil.DataType.FLOAT_MAT2X4,
     67    gluShaderUtil.DataType.FLOAT_MAT3X2,
     68    gluShaderUtil.DataType.FLOAT_MAT3,
     69    gluShaderUtil.DataType.FLOAT_MAT3X4,
     70    gluShaderUtil.DataType.FLOAT_MAT4X2,
     71    gluShaderUtil.DataType.FLOAT_MAT4X3,
     72    gluShaderUtil.DataType.FLOAT_MAT4,
     73 
     74    gluShaderUtil.DataType.INT,
     75    gluShaderUtil.DataType.INT_VEC2,
     76    gluShaderUtil.DataType.INT_VEC3,
     77    gluShaderUtil.DataType.INT_VEC4,
     78 
     79    gluShaderUtil.DataType.UINT,
     80    gluShaderUtil.DataType.UINT_VEC2,
     81    gluShaderUtil.DataType.UINT_VEC3,
     82    gluShaderUtil.DataType.UINT_VEC4,
     83 
     84    gluShaderUtil.DataType.BOOL,
     85    gluShaderUtil.DataType.BOOL_VEC2,
     86    gluShaderUtil.DataType.BOOL_VEC3,
     87    gluShaderUtil.DataType.BOOL_VEC4,
     88 
     89    gluShaderUtil.DataType.SAMPLER_2D,
     90    gluShaderUtil.DataType.SAMPLER_CUBE
     91        // \note We don't test all sampler types here.
     92    ];
     93 
     94    /**
     95     * Returns a substring from the beginning to the last occurence of the
     96     * specified character
     97     * @param {string} str The string in which to search
     98     * @param {string} c A single character
     99     * @return {string}
    100     */
    101    es3fUniformApiTests.beforeLast = function(str, c) {
    102        return str.substring(0, str.lastIndexOf(c));
    103    };
    104 
    105    /**
    106     * es3fUniformApiTests.fillWithColor
    107     * @param {tcuTexture.PixelBufferAccess} access ,
    108     * @param {Array<number>} color Array of four color components.
    109     */
    110    es3fUniformApiTests.fillWithColor = function(access, color) {
    111        for (var z = 0; z < access.getDepth(); z++)
    112        for (var y = 0; y < access.getHeight(); y++)
    113        for (var x = 0; x < access.getWidth(); x++)
    114            access.setPixel(color, x, y, z);
    115    };
    116 
    117    /**
    118     * @param {gluShaderUtil.DataType} type
    119     * @return {number}
    120     */
    121    es3fUniformApiTests.getSamplerNumLookupDimensions = function(type) {
    122        switch (type) {
    123            case gluShaderUtil.DataType.SAMPLER_2D:
    124            case gluShaderUtil.DataType.INT_SAMPLER_2D:
    125            case gluShaderUtil.DataType.UINT_SAMPLER_2D:
    126                return 2;
    127 
    128            case gluShaderUtil.DataType.SAMPLER_3D:
    129            case gluShaderUtil.DataType.INT_SAMPLER_3D:
    130            case gluShaderUtil.DataType.UINT_SAMPLER_3D:
    131            case gluShaderUtil.DataType.SAMPLER_2D_SHADOW:
    132            case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
    133            case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY:
    134            case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
    135            case gluShaderUtil.DataType.SAMPLER_CUBE:
    136            case gluShaderUtil.DataType.INT_SAMPLER_CUBE:
    137            case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
    138                return 3;
    139 
    140            case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW:
    141            case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW:
    142                return 4;
    143 
    144            default:
    145                throw new Error('es3fUniformApiTests.getSamplerNumLookupDimensions - Invalid type');
    146        }
    147    };
    148 
    149   /**
    150    * @param {gluShaderUtil.DataType} type
    151    * @return {gluShaderUtil.DataType}
    152    */
    153    es3fUniformApiTests.getSamplerLookupReturnType = function(type) {
    154        switch (type) {
    155            case gluShaderUtil.DataType.SAMPLER_2D:
    156            case gluShaderUtil.DataType.SAMPLER_CUBE:
    157            case gluShaderUtil.DataType.SAMPLER_2D_ARRAY:
    158            case gluShaderUtil.DataType.SAMPLER_3D:
    159                return gluShaderUtil.DataType.FLOAT_VEC4;
    160 
    161            case gluShaderUtil.DataType.UINT_SAMPLER_2D:
    162            case gluShaderUtil.DataType.UINT_SAMPLER_CUBE:
    163            case gluShaderUtil.DataType.UINT_SAMPLER_2D_ARRAY:
    164            case gluShaderUtil.DataType.UINT_SAMPLER_3D:
    165                return gluShaderUtil.DataType.UINT_VEC4;
    166 
    167            case gluShaderUtil.DataType.INT_SAMPLER_2D:
    168            case gluShaderUtil.DataType.INT_SAMPLER_CUBE:
    169            case gluShaderUtil.DataType.INT_SAMPLER_2D_ARRAY:
    170            case gluShaderUtil.DataType.INT_SAMPLER_3D:
    171                return gluShaderUtil.DataType.INT_VEC4;
    172 
    173            case gluShaderUtil.DataType.SAMPLER_2D_SHADOW:
    174            case gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW:
    175            case gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW:
    176                return gluShaderUtil.DataType.FLOAT;
    177 
    178            default:
    179                throw new Error('es3fUniformApiTests.getSamplerLookupReturnType - Invalid type');
    180        }
    181    };
    182 
    183    /**
    184     * @param {gluShaderUtil.DataType} T DataType to compare the type. Used to be a template param
    185     * @param {gluShaderUtil.DataType} t
    186     * @return {boolean}
    187     */
    188    es3fUniformApiTests.dataTypeEquals = function(T, t) {
    189        return t == T;
    190    };
    191 
    192    /**
    193     * @param {number} N Row number. Used to be a template parameter
    194     * @param {gluShaderUtil.DataType} t
    195     * @return {boolean}
    196     */
    197    es3fUniformApiTests.dataTypeIsMatrixWithNRows = function(N, t) {
    198        return gluShaderUtil.isDataTypeMatrix(t) && gluShaderUtil.getDataTypeMatrixNumRows(t) == N;
    199    };
    200 
    201   /**
    202    * @param {gluVarType.VarType} type
    203    * @param {es3fUniformApiTests.dataTypePredicate} predicate
    204    * @return {boolean}
    205    */
    206    es3fUniformApiTests.typeContainsMatchingBasicType = function(type, predicate) {
    207        if (type.isBasicType())
    208            return predicate(type.getBasicType());
    209        else if (type.isArrayType())
    210            return es3fUniformApiTests.typeContainsMatchingBasicType(type.getElementType(), predicate);
    211        else {
    212            assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.typeContainsMatchingBasicType - not a struct type', false, true);
    213            /** @type {gluVarType.StructType} */ var structType = type.getStruct();
    214            for (var i = 0; i < structType.getSize(); i++)
    215                if (es3fUniformApiTests.typeContainsMatchingBasicType(structType.getMember(i).getType(), predicate))
    216                    return true;
    217            return false;
    218        }
    219    };
    220 
    221    /**
    222     * @param {Array<gluShaderUtil.DataType>} dst
    223     * @param {gluVarType.VarType} type
    224     */
    225    es3fUniformApiTests.getDistinctSamplerTypes = function(dst, type) {
    226        if (type.isBasicType()) {
    227            /** @type {gluShaderUtil.DataType} */ var basicType = type.getBasicType();
    228            if (gluShaderUtil.isDataTypeSampler(basicType) && dst.indexOf(basicType) == -1)
    229                dst.push(basicType);
    230        } else if (type.isArrayType())
    231            es3fUniformApiTests.getDistinctSamplerTypes(dst, type.getElementType());
    232        else {
    233            assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.getDistinctSamplerTypes - not a struct type', false, true);
    234            /** @type {gluVarType.StructType} */ var structType = type.getStruct();
    235            for (var i = 0; i < structType.getSize(); i++)
    236                es3fUniformApiTests.getDistinctSamplerTypes(dst, structType.getMember(i).getType());
    237        }
    238    };
    239 
    240    /**
    241     * @param {gluVarType.VarType} type
    242     * @return {number}
    243     */
    244    es3fUniformApiTests.getNumSamplersInType = function(type) {
    245        if (type.isBasicType())
    246            return gluShaderUtil.isDataTypeSampler(type.getBasicType()) ? 1 : 0;
    247        else if (type.isArrayType())
    248            return es3fUniformApiTests.getNumSamplersInType(type.getElementType()) * type.getArraySize();
    249        else {
    250            assertMsgOptions(type.isStructType(), 'es3fUniformApiTests.getNumSamplersInType - not a struct type', false, true);
    251            /** @type {gluVarType.StructType} */ var structType = type.getStruct();
    252            /** @type {number} */ var sum = 0;
    253            for (var i = 0; i < structType.getSize(); i++)
    254                sum += es3fUniformApiTests.getNumSamplersInType(structType.getMember(i).getType());
    255            return sum;
    256        }
    257    };
    258 
    259    /** @typedef { {type: gluVarType.VarType, ndx: number}} */
    260    es3fUniformApiTests.VarTypeWithIndex;
    261 
    262    /**
    263     * @param {number} maxDepth
    264     * @param {number} curStructIdx Out parameter, instead returning it in the VarTypeWithIndex structure.
    265     * @param {Array<gluVarType.StructType>} structTypesDst
    266     * @param {deRandom.Random} rnd
    267     * @return {es3fUniformApiTests.VarTypeWithIndex}
    268     */
    269    es3fUniformApiTests.generateRandomType = function(maxDepth, curStructIdx, structTypesDst, rnd) {
    270        /** @type {boolean} */ var isStruct = maxDepth > 0 && rnd.getFloat() < 0.2;
    271        /** @type {boolean} */ var isArray = rnd.getFloat() < 0.3;
    272 
    273        if (isStruct) {
    274            /** @type {number} */ var numMembers = rnd.getInt(1, 5);
    275            /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + curStructIdx++);
    276 
    277            for (var i = 0; i < numMembers; i++) {
    278                /** @type {es3fUniformApiTests.VarTypeWithIndex} */ var typeWithIndex = es3fUniformApiTests.generateRandomType(maxDepth - 1, curStructIdx, structTypesDst, rnd);
    279                curStructIdx = typeWithIndex.ndx;
    280                structType.addMember('m' + i, typeWithIndex.type);
    281            }
    282 
    283            structTypesDst.push(structType);
    284            return (isArray ? {
    285                type: gluVarType.newTypeArray(gluVarType.newTypeStruct(structType), rnd.getInt(1, 5)),
    286                ndx: curStructIdx
    287            }
    288            : {
    289                type: gluVarType.newTypeStruct(structType),
    290                ndx: curStructIdx
    291            });
    292        } else {
    293            /** @type {gluShaderUtil.DataType} */ var basicType = es3fUniformApiTests.s_testDataTypes[rnd.getInt(0, es3fUniformApiTests.s_testDataTypes.length - 1)];
    294            /** @type {gluShaderUtil.precision} */ var precision;
    295            if (!gluShaderUtil.isDataTypeBoolOrBVec(basicType))
    296                precision = gluShaderUtil.precision.PRECISION_MEDIUMP;
    297            return (isArray ? {
    298                type: gluVarType.newTypeArray(gluVarType.newTypeBasic(basicType, precision), rnd.getInt(1, 5)),
    299                ndx: curStructIdx
    300            }
    301            : {
    302                type: gluVarType.newTypeBasic(basicType, precision),
    303                ndx: curStructIdx
    304            });
    305        }
    306    };
    307 
    308    /**
    309     * es3fUniformApiTests.SamplerV structure
    310     * @constructor
    311     */
    312    es3fUniformApiTests.SamplerV = function() {
    313        this.samplerV = {
    314            /** @type {number} */ unit: 0,
    315            /** @type {Array<number>} */ fillColor: []
    316        };
    317    };
    318 
    319    /**
    320     * es3fUniformApiTests.VarValue class. may contain different types.
    321     * @constructor
    322     */
    323    es3fUniformApiTests.VarValue = function() {
    324        /** @type {gluShaderUtil.DataType} */ this.type;
    325        /** @type {Array<number | boolean> | es3fUniformApiTests.SamplerV} */ this.val = [];
    326    };
    327 
    328    /**
    329     * @enum {number}
    330     */
    331    es3fUniformApiTests.CaseShaderType = {
    332        VERTEX: 0,
    333        FRAGMENT: 1,
    334        BOTH: 2
    335    };
    336 
    337    /**
    338     * es3fUniformApiTests.Uniform struct.
    339     * @param {string} name_
    340     * @param {gluVarType.VarType} type_
    341     * @constructor
    342     */
    343    es3fUniformApiTests.Uniform = function(name_, type_) {
    344        /** @type {string} */ this.name = name_;
    345        /** @type {gluVarType.VarType} */ this.type = type_;
    346    };
    347 
    348    // A set of uniforms, along with related struct types.
    349    /**
    350     * class es3fUniformApiTests.UniformCollection
    351     * @constructor
    352     */
    353    es3fUniformApiTests.UniformCollection = function() {
    354        /** @type {Array<es3fUniformApiTests.Uniform>} */ this.m_uniforms = [];
    355        /** @type {Array<gluVarType.StructType>} */ this.m_structTypes = [];
    356    };
    357 
    358    /**
    359     * @return {number}
    360     */
    361    es3fUniformApiTests.UniformCollection.prototype.getNumUniforms = function() {return this.m_uniforms.length;};
    362 
    363    /**
    364     * @return {number}
    365     */
    366    es3fUniformApiTests.UniformCollection.prototype.getNumStructTypes = function() {return this.m_structTypes.length;};
    367 
    368    /**
    369     * @param {number} ndx
    370     * @return {es3fUniformApiTests.Uniform}
    371     */
    372    es3fUniformApiTests.UniformCollection.prototype.getUniform = function(ndx) {return this.m_uniforms[ndx];};
    373 
    374    /**
    375     * @param {number} ndx
    376     * @return {gluVarType.StructType}
    377     */
    378    es3fUniformApiTests.UniformCollection.prototype.getStructType = function(ndx) {return this.m_structTypes[ndx];};
    379 
    380    /**
    381     * @param {es3fUniformApiTests.Uniform} uniform
    382     */
    383    es3fUniformApiTests.UniformCollection.prototype.addUniform = function(uniform) {this.m_uniforms.push(uniform);};
    384 
    385    /**
    386     * @param {gluVarType.StructType} type
    387     */
    388    es3fUniformApiTests.UniformCollection.prototype.addStructType = function(type) {this.m_structTypes.push(type);};
    389 
    390    // Add the contents of m_uniforms and m_structTypes to receiver, and remove them from this one.
    391    // \note receiver takes ownership of the struct types.
    392    /**
    393     * @param {es3fUniformApiTests.UniformCollection} receiver
    394     */
    395    es3fUniformApiTests.UniformCollection.prototype.moveContents = function(receiver) {
    396        for (var i = 0; i < this.m_uniforms.length; i++)
    397            receiver.addUniform(this.m_uniforms[i]);
    398        this.m_uniforms.length = 0;
    399 
    400        for (var i = 0; i < this.m_structTypes.length; i++)
    401            receiver.addStructType(this.m_structTypes[i]);
    402        this.m_structTypes.length = 0;
    403    };
    404 
    405    /**
    406     * @param {es3fUniformApiTests.dataTypePredicate} predicate
    407     * @return {boolean}
    408     */
    409    es3fUniformApiTests.UniformCollection.prototype.containsMatchingBasicType = function(predicate) {
    410        for (var i = 0; i < this.m_uniforms.length; i++)
    411            if (es3fUniformApiTests.typeContainsMatchingBasicType(this.m_uniforms[i].type, predicate))
    412                return true;
    413        return false;
    414    };
    415 
    416    /**
    417     * @return {Array<gluShaderUtil.DataType>}
    418     */
    419    es3fUniformApiTests.UniformCollection.prototype.getSamplerTypes = function() {
    420        /** @type {Array<gluShaderUtil.DataType>} */ var samplerTypes = [];
    421        for (var i = 0; i < this.m_uniforms.length; i++)
    422            es3fUniformApiTests.getDistinctSamplerTypes(samplerTypes, this.m_uniforms[i].type);
    423        return samplerTypes;
    424    };
    425 
    426    /**
    427     * @return {boolean}
    428     */
    429    es3fUniformApiTests.UniformCollection.prototype.containsSeveralSamplerTypes = function() {
    430        return this.getSamplerTypes().length > 1;
    431    };
    432 
    433    /**
    434     * @return {number}
    435     */
    436    es3fUniformApiTests.UniformCollection.prototype.getNumSamplers = function() {
    437        var sum = 0;
    438        for (var i = 0; i < this.m_uniforms.length; i++)
    439            sum += es3fUniformApiTests.getNumSamplersInType(this.m_uniforms[i].type);
    440        return sum;
    441    };
    442 
    443    /**
    444     * @param {gluShaderUtil.DataType} type
    445     * @param {string=} nameSuffix
    446     * @return {es3fUniformApiTests.UniformCollection}
    447     */
    448    es3fUniformApiTests.UniformCollection.basic = function(type, nameSuffix) {
    449        if (nameSuffix === undefined) nameSuffix = '';
    450        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    451        /** @type {gluShaderUtil.precision} */ var prec;
    452        if (!gluShaderUtil.isDataTypeBoolOrBVec(type))
    453            prec = gluShaderUtil.precision.PRECISION_MEDIUMP;
    454        res.m_uniforms.push(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeBasic(type, prec)));
    455        return res;
    456    };
    457 
    458    /**
    459     * @param {gluShaderUtil.DataType} type
    460     * @param {string=} nameSuffix
    461     * @return {es3fUniformApiTests.UniformCollection}
    462     */
    463    es3fUniformApiTests.UniformCollection.basicArray = function(type, nameSuffix) {
    464        if (nameSuffix === undefined) nameSuffix = '';
    465        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    466        /** @type {gluShaderUtil.precision} */ var prec;
    467        if (!gluShaderUtil.isDataTypeBoolOrBVec(type))
    468            prec = gluShaderUtil.precision.PRECISION_MEDIUMP;
    469        res.m_uniforms.push(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeArray(gluVarType.newTypeBasic(type, prec), 3)));
    470        return res;
    471    };
    472 
    473    /**
    474     * @param {gluShaderUtil.DataType} type0
    475     * @param {gluShaderUtil.DataType} type1
    476     * @param {boolean} containsArrays
    477     * @param {string=} nameSuffix
    478     * @return {es3fUniformApiTests.UniformCollection}
    479     */
    480    es3fUniformApiTests.UniformCollection.basicStruct = function(type0, type1, containsArrays, nameSuffix) {
    481        if (nameSuffix === undefined) nameSuffix = '';
    482        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    483        /** @type {gluShaderUtil.precision} */ var prec0;
    484        if (!gluShaderUtil.isDataTypeBoolOrBVec(type0))
    485            prec0 = gluShaderUtil.precision.PRECISION_MEDIUMP;
    486        /** @type {gluShaderUtil.precision} */ var prec1;
    487        if (!gluShaderUtil.isDataTypeBoolOrBVec(type1))
    488            prec1 = gluShaderUtil.precision.PRECISION_MEDIUMP;
    489 
    490        /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + nameSuffix);
    491        structType.addMember('m0', gluVarType.newTypeBasic(type0, prec0));
    492        structType.addMember('m1', gluVarType.newTypeBasic(type1, prec1));
    493        if (containsArrays) {
    494            structType.addMember('m2', gluVarType.newTypeArray(gluVarType.newTypeBasic(type0, prec0), 3));
    495            structType.addMember('m3', gluVarType.newTypeArray(gluVarType.newTypeBasic(type1, prec1), 3));
    496        }
    497 
    498        res.addStructType(structType);
    499        res.addUniform(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeStruct(structType)));
    500 
    501        return res;
    502    };
    503 
    504    /**
    505     * @param {gluShaderUtil.DataType} type0
    506     * @param {gluShaderUtil.DataType} type1
    507     * @param {boolean} containsArrays
    508     * @param {string=} nameSuffix
    509     * @return {es3fUniformApiTests.UniformCollection}
    510     */
    511    es3fUniformApiTests.UniformCollection.structInArray = function(type0, type1, containsArrays, nameSuffix) {
    512        if (nameSuffix === undefined) nameSuffix = '';
    513        /** @type {es3fUniformApiTests.UniformCollection} */ var res = es3fUniformApiTests.UniformCollection.basicStruct(type0, type1, containsArrays, nameSuffix);
    514        res.getUniform(0).type = gluVarType.newTypeArray(res.getUniform(0).type, 3);
    515        return res;
    516    };
    517 
    518    /**
    519     * @param {gluShaderUtil.DataType} type0
    520     * @param {gluShaderUtil.DataType} type1
    521     * @param {string=} nameSuffix
    522     * @return {es3fUniformApiTests.UniformCollection}
    523     */
    524    es3fUniformApiTests.UniformCollection.nestedArraysStructs = function(type0, type1, nameSuffix) {
    525        if (nameSuffix === undefined) nameSuffix = '';
    526        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    527        /** @type {gluShaderUtil.precision} */ var prec0;
    528        if (!gluShaderUtil.isDataTypeBoolOrBVec(type0))
    529            prec0 = gluShaderUtil.precision.PRECISION_MEDIUMP;
    530        /** @type {gluShaderUtil.precision} */ var prec1;
    531        if (!gluShaderUtil.isDataTypeBoolOrBVec(type1))
    532            prec1 = gluShaderUtil.precision.PRECISION_MEDIUMP;
    533        /** @type {gluVarType.StructType} */ var structType = gluVarType.newStructType('structType' + nameSuffix);
    534        /** @type {gluVarType.StructType} */ var subStructType = gluVarType.newStructType('subStructType' + nameSuffix);
    535        /** @type {gluVarType.StructType} */ var subSubStructType = gluVarType.newStructType('subSubStructType' + nameSuffix);
    536 
    537        subSubStructType.addMember('mss0', gluVarType.newTypeBasic(type0, prec0));
    538        subSubStructType.addMember('mss1', gluVarType.newTypeBasic(type1, prec1));
    539 
    540        subStructType.addMember('ms0', gluVarType.newTypeBasic(type1, prec1));
    541        subStructType.addMember('ms1', gluVarType.newTypeArray(gluVarType.newTypeBasic(type0, prec0), 2));
    542        subStructType.addMember('ms2', gluVarType.newTypeArray(gluVarType.newTypeStruct(subSubStructType), 2));
    543 
    544        structType.addMember('m0', gluVarType.newTypeBasic(type0, prec0));
    545        structType.addMember('m1', gluVarType.newTypeStruct(subStructType));
    546        structType.addMember('m2', gluVarType.newTypeBasic(type1, prec1));
    547 
    548        res.addStructType(subSubStructType);
    549        res.addStructType(subStructType);
    550        res.addStructType(structType);
    551 
    552        res.addUniform(new es3fUniformApiTests.Uniform('u_var' + nameSuffix, gluVarType.newTypeStruct(structType)));
    553 
    554        return res;
    555    };
    556 
    557    /**
    558     * @param {string=} nameSuffix
    559     * @return {es3fUniformApiTests.UniformCollection}
    560     */
    561    es3fUniformApiTests.UniformCollection.multipleBasic = function(nameSuffix) {
    562        if (nameSuffix === undefined) nameSuffix = '';
    563        /** @type {Array<gluShaderUtil.DataType>} */ var types = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT_VEC3, gluShaderUtil.DataType.UINT_VEC4, gluShaderUtil.DataType.FLOAT_MAT3, gluShaderUtil.DataType.BOOL_VEC2];
    564        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    565 
    566        for (var i = 0; i < types.length; i++) {
    567            /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.basic(types[i], '_' + i + nameSuffix);
    568            sub.moveContents(res);
    569        }
    570 
    571        return res;
    572    };
    573 
    574    /**
    575     * @param {string=} nameSuffix
    576     * @return {es3fUniformApiTests.UniformCollection}
    577     */
    578    es3fUniformApiTests.UniformCollection.multipleBasicArray = function(nameSuffix) {
    579        if (nameSuffix === undefined) nameSuffix = '';
    580        /** @type {Array<gluShaderUtil.DataType>} */ var types = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT_VEC3, gluShaderUtil.DataType.BOOL_VEC2];
    581        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    582 
    583        for (var i = 0; i < types.length; i++) {
    584            /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.basicArray(types[i], '_' + i + nameSuffix);
    585            sub.moveContents(res);
    586        }
    587 
    588        return res;
    589    };
    590 
    591    /**
    592     * @param {string=} nameSuffix
    593     * @return {es3fUniformApiTests.UniformCollection}
    594     */
    595    es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs = function(nameSuffix) {
    596        if (nameSuffix === undefined) nameSuffix = '';
    597        /** @type {Array<gluShaderUtil.DataType>} */ var types0 = [gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.INT, gluShaderUtil.DataType.BOOL_VEC4];
    598        /** @type {Array<gluShaderUtil.DataType>} */ var types1 = [gluShaderUtil.DataType.FLOAT_VEC4, gluShaderUtil.DataType.INT_VEC4, gluShaderUtil.DataType.BOOL];
    599        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    600 
    601        assertMsgOptions(types0.length == types1.length, 'es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs - lengths are not the same', false, true);
    602 
    603        for (var i = 0; i < types0.length; i++) {
    604            /** @type {es3fUniformApiTests.UniformCollection} */ var sub = es3fUniformApiTests.UniformCollection.nestedArraysStructs(types0[i], types1[i], '_' + i + nameSuffix);
    605            sub.moveContents(res);
    606        }
    607 
    608        return res;
    609    };
    610 
    611    /**
    612     * @param {number} seed
    613     * @return {es3fUniformApiTests.UniformCollection}
    614     */
    615    es3fUniformApiTests.UniformCollection.random = function(seed) {
    616        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed);
    617        /** @type {number} */ var numUniforms = rnd.getInt(1, 5);
    618        /** @type {number} */ var structIdx = 0;
    619        /** @type {es3fUniformApiTests.UniformCollection} */ var res = new es3fUniformApiTests.UniformCollection();
    620 
    621        for (var i = 0; i < numUniforms; i++) {
    622            /** @type {Array<gluVarType.StructType>} */ var structTypes = [];
    623            /** @type {es3fUniformApiTests.Uniform} */ var uniform = new es3fUniformApiTests.Uniform('u_var' + i, new gluVarType.VarType());
    624 
    625            // \note Discard uniforms that would cause number of samplers to exceed es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS.
    626            do {
    627                var temp = es3fUniformApiTests.generateRandomType(3, structIdx, structTypes, rnd);
    628                structIdx = temp.ndx;
    629                uniform.type = temp.type;
    630            } while (res.getNumSamplers() + es3fUniformApiTests.getNumSamplersInType(uniform.type) > es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS);
    631 
    632            res.addUniform(uniform);
    633            for (var j = 0; j < structTypes.length; j++)
    634                res.addStructType(structTypes[j]);
    635        }
    636 
    637        return res;
    638    };
    639 
    640    /**
    641     * @param {es3fUniformApiTests.VarValue} sampler
    642     * @return {es3fUniformApiTests.VarValue}
    643     */
    644    es3fUniformApiTests.getSamplerFillValue = function(sampler) {
    645        assertMsgOptions(gluShaderUtil.isDataTypeSampler(sampler.type), 'es3fUniformApiTests.getSamplerFillValue - not a sampler type', false, true);
    646 
    647        /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
    648        result.type = es3fUniformApiTests.getSamplerLookupReturnType(sampler.type);
    649 
    650        switch (result.type) {
    651            case gluShaderUtil.DataType.FLOAT_VEC4:
    652                for (var i = 0; i < 4; i++)
    653                    result.val[i] = sampler.val.samplerV.fillColor[i];
    654                break;
    655            case gluShaderUtil.DataType.UINT_VEC4:
    656                for (var i = 0; i < 4; i++)
    657                    result.val[i] = sampler.val.samplerV.fillColor[i];
    658                break;
    659            case gluShaderUtil.DataType.INT_VEC4:
    660                for (var i = 0; i < 4; i++)
    661                    result.val[i] = sampler.val.samplerV.fillColor[i];
    662                break;
    663            case gluShaderUtil.DataType.FLOAT:
    664                result.val[0] = sampler.val.samplerV.fillColor[0];
    665                break;
    666            default:
    667                throw new Error('es3fUniformApiTests.getSamplerFillValue - Invalid type');
    668        }
    669 
    670        return result;
    671    };
    672 
    673    /**
    674     * @param {es3fUniformApiTests.VarValue} sampler
    675     * @return {es3fUniformApiTests.VarValue}
    676     */
    677    es3fUniformApiTests.getSamplerUnitValue = function(sampler) {
    678        assertMsgOptions(gluShaderUtil.isDataTypeSampler(sampler.type), 'es3fUniformApiTests.getSamplerUnitValue - not a sampler type', false, true);
    679 
    680        /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
    681        result.type = gluShaderUtil.DataType.INT;
    682        result.val[0] = sampler.val.samplerV.unit;
    683 
    684        return result;
    685    };
    686 
    687    /**
    688     * @param {gluShaderUtil.DataType} original
    689     * @return {gluShaderUtil.DataType}
    690     */
    691    es3fUniformApiTests.getDataTypeTransposedMatrix = function(original) {
    692        return gluShaderUtil.getDataTypeMatrix(gluShaderUtil.getDataTypeMatrixNumRows(original), gluShaderUtil.getDataTypeMatrixNumColumns(original));
    693    };
    694 
    695    /**
    696     * @param {es3fUniformApiTests.VarValue} original
    697     * @return {es3fUniformApiTests.VarValue}
    698     */
    699    es3fUniformApiTests.getTransposeMatrix = function(original) {
    700        assertMsgOptions(gluShaderUtil.isDataTypeMatrix(original.type), 'es3fUniformApiTests.getTransposeMatrix - not a matrix', false, true);
    701 
    702        /** @type {number} */ var rows = gluShaderUtil.getDataTypeMatrixNumRows(original.type);
    703        /** @type {number} */ var cols = gluShaderUtil.getDataTypeMatrixNumColumns(original.type);
    704        /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
    705        result.type = es3fUniformApiTests.getDataTypeTransposedMatrix(original.type);
    706 
    707        for (var i = 0; i < rows; i++)
    708        for (var j = 0; j < cols; j++)
    709            result.val[i * cols + j] = original.val[j * rows + i];
    710 
    711        return result;
    712    };
    713 
    714    /**
    715     * @param {es3fUniformApiTests.VarValue} value
    716     * @return {string}
    717     */
    718    es3fUniformApiTests.shaderVarValueStr = function(value) {
    719        /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(value.type);
    720        /** @type {string} */ var result = '';
    721 
    722        if (numElems > 1)
    723            result += gluShaderUtil.getDataTypeName(value.type) + '(';
    724 
    725        for (var i = 0; i < numElems; i++) {
    726            if (i > 0)
    727                result += ', ';
    728 
    729            if (gluShaderUtil.isDataTypeFloatOrVec(value.type) || gluShaderUtil.isDataTypeMatrix(value.type))
    730                result += value.val[i].toFixed(2);
    731            else if (gluShaderUtil.isDataTypeIntOrIVec((value.type)))
    732                result += value.val[i];
    733            else if (gluShaderUtil.isDataTypeUintOrUVec((value.type)))
    734                result += value.val[i] + 'u';
    735            else if (gluShaderUtil.isDataTypeBoolOrBVec((value.type)))
    736                result += value.val[i] ? 'true' : 'false';
    737            else if (gluShaderUtil.isDataTypeSampler((value.type)))
    738                result += es3fUniformApiTests.shaderVarValueStr(es3fUniformApiTests.getSamplerFillValue(value));
    739            else
    740                throw new Error('es3fUniformApiTests.shaderVarValueStr - invalid type');
    741        }
    742 
    743        if (numElems > 1)
    744            result += ')';
    745 
    746        return result;
    747    };
    748 
    749    /**
    750     * @param {es3fUniformApiTests.VarValue} value
    751     * @return {string}
    752     */
    753    es3fUniformApiTests.apiVarValueStr = function(value) {
    754        /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(value.type);
    755        /** @type {string} */ var result = '';
    756 
    757        if (numElems > 1)
    758            result += '(';
    759 
    760        for (var i = 0; i < numElems; i++) {
    761            if (i > 0)
    762                result += ', ';
    763 
    764            if (gluShaderUtil.isDataTypeFloatOrVec(value.type) || gluShaderUtil.isDataTypeMatrix(value.type))
    765                result += value.val[i].toFixed(2);
    766            else if (gluShaderUtil.isDataTypeIntOrIVec(value.type) ||
    767            gluShaderUtil.isDataTypeUintOrUVec(value.type))
    768                result += value.val[i];
    769            else if (gluShaderUtil.isDataTypeBoolOrBVec(value.type))
    770                result += value.val[i] ? 'true' : 'false';
    771            else if (gluShaderUtil.isDataTypeSampler(value.type))
    772                result += value.val.samplerV.unit;
    773            else
    774                throw new Error('es3fUniformApiTests.apiVarValueStr - Invalid type');
    775        }
    776 
    777        if (numElems > 1)
    778            result += ')';
    779 
    780        return result;
    781    };
    782 
    783    // samplerUnit used if type is a sampler type. \note Samplers' unit numbers are not randomized.
    784    /**
    785     * @param {gluShaderUtil.DataType} type
    786     * @param {deRandom.Random} rnd
    787     * @param {number=} samplerUnit
    788     * @return {es3fUniformApiTests.VarValue}
    789     */
    790    es3fUniformApiTests.generateRandomVarValue = function(type, rnd, samplerUnit) {
    791        if (samplerUnit === undefined) samplerUnit = -1;
    792        /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(type);
    793        /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
    794        result.type = type;
    795 
    796        assertMsgOptions(
    797            (samplerUnit >= 0) == (gluShaderUtil.isDataTypeSampler(type)),
    798            'es3fUniformApiTests.generateRandomVarValue - sampler units do not match type', false, true
    799        );
    800 
    801        if (gluShaderUtil.isDataTypeFloatOrVec(type) || gluShaderUtil.isDataTypeMatrix(type)) {
    802            for (var i = 0; i < numElems; i++)
    803                result.val[i] = rnd.getFloat(-10.0, 10.0);
    804        } else if (gluShaderUtil.isDataTypeIntOrIVec(type)) {
    805            for (var i = 0; i < numElems; i++)
    806                result.val[i] = rnd.getInt(-10, 10);
    807        } else if (gluShaderUtil.isDataTypeUintOrUVec(type)) {
    808            for (var i = 0; i < numElems; i++)
    809                result.val[i] = rnd.getInt(0, 10);
    810        } else if (gluShaderUtil.isDataTypeBoolOrBVec(type)) {
    811            for (var i = 0; i < numElems; i++)
    812                result.val[i] = rnd.getBool();
    813        } else if (gluShaderUtil.isDataTypeSampler(type)) {
    814            /** @type {gluShaderUtil.DataType} */ var texResultType = es3fUniformApiTests.getSamplerLookupReturnType(type);
    815            /** @type {gluShaderUtil.DataType} */ var texResultScalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(texResultType);
    816            /** @type {number} */ var texResultNumDims = gluShaderUtil.getDataTypeScalarSize(texResultType);
    817 
    818            result.val = new es3fUniformApiTests.SamplerV();
    819            result.val.samplerV.unit = samplerUnit;
    820 
    821            for (var i = 0; i < texResultNumDims; i++) {
    822                switch (texResultScalarType) {
    823                    case gluShaderUtil.DataType.FLOAT: result.val.samplerV.fillColor[i] = rnd.getFloat(0.0, 1.0); break;
    824                    case gluShaderUtil.DataType.INT: result.val.samplerV.fillColor[i] = rnd.getInt(-10, 10); break;
    825                    case gluShaderUtil.DataType.UINT: result.val.samplerV.fillColor[i] = rnd.getInt(0, 10); break;
    826                    default:
    827                        throw new Error('es3fUniformApiTests.generateRandomVarValue - Invalid scalar type');
    828                }
    829            }
    830        } else
    831            throw new Error('es3fUniformApiTests.generateRandomVarValue - Invalid type');
    832 
    833        return result;
    834    };
    835 
    836    /**
    837     * @param {gluShaderUtil.DataType} type
    838     * @return {es3fUniformApiTests.VarValue}
    839     */
    840    es3fUniformApiTests.generateZeroVarValue = function(type) {
    841        /** @type {number} */ var numElems = gluShaderUtil.getDataTypeScalarSize(type);
    842        /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
    843        result.type = type;
    844 
    845        if (gluShaderUtil.isDataTypeFloatOrVec(type) || gluShaderUtil.isDataTypeMatrix(type)) {
    846            for (var i = 0; i < numElems; i++)
    847                result.val[i] = 0.0;
    848        } else if (gluShaderUtil.isDataTypeIntOrIVec(type)) {
    849            for (var i = 0; i < numElems; i++)
    850                result.val[i] = 0;
    851        } else if (gluShaderUtil.isDataTypeUintOrUVec(type)) {
    852            for (var i = 0; i < numElems; i++)
    853                result.val[i] = 0;
    854        } else if (gluShaderUtil.isDataTypeBoolOrBVec(type)) {
    855            for (var i = 0; i < numElems; i++)
    856                result.val[i] = false;
    857        } else if (gluShaderUtil.isDataTypeSampler(type)) {
    858            /** @type {gluShaderUtil.DataType} */ var texResultType = es3fUniformApiTests.getSamplerLookupReturnType(type);
    859            /** @type {gluShaderUtil.DataType} */ var texResultScalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(texResultType);
    860            /** @type {number} */ var texResultNumDims = gluShaderUtil.getDataTypeScalarSize(texResultType);
    861 
    862            result.val = new es3fUniformApiTests.SamplerV();
    863            result.val.samplerV.unit = 0;
    864 
    865            for (var i = 0; i < texResultNumDims; i++) {
    866                switch (texResultScalarType) {
    867                    case gluShaderUtil.DataType.FLOAT: result.val.samplerV.fillColor[i] = 0.12 * i; break;
    868                    case gluShaderUtil.DataType.INT: result.val.samplerV.fillColor[i] = -2 + i; break;
    869                    case gluShaderUtil.DataType.UINT: result.val.samplerV.fillColor[i] = 4 + i; break;
    870                    default:
    871                        throw new Error('es3fUniformApiTests.generateZeroVarValue - Invalid scalar type');
    872                }
    873            }
    874        } else
    875            throw new Error('es3fUniformApiTests.generateZeroVarValue - Invalid type');
    876 
    877        return result;
    878    };
    879 
    880    /**
    881     * @param {es3fUniformApiTests.VarValue} a
    882     * @param {es3fUniformApiTests.VarValue} b
    883     * @return {boolean}
    884     */
    885    es3fUniformApiTests.apiVarValueEquals = function(a, b) {
    886        /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(a.type);
    887        /** @type {number} */ var floatThreshold = 0.05;
    888 
    889        assertMsgOptions(a.type == b.type, 'es3fUniformApiTests.apiVarValueEquals - types are different', false, true);
    890 
    891        if (gluShaderUtil.isDataTypeFloatOrVec(a.type) || gluShaderUtil.isDataTypeMatrix(a.type)) {
    892            for (var i = 0; i < size; i++)
    893                if (Math.abs(a.val[i] - b.val[i]) >= floatThreshold)
    894                    return false;
    895        } else if (gluShaderUtil.isDataTypeIntOrIVec(a.type)) {
    896            for (var i = 0; i < size; i++)
    897                if (a.val[i] != b.val[i])
    898                    return false;
    899        } else if (gluShaderUtil.isDataTypeUintOrUVec(a.type)) {
    900            for (var i = 0; i < size; i++)
    901                if (a.val[i] != b.val[i])
    902                    return false;
    903        } else if (gluShaderUtil.isDataTypeBoolOrBVec(a.type)) {
    904            for (var i = 0; i < size; i++)
    905                if (a.val[i] != b.val[i])
    906                    return false;
    907        } else if (gluShaderUtil.isDataTypeSampler(a.type)) {
    908            if (a.val.samplerV.unit != b.val.samplerV.unit)
    909                return false;
    910        } else
    911            throw new Error('es3fUniformApiTests.apiVarValueEquals - Invalid type');
    912 
    913        return true;
    914    };
    915 
    916    /**
    917     * @param {es3fUniformApiTests.VarValue} boolValue
    918     * @param {gluShaderUtil.DataType} targetScalarType
    919     * @param {deRandom.Random} rnd
    920     * @return {es3fUniformApiTests.VarValue}
    921     */
    922    es3fUniformApiTests.getRandomBoolRepresentation = function(boolValue, targetScalarType, rnd) {
    923        assertMsgOptions(
    924            gluShaderUtil.isDataTypeBoolOrBVec(boolValue.type),
    925            'es3fUniformApiTests.getRandomBoolRepresentation - Data type not boolean or boolean vector',
    926            false,
    927            true
    928        );
    929 
    930        /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(boolValue.type);
    931        /** @type {gluShaderUtil.DataType} */ var targetType = size == 1 ? targetScalarType : gluShaderUtil.getDataTypeVector(targetScalarType, size);
    932        /** @type {es3fUniformApiTests.VarValue} */ var result = new es3fUniformApiTests.VarValue();
    933        result.type = targetType;
    934 
    935        switch (targetScalarType) {
    936            case gluShaderUtil.DataType.INT:
    937                for (var i = 0; i < size; i++) {
    938                    if (boolValue.val[i]) {
    939                        result.val[i] = rnd.getInt(-10, 10);
    940                        if (result.val[i] == 0)
    941                            result.val[i] = 1;
    942                    } else
    943                        result.val[i] = 0;
    944                }
    945                break;
    946 
    947            case gluShaderUtil.DataType.UINT:
    948                for (var i = 0; i < size; i++) {
    949                    if (boolValue.val[i])
    950                        result.val[i] = rnd.getInt(1, 10);
    951                    else
    952                        result.val[i] = 0;
    953                }
    954                break;
    955 
    956            case gluShaderUtil.DataType.FLOAT:
    957                for (var i = 0; i < size; i++) {
    958                    if (boolValue.val[i]) {
    959                        result.val[i] = rnd.getFloat(-10.0, 10.0);
    960                        if (result.val[i] == 0.0)
    961                            result.val[i] = 1.0;
    962                    } else
    963                        result.val[i] = 0;
    964                }
    965                break;
    966 
    967            default:
    968                throw new Error('es3fUniformApiTests.getRandomBoolRepresentation - Invalid type');
    969        }
    970 
    971        return result;
    972    };
    973 
    974    /**
    975     * @param {es3fUniformApiTests.CaseShaderType} type
    976     * @return {?string}
    977     */
    978    es3fUniformApiTests.getCaseShaderTypeName = function(type) {
    979        switch (type) {
    980            case es3fUniformApiTests.CaseShaderType.VERTEX: return 'vertex';
    981            case es3fUniformApiTests.CaseShaderType.FRAGMENT: return 'fragment';
    982            case es3fUniformApiTests.CaseShaderType.BOTH: return 'both';
    983            default:
    984                throw new Error('es3fUniformApiTests.getCaseShaderTypeName - Invalid shader type');
    985        }
    986    };
    987 
    988    /**
    989     * @param {number} seed
    990     * @return {number}
    991     */
    992    es3fUniformApiTests.randomCaseShaderType = function(seed) {
    993        return (new deRandom.Random(seed)).getInt(0, Object.keys(es3fUniformApiTests.CaseShaderType).length - 1);
    994    };
    995 
    996    //es3fUniformApiTests.UniformCase definitions
    997 
    998    /**
    999     * es3fUniformApiTests.Feature - Implemented as a function to create an object without unwanted properties.
   1000     * @constructor
   1001     */
   1002    es3fUniformApiTests.Feature = function() {
   1003        // ARRAYUSAGE_ONLY_MIDDLE_INDEX: only middle index of each array is used in shader. If not given, use all indices.
   1004        this.ARRAYUSAGE_ONLY_MIDDLE_INDEX = false;
   1005 
   1006        // UNIFORMFUNC_VALUE: use pass-by-value versions of uniform assignment funcs, e.g. glUniform1f(), where possible. If not given, use pass-by-pointer versions.
   1007        this.UNIFORMFUNC_VALUE = false;
   1008 
   1009        // MATRIXMODE_ROWMAJOR: pass matrices to GL in row major form. If not given, use column major.
   1010        this.MATRIXMODE_ROWMAJOR = false;
   1011 
   1012        // ARRAYASSIGN: how basic-type arrays are assigned with glUniform*(). If none given, assign each element of an array separately.
   1013        this.ARRAYASSIGN_FULL = false; //!< Assign all elements of an array with one glUniform*().
   1014        this.ARRAYASSIGN_BLOCKS_OF_TWO = false; //!< Assign two elements per one glUniform*().
   1015 
   1016        // UNIFORMUSAGE_EVERY_OTHER: use about half of the uniforms. If not given, use all uniforms (except that some array indices may be omitted according to ARRAYUSAGE).
   1017        this.UNIFORMUSAGE_EVERY_OTHER = false;
   1018 
   1019        // BOOLEANAPITYPE: type used to pass booleans to and from GL api. If none given, use float.
   1020        this.BOOLEANAPITYPE_INT = false;
   1021        this.BOOLEANAPITYPE_UINT = false;
   1022 
   1023        // UNIFORMVALUE_ZERO: use zero-valued uniforms. If not given, use random uniform values.
   1024        this.UNIFORMVALUE_ZERO = false;
   1025 
   1026        // ARRAY_FIRST_ELEM_NAME_NO_INDEX: in certain API functions, when referring to the first element of an array, use just the array name without [0] at the end.
   1027        this.ARRAY_FIRST_ELEM_NAME_NO_INDEX = false;
   1028    };
   1029 
   1030    // A basic uniform is a uniform (possibly struct or array member) whose type is a basic type (e.g. float, ivec4, sampler2d).
   1031    /**
   1032     * @constructor
   1033     * @param {string} name_
   1034     * @param {gluShaderUtil.DataType} type_
   1035     * @param {boolean} isUsedInShader_
   1036     * @param {es3fUniformApiTests.VarValue} finalValue_
   1037     * @param {string=} rootName_
   1038     * @param {number=} elemNdx_
   1039     * @param {number=} rootSize_
   1040     */
   1041    es3fUniformApiTests.BasicUniform = function(name_, type_, isUsedInShader_, finalValue_, rootName_, elemNdx_, rootSize_) {
   1042        /** @type {string} */ this.name = name_;
   1043        /** @type {gluShaderUtil.DataType} */ this.type = type_;
   1044        /** @type {boolean} */ this.isUsedInShader = isUsedInShader_;
   1045        /** @type {es3fUniformApiTests.VarValue} */ this.finalValue = finalValue_; //!< The value we ultimately want to set for this uniform.
   1046 
   1047        /** @type {string} */ this.rootName = rootName_ === undefined ? name_ : rootName_; //!< If this is a member of a basic-typed array, rootName is the name of that array with "[0]" appended. Otherwise it equals name.
   1048        /** @type {number} */ this.elemNdx = elemNdx_ === undefined ? -1 : elemNdx_; //!< If this is a member of a basic-typed array, elemNdx is the index in that array. Otherwise -1.
   1049        /** @type {number} */ this.rootSize = rootSize_ === undefined ? 1 : rootSize_; //!< If this is a member of a basic-typed array, rootSize is the size of that array. Otherwise 1.
   1050    };
   1051 
   1052    /**
   1053     * @param {Array<es3fUniformApiTests.BasicUniform>} vec
   1054     * @param {string} name
   1055     * @return {es3fUniformApiTests.BasicUniform}
   1056     */
   1057    es3fUniformApiTests.BasicUniform.findWithName = function(vec, name) {
   1058        for (var i = 0; i < vec.length; i++) {
   1059            if (vec[i].name == name)
   1060                return vec[i];
   1061        }
   1062        return null;
   1063    };
   1064 
   1065    // Reference values for info that is expected to be reported by glGetActiveUniform() or glGetActiveUniforms().
   1066    /**
   1067     * @constructor
   1068     * @param {string} name_
   1069     * @param {gluShaderUtil.DataType} type_
   1070     * @param {boolean} used
   1071     */
   1072    es3fUniformApiTests.BasicUniformReportRef = function(name_, type_, used) {
   1073        /** @type {string} */ this.name = name_;
   1074        // \note minSize and maxSize are for arrays and can be distinct since implementations are allowed, but not required, to trim the inactive end indices of arrays.
   1075        /** @type {number} */ this.minSize = 1;
   1076        /** @type {number} */ this.maxSize = 1;
   1077        /** @type {gluShaderUtil.DataType} */ this.type = type_;
   1078        /** @type {boolean} */ this.isUsedInShader = used;
   1079    };
   1080 
   1081    /**
   1082     * To be used after constructor
   1083     * @param {number} minS
   1084     * @param {number} maxS
   1085     * @return {es3fUniformApiTests.BasicUniformReportRef}
   1086     */
   1087    es3fUniformApiTests.BasicUniformReportRef.prototype.constructor_A = function(minS, maxS) {
   1088        this.minSize = minS;
   1089        this.maxSize = maxS;
   1090 
   1091        assertMsgOptions(
   1092            this.minSize <= this.maxSize,
   1093            'es3fUniformApiTests.BasicUniformReportRef.prototype.constructor_A - min size not smaller or equal than max size',
   1094            false,
   1095            true
   1096        );
   1097 
   1098        return this;
   1099    };
   1100 
   1101    // Info that is actually reported by glGetActiveUniform() or glGetActiveUniforms().
   1102    /**
   1103     * @constructor
   1104     * @param {string} name_
   1105     * @param {number} nameLength_
   1106     * @param {number} size_
   1107     * @param {gluShaderUtil.DataType} type_
   1108     * @param {number} index_
   1109     */
   1110    es3fUniformApiTests.BasicUniformReportGL = function(name_, nameLength_, size_, type_, index_) {
   1111        this.name = name_;
   1112        this.nameLength = nameLength_;
   1113        this.size = size_;
   1114        this.type = type_;
   1115        this.index = index_;
   1116    };
   1117 
   1118    /**
   1119     * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} vec
   1120     * @param {string} name
   1121     * @return {es3fUniformApiTests.BasicUniformReportGL}
   1122     */
   1123    es3fUniformApiTests.BasicUniformReportGL.findWithName = function(vec, name) {
   1124        for (var i = 0; i < vec.length; i++) {
   1125            if (vec[i].name == name)
   1126                return vec[i];
   1127        }
   1128        return null;
   1129    };
   1130 
   1131    /**
   1132     * es3fUniformApiTests.UniformCase class, inherits from TestCase class
   1133     * @constructor
   1134     * @param {string} name
   1135     * @param {string} description
   1136     * @extends {tcuTestCase.DeqpTest}
   1137     */
   1138    es3fUniformApiTests.UniformCase = function(name, description) { // \note Randomizes caseType, uniformCollection and features.
   1139        tcuTestCase.DeqpTest.call(this, name, description);
   1140 
   1141        /** @type {es3fUniformApiTests.Feature} */ this.m_features;
   1142        /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ this.m_uniformCollection;
   1143 
   1144        /** @type {number} */ this.m_caseShaderType = 0;
   1145 
   1146        /** @type {Array<gluTexture.Texture2D>} */ this.m_textures2d = [];
   1147        /** @type {Array<gluTexture.TextureCube>} */ this.m_texturesCube = [];
   1148        /** @type {Array<number>} */ this.m_filledTextureUnits = [];
   1149    };
   1150 
   1151    es3fUniformApiTests.UniformCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
   1152    /** es3fUniformApiTests.UniformCase prototype restore */
   1153    es3fUniformApiTests.UniformCase.prototype.constructor = es3fUniformApiTests.UniformCase;
   1154 
   1155    /**
   1156     * es3fUniformApiTests.UniformCase newC. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
   1157     * @param {number} seed
   1158     * @return {es3fUniformApiTests.UniformCase}
   1159     */
   1160    es3fUniformApiTests.UniformCase.prototype.newC = function(seed) {
   1161        this.m_features = this.randomFeatures(seed);
   1162        this.m_uniformCollection = es3fUniformApiTests.UniformCollection.random(seed);
   1163        this.m_caseShaderType = es3fUniformApiTests.randomCaseShaderType(seed);
   1164 
   1165        return this;
   1166    };
   1167 
   1168    /**
   1169     * es3fUniformApiTests.UniformCase new_B (static). Creates a es3fUniformApiTests.UniformCase
   1170     * @param {string} name
   1171     * @param {string} description
   1172     * @param {number} seed
   1173     * @return {es3fUniformApiTests.UniformCase}
   1174     */
   1175    es3fUniformApiTests.UniformCase.new_C = function(name, description, seed) {
   1176        var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newC(seed);
   1177 
   1178        return uniformCase;
   1179    };
   1180 
   1181    /**
   1182     * es3fUniformApiTests.UniformCase new_B. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
   1183     * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
   1184     * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
   1185     * @param {es3fUniformApiTests.Feature} features
   1186     * @return {es3fUniformApiTests.UniformCase}
   1187     */
   1188    es3fUniformApiTests.UniformCase.prototype.newB = function(caseShaderType, uniformCollection, features) {
   1189        this.m_caseShaderType = caseShaderType;
   1190        this.m_uniformCollection = uniformCollection;
   1191        this.m_features = features;
   1192 
   1193        return this;
   1194    };
   1195 
   1196    /**
   1197     * es3fUniformApiTests.UniformCase new_B (static). Creates a es3fUniformApiTests.UniformCase
   1198     * @param {string} name
   1199     * @param {string} description
   1200     * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
   1201     * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
   1202     * @param {es3fUniformApiTests.Feature} features
   1203     * @return {es3fUniformApiTests.UniformCase}
   1204     */
   1205    es3fUniformApiTests.UniformCase.new_B = function(name, description, caseShaderType, uniformCollection, features) {
   1206        var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newB(caseShaderType, uniformCollection, features);
   1207 
   1208        return uniformCase;
   1209    };
   1210 
   1211    /**
   1212     * es3fUniformApiTests.UniformCase new_A. Creates a es3fUniformApiTests.UniformCase. Use after constructor.
   1213     * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
   1214     * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
   1215     * @return {es3fUniformApiTests.UniformCase}
   1216     */
   1217    es3fUniformApiTests.UniformCase.prototype.newA = function(caseShaderType, uniformCollection) {
   1218       this.m_caseShaderType = caseShaderType;
   1219       this.m_uniformCollection = uniformCollection;
   1220       this.m_features = null;
   1221 
   1222       return this;
   1223    };
   1224 
   1225    /**
   1226     * es3fUniformApiTests.UniformCase new_A (static). Creates a es3fUniformApiTests.UniformCase
   1227     * @param {string} name
   1228     * @param {string} description
   1229     * @param {es3fUniformApiTests.CaseShaderType} caseShaderType
   1230     * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
   1231     * @return {es3fUniformApiTests.UniformCase}
   1232     */
   1233    es3fUniformApiTests.UniformCase.new_A = function(name, description, caseShaderType, uniformCollection) {
   1234        var uniformCase = new es3fUniformApiTests.UniformCase(name, description).newA(caseShaderType, uniformCollection);
   1235 
   1236        return uniformCase;
   1237    };
   1238 
   1239    /**
   1240     * @param {number} seed
   1241     * @return {es3fUniformApiTests.Feature}
   1242     */
   1243    es3fUniformApiTests.UniformCase.prototype.randomFeatures = function(seed) {
   1244        /** @type {es3fUniformApiTests.Feature} */ var result = new es3fUniformApiTests.Feature();
   1245 
   1246        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(seed);
   1247 
   1248        result.ARRAYUSAGE_ONLY_MIDDLE_INDEX = rnd.getBool();
   1249        result.UNIFORMFUNC_VALUE = rnd.getBool();
   1250        result.MATRIXMODE_ROWMAJOR = rnd.getBool();
   1251        result.ARRAYASSIGN_FULL = rnd.getBool();
   1252        result.ARRAYASSIGN_BLOCKS_OF_TWO = !result.ARRAYASSIGN_FULL;
   1253        result.UNIFORMUSAGE_EVERY_OTHER = rnd.getBool();
   1254        result.BOOLEANAPITYPE_INT = rnd.getBool();
   1255        result.BOOLEANAPITYPE_UINT = !result.BOOLEANAPITYPE_INT;
   1256        result.UNIFORMVALUE_ZERO = rnd.getBool();
   1257 
   1258        return result;
   1259    };
   1260 
   1261    /**
   1262     * Initialize the es3fUniformApiTests.UniformCase
   1263     */
   1264    es3fUniformApiTests.UniformCase.prototype.init = function() {
   1265        /** @type {number} */ var numSamplerUniforms = this.m_uniformCollection.getNumSamplers();
   1266        /** @type {number} */ var vertexTexUnitsRequired = this.m_caseShaderType != es3fUniformApiTests.CaseShaderType.FRAGMENT ? numSamplerUniforms : 0;
   1267        /** @type {number} */ var fragmentTexUnitsRequired = this.m_caseShaderType != es3fUniformApiTests.CaseShaderType.VERTEX ? numSamplerUniforms : 0;
   1268        /** @type {number} */ var combinedTexUnitsRequired = vertexTexUnitsRequired + fragmentTexUnitsRequired;
   1269        var vertexTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS));
   1270        var fragmentTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
   1271        var combinedTexUnitsSupported = /** @type {number} */ (gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS));
   1272 
   1273        assertMsgOptions(
   1274            numSamplerUniforms <= es3fUniformApiTests.MAX_NUM_SAMPLER_UNIFORMS,
   1275            'es3fUniformApiTests.UniformCase.prototype.init - sampler uniforms exceed MAX_NUM_SAMPLER_UNIFORMS',
   1276            false,
   1277            true
   1278        );
   1279 
   1280        if (vertexTexUnitsRequired > vertexTexUnitsSupported)
   1281            testFailedOptions('' + vertexTexUnitsRequired + ' vertex texture units required, ' + vertexTexUnitsSupported + ' supported', true);
   1282        if (fragmentTexUnitsRequired > fragmentTexUnitsSupported)
   1283            testFailedOptions('' + fragmentTexUnitsRequired + ' fragment texture units required, ' + fragmentTexUnitsSupported + ' supported', true);
   1284        if (combinedTexUnitsRequired > combinedTexUnitsSupported)
   1285            testFailedOptions('' + combinedTexUnitsRequired + ' combined texture units required, ' + combinedTexUnitsSupported + ' supported', true);
   1286    };
   1287 
   1288    /**
   1289     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniformsDst
   1290     * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsDst
   1291     * @param {gluVarType.VarType} varType
   1292     * @param {string} varName
   1293     * @param {boolean} isParentActive
   1294     * @param {number} samplerUnitCounter
   1295     * @param {deRandom.Random} rnd
   1296     * @return {number} Used to be output parameter. Sampler unit count
   1297     */
   1298    es3fUniformApiTests.UniformCase.prototype.generateBasicUniforms = function(basicUniformsDst, basicUniformReportsDst, varType, varName, isParentActive, samplerUnitCounter, rnd) {
   1299        /** @type {es3fUniformApiTests.VarValue} */ var value;
   1300 
   1301        if (varType.isBasicType()) {
   1302            /** @type {boolean} */ var isActive = isParentActive && (this.m_features.UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.length % 2 == 0 : true);
   1303            /** @type {gluShaderUtil.DataType} */ var type = varType.getBasicType();
   1304            value = this.m_features.UNIFORMVALUE_ZERO ? es3fUniformApiTests.generateZeroVarValue(type) :
   1305            gluShaderUtil.isDataTypeSampler(type) ? es3fUniformApiTests.generateRandomVarValue(type, rnd, samplerUnitCounter++) :
   1306                                                es3fUniformApiTests.generateRandomVarValue(varType.getBasicType(), rnd);
   1307 
   1308            basicUniformsDst.push(new es3fUniformApiTests.BasicUniform(varName, varType.getBasicType(), isActive, value));
   1309            basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportRef(varName, varType.getBasicType(), isActive));
   1310        } else if (varType.isArrayType()) {
   1311            /** @type {number} */ var size = varType.getArraySize();
   1312            /** @type {string} */ var arrayRootName = '' + varName + '[0]';
   1313            /** @type {Array<boolean>} */ var isElemActive = [];
   1314 
   1315            for (var elemNdx = 0; elemNdx < varType.getArraySize(); elemNdx++) {
   1316                /** @type {string} */ var indexedName = '' + varName + '[' + elemNdx + ']';
   1317                /** @type {boolean} */ var isCurElemActive = isParentActive &&
   1318                                                  (this.m_features.UNIFORMUSAGE_EVERY_OTHER ? basicUniformsDst.length % 2 == 0 : true) &&
   1319                                                  (this.m_features.ARRAYUSAGE_ONLY_MIDDLE_INDEX ? elemNdx == Math.floor(size / 2) : true);
   1320 
   1321                isElemActive.push(isCurElemActive);
   1322 
   1323                if (varType.getElementType().isBasicType()) {
   1324                    // \note We don't want separate entries in basicUniformReportsDst for elements of basic-type arrays.
   1325                    /** @type {gluShaderUtil.DataType} */ var elemBasicType = varType.getElementType().getBasicType();
   1326                    value = this.m_features.UNIFORMVALUE_ZERO ? es3fUniformApiTests.generateZeroVarValue(elemBasicType) :
   1327                    gluShaderUtil.isDataTypeSampler(elemBasicType) ? es3fUniformApiTests.generateRandomVarValue(elemBasicType, rnd, samplerUnitCounter++) :
   1328                                                        es3fUniformApiTests.generateRandomVarValue(elemBasicType, rnd);
   1329 
   1330                    basicUniformsDst.push(new es3fUniformApiTests.BasicUniform(indexedName, elemBasicType, isCurElemActive, value, arrayRootName, elemNdx, size));
   1331                } else
   1332                    samplerUnitCounter = this.generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, varType.getElementType(), indexedName, isCurElemActive, samplerUnitCounter, rnd);
   1333            }
   1334 
   1335            if (varType.getElementType().isBasicType()) {
   1336                /** @type {number} */ var minSize;
   1337                for (minSize = varType.getArraySize(); minSize > 0 && !isElemActive[minSize - 1]; minSize--) {}
   1338 
   1339                basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportRef(arrayRootName, varType.getElementType().getBasicType(), isParentActive && minSize > 0).constructor_A(minSize, size));
   1340            }
   1341        } else {
   1342            assertMsgOptions(
   1343                varType.isStructType(),
   1344                'es3fUniformApiTests.UniformCase.prototype.generateBasicUniforms - not a struct type',
   1345                false,
   1346                true
   1347            );
   1348 
   1349            /** @type {gluVarType.StructType} */ var structType = varType.getStruct();
   1350 
   1351            for (var i = 0; i < structType.getSize(); i++) {
   1352                /** @type {gluVarType.StructMember} */ var member = structType.getMember(i);
   1353                /** @type {string} */ var memberFullName = '' + varName + '.' + member.getName();
   1354 
   1355                samplerUnitCounter = this.generateBasicUniforms(basicUniformsDst, basicUniformReportsDst, member.getType(), memberFullName, isParentActive, samplerUnitCounter, rnd);
   1356            }
   1357        }
   1358 
   1359        return samplerUnitCounter;
   1360    };
   1361 
   1362    /**
   1363     * @param {string} dst
   1364     * @return {string}
   1365     */
   1366    es3fUniformApiTests.UniformCase.prototype.writeUniformDefinitions = function(dst) {
   1367        for (var i = 0; i < this.m_uniformCollection.getNumStructTypes(); i++)
   1368            dst += gluVarType.declareStructType(this.m_uniformCollection.getStructType(i), 0) + ';\n';
   1369 
   1370        for (var i = 0; i < this.m_uniformCollection.getNumUniforms(); i++)
   1371            dst += 'uniform ' + gluVarType.declareVariable(this.m_uniformCollection.getUniform(i).type, this.m_uniformCollection.getUniform(i).name, 0) + ';\n';
   1372 
   1373        dst += '\n';
   1374 
   1375        var compareFuncs = [{
   1376                requiringTypes: [gluShaderUtil.isDataTypeFloatOrVec, gluShaderUtil.isDataTypeMatrix],
   1377                definition: 'mediump float compare_float (mediump float a, mediump float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; }'
   1378            },{
   1379                requiringTypes: [
   1380                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC2, t);},
   1381                    function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(2, t);}
   1382                ],
   1383                definition: 'mediump float compare_vec2 (mediump vec2 a, mediump vec2 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }'
   1384            },{
   1385                requiringTypes: [
   1386                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC3, t);},
   1387                    function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(3, t);}
   1388                ],
   1389                definition: 'mediump float compare_vec3 (mediump vec3 a, mediump vec3 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }'
   1390            },{
   1391                requiringTypes: [
   1392                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_VEC4, t);},
   1393                    function(t) {return es3fUniformApiTests.dataTypeIsMatrixWithNRows(4, t);}],
   1394                definition: 'mediump float compare_vec4 (mediump vec4 a, mediump vec4 b) { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }'
   1395            },{
   1396                requiringTypes: [
   1397                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2, t);},
   1398                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1399                ],
   1400                definition: 'mediump float compare_mat2 (mediump mat2 a, mediump mat2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }'
   1401            },{
   1402                requiringTypes: [
   1403                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2X3, t);},
   1404                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1405                ],
   1406                definition: 'mediump float compare_mat2x3 (mediump mat2x3 a, mediump mat2x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }'
   1407            },{
   1408                requiringTypes: [
   1409                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT2X4, t);},
   1410                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1411                ],
   1412                definition: 'mediump float compare_mat2x4 (mediump mat2x4 a, mediump mat2x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }'
   1413            },{
   1414                requiringTypes: [
   1415                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3X2, t);},
   1416                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1417                ],
   1418                definition: 'mediump float compare_mat3x2 (mediump mat3x2 a, mediump mat3x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }'
   1419            },{
   1420                requiringTypes: [
   1421                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3, t);},
   1422                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1423                ],
   1424                definition: 'mediump float compare_mat3 (mediump mat3 a, mediump mat3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }'
   1425            },{
   1426                requiringTypes: [
   1427                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT3X4, t);},
   1428                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1429                ],
   1430                definition: 'mediump float compare_mat3x4 (mediump mat3x4 a, mediump mat3x4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }'
   1431            },{
   1432                requiringTypes: [
   1433                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4X2, t);},
   1434                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1435                ],
   1436                definition: 'mediump float compare_mat4x2 (mediump mat4x2 a, mediump mat4x2 b) { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }'
   1437            },{
   1438                requiringTypes: [
   1439                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4X3, t);},
   1440                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1441                ],
   1442                definition: 'mediump float compare_mat4x3 (mediump mat4x3 a, mediump mat4x3 b) { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }'
   1443            },{
   1444                requiringTypes: [
   1445                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.FLOAT_MAT4, t);},
   1446                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1447                ],
   1448                definition: 'mediump float compare_mat4 (mediump mat4 a, mediump mat4 b) { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }'
   1449            },{
   1450                requiringTypes: [
   1451                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT, t);},
   1452                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1453                ],
   1454                definition: 'mediump float compare_int (mediump int a, mediump int b) { return a == b ? 1.0 : 0.0; }'
   1455            },{
   1456                requiringTypes: [
   1457                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC2, t);},
   1458                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1459                ],
   1460                definition: 'mediump float compare_ivec2 (mediump ivec2 a, mediump ivec2 b) { return a == b ? 1.0 : 0.0; }'
   1461            },{
   1462                requiringTypes: [
   1463                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC3, t);},
   1464                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1465                ],
   1466                definition: 'mediump float compare_ivec3 (mediump ivec3 a, mediump ivec3 b) { return a == b ? 1.0 : 0.0; }'
   1467            },{
   1468                requiringTypes: [
   1469                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INT_VEC4, t);},
   1470                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1471                ],
   1472                definition: 'mediump float compare_ivec4 (mediump ivec4 a, mediump ivec4 b) { return a == b ? 1.0 : 0.0; }'
   1473            },{
   1474                requiringTypes: [
   1475                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT, t);},
   1476                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1477                ],
   1478                definition: 'mediump float compare_uint (mediump uint a, mediump uint b) { return a == b ? 1.0 : 0.0; }'
   1479            },{
   1480                requiringTypes: [
   1481                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC2, t);},
   1482                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1483                ],
   1484                definition: 'mediump float compare_uvec2 (mediump uvec2 a, mediump uvec2 b) { return a == b ? 1.0 : 0.0; }'
   1485            },{
   1486                requiringTypes: [
   1487                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC3, t);},
   1488                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1489                ],
   1490                definition: 'mediump float compare_uvec3 (mediump uvec3 a, mediump uvec3 b) { return a == b ? 1.0 : 0.0; }'
   1491            },{
   1492                requiringTypes: [
   1493                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.UINT_VEC4, t);},
   1494                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1495                ],
   1496                definition: 'mediump float compare_uvec4 (mediump uvec4 a, mediump uvec4 b) { return a == b ? 1.0 : 0.0; }'
   1497            },{
   1498                requiringTypes: [
   1499                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL, t);},
   1500                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1501                ],
   1502                definition: 'mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }'
   1503            },{
   1504                requiringTypes: [
   1505                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC2, t);},
   1506                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1507                ],
   1508                definition: 'mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }'
   1509            },{
   1510                requiringTypes: [
   1511                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC3, t);},
   1512                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1513                ],
   1514                definition: 'mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }'
   1515            },{
   1516                requiringTypes: [
   1517                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.BOOL_VEC4, t);},
   1518                    function(t) {return es3fUniformApiTests.dataTypeEquals(gluShaderUtil.DataType.INVALID, t);}
   1519                ],
   1520                definition: 'mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }'
   1521            }
   1522        ];
   1523 
   1524        /** @type {Array<gluShaderUtil.DataType>} */ var samplerTypes = this.m_uniformCollection.getSamplerTypes();
   1525 
   1526        for (var compFuncNdx = 0; compFuncNdx < compareFuncs.length; compFuncNdx++) {
   1527            /** @type {Array<es3fUniformApiTests.dataTypePredicate>} */ var typeReq = compareFuncs[compFuncNdx].requiringTypes;
   1528            /** @type {boolean} */ var containsTypeSampler = false;
   1529 
   1530            for (var i = 0; i < samplerTypes.length; i++) {
   1531                if (gluShaderUtil.isDataTypeSampler(samplerTypes[i])) {
   1532                    /** @type {gluShaderUtil.DataType} */ var retType = es3fUniformApiTests.getSamplerLookupReturnType(samplerTypes[i]);
   1533                    if (typeReq[0](retType) || typeReq[1](retType)) {
   1534                        containsTypeSampler = true;
   1535                        break;
   1536                    }
   1537                }
   1538            }
   1539 
   1540            if (containsTypeSampler || this.m_uniformCollection.containsMatchingBasicType(typeReq[0]) || this.m_uniformCollection.containsMatchingBasicType(typeReq[1]))
   1541                dst += compareFuncs[compFuncNdx].definition + '\n';
   1542        }
   1543 
   1544        return dst;
   1545    };
   1546 
   1547    /**
   1548     * @param {string} dst
   1549     * @param {es3fUniformApiTests.BasicUniform} uniform
   1550     * @return {string} Used to write the string in the output parameter
   1551     */
   1552    es3fUniformApiTests.UniformCase.prototype.writeUniformCompareExpr = function(dst, uniform) {
   1553        if (gluShaderUtil.isDataTypeSampler(uniform.type))
   1554            dst += 'compare_' + gluShaderUtil.getDataTypeName(es3fUniformApiTests.getSamplerLookupReturnType(uniform.type)) + '(texture(' + uniform.name + ', vec' + es3fUniformApiTests.getSamplerNumLookupDimensions(uniform.type) + '(0.0))'; //WebGL2.0
   1555        else
   1556            dst += 'compare_' + gluShaderUtil.getDataTypeName(uniform.type) + '(' + uniform.name;
   1557 
   1558        dst += ', ' + es3fUniformApiTests.shaderVarValueStr(uniform.finalValue) + ')';
   1559 
   1560        return dst;
   1561    };
   1562 
   1563    /**
   1564     * @param {string} dst
   1565     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   1566     * @param {string} variableName
   1567     * @return {string} Used to write the string in the output parameter
   1568     */
   1569    es3fUniformApiTests.UniformCase.prototype.writeUniformComparisons = function(dst, basicUniforms, variableName) {
   1570        for (var i = 0; i < basicUniforms.length; i++) {
   1571            /** @type {es3fUniformApiTests.BasicUniform} */ var unif = basicUniforms[i];
   1572 
   1573            if (unif.isUsedInShader) {
   1574                dst += '\t' + variableName + ' *= ';
   1575                dst = this.writeUniformCompareExpr(dst, basicUniforms[i]);
   1576                dst += ';\n';
   1577            } else
   1578                dst += '\t// UNUSED: ' + basicUniforms[i].name + '\n';
   1579        }
   1580 
   1581        return dst;
   1582    };
   1583 
   1584    /**
   1585     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   1586     * @return {string}
   1587     */
   1588    es3fUniformApiTests.UniformCase.prototype.generateVertexSource = function(basicUniforms) {
   1589        /** @type {boolean} */ var isVertexCase = this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.VERTEX || this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.BOTH;
   1590        /** @type {string} */ var result = '';
   1591 
   1592        result += '#version 300 es\n' +
   1593                  'in highp vec4 a_position;\n' +
   1594                  'out mediump float v_vtxOut;\n' +
   1595                  '\n';
   1596 
   1597        if (isVertexCase)
   1598            result = this.writeUniformDefinitions(result);
   1599 
   1600        result += '\n' +
   1601                  'void main (void)\n' +
   1602                  ' {\n' +
   1603                  ' gl_Position = a_position;\n' +
   1604                  ' v_vtxOut = 1.0;\n';
   1605 
   1606        if (isVertexCase)
   1607            result = this.writeUniformComparisons(result, basicUniforms, 'v_vtxOut');
   1608 
   1609        result += '}\n';
   1610 
   1611        return result;
   1612    };
   1613 
   1614    /**
   1615     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   1616     * @return {string}
   1617     */
   1618    es3fUniformApiTests.UniformCase.prototype.generateFragmentSource = function(basicUniforms) {
   1619        /**@type {boolean} */ var isFragmentCase = this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.FRAGMENT || this.m_caseShaderType == es3fUniformApiTests.CaseShaderType.BOTH;
   1620        /**@type {string} */ var result = '';
   1621 
   1622        result += '#version 300 es\n' +
   1623                  'in mediump float v_vtxOut;\n' +
   1624                  '\n';
   1625 
   1626        if (isFragmentCase)
   1627            result = this.writeUniformDefinitions(result);
   1628 
   1629        result += '\n' +
   1630                  'layout(location = 0) out mediump vec4 dEQP_FragColor;\n' +
   1631                  '\n' +
   1632                  'void main (void)\n' +
   1633                  ' {\n' +
   1634                  ' mediump float result = v_vtxOut;\n';
   1635 
   1636        if (isFragmentCase)
   1637            result = this.writeUniformComparisons(result, basicUniforms, 'result');
   1638 
   1639        result += ' dEQP_FragColor = vec4(result, result, result, 1.0);\n' +
   1640                  '}\n';
   1641 
   1642        return result;
   1643    };
   1644 
   1645    /**
   1646     * @param {es3fUniformApiTests.VarValue} value
   1647     */
   1648    es3fUniformApiTests.UniformCase.prototype.setupTexture = function(value) {
   1649        // \note No handling for samplers other than 2D or cube.
   1650 
   1651        assertMsgOptions(
   1652            es3fUniformApiTests.getSamplerLookupReturnType(value.type) == gluShaderUtil.DataType.FLOAT_VEC4,
   1653            'es3fUniformApiTests.UniformCase.prototype.setupTexture - sampler return type should be vec4f', false, true
   1654        );
   1655 
   1656        /** @type {number} */ var width = 32;
   1657        /** @type {number} */ var height = 32;
   1658        /** @type {Array<number>} */ var color = value.val.samplerV.fillColor;
   1659        /** @type {tcuTexture.TextureCube} */ var refTexture;
   1660        /** @type {gluTexture.TextureCube} */ var texture;
   1661 
   1662        if (value.type == gluShaderUtil.DataType.SAMPLER_2D) {
   1663            texture = gluTexture.texture2DFromFormat(gl, gl.RGBA, gl.UNSIGNED_BYTE, width, height);
   1664            refTexture = texture.getRefTexture();
   1665            this.m_textures2d.push(texture);
   1666 
   1667            refTexture.allocLevel(0);
   1668            es3fUniformApiTests.fillWithColor(refTexture.getLevel(0), color);
   1669 
   1670           gl.activeTexture(gl.TEXTURE0 + value.val.samplerV.unit);
   1671            this.m_filledTextureUnits.push(value.val.samplerV.unit);
   1672            texture.upload();
   1673           gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   1674           gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   1675           gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   1676           gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
   1677        } else if (value.type == gluShaderUtil.DataType.SAMPLER_CUBE) {
   1678            assertMsgOptions(width == height, 'es3fUniformApiTests.UniformCase.prototype.setupTexture - non square texture', false, true);
   1679 
   1680            texture = gluTexture.cubeFromFormat(gl, gl.RGBA, gl.UNSIGNED_BYTE, width);
   1681            refTexture = texture.getRefTexture();
   1682            this.m_texturesCube.push(texture);
   1683 
   1684            for (var face in tcuTexture.CubeFace) {
   1685                refTexture.allocLevel(tcuTexture.CubeFace[face], 0);
   1686                es3fUniformApiTests.fillWithColor(refTexture.getLevelFace(0, tcuTexture.CubeFace[face]), color);
   1687            }
   1688 
   1689           gl.activeTexture(gl.TEXTURE0 + value.val.samplerV.unit);
   1690            this.m_filledTextureUnits.push(value.val.samplerV.unit);
   1691            texture.upload();
   1692           gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   1693           gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   1694           gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   1695           gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
   1696        } else
   1697            throw new Error('es3fUniformApiTests.UniformCase.prototype.setupTexture - Invalid sampler type');
   1698    };
   1699 
   1700    /**
   1701     * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} basicUniformReportsDst
   1702     * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
   1703     * @param {WebGLProgram} programGL
   1704     * @return {boolean}
   1705     */
   1706    es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne = function(basicUniformReportsDst, basicUniformReportsRef, programGL) {
   1707        /** @type {WebGLProgram} */ var numActiveUniforms;
   1708        /** @type {boolean} */ var success = true;
   1709 
   1710       numActiveUniforms = /** @type {WebGLProgram} */ (gl.getProgramParameter(programGL, gl.ACTIVE_UNIFORMS));
   1711        bufferedLogToConsole('// Number of active uniforms reported: ' + numActiveUniforms);
   1712 
   1713        for (var unifNdx = 0; unifNdx < numActiveUniforms; unifNdx++) {
   1714            /** @type {number} (GLint)*/ var reportedSize = -1;
   1715            /** @type {number} (GLenum)*/ var reportedTypeGL = gl.NONE;
   1716            /** @type {gluShaderUtil.DataType} */ var reportedType;
   1717            /** @type {string} */ var reportedNameStr;
   1718            /** @type {WebGLActiveInfo} */ var activeInfo;
   1719 
   1720           activeInfo = gl.getActiveUniform(programGL, unifNdx);
   1721 
   1722            reportedNameStr = activeInfo.name;
   1723            reportedTypeGL = activeInfo.type;
   1724            reportedSize = activeInfo.size;
   1725 
   1726            reportedType = gluShaderUtil.getDataTypeFromGLType(reportedTypeGL);
   1727 
   1728            checkMessage(reportedType !== undefined, 'Invalid uniform type');
   1729 
   1730            bufferedLogToConsole('// Got name = ' + reportedNameStr + ', size = ' + reportedSize + ', type = ' + gluShaderUtil.getDataTypeName(reportedType));
   1731 
   1732            // Ignore built-in uniforms.
   1733            if (reportedNameStr.indexOf('gl_') == -1) {
   1734                /** @type {number} */ var referenceNdx;
   1735                for (referenceNdx = 0; referenceNdx < basicUniformReportsRef.length; referenceNdx++) {
   1736                    if (basicUniformReportsRef[referenceNdx].name == reportedNameStr)
   1737                        break;
   1738                }
   1739 
   1740                if (referenceNdx >= basicUniformReportsRef.length) {
   1741                    bufferedLogToConsole('// FAILURE: invalid non-built-in uniform name reported');
   1742                    success = false;
   1743                } else {
   1744                    /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var reference = basicUniformReportsRef[referenceNdx];
   1745 
   1746                    assertMsgOptions(
   1747                        reference.type !== undefined,
   1748                        'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - type is undefined',
   1749                        false,
   1750                        true
   1751                    );
   1752                    assertMsgOptions(
   1753                        reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader),
   1754                        'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - uniform min size does not match usage in shader',
   1755                        false,
   1756                        true
   1757                    );
   1758                    assertMsgOptions(
   1759                        reference.minSize <= reference.maxSize,
   1760                        'es3fUniformApiTests.UniformCase.prototype.getActiveUniformsOneByOne - uniform min size bigger than max size',
   1761                        false,
   1762                        true
   1763                    );
   1764 
   1765                    if (es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, reportedNameStr) !== null) {
   1766                        bufferedLogToConsole('// FAILURE: same uniform name reported twice');
   1767                        success = false;
   1768                    }
   1769 
   1770                    basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportGL(reportedNameStr, reportedNameStr.length, reportedSize, reportedType, unifNdx));
   1771 
   1772                    if (reportedType != reference.type) {
   1773                        bufferedLogToConsole('// FAILURE: wrong type reported, should be ' + gluShaderUtil.getDataTypeName(reference.type));
   1774                        success = false;
   1775                    }
   1776                    if (reportedSize < reference.minSize || reportedSize > reference.maxSize) {
   1777                        bufferedLogToConsole('// FAILURE: wrong size reported, should be ' +
   1778                            (reference.minSize == reference.maxSize ? reference.minSize : 'in the range [' + reference.minSize + ', ' + reference.maxSize + ']'));
   1779 
   1780                        success = false;
   1781                    }
   1782                }
   1783            }
   1784        }
   1785 
   1786        for (var i = 0; i < basicUniformReportsRef.length; i++) {
   1787            /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var expected = basicUniformReportsRef[i];
   1788            if (expected.isUsedInShader && es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, expected.name) === null) {
   1789                bufferedLogToConsole('// FAILURE: uniform with name ' + expected.name + ' was not reported by GL');
   1790                success = false;
   1791            }
   1792        }
   1793 
   1794        return success;
   1795    };
   1796 
   1797    /**
   1798     * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} basicUniformReportsDst
   1799     * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
   1800     * @param {WebGLProgram} programGL
   1801     * @return {boolean}
   1802     */
   1803    es3fUniformApiTests.UniformCase.prototype.getActiveUniforms = function(basicUniformReportsDst, basicUniformReportsRef, programGL) {
   1804        /** @type {Array<string>} */ var queryNames = new Array(basicUniformReportsRef.length);
   1805        /** @type {Array<string>} */ var queryNamesC = new Array(basicUniformReportsRef.length);
   1806        /** @type {Array<number>} (GLuint) */ var uniformIndices = new Array(basicUniformReportsRef.length);
   1807        /** @type {Array<number>} */ var validUniformIndices = []; // This shall have the same contents, and in same order, as uniformIndices, but with gl.INVALID_INDEX entries removed.
   1808        /** @type {boolean} */ var success = true;
   1809 
   1810        for (var i = 0; i < basicUniformReportsRef.length; i++) {
   1811            /** @type {string} */ var name = basicUniformReportsRef[i].name;
   1812            queryNames[i] = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && name[name.length - 1] == ']' ? es3fUniformApiTests.beforeLast(name, '[') : name;
   1813            queryNamesC[i] = queryNames[i];
   1814        }
   1815 
   1816       uniformIndices = gl.getUniformIndices(programGL, queryNamesC);
   1817 
   1818        for (var i = 0; i < uniformIndices.length; i++) {
   1819            if (uniformIndices[i] != gl.INVALID_INDEX)
   1820                validUniformIndices.push(uniformIndices[i]);
   1821            else {
   1822                if (basicUniformReportsRef[i].isUsedInShader) {
   1823                    bufferedLogToConsole('// FAILURE: uniform with name ' + basicUniformReportsRef[i].name + ' received gl.INVALID_INDEX');
   1824                    success = false;
   1825                }
   1826            }
   1827        }
   1828 
   1829        if (validUniformIndices.length > 0) {
   1830            /** @type {Array<string>} */ var uniformNameBuf = new Array(validUniformIndices.length);
   1831            /** @type {Array<number>} (GLint) */ var uniformSizeBuf = new Array(validUniformIndices.length);
   1832            /** @type {Array<number>} (GLint) */ var uniformTypeBuf = new Array(validUniformIndices.length);
   1833 
   1834           uniformSizeBuf = gl.getActiveUniforms(programGL, validUniformIndices, gl.UNIFORM_SIZE);
   1835           uniformTypeBuf = gl.getActiveUniforms(programGL, validUniformIndices, gl.UNIFORM_TYPE);
   1836 
   1837            /** @type {number} */ var validNdx = -1; // Keeps the corresponding index to validUniformIndices while unifNdx is the index to uniformIndices.
   1838            for (var unifNdx = 0; unifNdx < uniformIndices.length; unifNdx++) {
   1839                if (uniformIndices[unifNdx] == gl.INVALID_INDEX)
   1840                    continue;
   1841 
   1842                validNdx++;
   1843 
   1844                /** @type {es3fUniformApiTests.BasicUniformReportRef} */ var reference = basicUniformReportsRef[unifNdx];
   1845                /** @type {number} */ var reportedIndex = validUniformIndices[validNdx];
   1846                /** @type {number} */ var reportedNameLength = reference.name.length;
   1847                /** @type {number} */ var reportedSize = uniformSizeBuf[validNdx];
   1848                /** @type {gluShaderUtil.DataType} */ var reportedType = gluShaderUtil.getDataTypeFromGLType(uniformTypeBuf[validNdx]);
   1849                /** @type {string} */ var reportedNameStr = reference.name;
   1850 
   1851                bufferedLogToConsole('// Got name size = ' + reportedSize +
   1852                    ', type = ' + gluShaderUtil.getDataTypeName(reportedType) +
   1853                    ' for the uniform at index ' + reportedIndex + ' (' + reference.name + ')');
   1854 
   1855                assertMsgOptions(
   1856                    reference.type !== undefined,
   1857                    'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - type is undefined',
   1858                    false,
   1859                    true
   1860                );
   1861                assertMsgOptions(
   1862                    reference.minSize >= 1 || (reference.minSize == 0 && !reference.isUsedInShader),
   1863                    'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - uniform min size does not match usage in shader',
   1864                    false,
   1865                    true
   1866                );
   1867                assertMsgOptions(
   1868                    reference.minSize <= reference.maxSize,
   1869                    'es3fUniformApiTests.UniformCase.prototype.getActiveUniforms - uniform min size bigger than max size',
   1870                    false,
   1871                    true
   1872                );
   1873 
   1874                if (es3fUniformApiTests.BasicUniformReportGL.findWithName(basicUniformReportsDst, reportedNameStr) !== null) {
   1875                    bufferedLogToConsole('// FAILURE: same uniform name reported twice');
   1876                    success = false;
   1877                }
   1878                basicUniformReportsDst.push(new es3fUniformApiTests.BasicUniformReportGL(reference.name, reportedNameLength, reportedSize, reportedType, reportedIndex));
   1879 
   1880                if (reportedType != reference.type) {
   1881                    bufferedLogToConsole('// FAILURE: wrong type reported, should be ' + gluShaderUtil.getDataTypeName(reference.type));
   1882                    success = false;
   1883                }
   1884 
   1885                if (reportedSize < reference.minSize || reportedSize > reference.maxSize) {
   1886                    bufferedLogToConsole('// FAILURE: wrong size reported, should be ' +
   1887                        (reference.minSize == reference.maxSize ? reference.minSize : 'in the range [' + reference.minSize + ', ' + reference.maxSize + ']'));
   1888 
   1889                    success = false;
   1890                }
   1891            }
   1892        }
   1893 
   1894        return success;
   1895    };
   1896 
   1897    /**
   1898     * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} uniformResults
   1899     * @param {Array<es3fUniformApiTests.BasicUniformReportGL>} uniformsResults
   1900     * @return {boolean}
   1901     */
   1902    es3fUniformApiTests.UniformCase.prototype.uniformVsUniformsComparison = function(uniformResults, uniformsResults) {
   1903        /** @type {boolean} */ var success = true;
   1904        /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformsResult;
   1905 
   1906        for (var uniformResultNdx = 0; uniformResultNdx < uniformResults.length; uniformResultNdx++) {
   1907            /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformResult = uniformResults[uniformResultNdx];
   1908            /** @type {string} */ var uniformName = uniformResult.name;
   1909            uniformsResult = es3fUniformApiTests.BasicUniformReportGL.findWithName(uniformsResults, uniformName);
   1910 
   1911            if (uniformsResult !== null) {
   1912                bufferedLogToConsole('// Checking uniform ' + uniformName);
   1913 
   1914                if (uniformResult.index != uniformsResult.index) {
   1915                    bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetUniformIndices() gave different indices for uniform ' + uniformName);
   1916                    success = false;
   1917                }
   1918                if (uniformResult.nameLength != uniformsResult.nameLength) {
   1919                    bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave incompatible name lengths for uniform ' + uniformName);
   1920                    success = false;
   1921                }
   1922                if (uniformResult.size != uniformsResult.size) {
   1923                    bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave different sizes for uniform ' + uniformName);
   1924                    success = false;
   1925                }
   1926                if (uniformResult.type != uniformsResult.type) {
   1927                    bufferedLogToConsole('// FAILURE: glGetActiveUniform() and glGetActiveUniforms() gave different types for uniform ' + uniformName);
   1928                    success = false;
   1929                }
   1930            } else {
   1931                bufferedLogToConsole('// FAILURE: uniform ' + uniformName + ' was reported active by glGetActiveUniform() but not by glGetUniformIndices()');
   1932                success = false;
   1933            }
   1934        }
   1935 
   1936        for (var uniformsResultNdx = 0; uniformsResultNdx < uniformsResults.length; uniformsResultNdx++) {
   1937            uniformsResult = uniformsResults[uniformsResultNdx];
   1938            /** @type {string} */ var uniformsName = uniformsResult.name;
   1939            /** @type {es3fUniformApiTests.BasicUniformReportGL} */ var uniformsResultIt = es3fUniformApiTests.BasicUniformReportGL.findWithName(uniformsResults, uniformsName);
   1940 
   1941            if (uniformsResultIt === null) {
   1942                bufferedLogToConsole('// FAILURE: uniform ' + uniformsName + ' was reported active by glGetUniformIndices() but not by glGetActiveUniform()');
   1943                success = false;
   1944            }
   1945        }
   1946 
   1947        return success;
   1948    };
   1949 
   1950    /**
   1951     * @param {Array<es3fUniformApiTests.VarValue>} valuesDst
   1952     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   1953     * @param {WebGLProgram} programGL
   1954     * @return {boolean}
   1955     */
   1956    es3fUniformApiTests.UniformCase.prototype.getUniforms = function(valuesDst, basicUniforms, programGL) {
   1957        /** @type {boolean} */ var success = true;
   1958 
   1959        for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
   1960            /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
   1961            /** @type {string} */ var queryName = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? es3fUniformApiTests.beforeLast(uniform.name, '[') : uniform.name;
   1962            /** @type {WebGLUniformLocation} */ var location = gl.getUniformLocation(programGL, queryName);
   1963            /** @type {number} */ var size = gluShaderUtil.getDataTypeScalarSize(uniform.type);
   1964            /** @type {es3fUniformApiTests.VarValue} */ var value = new es3fUniformApiTests.VarValue();
   1965 
   1966            if (!location) {
   1967                value.type = gluShaderUtil.DataType.INVALID;
   1968                valuesDst.push(value);
   1969                if (uniform.isUsedInShader) {
   1970                    bufferedLogToConsole('// FAILURE: ' + uniform.name + ' was used in shader, but has location -1');
   1971                    success = false;
   1972                }
   1973                continue;
   1974            }
   1975 
   1976            value.type = uniform.type;
   1977 
   1978            var result = /** @type {number} */ (gl.getUniform(programGL, location));
   1979 
   1980            if (gluShaderUtil.isDataTypeSampler(uniform.type)) {
   1981                value.val = new es3fUniformApiTests.SamplerV();
   1982                value.val.samplerV.unit = result;
   1983            } else
   1984                value.val = /** @type {Array<number>} */ (result.length === undefined ? [result] : result);
   1985 
   1986            valuesDst.push(value);
   1987 
   1988            bufferedLogToConsole('// Got ' + uniform.name + ' value ' + es3fUniformApiTests.apiVarValueStr(value));
   1989        }
   1990 
   1991        return success;
   1992    };
   1993 
   1994    /**
   1995     * @param {Array<es3fUniformApiTests.VarValue>} values
   1996     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   1997     * @return {boolean}
   1998     */
   1999    es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues = function(values, basicUniforms) {
   2000        /** @type {boolean} */ var success = true;
   2001 
   2002        assertMsgOptions(
   2003            values.length == basicUniforms.length,
   2004            'es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues - lengths do not match',
   2005            false,
   2006            true
   2007        );
   2008 
   2009        for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
   2010            /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
   2011            /** @type {es3fUniformApiTests.VarValue} */ var unifValue = values[unifNdx];
   2012            /** @type {number} */ var valSize = gluShaderUtil.getDataTypeScalarSize(uniform.type);
   2013 
   2014            bufferedLogToConsole('// Checking uniform ' + uniform.name);
   2015 
   2016            if (unifValue.type == gluShaderUtil.DataType.INVALID) // This happens when glGetUniformLocation() returned -1.
   2017                continue;
   2018 
   2019            var CHECK_UNIFORM = function(ZERO) {
   2020                do {
   2021                    for (var i = 0; i < valSize; i++) {
   2022                        if (unifValue.val[i] != ZERO) {
   2023                            bufferedLogToConsole('// FAILURE: uniform ' + uniform.name + ' has non-zero initial value');
   2024                            success = false;
   2025                        }
   2026                    }
   2027                } while (false);
   2028            };
   2029 
   2030            if (gluShaderUtil.isDataTypeFloatOrVec(uniform.type) || gluShaderUtil.isDataTypeMatrix(uniform.type))
   2031                CHECK_UNIFORM(0.0);
   2032            else if (gluShaderUtil.isDataTypeIntOrIVec(uniform.type))
   2033                CHECK_UNIFORM(0);
   2034            else if (gluShaderUtil.isDataTypeUintOrUVec(uniform.type))
   2035                CHECK_UNIFORM(0);
   2036            else if (gluShaderUtil.isDataTypeBoolOrBVec(uniform.type))
   2037                CHECK_UNIFORM(false);
   2038            else if (gluShaderUtil.isDataTypeSampler(uniform.type)) {
   2039                if (unifValue.val.samplerV.unit != 0) {
   2040                    bufferedLogToConsole('// FAILURE: uniform ' + uniform.name + ' has non-zero initial value');
   2041                    success = false;
   2042                }
   2043            } else
   2044                throw new Error('es3fUniformApiTests.UniformCase.prototype.checkUniformDefaultValues - invalid uniform type');
   2045        }
   2046 
   2047        return success;
   2048    };
   2049 
   2050    /**
   2051     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   2052     * @param {WebGLProgram} programGL
   2053     * @param {deRandom.Random} rnd
   2054     */
   2055    es3fUniformApiTests.UniformCase.prototype.assignUniforms = function(basicUniforms, programGL, rnd) {
   2056        /** @type {boolean} */ var transpose = false; //No support to transpose uniform matrices in WebGL, must always be false. (this.m_features.MATRIXMODE_ROWMAJOR) != 0;
   2057        /** @type {boolean} (GLboolean) */ var transposeGL = transpose;
   2058        /** @type {gluShaderUtil.DataType} */ var boolApiType = this.m_features.BOOLEANAPITYPE_INT ? gluShaderUtil.DataType.INT :
   2059                                                this.m_features.BOOLEANAPITYPE_UINT ? gluShaderUtil.DataType.UINT :
   2060                                                gluShaderUtil.DataType.FLOAT;
   2061 
   2062        for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
   2063            /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
   2064            /** @type {boolean} */ var isArrayMember = uniform.elemNdx >= 0;
   2065            /** @type {string} */ var queryName = this.m_features.ARRAY_FIRST_ELEM_NAME_NO_INDEX && uniform.elemNdx == 0 ? es3fUniformApiTests.beforeLast(uniform.name, '[') : uniform.name;
   2066            /** @type {number} */ var numValuesToAssign = !isArrayMember ? 1 :
   2067                                                        this.m_features.ARRAYASSIGN_FULL ? (uniform.elemNdx == 0 ? uniform.rootSize : 0) :
   2068                                                        this.m_features.ARRAYASSIGN_BLOCKS_OF_TWO ? (uniform.elemNdx % 2 == 0 ? 2 : 0) :
   2069                                                        /* Default: assign array elements separately */ 1;
   2070 
   2071            assertMsgOptions(
   2072                numValuesToAssign >= 0,
   2073                'es3fUniformApiTests.UniformCase.prototype.assignUniforms - number of values to assign not a positive integer',
   2074                false,
   2075                true
   2076            );
   2077            assertMsgOptions(
   2078                numValuesToAssign == 1 || isArrayMember,
   2079                'es3fUniformApiTests.UniformCase.prototype.assignUniforms - not an array member and number of values to assign not 1',
   2080                false,
   2081                true
   2082            );
   2083 
   2084            if (numValuesToAssign == 0) {
   2085                bufferedLogToConsole('// es3fUniformApiTests.Uniform ' + uniform.name + ' is covered by another glUniform*v() call to the same array');
   2086                continue;
   2087            }
   2088 
   2089            /** @type {WebGLUniformLocation} */ var location = gl.getUniformLocation(programGL, queryName);
   2090            /** @type {number} */ var typeSize = gluShaderUtil.getDataTypeScalarSize(uniform.type);
   2091            /** @type {boolean} */ var assignByValue = this.m_features.UNIFORMFUNC_VALUE && !gluShaderUtil.isDataTypeMatrix(uniform.type) && numValuesToAssign == 1;
   2092            /** @type {Array<es3fUniformApiTests.VarValue>} */ var valuesToAssign = [];
   2093            /** @type {Array<number>} */ var buffer;
   2094 
   2095            for (var i = 0; i < numValuesToAssign; i++) {
   2096                /** @type {string} */ var curName = isArrayMember ? es3fUniformApiTests.beforeLast(uniform.rootName, '[') + '[' + (uniform.elemNdx + i) + ']' : uniform.name;
   2097                /** @type {es3fUniformApiTests.VarValue} */ var unifValue = new es3fUniformApiTests.VarValue();
   2098 
   2099                if (isArrayMember) {
   2100                    /** @type {es3fUniformApiTests.BasicUniform} */ var elemUnif = es3fUniformApiTests.BasicUniform.findWithName(basicUniforms, curName);
   2101                    if (elemUnif === null)
   2102                        continue;
   2103                    unifValue = elemUnif.finalValue;
   2104                } else
   2105                    unifValue = uniform.finalValue;
   2106 
   2107                /** @type {es3fUniformApiTests.VarValue} */ var apiValue = gluShaderUtil.isDataTypeBoolOrBVec(unifValue.type) ? es3fUniformApiTests.getRandomBoolRepresentation(unifValue, boolApiType, rnd) :
   2108                gluShaderUtil.isDataTypeSampler(unifValue.type) ? es3fUniformApiTests.getSamplerUnitValue(unifValue) :
   2109                                        unifValue;
   2110 
   2111                valuesToAssign.push(gluShaderUtil.isDataTypeMatrix(apiValue.type) && transpose ? es3fUniformApiTests.getTransposeMatrix(apiValue) : apiValue);
   2112 
   2113                if (gluShaderUtil.isDataTypeBoolOrBVec(uniform.type))
   2114                    bufferedLogToConsole('// Using type ' + gluShaderUtil.getDataTypeName(boolApiType) + ' to set boolean value ' + es3fUniformApiTests.apiVarValueStr(unifValue) + ' for ' + curName);
   2115                else if (gluShaderUtil.isDataTypeSampler(uniform.type))
   2116                    bufferedLogToConsole('// Texture for the sampler uniform ' + curName + ' will be filled with color ' + es3fUniformApiTests.apiVarValueStr(es3fUniformApiTests.getSamplerFillValue(uniform.finalValue)));
   2117            }
   2118 
   2119            assertMsgOptions(
   2120                valuesToAssign.length > 0,
   2121                'es3fUniformApiTests.UniformCase.prototype.assignUniforms - values quantity less than one',
   2122                false,
   2123                true
   2124            );
   2125 
   2126            if (gluShaderUtil.isDataTypeFloatOrVec(valuesToAssign[0].type)) {
   2127                if (assignByValue) {
   2128                    switch (typeSize) {
   2129                        case 1: gl.uniform1f(location, valuesToAssign[0].val[0]); break;
   2130                        case 2: gl.uniform2f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
   2131                        case 3: gl.uniform3f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
   2132                        case 4: gl.uniform4f(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
   2133                        default:
   2134                            throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
   2135                    }
   2136                } else {
   2137                    buffer = new Array(valuesToAssign.length * typeSize);
   2138                    for (var i = 0; i < buffer.length; i++)
   2139                        buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
   2140 
   2141                    switch (typeSize) {
   2142                        case 1: gl.uniform1fv(location, buffer); break;
   2143                        case 2: gl.uniform2fv(location, buffer); break;
   2144                        case 3: gl.uniform3fv(location, buffer); break;
   2145                        case 4: gl.uniform4fv(location, buffer); break;
   2146                        default:
   2147                            throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
   2148                    }
   2149                }
   2150            } else if (gluShaderUtil.isDataTypeMatrix(valuesToAssign[0].type)) {
   2151                assertMsgOptions(
   2152                    !assignByValue,
   2153                    'es3fUniformApiTests.UniformCase.prototype.assignUniforms - assigning by value in matrix type',
   2154                    false, true
   2155                );
   2156 
   2157                buffer = new Array(valuesToAssign.length * typeSize);
   2158                for (var i = 0; i < buffer.length; i++)
   2159                    buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
   2160 
   2161                switch (uniform.type) {
   2162                    case gluShaderUtil.DataType.FLOAT_MAT2: gl.uniformMatrix2fv(location, transposeGL, new Float32Array(buffer)); break;
   2163                    case gluShaderUtil.DataType.FLOAT_MAT3: gl.uniformMatrix3fv(location, transposeGL, new Float32Array(buffer)); break;
   2164                    case gluShaderUtil.DataType.FLOAT_MAT4: gl.uniformMatrix4fv(location, transposeGL, new Float32Array(buffer)); break;
   2165                    case gluShaderUtil.DataType.FLOAT_MAT2X3: gl.uniformMatrix2x3fv(location, transposeGL, new Float32Array(buffer)); break;
   2166                    case gluShaderUtil.DataType.FLOAT_MAT2X4: gl.uniformMatrix2x4fv(location, transposeGL, new Float32Array(buffer)); break;
   2167                    case gluShaderUtil.DataType.FLOAT_MAT3X2: gl.uniformMatrix3x2fv(location, transposeGL, new Float32Array(buffer)); break;
   2168                    case gluShaderUtil.DataType.FLOAT_MAT3X4: gl.uniformMatrix3x4fv(location, transposeGL, new Float32Array(buffer)); break;
   2169                    case gluShaderUtil.DataType.FLOAT_MAT4X2: gl.uniformMatrix4x2fv(location, transposeGL, new Float32Array(buffer)); break;
   2170                    case gluShaderUtil.DataType.FLOAT_MAT4X3: gl.uniformMatrix4x3fv(location, transposeGL, new Float32Array(buffer)); break;
   2171                    default:
   2172                        throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid uniform type');
   2173                }
   2174            } else if (gluShaderUtil.isDataTypeIntOrIVec(valuesToAssign[0].type)) {
   2175                if (assignByValue) {
   2176                    switch (typeSize) {
   2177                        case 1: gl.uniform1i(location, valuesToAssign[0].val[0]); break;
   2178                        case 2: gl.uniform2i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
   2179                        case 3: gl.uniform3i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
   2180                        case 4: gl.uniform4i(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
   2181                        default:
   2182                            throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
   2183                    }
   2184                } else {
   2185                    buffer = new Array(valuesToAssign.length * typeSize);
   2186                    for (var i = 0; i < buffer.length; i++)
   2187                        buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
   2188 
   2189                    switch (typeSize) {
   2190                        case 1: gl.uniform1iv(location, buffer); break;
   2191                        case 2: gl.uniform2iv(location, buffer); break;
   2192                        case 3: gl.uniform3iv(location, buffer); break;
   2193                        case 4: gl.uniform4iv(location, buffer); break;
   2194                        default:
   2195                            throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
   2196                    }
   2197                }
   2198            } else if (gluShaderUtil.isDataTypeUintOrUVec(valuesToAssign[0].type)) {
   2199                if (assignByValue) {
   2200                    switch (typeSize) {
   2201                        case 1: gl.uniform1ui(location, valuesToAssign[0].val[0]); break;
   2202                        case 2: gl.uniform2ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1]); break;
   2203                        case 3: gl.uniform3ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2]); break;
   2204                        case 4: gl.uniform4ui(location, valuesToAssign[0].val[0], valuesToAssign[0].val[1], valuesToAssign[0].val[2], valuesToAssign[0].val[3]); break;
   2205                        default:
   2206                            throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
   2207                    }
   2208                } else {
   2209                    buffer = new Array(valuesToAssign.length * typeSize);
   2210                    for (var i = 0; i < buffer.length; i++)
   2211                        buffer[i] = valuesToAssign[Math.floor(i / typeSize)].val[i % typeSize];
   2212 
   2213                    switch (typeSize) {
   2214                        case 1: gl.uniform1uiv(location, buffer); break;
   2215                        case 2: gl.uniform2uiv(location, buffer); break;
   2216                        case 3: gl.uniform3uiv(location, buffer); break;
   2217                        case 4: gl.uniform4uiv(location, buffer); break;
   2218                        default:
   2219                            throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid type size');
   2220                    }
   2221                }
   2222            } else if (gluShaderUtil.isDataTypeSampler(valuesToAssign[0].type)) {
   2223                if (assignByValue)
   2224                   gl.uniform1i(location, uniform.finalValue.val.samplerV.unit);
   2225                else {
   2226                    var unit = /** @type {Array<number>} */ (uniform.finalValue.val);
   2227                   gl.uniform1iv(location, unit);
   2228                }
   2229            } else
   2230                throw new Error('es3fUniformApiTests.UniformCase.prototype.assignUniforms - Invalid uniform type');
   2231        }
   2232    };
   2233 
   2234    /**
   2235     * @param {Array<es3fUniformApiTests.VarValue>} values
   2236     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   2237     * @return {boolean}
   2238     */
   2239    es3fUniformApiTests.UniformCase.prototype.compareUniformValues = function(values, basicUniforms) {
   2240        /** @type {boolean} */ var success = true;
   2241 
   2242        for (var unifNdx = 0; unifNdx < basicUniforms.length; unifNdx++) {
   2243            /** @type {es3fUniformApiTests.BasicUniform} */ var uniform = basicUniforms[unifNdx];
   2244            /** @type {es3fUniformApiTests.VarValue} */ var unifValue = values[unifNdx];
   2245 
   2246            bufferedLogToConsole('// Checking uniform ' + uniform.name);
   2247 
   2248            if (unifValue.type == gluShaderUtil.DataType.INVALID) // This happens when glGetUniformLocation() returned -1.
   2249                continue;
   2250 
   2251            if (!es3fUniformApiTests.apiVarValueEquals(unifValue, uniform.finalValue)) {
   2252                bufferedLogToConsole('// FAILURE: value obtained with glGetUniform*() for uniform ' + uniform.name + ' differs from value set with glUniform*()');
   2253                success = false;
   2254            }
   2255        }
   2256 
   2257        return success;
   2258    };
   2259 
   2260    /** @const @type {number} */ es3fUniformApiTests.VIEWPORT_WIDTH = 128;
   2261    /** @const @type {number} */ es3fUniformApiTests.VIEWPORT_HEIGHT = 128;
   2262 
   2263    /**
   2264     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   2265     * @param {gluShaderProgram.ShaderProgram} program
   2266     * @param {deRandom.Random} rnd
   2267     * @return {boolean}
   2268     */
   2269    es3fUniformApiTests.UniformCase.prototype.renderTest = function(basicUniforms, program, rnd) {
   2270        //const tcu::RenderTarget& renderTarget = m_context.getRenderTarget();
   2271        /** @const */ var viewportW = Math.min(gl.canvas.width, es3fUniformApiTests.VIEWPORT_WIDTH);
   2272        /** @const */ var viewportH = Math.min(gl.canvas.height, es3fUniformApiTests.VIEWPORT_HEIGHT);
   2273        /** @const */ var viewportX = rnd.getInt(0, gl.canvas.width - viewportW);
   2274        /** @const */ var viewportY = rnd.getInt(0, gl.canvas.height - viewportH);
   2275        /** @type {tcuSurface.Surface} */ var renderedImg = new tcuSurface.Surface(viewportW, viewportH);
   2276 
   2277        // Assert that no two samplers of different types have the same texture unit - this is an error in GL.
   2278        for (var i = 0; i < basicUniforms.length; i++) {
   2279            if (gluShaderUtil.isDataTypeSampler(basicUniforms[i].type)) {
   2280                for (var j = 0; j < i; j++) {
   2281                    if (gluShaderUtil.isDataTypeSampler(basicUniforms[j].type) && basicUniforms[i].type != basicUniforms[j].type)
   2282                        assertMsgOptions(
   2283                            basicUniforms[i].finalValue.val.samplerV.unit != basicUniforms[j].finalValue.val.samplerV.unit,
   2284                            'es3fUniformApiTests.UniformCase.prototype.renderTest - sampler units have the same texture unit',
   2285                            false, true
   2286                        );
   2287                }
   2288            }
   2289        }
   2290 
   2291        for (var i = 0; i < basicUniforms.length; i++) {
   2292            if (gluShaderUtil.isDataTypeSampler(basicUniforms[i].type) && this.m_filledTextureUnits.indexOf(basicUniforms[i].finalValue.val) == -1) {
   2293                bufferedLogToConsole('// Filling texture at unit ' + es3fUniformApiTests.apiVarValueStr(basicUniforms[i].finalValue) + ' with color ' + es3fUniformApiTests.shaderVarValueStr(basicUniforms[i].finalValue));
   2294                this.setupTexture(basicUniforms[i].finalValue);
   2295            }
   2296        }
   2297 
   2298       gl.viewport(viewportX, viewportY, viewportW, viewportH);
   2299 
   2300        /** @type {Float32Array} */ var position = new Float32Array([
   2301            -1.0, -1.0, 0.0, 1.0,
   2302            -1.0, 1.0, 0.0, 1.0,
   2303            1.0, -1.0, 0.0, 1.0,
   2304            1.0, 1.0, 0.0, 1.0
   2305        ]);
   2306 
   2307        /** @type {Uint16Array} */
   2308        var indices = new Uint16Array([0, 1, 2, 2, 1, 3]);
   2309 
   2310        /** @type {number} */ var posLoc = gl.getAttribLocation(program.getProgram(), 'a_position');
   2311        gl.enableVertexAttribArray(posLoc);
   2312 
   2313        var gl_position_buffer = gl.createBuffer();
   2314        gl.bindBuffer(gl.ARRAY_BUFFER, gl_position_buffer);
   2315        gl.bufferData(gl.ARRAY_BUFFER, position, gl.STATIC_DRAW);
   2316        gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
   2317 
   2318        var gl_index_buffer = gl.createBuffer();
   2319        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_index_buffer);
   2320        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
   2321 
   2322        gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
   2323 
   2324        renderedImg.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
   2325 
   2326        /** @type {number} */ var numFailedPixels = 0;
   2327        var whitePixel = new gluDrawUtil.Pixel([255.0, 255.0, 255.0, 255.0]);
   2328        for (var y = 0; y < renderedImg.getHeight(); y++) {
   2329            for (var x = 0; x < renderedImg.getWidth(); x++) {
   2330                var currentPixel = new gluDrawUtil.Pixel(renderedImg.getPixel(x, y));
   2331                if (!whitePixel.equals(currentPixel))
   2332                    numFailedPixels += 1;
   2333            }
   2334        }
   2335 
   2336        if (numFailedPixels > 0) {
   2337            //TODO: log << TestLog::Image("RenderedImage", "Rendered image", renderedImg);
   2338            bufferedLogToConsole('FAILURE: image comparison failed, got ' + numFailedPixels + ' non-white pixels');
   2339            return false;
   2340        } else {
   2341            bufferedLogToConsole('Success: got all-white pixels (all uniforms have correct values)');
   2342            return true;
   2343        }
   2344    };
   2345 
   2346    /**
   2347     * @return {tcuTestCase.IterateResult}
   2348     */
   2349    es3fUniformApiTests.UniformCase.prototype.iterate = function() {
   2350        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ deRandom.getBaseSeed());
   2351        /** @type {Array<es3fUniformApiTests.BasicUniform>} */ var basicUniforms = [];
   2352        /** @type {Array<es3fUniformApiTests.BasicUniformReportRef>} */ var basicUniformReportsRef = [];
   2353 
   2354        /** @type {number} */ var samplerUnitCounter = 0;
   2355        for (var i = 0; i < this.m_uniformCollection.getNumUniforms(); i++)
   2356            samplerUnitCounter = this.generateBasicUniforms(basicUniforms, basicUniformReportsRef, this.m_uniformCollection.getUniform(i).type, this.m_uniformCollection.getUniform(i).name, true, samplerUnitCounter, rnd);
   2357 
   2358        /** @type {string} */ var vertexSource = this.generateVertexSource(basicUniforms);
   2359        /** @type {string} */ var fragmentSource = this.generateFragmentSource(basicUniforms);
   2360        /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertexSource, fragmentSource));
   2361 
   2362        bufferedLogToConsole(program.getProgramInfo().infoLog);
   2363 
   2364        if (!program.isOk()) {
   2365            testFailedOptions('Compile failed', false);
   2366            return tcuTestCase.IterateResult.STOP;
   2367        }
   2368 
   2369       gl.useProgram(program.getProgram());
   2370 
   2371        /** @type {boolean} */ var success = this.test(basicUniforms, basicUniformReportsRef, program, rnd);
   2372        assertMsgOptions(success, '', true, false);
   2373 
   2374        return tcuTestCase.IterateResult.STOP;
   2375    };
   2376 
   2377    /**
   2378     * @enum {number}
   2379     */
   2380    es3fUniformApiTests.CaseType = {
   2381        UNIFORM: 0, //!< Check info returned by glGetActiveUniform().
   2382        INDICES_UNIFORMSIV: 1, //!< Check info returned by glGetUniformIndices() + glGetActiveUniforms(). TODO: Check 'IV' part
   2383        CONSISTENCY: 2 //!< Query info with both above methods, and check consistency.
   2384    };
   2385 
   2386    /**
   2387     * es3fUniformApiTests.UniformInfoQueryCase class
   2388     * @constructor
   2389     * @param {string} name
   2390     * @param {string} description
   2391     * @param {es3fUniformApiTests.CaseShaderType} shaderType
   2392     * @param {es3fUniformApiTests.UniformCollection} uniformCollection
   2393     * @param {es3fUniformApiTests.CaseType} caseType
   2394     * @param {es3fUniformApiTests.Feature} additionalFeatures
   2395     * @extends {es3fUniformApiTests.UniformCase}
   2396     */
   2397    es3fUniformApiTests.UniformInfoQueryCase = function(name, description, shaderType, uniformCollection, caseType, additionalFeatures) {
   2398        es3fUniformApiTests.UniformCase.call(this, name, description);
   2399        this.newB(shaderType, uniformCollection, additionalFeatures);
   2400        /** @type {es3fUniformApiTests.CaseType} */ this.m_caseType = caseType;
   2401    };
   2402 
   2403    es3fUniformApiTests.UniformInfoQueryCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
   2404    /** Constructor restore */
   2405    es3fUniformApiTests.UniformInfoQueryCase.prototype.constructor = es3fUniformApiTests.UniformInfoQueryCase;
   2406 
   2407    /**
   2408     * @param {es3fUniformApiTests.CaseType} caseType
   2409     * @return {?string}
   2410     */
   2411    es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeName = function(caseType) {
   2412        switch (caseType) {
   2413            case es3fUniformApiTests.CaseType.UNIFORM: return 'active_uniform';
   2414            case es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV: return 'indices_active_uniformsiv';
   2415            case es3fUniformApiTests.CaseType.CONSISTENCY: return 'consistency';
   2416            default:
   2417                throw new Error('Invalid type');
   2418        }
   2419    };
   2420 
   2421    /**
   2422     * @param {es3fUniformApiTests.CaseType} caseType
   2423     * @return {?string}
   2424     */
   2425    es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeDescription = function(caseType) {
   2426       switch (caseType) {
   2427           case es3fUniformApiTests.CaseType.UNIFORM: return 'Test glGetActiveUniform()';
   2428           case es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV: return 'Test glGetUniformIndices() along with glGetActiveUniforms()';
   2429           case es3fUniformApiTests.CaseType.CONSISTENCY: return 'Check consistency between results from glGetActiveUniform() and glGetUniformIndices() + glGetActiveUniforms()';
   2430           default:
   2431               throw new Error('Invalid type');
   2432       }
   2433    };
   2434 
   2435    // \note Although this is only used in UniformApiTest::es3fUniformApiTests.init, it needs to be defined here as it's used as a template argument.
   2436    /**
   2437     * @constructor
   2438     * @param {?string} name
   2439     * @param {es3fUniformApiTests.UniformCollection} uniformCollection_
   2440     */
   2441    es3fUniformApiTests.UniformCollectionCase = function(name, uniformCollection_) {
   2442        /** @type {string} */ this.namePrefix = name ? name + '_' : '';
   2443        /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ this.uniformCollection = uniformCollection_;
   2444    };
   2445 
   2446    /**
   2447     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   2448     * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
   2449     * @param {gluShaderProgram.ShaderProgram} program
   2450     * @param {deRandom.Random} rnd
   2451     * @return {boolean}
   2452     */
   2453    es3fUniformApiTests.UniformInfoQueryCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
   2454        /** @type {WebGLProgram} */ var programGL = program.getProgram();
   2455        /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var basicUniformReportsUniform = [];
   2456        /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var basicUniformReportsUniforms = [];
   2457        /** @type {boolean} */ var success;
   2458 
   2459        if (this.m_caseType == es3fUniformApiTests.CaseType.UNIFORM || this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
   2460            success = false;
   2461 
   2462            //TODO:: const ScopedLogSection section(log, "InfoGetActiveUniform", "es3fUniformApiTests.Uniform information queries with glGetActiveUniform()");
   2463            success = this.getActiveUniformsOneByOne(basicUniformReportsUniform, basicUniformReportsRef, programGL);
   2464 
   2465            if (!success) {
   2466                if (this.m_caseType == es3fUniformApiTests.CaseType.UNIFORM)
   2467                    return false;
   2468                else {
   2469                    assertMsgOptions(
   2470                        this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY,
   2471                        'es3fUniformApiTests.UniformInfoQueryCase.prototype.test - case type is not consistency',
   2472                        false,
   2473                        true
   2474                    );
   2475                    bufferedLogToConsole('// Note: this is a consistency case, so ignoring above failure(s)');
   2476                }
   2477            }
   2478        }
   2479 
   2480        if (this.m_caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV || this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
   2481            success = false;
   2482 
   2483            //TODO: const ScopedLogSection section(log, "InfoGetActiveUniforms", "es3fUniformApiTests.Uniform information queries with glGetUniformIndices() and glGetActiveUniforms()");
   2484            success = this.getActiveUniforms(basicUniformReportsUniforms, basicUniformReportsRef, programGL);
   2485 
   2486            if (!success) {
   2487                if (this.m_caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV)
   2488                    return false;
   2489                else {
   2490                    assertMsgOptions(
   2491                        this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY,
   2492                        'es3fUniformApiTests.UniformInfoQueryCase.prototype.test - case type is not consistency',
   2493                        false,
   2494                        true
   2495                    );
   2496                    bufferedLogToConsole('// Note: this is a consistency case, so ignoring above failure(s)');
   2497                }
   2498            }
   2499        }
   2500 
   2501        if (this.m_caseType == es3fUniformApiTests.CaseType.CONSISTENCY) {
   2502            success = false;
   2503 
   2504            //TODO: const ScopedLogSection section(log, "CompareUniformVsUniforms", "Comparison of results from glGetActiveUniform() and glGetActiveUniforms()");
   2505            success = this.uniformVsUniformsComparison(basicUniformReportsUniform, basicUniformReportsUniforms);
   2506 
   2507            if (!success)
   2508                return false;
   2509        }
   2510 
   2511        return true;
   2512    };
   2513 
   2514    /**
   2515     * @enum {number}
   2516     */
   2517    es3fUniformApiTests.ValueToCheck = {
   2518        INITIAL: 0, //!< Verify the initial values of the uniforms (i.e. check that they're zero).
   2519        ASSIGNED: 1 //!< Assign values to uniforms with glUniform*(), and check those.
   2520    };
   2521 
   2522    /**
   2523     * @enum {number}
   2524     */
   2525    es3fUniformApiTests.CheckMethod = {
   2526        GET_UNIFORM: 0, //!< Check values with glGetUniform*().
   2527        RENDER: 1 //!< Check values by rendering with the value-checking shader.
   2528    };
   2529 
   2530    /**
   2531     * @enum {number}
   2532     */
   2533    es3fUniformApiTests.AssignMethod = {
   2534        POINTER: 0,
   2535        VALUE: 1
   2536    };
   2537 
   2538    /**
   2539     * es3fUniformApiTests.UniformValueCase test class
   2540     * @constructor
   2541     * @param {string} name
   2542     * @param {string} description
   2543     * @param {es3fUniformApiTests.CaseShaderType} shaderType
   2544     * @param {es3fUniformApiTests.UniformCollection} uniformCollection (SharedPtr)
   2545     * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
   2546     * @param {es3fUniformApiTests.CheckMethod} checkMethod
   2547     * @param {?es3fUniformApiTests.AssignMethod} assignMethod
   2548     * @param {es3fUniformApiTests.Feature} additionalFeatures
   2549     * @extends {es3fUniformApiTests.UniformCase}
   2550     */
   2551    es3fUniformApiTests.UniformValueCase = function(name, description, shaderType, uniformCollection, valueToCheck, checkMethod, assignMethod, additionalFeatures) {
   2552        es3fUniformApiTests.UniformCase.call(this, name, description);
   2553 
   2554        additionalFeatures.UNIFORMVALUE_ZERO |= valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL;
   2555        additionalFeatures.UNIFORMFUNC_VALUE |= assignMethod == es3fUniformApiTests.AssignMethod.VALUE;
   2556        this.newB(shaderType, uniformCollection, additionalFeatures);
   2557 
   2558        this.m_valueToCheck = valueToCheck;
   2559        this.m_checkMethod = checkMethod;
   2560 
   2561        assertMsgOptions(
   2562            !(assignMethod === undefined && valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED),
   2563            'es3fUniformApiTests.UniformValueCase - assign method is undefined when value to check requires it',
   2564            false,
   2565            true
   2566        );
   2567    };
   2568 
   2569    es3fUniformApiTests.UniformValueCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
   2570    /** Constructor restore */
   2571    es3fUniformApiTests.UniformValueCase.prototype.constructor = es3fUniformApiTests.UniformValueCase;
   2572 
   2573    /**
   2574     * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
   2575     * @return {?string}
   2576     */
   2577    es3fUniformApiTests.UniformValueCase.getValueToCheckName = function(valueToCheck) {
   2578        switch (valueToCheck) {
   2579            case es3fUniformApiTests.ValueToCheck.INITIAL: return 'initial';
   2580            case es3fUniformApiTests.ValueToCheck.ASSIGNED: return 'assigned';
   2581            default: throw new Error('es3fUniformApiTests.UniformValueCase.getValueToCheckName - Invalid value to check option');
   2582        }
   2583    };
   2584 
   2585    /**
   2586     * @param {es3fUniformApiTests.ValueToCheck} valueToCheck
   2587     * @return {?string}
   2588     */
   2589    es3fUniformApiTests.UniformValueCase.getValueToCheckDescription = function(valueToCheck) {
   2590        switch (valueToCheck) {
   2591            case es3fUniformApiTests.ValueToCheck.INITIAL: return 'Check initial uniform values (zeros)';
   2592            case es3fUniformApiTests.ValueToCheck.ASSIGNED: return 'Check assigned uniform values';
   2593            default: throw new Error('es3fUniformApiTests.UniformValueCase.getValueToCheckDescription - Invalid value to check option');
   2594        }
   2595    };
   2596 
   2597    /**
   2598     * @param {es3fUniformApiTests.CheckMethod} checkMethod
   2599     * @return {?string}
   2600     */
   2601    es3fUniformApiTests.UniformValueCase.getCheckMethodName = function(checkMethod) {
   2602        switch (checkMethod) {
   2603            case es3fUniformApiTests.CheckMethod.GET_UNIFORM: return 'get_uniform';
   2604            case es3fUniformApiTests.CheckMethod.RENDER: return 'render';
   2605            default: throw new Error('es3fUniformApiTests.UniformValueCase.getCheckMethodName - Invalid check method');
   2606        }
   2607    };
   2608 
   2609    /**
   2610     * @param {es3fUniformApiTests.CheckMethod} checkMethod
   2611     * @return {?string}
   2612     */
   2613    es3fUniformApiTests.UniformValueCase.getCheckMethodDescription = function(checkMethod) {
   2614        switch (checkMethod) {
   2615            case es3fUniformApiTests.CheckMethod.GET_UNIFORM: return 'Verify values with glGetUniform*()';
   2616            case es3fUniformApiTests.CheckMethod.RENDER: return 'Verify values by rendering';
   2617            default: throw new Error('es3fUniformApiTests.UniformValueCase.getCheckMethodDescription - Invalid check method');
   2618        }
   2619    };
   2620 
   2621    /**
   2622     * @param {es3fUniformApiTests.AssignMethod} assignMethod
   2623     * @return {?string}
   2624     */
   2625    es3fUniformApiTests.UniformValueCase.getAssignMethodName = function(assignMethod) {
   2626        switch (assignMethod) {
   2627            case es3fUniformApiTests.AssignMethod.POINTER: return 'by_pointer';
   2628            case es3fUniformApiTests.AssignMethod.VALUE: return 'by_value';
   2629            default: throw new Error('es3fUniformApiTests.UniformValueCase.getAssignMethodName - Invalid assign method');
   2630        }
   2631    };
   2632 
   2633    /**
   2634     * @param {es3fUniformApiTests.AssignMethod} assignMethod
   2635     * @return {?string}
   2636     */
   2637    es3fUniformApiTests.UniformValueCase.getAssignMethodDescription = function(assignMethod) {
   2638        switch (assignMethod) {
   2639            case es3fUniformApiTests.AssignMethod.POINTER: return 'Assign values by-pointer';
   2640            case es3fUniformApiTests.AssignMethod.VALUE: return 'Assign values by-value';
   2641            default: throw new Error('es3fUniformApiTests.UniformValueCase.getAssignMethodDescription - Invalid assign method');
   2642        }
   2643    };
   2644 
   2645    /**
   2646     * es3fUniformApiTests.UniformValueCase test function
   2647     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   2648     * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
   2649     * @param {gluShaderProgram.ShaderProgram} program
   2650     * @param {deRandom.Random} rnd
   2651     * @return {boolean}
   2652     */
   2653    es3fUniformApiTests.UniformValueCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
   2654        /** @type {WebGLProgram} */ var programGL = program.getProgram();
   2655 
   2656        if (this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED) {
   2657            //TODO: const ScopedLogSection section(log, "UniformAssign", "es3fUniformApiTests.Uniform value assignments");
   2658            this.assignUniforms(basicUniforms, programGL, rnd);
   2659        } else
   2660            assertMsgOptions(
   2661                this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL,
   2662                'es3fUniformApiTests.UniformValueCase.prototype.test - value to check not initial',
   2663                false, true
   2664            );
   2665 
   2666        /** @type {boolean}*/ var success;
   2667 
   2668        if (this.m_checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM) {
   2669            /** @type {Array<es3fUniformApiTests.VarValue>} */ var values = [];
   2670 
   2671            //TODO: const ScopedLogSection section(log, "GetUniforms", "es3fUniformApiTests.Uniform value query");
   2672            success = this.getUniforms(values, basicUniforms, program.getProgram());
   2673 
   2674            if (!success)
   2675                return false;
   2676 
   2677            if (this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.ASSIGNED) {
   2678                //TODO: const ScopedLogSection section(log, "ValueCheck", "Verify that the reported values match the assigned values");
   2679                success = this.compareUniformValues(values, basicUniforms);
   2680 
   2681                if (!success)
   2682                    return false;
   2683            } else {
   2684                assertMsgOptions(
   2685                    this.m_valueToCheck == es3fUniformApiTests.ValueToCheck.INITIAL,
   2686                    'es3fUniformApiTests.UniformValueCase.prototype.test - value to check not initial',
   2687                    false, true
   2688                );
   2689 
   2690                //TODO: const ScopedLogSection section(log, "ValueCheck", "Verify that the uniforms have correct initial values (zeros)");
   2691                success = this.checkUniformDefaultValues(values, basicUniforms);
   2692 
   2693                if (!success)
   2694                    return false;
   2695            }
   2696        } else {
   2697            assertMsgOptions(
   2698                this.m_checkMethod == es3fUniformApiTests.CheckMethod.RENDER,
   2699                'es3fUniformApiTests.UniformValueCase.prototype.test - check method different than RENDER',
   2700                false, true
   2701            );
   2702 
   2703            //TODO: const ScopedLogSection section(log, "RenderTest", "Render test");
   2704            success = this.renderTest(basicUniforms, program, rnd);
   2705 
   2706            if (!success)
   2707                return false;
   2708        }
   2709 
   2710        return true;
   2711    };
   2712 
   2713    /**
   2714     * es3fUniformApiTests.RandomUniformCase test class
   2715     * @constructor
   2716     * @param {string} name
   2717     * @param {string} description
   2718     * @param {number} seed
   2719     * @extends {es3fUniformApiTests.UniformCase}
   2720     */
   2721    es3fUniformApiTests.RandomUniformCase = function(name, description, seed) {
   2722        es3fUniformApiTests.UniformCase.call(this, name, description);
   2723        this.newC(seed ^ deRandom.getBaseSeed());
   2724    };
   2725 
   2726    es3fUniformApiTests.RandomUniformCase.prototype = Object.create(es3fUniformApiTests.UniformCase.prototype);
   2727    /** Constructor restore */
   2728    es3fUniformApiTests.RandomUniformCase.prototype.constructor = es3fUniformApiTests.RandomUniformCase;
   2729 
   2730    /**
   2731     * @param {Array<es3fUniformApiTests.BasicUniform>} basicUniforms
   2732     * @param {Array<es3fUniformApiTests.BasicUniformReportRef>} basicUniformReportsRef
   2733     * @param {gluShaderProgram.ShaderProgram} program
   2734     * @param {deRandom.Random} rnd
   2735     * @return {boolean}
   2736     */
   2737    es3fUniformApiTests.RandomUniformCase.prototype.test = function(basicUniforms, basicUniformReportsRef, program, rnd) {
   2738        // \note Different sampler types may not be bound to same unit when rendering.
   2739        /** @type {boolean}*/ var renderingPossible = !this.m_features.UNIFORMVALUE_ZERO || !this.m_uniformCollection.containsSeveralSamplerTypes();
   2740 
   2741        /** @type {boolean} */ var performGetActiveUniforms = rnd.getBool();
   2742        /** @type {boolean} */ var performGetActiveUniformsiv = rnd.getBool();
   2743        /** @type {boolean} */ var performUniformVsUniformsivComparison = performGetActiveUniforms && performGetActiveUniformsiv && rnd.getBool();
   2744        /** @type {boolean} */ var performGetUniforms = rnd.getBool();
   2745        /** @type {boolean} */ var performCheckUniformDefaultValues = performGetUniforms && rnd.getBool();
   2746        /** @type {boolean} */ var performAssignUniforms = rnd.getBool();
   2747        /** @type {boolean} */ var performCompareUniformValues = performGetUniforms && performAssignUniforms && rnd.getBool();
   2748        /** @type {boolean} */ var performRenderTest = renderingPossible && performAssignUniforms && rnd.getBool();
   2749        /** @type {WebGLProgram} */ var programGL = program.getProgram();
   2750 
   2751        if (!(performGetActiveUniforms || performGetActiveUniformsiv || performUniformVsUniformsivComparison || performGetUniforms || performCheckUniformDefaultValues || performAssignUniforms || performCompareUniformValues || performRenderTest))
   2752            performGetActiveUniforms = true; // Do something at least.
   2753 
   2754        var PERFORM_AND_CHECK = function(CALL, SECTION_NAME, SECTION_DESCRIPTION) {
   2755            //TODO: const ScopedLogSection section(log, (SECTION_NAME), (SECTION_DESCRIPTION));
   2756            /** @type {boolean} */ var success = CALL();
   2757            if (!success)
   2758                return false;
   2759        };
   2760 
   2761        /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var reportsUniform = [];
   2762        /** @type {Array<es3fUniformApiTests.BasicUniformReportGL>} */ var reportsUniformsiv = [];
   2763 
   2764        var current = this; //To use "this" in anonymous function.
   2765 
   2766        if (performGetActiveUniforms)
   2767            PERFORM_AND_CHECK(function() {current.getActiveUniformsOneByOne(reportsUniform, basicUniformReportsRef, programGL);}, 'InfoGetActiveUniform', 'es3fUniformApiTests.Uniform information queries with glGetActiveUniform()');
   2768 
   2769        if (performGetActiveUniformsiv)
   2770            PERFORM_AND_CHECK(function() {current.getActiveUniforms(reportsUniformsiv, basicUniformReportsRef, programGL);}, 'InfoGetActiveUniformsiv', 'es3fUniformApiTests.Uniform information queries with glGetIndices() and glGetActiveUniformsiv()');
   2771 
   2772        if (performUniformVsUniformsivComparison)
   2773            PERFORM_AND_CHECK(function() {current.uniformVsUniformsComparison(reportsUniform, reportsUniformsiv);}, 'CompareUniformVsUniformsiv', 'Comparison of results from glGetActiveUniform() and glGetActiveUniformsiv()');
   2774 
   2775        /** @type {Array<es3fUniformApiTests.VarValue>} */ var uniformDefaultValues = [];
   2776 
   2777        if (performGetUniforms)
   2778            PERFORM_AND_CHECK(function() {current.getUniforms(uniformDefaultValues, basicUniforms, programGL);}, 'GetUniformDefaults', 'es3fUniformApiTests.Uniform default value query');
   2779 
   2780        if (performCheckUniformDefaultValues)
   2781            PERFORM_AND_CHECK(function() {current.checkUniformDefaultValues(uniformDefaultValues, basicUniforms);}, 'DefaultValueCheck', 'Verify that the uniforms have correct initial values (zeros)');
   2782 
   2783        /** @type {Array<es3fUniformApiTests.VarValue>} */ var uniformValues = [];
   2784 
   2785        if (performAssignUniforms) {
   2786            //TODO: const ScopedLogSection section(log, "UniformAssign", "es3fUniformApiTests.Uniform value assignments");
   2787            this.assignUniforms(basicUniforms, programGL, rnd);
   2788        }
   2789 
   2790        if (performCompareUniformValues) {
   2791            PERFORM_AND_CHECK(function() {current.getUniforms(uniformValues, basicUniforms, programGL);}, 'GetUniforms', 'es3fUniformApiTests.Uniform value query');
   2792            PERFORM_AND_CHECK(function() {current.compareUniformValues(uniformValues, basicUniforms);}, 'ValueCheck', 'Verify that the reported values match the assigned values');
   2793        }
   2794 
   2795        if (performRenderTest)
   2796            PERFORM_AND_CHECK(function() {current.renderTest(basicUniforms, program, rnd);}, 'RenderTest', 'Render test');
   2797 
   2798        return true;
   2799    };
   2800 
   2801    /**
   2802     * Initializes the tests to be performed.
   2803     */
   2804    es3fUniformApiTests.init = function() {
   2805        var state = tcuTestCase.runner;
   2806        var testGroup = state.testCases;
   2807 
   2808        // Generate sets of UniformCollections that are used by several cases.
   2809        /**
   2810         * @enum
   2811         */
   2812        var UniformCollections = {
   2813            BASIC: 0,
   2814            BASIC_ARRAY: 1,
   2815            BASIC_STRUCT: 2,
   2816            STRUCT_IN_ARRAY: 3,
   2817            ARRAY_IN_STRUCT: 4,
   2818            NESTED_STRUCTS_ARRAYS: 5,
   2819            MULTIPLE_BASIC: 6,
   2820            MULTIPLE_BASIC_ARRAY: 7,
   2821            MULTIPLE_NESTED_STRUCTS_ARRAYS: 8
   2822        };
   2823 
   2824        /**
   2825         * @constructor
   2826         */
   2827        var UniformCollectionGroup = function() {
   2828            /** @type {string} */ this.name = '';
   2829            /** @type {Array<es3fUniformApiTests.UniformCollectionCase>} */ this.cases = [];
   2830        };
   2831 
   2832        /** @type {Array<UniformCollectionGroup>} */ var defaultUniformCollections = new Array(Object.keys(UniformCollections).length);
   2833 
   2834        /** @type {string} */ var name;
   2835 
   2836        //Initialize
   2837        for (var i = 0; i < defaultUniformCollections.length; i++) defaultUniformCollections[i] = new UniformCollectionGroup();
   2838 
   2839        defaultUniformCollections[UniformCollections.BASIC].name = 'basic';
   2840        defaultUniformCollections[UniformCollections.BASIC_ARRAY].name = 'basic_array';
   2841        defaultUniformCollections[UniformCollections.BASIC_STRUCT].name = 'basic_struct';
   2842        defaultUniformCollections[UniformCollections.STRUCT_IN_ARRAY].name = 'struct_in_array';
   2843        defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT].name = 'array_in_struct';
   2844        defaultUniformCollections[UniformCollections.NESTED_STRUCTS_ARRAYS].name = 'nested_structs_arrays';
   2845        defaultUniformCollections[UniformCollections.MULTIPLE_BASIC].name = 'multiple_basic';
   2846        defaultUniformCollections[UniformCollections.MULTIPLE_BASIC_ARRAY].name = 'multiple_basic_array';
   2847        defaultUniformCollections[UniformCollections.MULTIPLE_NESTED_STRUCTS_ARRAYS].name = 'multiple_nested_structs_arrays';
   2848 
   2849        for (var dataTypeNdx = 0; dataTypeNdx < es3fUniformApiTests.s_testDataTypes.length; dataTypeNdx++) {
   2850            /** @type {gluShaderUtil.DataType} */ var dataType = es3fUniformApiTests.s_testDataTypes[dataTypeNdx];
   2851            /** @type {string} */ var typeName = gluShaderUtil.getDataTypeName(dataType);
   2852 
   2853            defaultUniformCollections[UniformCollections.BASIC].cases.push(new es3fUniformApiTests.UniformCollectionCase(typeName, es3fUniformApiTests.UniformCollection.basic(dataType)));
   2854 
   2855            if (gluShaderUtil.isDataTypeScalar(dataType) ||
   2856                (gluShaderUtil.isDataTypeVector(dataType) && gluShaderUtil.getDataTypeScalarSize(dataType) == 4) ||
   2857                dataType == gluShaderUtil.DataType.FLOAT_MAT4 ||
   2858                dataType == gluShaderUtil.DataType.SAMPLER_2D)
   2859                defaultUniformCollections[UniformCollections.BASIC_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(typeName, es3fUniformApiTests.UniformCollection.basicArray(dataType)));
   2860 
   2861            if (gluShaderUtil.isDataTypeScalar(dataType) ||
   2862                dataType == gluShaderUtil.DataType.FLOAT_MAT4 ||
   2863                dataType == gluShaderUtil.DataType.SAMPLER_2D) {
   2864                /** @type {gluShaderUtil.DataType} */ var secondDataType;
   2865                if (gluShaderUtil.isDataTypeScalar(dataType))
   2866                    secondDataType = gluShaderUtil.getDataTypeVector(dataType, 4);
   2867                else if (dataType == gluShaderUtil.DataType.FLOAT_MAT4)
   2868                    secondDataType = gluShaderUtil.DataType.FLOAT_MAT2;
   2869                else if (dataType == gluShaderUtil.DataType.SAMPLER_2D)
   2870                    secondDataType = gluShaderUtil.DataType.SAMPLER_CUBE;
   2871 
   2872                assertMsgOptions(
   2873                    secondDataType !== undefined,
   2874                    'es3fUniformApiTests.init - second data type undefined',
   2875                    false, true
   2876                );
   2877 
   2878                /** @type {string} */ var secondTypeName = gluShaderUtil.getDataTypeName(secondDataType);
   2879                name = typeName + '_' + secondTypeName;
   2880 
   2881                defaultUniformCollections[UniformCollections.BASIC_STRUCT].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.basicStruct(dataType, secondDataType, false)));
   2882                defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.basicStruct(dataType, secondDataType, true)));
   2883                defaultUniformCollections[UniformCollections.STRUCT_IN_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.structInArray(dataType, secondDataType, false)));
   2884                defaultUniformCollections[UniformCollections.NESTED_STRUCTS_ARRAYS].cases.push(new es3fUniformApiTests.UniformCollectionCase(name, es3fUniformApiTests.UniformCollection.nestedArraysStructs(dataType, secondDataType)));
   2885            }
   2886        }
   2887        defaultUniformCollections[UniformCollections.MULTIPLE_BASIC].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleBasic()));
   2888        defaultUniformCollections[UniformCollections.MULTIPLE_BASIC_ARRAY].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleBasicArray()));
   2889        defaultUniformCollections[UniformCollections.MULTIPLE_NESTED_STRUCTS_ARRAYS].cases.push(new es3fUniformApiTests.UniformCollectionCase(null, es3fUniformApiTests.UniformCollection.multipleNestedArraysStructs()));
   2890 
   2891        // Info-query cases (check info returned by e.g. glGetActiveUniforms()).
   2892 
   2893        // info_query
   2894        /** @type {tcuTestCase.DeqpTest} */
   2895        var infoQueryGroup = tcuTestCase.newTest('info_query', 'Test uniform info querying functions');
   2896        testGroup.addChild(infoQueryGroup);
   2897 
   2898        /** @type {UniformCollectionGroup} */ var collectionGroup;
   2899        /** @type {es3fUniformApiTests.UniformCollectionCase} */ var collectionCase;
   2900        /** @type {es3fUniformApiTests.UniformCollection} (SharedPtr) */ var uniformCollection;
   2901        /** @type {es3fUniformApiTests.Feature} */ var features;
   2902        /** @type {tcuTestCase.DeqpTest} */ var collectionTestGroup;
   2903        /** @type {string} */ var collName;
   2904        /** @type {es3fUniformApiTests.CheckMethod} */ var checkMethod;
   2905        /** @type {tcuTestCase.DeqpTest} */ var checkMethodGroup;
   2906        /** @type {string} */ var collectionGroupName;
   2907        /** @type {boolean} */ var containsBooleans;
   2908        /** @type {boolean} */ var varyBoolApiType;
   2909        /** @type {number} */ var numBoolVariations;
   2910        /** @type {es3fUniformApiTests.Feature} */ var booleanTypeFeat;
   2911        /** @type {string} */ var booleanTypeName;
   2912        /** @type {tcuTestCase.DeqpTest} */ var unusedUniformsGroup;
   2913 
   2914        /** @type {Array<string>} */ var shaderTypes = Object.keys(es3fUniformApiTests.CaseShaderType);
   2915 
   2916        for (var caseTypeI in es3fUniformApiTests.CaseType) {
   2917            /** @type {es3fUniformApiTests.CaseType} */ var caseType = es3fUniformApiTests.CaseType[caseTypeI];
   2918            /** @type {tcuTestCase.DeqpTest} */
   2919            var caseTypeGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeName(caseType), es3fUniformApiTests.UniformInfoQueryCase.getCaseTypeDescription(caseType));
   2920            infoQueryGroup.addChild(caseTypeGroup);
   2921 
   2922            for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
   2923                var numArrayFirstElemNameCases = caseType == es3fUniformApiTests.CaseType.INDICES_UNIFORMSIV && collectionGroupNdx == UniformCollections.BASIC_ARRAY ? 2 : 1;
   2924 
   2925                for (var referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) {
   2926                    collectionGroup = defaultUniformCollections[collectionGroupNdx];
   2927                    collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? '' : '_first_elem_without_brackets');
   2928                    collectionTestGroup = tcuTestCase.newTest(collectionGroupName, '');
   2929                    caseTypeGroup.addChild(collectionTestGroup);
   2930 
   2931                    for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
   2932                        collectionCase = collectionGroup.cases[collectionNdx];
   2933 
   2934                        for (var i = 0; i < shaderTypes.length; i++) {
   2935                            name = collectionCase.namePrefix + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
   2936                            uniformCollection = collectionCase.uniformCollection;
   2937 
   2938                            features = new es3fUniformApiTests.Feature();
   2939                            features.ARRAY_FIRST_ELEM_NAME_NO_INDEX = referToFirstArrayElemWithoutIndexI != 0;
   2940 
   2941                            collectionTestGroup.addChild(new es3fUniformApiTests.UniformInfoQueryCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection, caseType, features));
   2942                        }
   2943                    }
   2944                }
   2945            }
   2946 
   2947            // Info-querying cases when unused uniforms are present.
   2948 
   2949            unusedUniformsGroup = tcuTestCase.newTest('unused_uniforms', 'Test with unused uniforms');
   2950            caseTypeGroup.addChild(unusedUniformsGroup);
   2951 
   2952            collectionGroup = defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT];
   2953 
   2954            for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
   2955                collectionCase = collectionGroup.cases[collectionNdx];
   2956                collName = collectionCase.namePrefix;
   2957                uniformCollection = collectionCase.uniformCollection;
   2958 
   2959                for (var i = 0; i < shaderTypes.length; i++) {
   2960                    name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
   2961 
   2962                    features = new es3fUniformApiTests.Feature();
   2963                    features.UNIFORMUSAGE_EVERY_OTHER = true;
   2964                    features.ARRAYUSAGE_ONLY_MIDDLE_INDEX = true;
   2965 
   2966                    unusedUniformsGroup.addChild(new es3fUniformApiTests.UniformInfoQueryCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection, caseType, features));
   2967                }
   2968            }
   2969        }
   2970 
   2971        // Cases testing uniform values.
   2972 
   2973        // Cases checking uniforms' initial values (all must be zeros), with glGetUniform*() or by rendering.
   2974 
   2975        /** @type {tcuTestCase.DeqpTest} */ var initialValuesGroup = tcuTestCase.newTest(
   2976            'value.' + es3fUniformApiTests.UniformValueCase.getValueToCheckName(es3fUniformApiTests.ValueToCheck.INITIAL),
   2977            es3fUniformApiTests.UniformValueCase.getValueToCheckDescription(es3fUniformApiTests.ValueToCheck.INITIAL));
   2978        testGroup.addChild(initialValuesGroup);
   2979 
   2980        for (var checkMethodI in es3fUniformApiTests.CheckMethod) {
   2981            checkMethod = es3fUniformApiTests.CheckMethod[checkMethodI];
   2982            checkMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getCheckMethodName(checkMethod), es3fUniformApiTests.UniformValueCase.getCheckMethodDescription(checkMethod));
   2983            initialValuesGroup.addChild(checkMethodGroup);
   2984 
   2985            for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
   2986                collectionGroup = defaultUniformCollections[collectionGroupNdx];
   2987                collectionTestGroup = tcuTestCase.newTest(collectionGroup.name, '');
   2988                checkMethodGroup.addChild(collectionTestGroup);
   2989 
   2990                for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
   2991                    collectionCase = collectionGroup.cases[collectionNdx];
   2992                    collName = collectionCase.namePrefix;
   2993                    uniformCollection = collectionCase.uniformCollection;
   2994                    containsBooleans = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeBoolOrBVec);
   2995                    varyBoolApiType = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && containsBooleans &&
   2996                                                                (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
   2997                    numBoolVariations = varyBoolApiType ? 3 : 1;
   2998 
   2999                    if (checkMethod == es3fUniformApiTests.CheckMethod.RENDER && uniformCollection.containsSeveralSamplerTypes())
   3000                        continue; // \note Samplers' initial API values (i.e. their texture units) are 0, and no two samplers of different types shall have same unit when rendering.
   3001 
   3002                    for (var booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) {
   3003                        booleanTypeFeat = new es3fUniformApiTests.Feature();
   3004                        booleanTypeFeat.BOOLEANAPITYPE_INT = booleanTypeI == 1;
   3005                        booleanTypeFeat.BOOLEANAPITYPE_UINT = booleanTypeI == 2;
   3006 
   3007                        booleanTypeName = booleanTypeI == 1 ? 'int' :
   3008                                                            booleanTypeI == 2 ? 'uint' :
   3009                                                            'float';
   3010                        /** @type {string} */ var nameWithApiType = varyBoolApiType ? collName + 'api_' + booleanTypeName + '_' : collName;
   3011 
   3012                        for (var i = 0; i < shaderTypes.length; i++) {
   3013                            name = nameWithApiType + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
   3014                            collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
   3015                                                                                es3fUniformApiTests.ValueToCheck.INITIAL, checkMethod, null, booleanTypeFeat));
   3016                        }
   3017                    }
   3018                }
   3019            }
   3020        }
   3021 
   3022        // Cases that first assign values to each uniform, then check the values with glGetUniform*() or by rendering.
   3023 
   3024        /** @type {tcuTestCase.DeqpTest} */ var assignedValuesGroup = tcuTestCase.newTest(
   3025            'value.' + es3fUniformApiTests.UniformValueCase.getValueToCheckName(es3fUniformApiTests.ValueToCheck.ASSIGNED),
   3026            es3fUniformApiTests.UniformValueCase.getValueToCheckDescription(es3fUniformApiTests.ValueToCheck.ASSIGNED));
   3027        testGroup.addChild(assignedValuesGroup);
   3028 
   3029        for (var assignMethodI in es3fUniformApiTests.AssignMethod) {
   3030            /** @type {es3fUniformApiTests.AssignMethod} */ var assignMethod = es3fUniformApiTests.AssignMethod[assignMethodI];
   3031            /** @type {tcuTestCase.DeqpTest} */ var assignMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getAssignMethodName(assignMethod), es3fUniformApiTests.UniformValueCase.getAssignMethodDescription(assignMethod));
   3032            assignedValuesGroup.addChild(assignMethodGroup);
   3033 
   3034            for (var checkMethodI in es3fUniformApiTests.CheckMethod) {
   3035                checkMethod = es3fUniformApiTests.CheckMethod[checkMethodI];
   3036                checkMethodGroup = tcuTestCase.newTest(es3fUniformApiTests.UniformValueCase.getCheckMethodName(checkMethod), es3fUniformApiTests.UniformValueCase.getCheckMethodDescription(checkMethod));
   3037                assignMethodGroup.addChild(checkMethodGroup);
   3038 
   3039                for (var collectionGroupNdx = 0; collectionGroupNdx < Object.keys(UniformCollections).length; collectionGroupNdx++) {
   3040                    /** @type {number} */ var numArrayFirstElemNameCases = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && collectionGroupNdx == UniformCollections.BASIC_ARRAY ? 2 : 1;
   3041 
   3042                    for (var referToFirstArrayElemWithoutIndexI = 0; referToFirstArrayElemWithoutIndexI < numArrayFirstElemNameCases; referToFirstArrayElemWithoutIndexI++) {
   3043                        collectionGroup = defaultUniformCollections[collectionGroupNdx];
   3044                        collectionGroupName = collectionGroup.name + (referToFirstArrayElemWithoutIndexI == 0 ? '' : '_first_elem_without_brackets');
   3045                        collectionTestGroup = tcuTestCase.newTest(collectionGroupName, '');
   3046                        checkMethodGroup.addChild(collectionTestGroup);
   3047 
   3048                        for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
   3049                            collectionCase = collectionGroup.cases[collectionNdx];
   3050                            collName = collectionCase.namePrefix;
   3051                            uniformCollection = collectionCase.uniformCollection;
   3052                            containsBooleans = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeBoolOrBVec);
   3053                            varyBoolApiType = checkMethod == es3fUniformApiTests.CheckMethod.GET_UNIFORM && containsBooleans &&
   3054                                                                            (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
   3055                            numBoolVariations = varyBoolApiType ? 3 : 1;
   3056                            /** @type {boolean} */ var containsMatrices = uniformCollection.containsMatchingBasicType(gluShaderUtil.isDataTypeMatrix);
   3057                            /** @type {boolean} */ var varyMatrixMode = containsMatrices &&
   3058                                                                            (collectionGroupNdx == UniformCollections.BASIC || collectionGroupNdx == UniformCollections.BASIC_ARRAY);
   3059                            /** @type {number} */ var numMatVariations = varyMatrixMode ? 2 : 1;
   3060 
   3061                            if (containsMatrices && assignMethod != es3fUniformApiTests.AssignMethod.POINTER)
   3062                                continue;
   3063 
   3064                            for (var booleanTypeI = 0; booleanTypeI < numBoolVariations; booleanTypeI++) {
   3065                                booleanTypeFeat = new es3fUniformApiTests.Feature();
   3066                                booleanTypeFeat.BOOLEANAPITYPE_INT = booleanTypeI == 1;
   3067                                booleanTypeFeat.BOOLEANAPITYPE_UINT = booleanTypeI == 2;
   3068 
   3069                                booleanTypeName = booleanTypeI == 1 ? 'int' :
   3070                                                                        booleanTypeI == 2 ? 'uint' :
   3071                                                                        'float';
   3072                                /** @type {string} */ var nameWithBoolType = varyBoolApiType ? collName + 'api_' + booleanTypeName + '_' : collName;
   3073 
   3074                                for (var matrixTypeI = 0; matrixTypeI < numMatVariations; matrixTypeI++) {
   3075                                    /** @type {string} */ var nameWithMatrixType = nameWithBoolType + (matrixTypeI == 1 ? 'row_major_' : '');
   3076 
   3077                                    for (var i = 0; i < shaderTypes.length; i++) {
   3078                                        name = nameWithMatrixType + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
   3079 
   3080                                        booleanTypeFeat.ARRAY_FIRST_ELEM_NAME_NO_INDEX = referToFirstArrayElemWithoutIndexI != 0;
   3081                                        booleanTypeFeat.MATRIXMODE_ROWMAJOR = matrixTypeI == 1;
   3082 
   3083                                        collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
   3084                                                                                            es3fUniformApiTests.ValueToCheck.ASSIGNED, checkMethod, assignMethod, booleanTypeFeat));
   3085                                    }
   3086                                }
   3087                            }
   3088                        }
   3089                    }
   3090                }
   3091            }
   3092        }
   3093 
   3094        // Cases assign multiple basic-array elements with one glUniform*v() (i.e. the count parameter is bigger than 1).
   3095 
   3096        /** @type {es3fUniformApiTests.Feature} */ var arrayAssignFullMode = new es3fUniformApiTests.Feature();
   3097        arrayAssignFullMode.ARRAYASSIGN_FULL = true;
   3098 
   3099        /** @type {es3fUniformApiTests.Feature} */ var arrayAssignBlocksOfTwo = new es3fUniformApiTests.Feature();
   3100        arrayAssignFullMode.ARRAYASSIGN_BLOCKS_OF_TWO = true;
   3101 
   3102        var arrayAssignGroups =
   3103        [{arrayAssignMode: arrayAssignFullMode, name: 'basic_array_assign_full', description: 'Assign entire basic-type arrays per glUniform*v() call'}, {arrayAssignMode: arrayAssignBlocksOfTwo, name: 'basic_array_assign_partial', description: 'Assign two elements of a basic-type array per glUniform*v() call'}
   3104        ];
   3105 
   3106        for (var arrayAssignGroupNdx = 0; arrayAssignGroupNdx < arrayAssignGroups.length; arrayAssignGroupNdx++) {
   3107            /** @type {es3fUniformApiTests.Feature} */ var arrayAssignMode = arrayAssignGroups[arrayAssignGroupNdx].arrayAssignMode;
   3108            /** @type {string} */ var groupName = arrayAssignGroups[arrayAssignGroupNdx].name;
   3109            /** @type {string} */ var groupDesc = arrayAssignGroups[arrayAssignGroupNdx].description;
   3110 
   3111            /** @type {tcuTestCase.DeqpTest} */ var curArrayAssignGroup = tcuTestCase.newTest(groupName, groupDesc);
   3112            assignedValuesGroup.addChild(curArrayAssignGroup);
   3113 
   3114            /** @type {Array<number>} */ var basicArrayCollectionGroups = [UniformCollections.BASIC_ARRAY, UniformCollections.ARRAY_IN_STRUCT, UniformCollections.MULTIPLE_BASIC_ARRAY];
   3115 
   3116            for (var collectionGroupNdx = 0; collectionGroupNdx < basicArrayCollectionGroups.length; collectionGroupNdx++) {
   3117                collectionGroup = defaultUniformCollections[basicArrayCollectionGroups[collectionGroupNdx]];
   3118                collectionTestGroup = tcuTestCase.newTest(collectionGroup.name, '');
   3119                curArrayAssignGroup.addChild(collectionTestGroup);
   3120 
   3121                for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
   3122                    collectionCase = collectionGroup.cases[collectionNdx];
   3123                    collName = collectionCase.namePrefix;
   3124                    uniformCollection = collectionCase.uniformCollection;
   3125 
   3126                    for (var i = 0; i < shaderTypes.length; i++) {
   3127                        name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
   3128                        collectionTestGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
   3129                                                                            es3fUniformApiTests.ValueToCheck.ASSIGNED, es3fUniformApiTests.CheckMethod.GET_UNIFORM, es3fUniformApiTests.AssignMethod.POINTER,
   3130                                                                            arrayAssignMode));
   3131                    }
   3132                }
   3133            }
   3134        }
   3135 
   3136        // Value checking cases when unused uniforms are present.
   3137 
   3138        unusedUniformsGroup = tcuTestCase.newTest('unused_uniforms', 'Test with unused uniforms');
   3139        assignedValuesGroup.addChild(unusedUniformsGroup);
   3140 
   3141        collectionGroup = defaultUniformCollections[UniformCollections.ARRAY_IN_STRUCT];
   3142 
   3143        for (var collectionNdx = 0; collectionNdx < collectionGroup.cases.length; collectionNdx++) {
   3144            collectionCase = collectionGroup.cases[collectionNdx];
   3145            collName = collectionCase.namePrefix;
   3146            uniformCollection = collectionCase.uniformCollection;
   3147 
   3148            for (var i = 0; i < shaderTypes.length; i++) {
   3149                name = collName + es3fUniformApiTests.getCaseShaderTypeName(es3fUniformApiTests.CaseShaderType[shaderTypes[i]]);
   3150 
   3151                features = new es3fUniformApiTests.Feature();
   3152                features.ARRAYUSAGE_ONLY_MIDDLE_INDEX = true;
   3153                features.UNIFORMUSAGE_EVERY_OTHER = true;
   3154 
   3155                unusedUniformsGroup.addChild(new es3fUniformApiTests.UniformValueCase(name, '', es3fUniformApiTests.CaseShaderType[shaderTypes[i]], uniformCollection,
   3156                                                                    es3fUniformApiTests.ValueToCheck.ASSIGNED, es3fUniformApiTests.CheckMethod.GET_UNIFORM, es3fUniformApiTests.AssignMethod.POINTER,
   3157                                                                    features));
   3158            }
   3159        }
   3160 
   3161        // Random cases.
   3162 
   3163        /** @type {number} */ var numRandomCases = 100;
   3164        /** @type {tcuTestCase.DeqpTest} */ var randomGroup = tcuTestCase.newTest('random', 'Random cases');
   3165        testGroup.addChild(randomGroup);
   3166 
   3167        for (var ndx = 0; ndx < numRandomCases; ndx++)
   3168            randomGroup.addChild(new es3fUniformApiTests.RandomUniformCase('' + ndx, '', ndx));
   3169    };
   3170 
   3171    /**
   3172     * Create and execute the test cases
   3173     * @param {WebGL2RenderingContext} context
   3174     */
   3175    es3fUniformApiTests.run = function(context, range) {
   3176        gl = context;
   3177        //Set up Test Root parameters
   3178        var testName = 'uniform_api';
   3179        var testDescription = 'es3fUniformApiTests.Uniform API Tests';
   3180        var state = tcuTestCase.runner;
   3181 
   3182        state.testName = testName;
   3183        state.testCases = tcuTestCase.newTest(testName, testDescription, null);
   3184 
   3185        //Set up name and description of this test series.
   3186        setCurrentTestName(testName);
   3187        description(testDescription);
   3188 
   3189        try {
   3190            //Create test cases
   3191            es3fUniformApiTests.init();
   3192            if (range)
   3193                state.setRange(range);
   3194            //Run test cases
   3195            tcuTestCase.runTestCases();
   3196        }
   3197        catch (err) {
   3198            testFailedOptions('Failed to es3fUniformApiTests.run tests', false);
   3199            tcuTestCase.runner.terminate();
   3200        }
   3201    };
   3202 
   3203 });