tor-browser

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

glsVertexArrayTests.js (109733B)


      1 /*-------------------------------------------------------------------------
      2 * drawElements Quality Program OpenGL ES Utilities
      3 * ------------------------------------------------
      4 *
      5 * Copyright 2014 The Android Open Source Project
      6 *
      7 * Licensed under the Apache License, Version 2.0 (the "License");
      8 * you may not use this file except in compliance with the License.
      9 * You may obtain a copy of the License at
     10 *
     11 *      http://www.apache.org/licenses/LICENSE-2.0
     12 *
     13 * Unless required by applicable law or agreed to in writing, software
     14 * distributed under the License is distributed on an "AS IS" BASIS,
     15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16 * See the License for the specific language governing permissions and
     17 * limitations under the License.
     18 *
     19 */
     20 
     21 'use strict';
     22 goog.provide('modules.shared.glsVertexArrayTests');
     23 goog.require('framework.common.tcuFloat');
     24 goog.require('framework.common.tcuImageCompare');
     25 goog.require('framework.common.tcuLogImage');
     26 goog.require('framework.common.tcuPixelFormat');
     27 goog.require('framework.common.tcuRGBA');
     28 goog.require('framework.common.tcuSurface');
     29 goog.require('framework.common.tcuTestCase');
     30 goog.require('framework.delibs.debase.deMath');
     31 goog.require('framework.delibs.debase.deRandom');
     32 goog.require('framework.opengl.gluShaderUtil');
     33 goog.require('framework.opengl.simplereference.sglrGLContext');
     34 goog.require('framework.opengl.simplereference.sglrReferenceContext');
     35 goog.require('framework.opengl.simplereference.sglrShaderProgram');
     36 goog.require('framework.referencerenderer.rrFragmentOperations');
     37 goog.require('framework.referencerenderer.rrGenericVector');
     38 goog.require('framework.referencerenderer.rrShadingContext');
     39 goog.require('framework.referencerenderer.rrVertexAttrib');
     40 goog.require('framework.referencerenderer.rrVertexPacket');
     41 
     42 goog.scope(function() {
     43 
     44    var glsVertexArrayTests = modules.shared.glsVertexArrayTests;
     45    var tcuTestCase = framework.common.tcuTestCase;
     46    var tcuRGBA = framework.common.tcuRGBA;
     47    var tcuFloat = framework.common.tcuFloat;
     48    var tcuPixelFormat = framework.common.tcuPixelFormat;
     49    var tcuSurface = framework.common.tcuSurface;
     50    var tcuImageCompare = framework.common.tcuImageCompare;
     51    var tcuLogImage = framework.common.tcuLogImage;
     52    var gluShaderUtil = framework.opengl.gluShaderUtil;
     53    var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
     54    var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
     55    var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
     56    var deMath = framework.delibs.debase.deMath;
     57    var deRandom = framework.delibs.debase.deRandom;
     58    var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
     59    var rrGenericVector = framework.referencerenderer.rrGenericVector;
     60    var rrShadingContext = framework.referencerenderer.rrShadingContext;
     61    var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
     62    var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
     63 
     64    var DE_ASSERT = function(x) {
     65        if (!x)
     66            throw new Error('Assert failed');
     67    };
     68 
     69    /**
     70     * @interface
     71     */
     72    glsVertexArrayTests.deArray = function() {};
     73 
     74    /**
     75     * glsVertexArrayTests.deArray.Target enum
     76     * @enum
     77     */
     78    glsVertexArrayTests.deArray.Target = {
     79        ELEMENT_ARRAY: 0,
     80        ARRAY: 1
     81    };
     82 
     83    /**
     84     * glsVertexArrayTests.deArray.InputType enum
     85     * @enum
     86     */
     87    glsVertexArrayTests.deArray.InputType = {
     88        FLOAT: 0,
     89        /*FIXED: 1,
     90        DOUBLE: 2,*/
     91 
     92        BYTE: 1,
     93        SHORT: 2,
     94 
     95        UNSIGNED_BYTE: 3,
     96        UNSIGNED_SHORT: 4,
     97 
     98        INT: 5,
     99        UNSIGNED_INT: 6,
    100        HALF: 7,
    101        UNSIGNED_INT_2_10_10_10: 8,
    102        INT_2_10_10_10: 9
    103    };
    104 
    105    /**
    106     * glsVertexArrayTests.deArray.OutputType enum
    107     * @enum
    108     */
    109    glsVertexArrayTests.deArray.OutputType = {
    110        FLOAT: 0,
    111        VEC2: 1,
    112        VEC3: 2,
    113        VEC4: 3,
    114 
    115        INT: 4,
    116        UINT: 5,
    117 
    118        IVEC2: 6,
    119        IVEC3: 7,
    120        IVEC4: 8,
    121 
    122        UVEC2: 9,
    123        UVEC3: 10,
    124        UVEC4: 11
    125    };
    126 
    127    /**
    128     * glsVertexArrayTests.deArray.Usage enum
    129     * @enum
    130     */
    131    glsVertexArrayTests.deArray.Usage = {
    132        DYNAMIC_DRAW: 0,
    133        STATIC_DRAW: 1,
    134        STREAM_DRAW: 2,
    135 
    136        STREAM_READ: 3,
    137        STREAM_COPY: 4,
    138 
    139        STATIC_READ: 5,
    140        STATIC_COPY: 6,
    141 
    142        DYNAMIC_READ: 7,
    143        DYNAMIC_COPY: 8
    144    };
    145 
    146    /**
    147     * glsVertexArrayTests.deArray.Storage enum
    148     * @enum
    149     */
    150    glsVertexArrayTests.deArray.Storage = {
    151        USER: 0,
    152        BUFFER: 1
    153    };
    154 
    155    /**
    156     * glsVertexArrayTests.deArray.Primitive enum
    157     * @enum
    158     */
    159    glsVertexArrayTests.deArray.Primitive = {
    160        POINTS: 0,
    161        TRIANGLES: 1,
    162        TRIANGLE_FAN: 2,
    163        TRIANGLE_STRIP: 3
    164    };
    165 
    166    //glsVertexArrayTests.deArray static functions
    167 
    168    /**
    169     * @param {glsVertexArrayTests.deArray.Target} target
    170     * @return {string}
    171     */
    172    glsVertexArrayTests.deArray.targetToString = function(target) {
    173        DE_ASSERT(target < Object.keys(glsVertexArrayTests.deArray.Target).length);
    174 
    175        /** @type {Array<string>} */ var targets =
    176        [
    177            'element_array', // glsVertexArrayTests.deArray.Target.ELEMENT_ARRAY
    178            'array' // glsVertexArrayTests.deArray.Target.ARRAY
    179        ];
    180        DE_ASSERT(targets.length == Object.keys(glsVertexArrayTests.deArray.Target).length);
    181 
    182        return targets[target];
    183    };
    184 
    185    /**
    186     * @param {glsVertexArrayTests.deArray.InputType} type
    187     * @return {string}
    188     */
    189    glsVertexArrayTests.deArray.inputTypeToString = function(type) {
    190        DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.InputType).length);
    191 
    192        /** @type {Array<string>} */ var types =
    193        [
    194            'float', // glsVertexArrayTests.deArray.InputType.FLOAT
    195 
    196            'byte', // glsVertexArrayTests.deArray.InputType.BYTE
    197            'short', // glsVertexArrayTests.deArray.InputType.SHORT
    198 
    199            'unsigned_byte', // glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE
    200            'unsigned_short', // glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT
    201 
    202            'int', // glsVertexArrayTests.deArray.InputType.INT
    203            'unsigned_int', // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT
    204            'half', // glsVertexArrayTests.deArray.InputType.HALF
    205            'unsigned_int2_10_10_10', // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10
    206            'int2_10_10_10' // glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
    207        ];
    208        DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.InputType).length);
    209 
    210        return types[type];
    211    };
    212 
    213    /**
    214     * @param {glsVertexArrayTests.deArray.OutputType} type
    215     * @return {string}
    216     */
    217    glsVertexArrayTests.deArray.outputTypeToString = function(type) {
    218        DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.OutputType).length);
    219 
    220        /** @type {Array<string>} */ var types =
    221        [
    222            'float', // glsVertexArrayTests.deArray.OutputType.FLOAT
    223            'vec2', // glsVertexArrayTests.deArray.OutputType.VEC2
    224            'vec3', // glsVertexArrayTests.deArray.OutputType.VEC3
    225            'vec4', // glsVertexArrayTests.deArray.OutputType.VEC4
    226 
    227            'int', // glsVertexArrayTests.deArray.OutputType.INT
    228            'uint', // glsVertexArrayTests.deArray.OutputType.UINT
    229 
    230            'ivec2', // glsVertexArrayTests.deArray.OutputType.IVEC2
    231            'ivec3', // glsVertexArrayTests.deArray.OutputType.IVEC3
    232            'ivec4', // glsVertexArrayTests.deArray.OutputType.IVEC4
    233 
    234            'uvec2', // glsVertexArrayTests.deArray.OutputType.UVEC2
    235            'uvec3', // glsVertexArrayTests.deArray.OutputType.UVEC3
    236            'uvec4' // glsVertexArrayTests.deArray.OutputType.UVEC4
    237        ];
    238        DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.OutputType).length);
    239 
    240        return types[type];
    241    };
    242 
    243    /**
    244     * @param {glsVertexArrayTests.deArray.Usage} usage
    245     * @return {string}
    246     */
    247    glsVertexArrayTests.deArray.usageTypeToString = function(usage) {
    248        DE_ASSERT(usage < Object.keys(glsVertexArrayTests.deArray.Usage).length);
    249 
    250        /** @type {Array<string>} */ var usages =
    251        [
    252            'dynamic_draw', // glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW
    253            'static_draw', // glsVertexArrayTests.deArray.Usage.STATIC_DRAW
    254            'stream_draw', // glsVertexArrayTests.deArray.Usage.STREAM_DRAW
    255 
    256            'stream_read', // glsVertexArrayTests.deArray.Usage.STREAM_READ
    257            'stream_copy', // glsVertexArrayTests.deArray.Usage.STREAM_COPY
    258 
    259            'static_read', // glsVertexArrayTests.deArray.Usage.STATIC_READ
    260            'static_copy', // glsVertexArrayTests.deArray.Usage.STATIC_COPY
    261 
    262            'dynamic_read', // glsVertexArrayTests.deArray.Usage.DYNAMIC_READ
    263            'dynamic_copy' // glsVertexArrayTests.deArray.Usage.DYNAMIC_COPY
    264        ];
    265        DE_ASSERT(usages.length == Object.keys(glsVertexArrayTests.deArray.Usage).length);
    266 
    267        return usages[usage];
    268    };
    269 
    270    /**
    271     * @param {glsVertexArrayTests.deArray.Storage} storage
    272     * @return {string}
    273     */
    274    glsVertexArrayTests.deArray.storageToString = function(storage) {
    275        DE_ASSERT(storage < Object.keys(glsVertexArrayTests.deArray.Storage).length);
    276 
    277        /** @type {Array<string>} */ var storages =
    278        [
    279            'user_ptr', // glsVertexArrayTests.deArray.Storage.USER
    280            'buffer' // glsVertexArrayTests.deArray.Storage.BUFFER
    281        ];
    282        DE_ASSERT(storages.length == Object.keys(glsVertexArrayTests.deArray.Storage).length);
    283 
    284        return storages[storage];
    285    };
    286 
    287    /**
    288     * @param {glsVertexArrayTests.deArray.Primitive} primitive
    289     * @return {string}
    290     */
    291    glsVertexArrayTests.deArray.primitiveToString = function(primitive) {
    292        DE_ASSERT(primitive < Object.keys(glsVertexArrayTests.deArray.Primitive).length);
    293 
    294        /** @type {Array<string>} */ var primitives =
    295        [
    296            'points', // glsVertexArrayTests.deArray.Primitive.POINTS
    297            'triangles', // glsVertexArrayTests.deArray.Primitive.TRIANGLES
    298            'triangle_fan', // glsVertexArrayTests.deArray.Primitive.TRIANGLE_FAN
    299            'triangle_strip' // glsVertexArrayTests.deArray.Primitive.TRIANGLE_STRIP
    300        ];
    301        DE_ASSERT(primitives.length == Object.keys(glsVertexArrayTests.deArray.Primitive).length);
    302 
    303        return primitives[primitive];
    304    };
    305 
    306    /**
    307     * @param {glsVertexArrayTests.deArray.InputType} type
    308     * @return {number}
    309     */
    310    glsVertexArrayTests.deArray.inputTypeSize = function(type) {
    311        DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.InputType).length);
    312 
    313        /** @type {Array<number>} */ var size = [
    314            4, // glsVertexArrayTests.deArray.InputType.FLOAT
    315 
    316            1, // glsVertexArrayTests.deArray.InputType.BYTE
    317            2, // glsVertexArrayTests.deArray.InputType.SHORT
    318 
    319            1, // glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE
    320            2, // glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT
    321 
    322            4, // glsVertexArrayTests.deArray.InputType.INT
    323            4, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT
    324            2, // glsVertexArrayTests.deArray.InputType.HALF
    325            4 / 4, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10
    326            4 / 4 // glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
    327        ];
    328        DE_ASSERT(size.length == Object.keys(glsVertexArrayTests.deArray.InputType).length);
    329 
    330        return size[type];
    331    };
    332 
    333    /**
    334     * @param {glsVertexArrayTests.deArray.InputType} type
    335     * @return {boolean}
    336     */
    337    glsVertexArrayTests.inputTypeIsFloatType = function(type) {
    338        if (type == glsVertexArrayTests.deArray.InputType.FLOAT)
    339            return true;
    340        /*if (type == glsVertexArrayTests.deArray.InputType.FIXED)
    341            return true;
    342        if (type == glsVertexArrayTests.deArray.InputType.DOUBLE)
    343            return true;*/
    344        if (type == glsVertexArrayTests.deArray.InputType.HALF)
    345            return true;
    346        return false;
    347    };
    348 
    349    /**
    350     * @param {glsVertexArrayTests.deArray.OutputType} type
    351     * @return {boolean}
    352     */
    353    glsVertexArrayTests.outputTypeIsFloatType = function(type) {
    354        if (type == glsVertexArrayTests.deArray.OutputType.FLOAT ||
    355            type == glsVertexArrayTests.deArray.OutputType.VEC2 ||
    356            type == glsVertexArrayTests.deArray.OutputType.VEC3 ||
    357            type == glsVertexArrayTests.deArray.OutputType.VEC4)
    358            return true;
    359 
    360        return false;
    361    };
    362 
    363    //glsVertexArrayTests.deArray member functions (all virtual, since this is an interface)
    364 
    365    /**
    366     * @param {glsVertexArrayTests.deArray.Target} target
    367     * @param {number} size
    368     * @param {Uint8Array} data
    369     * @param {glsVertexArrayTests.deArray.Usage} usage
    370     */
    371    glsVertexArrayTests.deArray.prototype.data = function(target, size, data, usage) {};
    372 
    373    /**
    374     * @param {glsVertexArrayTests.deArray.Target} target
    375     * @param {number} offset
    376     * @param {number} size
    377     * @param {Uint8Array} data
    378     */
    379    glsVertexArrayTests.deArray.prototype.subdata = function(target, offset, size, data) {};
    380 
    381    /**
    382     * @param {number} attribNdx
    383     * @param {number} offset
    384     * @param {number} size
    385     * @param {glsVertexArrayTests.deArray.InputType} inType
    386     * @param {glsVertexArrayTests.deArray.OutputType} outType
    387     * @param {boolean} normalized
    388     * @param {number} stride
    389     */
    390    glsVertexArrayTests.deArray.prototype.bind = function(attribNdx, offset, size, inType, outType, normalized, stride) {};
    391 
    392    /**
    393     * unBind
    394     */
    395    glsVertexArrayTests.deArray.prototype.unBind = function() {};
    396 
    397    /**
    398     * @return {boolean}
    399     */
    400    glsVertexArrayTests.deArray.prototype.isBound = function() {};
    401 
    402    /**
    403     * @return {number}
    404     */
    405    glsVertexArrayTests.deArray.prototype.getComponentCount = function() {};
    406 
    407    /**
    408     * @return {glsVertexArrayTests.deArray.Target}
    409     */
    410    glsVertexArrayTests.deArray.prototype.getTarget = function() {};
    411 
    412    /**
    413     * @return {glsVertexArrayTests.deArray.InputType}
    414     */
    415    glsVertexArrayTests.deArray.prototype.getInputType = function() {};
    416 
    417    /**
    418     * @return {glsVertexArrayTests.deArray.OutputType}
    419     */
    420    glsVertexArrayTests.deArray.prototype.getOutputType = function() {};
    421 
    422    /**
    423     * @return {glsVertexArrayTests.deArray.Storage}
    424     */
    425    glsVertexArrayTests.deArray.prototype.getStorageType = function() {};
    426 
    427    /**
    428     * @return {boolean}
    429     */
    430    glsVertexArrayTests.deArray.prototype.getNormalized = function() {};
    431 
    432    /**
    433     * @return {number}
    434     */
    435    glsVertexArrayTests.deArray.prototype.getStride = function() {};
    436 
    437    /**
    438     * @return {number}
    439     */
    440    glsVertexArrayTests.deArray.prototype.getAttribNdx = function() {};
    441 
    442    /**
    443     * @param {number} attribNdx
    444     */
    445    glsVertexArrayTests.deArray.prototype.setAttribNdx = function(attribNdx) {};
    446 
    447    //glsVertexArrayTests.ContextArray class, implements glsVertexArrayTests.deArray interface
    448 
    449    /**
    450     * @constructor
    451     * @implements {glsVertexArrayTests.deArray}
    452     * @param {glsVertexArrayTests.deArray.Storage} storage
    453     * @param {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} context
    454     */
    455    glsVertexArrayTests.ContextArray = function(storage, context) {
    456        /** @type {glsVertexArrayTests.deArray.Storage} */ this.m_storage = storage;
    457        /** @type {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} */ this.m_ctx = context;
    458        /** @type {WebGLBuffer|sglrReferenceContext.DataBuffer|null} */ this.m_glBuffer = null;
    459 
    460        /** @type {boolean} */ this.m_bound = false;
    461        /** @type {number} */ this.m_attribNdx = 0;
    462        /** @type {number} */ this.m_size = 0;
    463        /** @type {Uint8Array} */ this.m_data = null;
    464        /** @type {number} */ this.m_componentCount = 1;
    465        /** @type {glsVertexArrayTests.deArray.Target} */ this.m_target = glsVertexArrayTests.deArray.Target.ARRAY;
    466        /** @type {glsVertexArrayTests.deArray.InputType} */ this.m_inputType = glsVertexArrayTests.deArray.InputType.FLOAT;
    467        /** @type {glsVertexArrayTests.deArray.OutputType} */ this.m_outputType = glsVertexArrayTests.deArray.OutputType.FLOAT;
    468        /** @type {boolean} */ this.m_normalize = false;
    469        /** @type {number} */ this.m_stride = 0;
    470        /** @type {number} */ this.m_offset = 0;
    471 
    472        if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
    473            this.m_glBuffer = this.m_ctx.createBuffer();
    474        }
    475    };
    476 
    477    // glsVertexArrayTests.ContextArray member functions
    478 
    479    /**
    480     * unBind
    481     */
    482    glsVertexArrayTests.ContextArray.prototype.unBind = function() { this.m_bound = false; };
    483 
    484    /**
    485     * @return {boolean}
    486     */
    487    glsVertexArrayTests.ContextArray.prototype.isBound = function() { return this.m_bound; };
    488 
    489    /**
    490     * @return {number}
    491     */
    492    glsVertexArrayTests.ContextArray.prototype.getComponentCount = function() { return this.m_componentCount; };
    493 
    494    /**
    495     * @return {glsVertexArrayTests.deArray.Target}
    496     */
    497    glsVertexArrayTests.ContextArray.prototype.getTarget = function() { return this.m_target; };
    498 
    499    /**
    500     * @return {glsVertexArrayTests.deArray.InputType}
    501     */
    502    glsVertexArrayTests.ContextArray.prototype.getInputType = function() { return this.m_inputType; };
    503 
    504    /**
    505     * @return {glsVertexArrayTests.deArray.OutputType}
    506     */
    507    glsVertexArrayTests.ContextArray.prototype.getOutputType = function() { return this.m_outputType; };
    508 
    509    /**
    510     * @return {glsVertexArrayTests.deArray.Storage}
    511     */
    512    glsVertexArrayTests.ContextArray.prototype.getStorageType = function() { return this.m_storage; };
    513 
    514    /**
    515     * @return {boolean}
    516     */
    517    glsVertexArrayTests.ContextArray.prototype.getNormalized = function() { return this.m_normalize; };
    518 
    519    /**
    520     * @return {number}
    521     */
    522    glsVertexArrayTests.ContextArray.prototype.getStride = function() { return this.m_stride; };
    523 
    524    /**
    525     * @return {number}
    526     */
    527    glsVertexArrayTests.ContextArray.prototype.getAttribNdx = function() { return this.m_attribNdx; };
    528 
    529    /**
    530     * @param {number} attribNdx
    531     */
    532    glsVertexArrayTests.ContextArray.prototype.setAttribNdx = function(attribNdx) { this.m_attribNdx = attribNdx; };
    533 
    534    /**
    535     * @param {glsVertexArrayTests.deArray.Target} target
    536     * @param {number} size
    537     * @param {Uint8Array} ptr
    538     * @param {glsVertexArrayTests.deArray.Usage} usage
    539     */
    540    glsVertexArrayTests.ContextArray.prototype.data = function(target, size, ptr, usage) {
    541        this.m_size = size;
    542        this.m_target = target;
    543 
    544        if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
    545            this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(target), this.m_glBuffer);
    546 
    547            //No need for size param here, as opposed to GL ES.
    548            this.m_ctx.bufferData(glsVertexArrayTests.ContextArray.targetToGL(target), ptr, glsVertexArrayTests.ContextArray.usageToGL(usage));
    549        } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER) {
    550            this.m_data = new Uint8Array(size);
    551            for (var i = 0; i < size; i++)
    552                this.m_data[i] = ptr[i];
    553        } else
    554            throw new Error('glsVertexArrayTests.ContextArray.prototype.data - Invalid storage type specified');
    555    };
    556 
    557    /**
    558     * @param {glsVertexArrayTests.deArray.Target} target
    559     * @param {number} offset
    560     * @param {number} size
    561     * @param {Uint8Array} ptr
    562     */
    563    glsVertexArrayTests.ContextArray.prototype.subdata = function(target, offset, size, ptr) {
    564        this.m_target = target;
    565 
    566        if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
    567            this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(target), this.m_glBuffer);
    568 
    569            this.m_ctx.bufferSubData(glsVertexArrayTests.ContextArray.targetToGL(target), offset, ptr);
    570        } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER)
    571            for (var i = offset; i < size; i++)
    572                this.m_data[i] = ptr[i];
    573        else
    574            throw new Error('glsVertexArrayTests.ContextArray.prototype.subdata - Invalid storage type specified');
    575    };
    576 
    577    /**
    578     * @param {number} attribNdx
    579     * @param {number} offset
    580     * @param {number} size
    581     * @param {glsVertexArrayTests.deArray.InputType} inType
    582     * @param {glsVertexArrayTests.deArray.OutputType} outType
    583     * @param {boolean} normalized
    584     * @param {number} stride
    585     */
    586    glsVertexArrayTests.ContextArray.prototype.bind = function(attribNdx, offset, size, inType, outType, normalized, stride) {
    587        this.m_attribNdx = attribNdx;
    588        this.m_bound = true;
    589        this.m_componentCount = size;
    590        this.m_inputType = inType;
    591        this.m_outputType = outType;
    592        this.m_normalize = normalized;
    593        this.m_stride = stride;
    594        this.m_offset = offset;
    595    };
    596 
    597    /**
    598     * @param {glsVertexArrayTests.deArray.Target} target
    599     */
    600    glsVertexArrayTests.ContextArray.prototype.bindIndexArray = function(target) {
    601        if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER) {
    602        } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
    603            this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(target), this.m_glBuffer);
    604        }
    605    };
    606 
    607    /**
    608     * @param {number} loc
    609     */
    610    glsVertexArrayTests.ContextArray.prototype.glBind = function(loc) {
    611        if (this.m_storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
    612            this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(this.m_target), this.m_glBuffer);
    613 
    614            if (!glsVertexArrayTests.inputTypeIsFloatType(this.m_inputType)) {
    615                // Input is not float type
    616 
    617                if (glsVertexArrayTests.outputTypeIsFloatType(this.m_outputType)) {
    618                    // Output type is float type
    619                    this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_offset);
    620                } else {
    621                    // Output type is int type
    622                    this.m_ctx.vertexAttribIPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_stride, this.m_offset);
    623                }
    624            } else {
    625                // Input type is float type
    626                // Output type must be float type
    627                DE_ASSERT(this.m_outputType == glsVertexArrayTests.deArray.OutputType.FLOAT || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC2 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC3 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC4);
    628 
    629                this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_offset);
    630            }
    631 
    632            this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(this.m_target), null);
    633        } else if (this.m_storage == glsVertexArrayTests.deArray.Storage.USER) {
    634            this.m_ctx.bindBuffer(glsVertexArrayTests.ContextArray.targetToGL(this.m_target), null);
    635 
    636            if (!glsVertexArrayTests.inputTypeIsFloatType(this.m_inputType)) {
    637                // Input is not float type
    638 
    639                if (glsVertexArrayTests.outputTypeIsFloatType(this.m_outputType)) {
    640                    // Output type is float type
    641                    this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_data.subarray(this.m_offset));
    642                } else {
    643                    // Output type is int type
    644                    this.m_ctx.vertexAttribIPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_stride, this.m_data.subarray(this.m_offset));
    645                }
    646            } else {
    647                // Input type is float type
    648 
    649                // Output type must be float type
    650                DE_ASSERT(this.m_outputType == glsVertexArrayTests.deArray.OutputType.FLOAT || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC2 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC3 || this.m_outputType == glsVertexArrayTests.deArray.OutputType.VEC4);
    651 
    652                this.m_ctx.vertexAttribPointer(loc, this.m_componentCount, glsVertexArrayTests.ContextArray.inputTypeToGL(this.m_inputType), this.m_normalize, this.m_stride, this.m_data.subarray(this.m_offset));
    653            }
    654        } else
    655            throw new Error('glsVertexArrayTests.ContextArray.prototype.glBind - Invalid storage type specified');
    656    };
    657 
    658    //glsVertexArrayTests.ContextArray static functions
    659 
    660    /**
    661     * @param {glsVertexArrayTests.deArray.Target} target
    662     * @return {number}
    663     */
    664    glsVertexArrayTests.ContextArray.targetToGL = function(target) {
    665        DE_ASSERT(target < Object.keys(glsVertexArrayTests.deArray.Target).length);
    666 
    667        /** @type {Array<number>} */ var targets =
    668        [
    669            gl.ELEMENT_ARRAY_BUFFER, // glsVertexArrayTests.deArray.Target.ELEMENT_ARRAY
    670            gl.ARRAY_BUFFER // glsVertexArrayTests.deArray.Target.ARRAY
    671        ];
    672 
    673        return targets[target];
    674    };
    675 
    676    /**
    677     * @param {glsVertexArrayTests.deArray.Usage} usage
    678     * @return {number}
    679     */
    680    glsVertexArrayTests.ContextArray.usageToGL = function(usage) {
    681        DE_ASSERT(usage < Object.keys(glsVertexArrayTests.deArray.Usage).length);
    682 
    683        /** @type {Array<number>} */ var usages =
    684        [
    685            gl.DYNAMIC_DRAW, // glsVertexArrayTests.deArray.Usage.DYNAMIC_DRAW
    686            gl.STATIC_DRAW, // glsVertexArrayTests.deArray.Usage.STATIC_DRAW
    687            gl.STREAM_DRAW, // glsVertexArrayTests.deArray.Usage.STREAM_DRAW
    688 
    689            gl.STREAM_READ, // glsVertexArrayTests.deArray.Usage.STREAM_READ
    690            gl.STREAM_COPY, // glsVertexArrayTests.deArray.Usage.STREAM_COPY
    691 
    692            gl.STATIC_READ, // glsVertexArrayTests.deArray.Usage.STATIC_READ
    693            gl.STATIC_COPY, // glsVertexArrayTests.deArray.Usage.STATIC_COPY
    694 
    695            gl.DYNAMIC_READ, // glsVertexArrayTests.deArray.Usage.DYNAMIC_READ
    696            gl.DYNAMIC_COPY // glsVertexArrayTests.deArray.Usage.DYNAMIC_COPY
    697        ];
    698        DE_ASSERT(usages.length == Object.keys(glsVertexArrayTests.deArray.Usage).length);
    699 
    700        return usages[usage];
    701    };
    702 
    703    /**
    704     * @param {glsVertexArrayTests.deArray.InputType} type
    705     * @return {number}
    706     */
    707    glsVertexArrayTests.ContextArray.inputTypeToGL = function(type) {
    708        DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.InputType).length);
    709 
    710        /** @type {Array<number>} */ var types =
    711        [
    712            gl.FLOAT, // glsVertexArrayTests.deArray.InputType.FLOAT
    713 
    714            gl.BYTE, // glsVertexArrayTests.deArray.InputType.BYTE
    715            gl.SHORT, // glsVertexArrayTests.deArray.InputType.SHORT
    716            gl.UNSIGNED_BYTE, // glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE
    717            gl.UNSIGNED_SHORT, // glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT
    718 
    719            gl.INT, // glsVertexArrayTests.deArray.InputType.INT
    720            gl.UNSIGNED_INT, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT
    721            gl.HALF_FLOAT, // glsVertexArrayTests.deArray.InputType.HALF
    722            gl.UNSIGNED_INT_2_10_10_10_REV, // glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10
    723            gl.INT_2_10_10_10_REV // glsVertexArrayTests.deArray.InputType.INT_2_10_10_10
    724        ];
    725        DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.InputType).length);
    726 
    727        return types[type];
    728    };
    729 
    730    /**
    731     * @param {glsVertexArrayTests.deArray.OutputType} type
    732     * @return {string}
    733     */
    734    glsVertexArrayTests.ContextArray.outputTypeToGLType = function(type) {
    735        DE_ASSERT(type < Object.keys(glsVertexArrayTests.deArray.OutputType).length);
    736 
    737        /** @type {Array<string>} */ var types =
    738        [
    739            'float', // glsVertexArrayTests.deArray.OutputType.FLOAT
    740            'vec2', // glsVertexArrayTests.deArray.OutputType.VEC2
    741            'vec3', // glsVertexArrayTests.deArray.OutputType.VEC3
    742            'vec4', // glsVertexArrayTests.deArray.OutputType.VEC4
    743 
    744            'int', // glsVertexArrayTests.deArray.OutputType.INT
    745            'uint', // glsVertexArrayTests.deArray.OutputType.UINT
    746 
    747            'ivec2', // glsVertexArrayTests.deArray.OutputType.IVEC2
    748            'ivec3', // glsVertexArrayTests.deArray.OutputType.IVEC3
    749            'ivec4', // glsVertexArrayTests.deArray.OutputType.IVEC4
    750 
    751            'uvec2', // glsVertexArrayTests.deArray.OutputType.UVEC2
    752            'uvec3', // glsVertexArrayTests.deArray.OutputType.UVEC3
    753            'uvec4' // glsVertexArrayTests.deArray.OutputType.UVEC4
    754        ];
    755        DE_ASSERT(types.length == Object.keys(glsVertexArrayTests.deArray.OutputType).length);
    756 
    757        return types[type];
    758    };
    759 
    760    /**
    761     * @param {glsVertexArrayTests.deArray.Primitive} primitive
    762     * @return {number}
    763     */
    764    glsVertexArrayTests.ContextArray.primitiveToGL = function(primitive) {
    765        /** @type {Array<number>} */ var primitives =
    766        [
    767            gl.POINTS, // glsVertexArrayTests.deArray.Primitive.POINTS
    768            gl.TRIANGLES, // glsVertexArrayTests.deArray.Primitive.TRIANGLES
    769            gl.TRIANGLE_FAN, // glsVertexArrayTests.deArray.Primitive.TRIANGLE_FAN
    770            gl.TRIANGLE_STRIP // glsVertexArrayTests.deArray.Primitive.TRIANGLE_STRIP
    771        ];
    772        DE_ASSERT(primitives.length == Object.keys(glsVertexArrayTests.deArray.Primitive).length);
    773 
    774        return primitives[primitive];
    775    };
    776 
    777    /**
    778     * @constructor
    779     * @param {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} drawContext
    780     */
    781    glsVertexArrayTests.ContextArrayPack = function(drawContext) {
    782        /** @type {WebGLRenderingContextBase} */ this.m_renderCtx = gl;
    783        //TODO: Reference rasterizer implementation.
    784        /** @type {sglrGLContext.GLContext | sglrReferenceContext.ReferenceContext} */ this.m_ctx = drawContext;
    785 
    786        /** @type {Array<glsVertexArrayTests.ContextArray>} */ this.m_arrays = [];
    787        /** @type {sglrShaderProgram.ShaderProgram} */ this.m_program;
    788        /** @type {tcuSurface.Surface} */ this.m_screen = new tcuSurface.Surface(
    789            Math.min(512, canvas.width),
    790            Math.min(512, canvas.height)
    791        );
    792    };
    793 
    794    /**
    795     * @return {number}
    796     */
    797    glsVertexArrayTests.ContextArrayPack.prototype.getArrayCount = function() {
    798        return this.m_arrays.length;
    799    };
    800 
    801    /**
    802     * @param {glsVertexArrayTests.deArray.Storage} storage
    803     */
    804    glsVertexArrayTests.ContextArrayPack.prototype.newArray = function(storage) {
    805        this.m_arrays.push(new glsVertexArrayTests.ContextArray(storage, this.m_ctx));
    806    };
    807 
    808    /**
    809     * @param {number} i
    810     * @return {glsVertexArrayTests.ContextArray}
    811     */
    812    glsVertexArrayTests.ContextArrayPack.prototype.getArray = function(i) {
    813        return this.m_arrays[i];
    814    };
    815 
    816    /**
    817     * updateProgram
    818     */
    819    glsVertexArrayTests.ContextArrayPack.prototype.updateProgram = function() {
    820        this.m_program = new glsVertexArrayTests.ContextShaderProgram(this.m_renderCtx, this.m_arrays);
    821    };
    822 
    823    /**
    824     * @param {glsVertexArrayTests.deArray.Primitive} primitive
    825     * @param {number} firstVertex
    826     * @param {number} vertexCount
    827     * @param {boolean} useVao
    828     * @param {number} coordScale
    829     * @param {number} colorScale
    830     */
    831    glsVertexArrayTests.ContextArrayPack.prototype.render = function(primitive, firstVertex, vertexCount, useVao, coordScale, colorScale) {
    832        var program;
    833        /** @type {(WebGLVertexArrayObject|sglrReferenceContext.VertexArray|null)} */ var vaoID = null;
    834 
    835        this.updateProgram();
    836 
    837        this.m_ctx.viewport(0, 0, this.m_screen.getWidth(), this.m_screen.getHeight());
    838        this.m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
    839        this.m_ctx.clear(gl.COLOR_BUFFER_BIT);
    840 
    841        program = this.m_ctx.createProgram(this.m_program);
    842 
    843        this.m_ctx.useProgram(program);
    844 
    845        this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(program, 'u_coordScale'), coordScale);
    846        this.m_ctx.uniform1f(this.m_ctx.getUniformLocation(program, 'u_colorScale'), colorScale);
    847 
    848        if (useVao) {
    849            vaoID = this.m_ctx.createVertexArray();
    850            this.m_ctx.bindVertexArray(vaoID);
    851        }
    852 
    853        /** @type {string} */ var attribName;
    854        /** @type {number} */ var loc;
    855        for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
    856            if (this.m_arrays[arrayNdx].isBound()) {
    857                attribName = 'a_' + this.m_arrays[arrayNdx].getAttribNdx();
    858                loc = this.m_ctx.getAttribLocation(program, attribName);
    859                this.m_ctx.enableVertexAttribArray(loc);
    860 
    861                this.m_arrays[arrayNdx].glBind(loc);
    862            }
    863        }
    864 
    865        DE_ASSERT((firstVertex % 6) == 0);
    866        //this.m_ctx.drawArrays(glsVertexArrayTests.ContextArray.primitiveToGL(primitive), firstVertex, vertexCount - firstVertex);
    867        this.m_ctx.drawQuads(gl.TRIANGLES, firstVertex, vertexCount - firstVertex);
    868 
    869        for (var arrayNdx = 0; arrayNdx < this.m_arrays.length; arrayNdx++) {
    870            if (this.m_arrays[arrayNdx].isBound()) {
    871                attribName = 'a_' + this.m_arrays[arrayNdx].getAttribNdx();
    872                loc = this.m_ctx.getAttribLocation(program, attribName);
    873 
    874                this.m_ctx.disableVertexAttribArray(loc);
    875            }
    876        }
    877 
    878        if (useVao)
    879            vaoID = this.m_ctx.deleteVertexArray(vaoID);
    880 
    881        this.m_ctx.deleteProgram(program);
    882        this.m_ctx.useProgram(null);
    883        this.m_ctx.readPixels(0, 0, this.m_screen.getWidth(), this.m_screen.getHeight(), gl.RGBA, gl.UNSIGNED_BYTE, this.m_screen.getAccess().getDataPtr());
    884    };
    885 
    886    /**
    887     * @return {tcuSurface.Surface}
    888     */
    889    glsVertexArrayTests.ContextArrayPack.prototype.getSurface = function() { return this.m_screen; };
    890 
    891    /**
    892     * glsVertexArrayTests.ContextShaderProgram class
    893     * @constructor
    894     * @extends {sglrShaderProgram.ShaderProgram}
    895     * @param {WebGLRenderingContextBase | sglrReferenceContext.ReferenceContext} ctx
    896     * @param {Array<glsVertexArrayTests.ContextArray>} arrays
    897     */
    898    glsVertexArrayTests.ContextShaderProgram = function(ctx, arrays) {
    899        sglrShaderProgram.ShaderProgram.call(this, this.createProgramDeclaration(ctx, arrays));
    900        this.m_componentCount = new Array(arrays.length);
    901        /** @type {Array<rrGenericVector.GenericVecType>} */ this.m_attrType = new Array(arrays.length);
    902 
    903        for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
    904            this.m_componentCount[arrayNdx] = this.getComponentCount(arrays[arrayNdx].getOutputType());
    905            this.m_attrType[arrayNdx] = this.mapOutputType(arrays[arrayNdx].getOutputType());
    906        }
    907    };
    908 
    909    glsVertexArrayTests.ContextShaderProgram.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    910    glsVertexArrayTests.ContextShaderProgram.prototype.constructor = glsVertexArrayTests.ContextShaderProgram;
    911 
    912    /**
    913     * glsVertexArrayTests.calcShaderColorCoord function
    914     * @param {Array<number>} coord (2 elements)
    915     * @param {Array<number>} color (3 elements)
    916     * @param {goog.NumberArray} attribValue (4 elements)
    917     * @param {boolean} isCoordinate
    918     * @param {number} numComponents
    919     */
    920    glsVertexArrayTests.calcShaderColorCoord = function(coord, color, attribValue, isCoordinate, numComponents) {
    921        if (isCoordinate)
    922            switch (numComponents) {
    923                case 1:
    924                    coord[0] = attribValue[0];
    925                    coord[1] = attribValue[0];
    926                    break;
    927                case 2:
    928                    coord[0] = attribValue[0];
    929                    coord[1] = attribValue[1];
    930                    break;
    931                case 3:
    932                    coord[0] = attribValue[0] + attribValue[2];
    933                    coord[1] = attribValue[1];
    934                    break;
    935                case 4:
    936                    coord[0] = attribValue[0] + attribValue[2];
    937                    coord[1] = attribValue[1] + attribValue[3];
    938                    break;
    939                default:
    940                    throw new Error('glsVertexArrayTests.calcShaderColorCoord - Invalid number of components');
    941            } else {
    942            switch (numComponents) {
    943                case 1:
    944                    color[0] = color[0] * attribValue[0];
    945                    break;
    946                case 2:
    947                    color[0] = color[0] * attribValue[0];
    948                    color[1] = color[1] * attribValue[1];
    949                    break;
    950                case 3:
    951                    color[0] = color[0] * attribValue[0];
    952                    color[1] = color[1] * attribValue[1];
    953                    color[2] = color[2] * attribValue[2];
    954                    break;
    955                case 4:
    956                    color[0] = color[0] * attribValue[0] * attribValue[3];
    957                    color[1] = color[1] * attribValue[1] * attribValue[3];
    958                    color[2] = color[2] * attribValue[2] * attribValue[3];
    959                    break;
    960                default:
    961                    throw new Error('glsVertexArrayTests.calcShaderColorCoord - Invalid number of components');
    962            }
    963        }
    964    };
    965 
    966    /**
    967     * glsVertexArrayTests.ContextShaderProgram.shadeVertices
    968     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    969     * @param {Array<rrVertexPacket.VertexPacket>} packets
    970     * @param {number} numPackets
    971     */
    972    glsVertexArrayTests.ContextShaderProgram.prototype.shadeVertices = function(inputs, packets, numPackets) {
    973        /** @type {number} */ var u_coordScale = this.getUniformByName('u_coordScale').value[0];
    974        /** @type {number} */ var u_colorScale = this.getUniformByName('u_colorScale').value[0];
    975 
    976        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    977            /** @type {number} */ var varyingLocColor = 0;
    978 
    979            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    980 
    981            // Calc output color
    982            /** @type {Array<number>} */ var coord = [1.0, 1.0];
    983            /** @type {Array<number>} */ var color = [1.0, 1.0, 1.0];
    984 
    985            for (var attribNdx = 0; attribNdx < this.m_attrType.length; attribNdx++) {
    986                /** @type {number} */ var numComponents = this.m_componentCount[attribNdx];
    987 
    988                glsVertexArrayTests.calcShaderColorCoord(coord, color, rrVertexAttrib.readVertexAttrib(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx, this.m_attrType[attribNdx]), attribNdx == 0, numComponents);
    989            }
    990 
    991            // Transform position
    992            packet.position = [u_coordScale * coord[0], u_coordScale * coord[1], 1.0, 1.0];
    993 
    994            // Pass color to FS
    995            packet.outputs[varyingLocColor] = [u_colorScale * color[0], u_colorScale * color[1], u_colorScale * color[2], 1.0];
    996        }
    997    };
    998 
    999    /**
   1000     * @param {Array<rrFragmentOperations.Fragment>} packets
   1001     * @param {rrShadingContext.FragmentShadingContext} context
   1002     */
   1003    glsVertexArrayTests.ContextShaderProgram.prototype.shadeFragments = function(packets, context) {
   1004        var varyingLocColor = 0;
   1005 
   1006        // Normal shading
   1007        for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx)
   1008            packets[packetNdx].value = rrShadingContext.readTriangleVarying(packets[packetNdx], context, varyingLocColor);
   1009    };
   1010 
   1011    /**
   1012     * @param {Array<glsVertexArrayTests.ContextArray>} arrays
   1013     * @return string
   1014     */
   1015    glsVertexArrayTests.ContextShaderProgram.prototype.genVertexSource = function(arrays) {
   1016        var vertexShaderSrc = '';
   1017        var params = [];
   1018 
   1019        params['VTX_IN'] = 'in';
   1020        params['VTX_OUT'] = 'out';
   1021        params['FRAG_IN'] = 'in';
   1022        params['FRAG_COLOR'] = 'dEQP_FragColor';
   1023        params['VTX_HDR'] = '#version 300 es\n';
   1024        params['FRAG_HDR'] = '#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
   1025 
   1026        vertexShaderSrc += params['VTX_HDR'];
   1027 
   1028        for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
   1029            vertexShaderSrc += params['VTX_IN'] + ' highp ' + glsVertexArrayTests.ContextArray.outputTypeToGLType(arrays[arrayNdx].getOutputType()) + ' a_' + arrays[arrayNdx].getAttribNdx() + ';\n';
   1030        }
   1031 
   1032        vertexShaderSrc +=
   1033        'uniform highp float u_coordScale;\n' +
   1034        'uniform highp float u_colorScale;\n' +
   1035        params['VTX_OUT'] + ' mediump vec4 v_color;\n' +
   1036        'void main(void)\n' +
   1037        ' {\n' +
   1038        '\tgl_PointSize = 1.0;\n' +
   1039        '\thighp vec2 coord = vec2(1.0, 1.0);\n' +
   1040        '\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n';
   1041 
   1042        for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++) {
   1043            if (arrays[arrayNdx].getAttribNdx() == 0) {
   1044                switch (arrays[arrayNdx].getOutputType()) {
   1045                    case (glsVertexArrayTests.deArray.OutputType.FLOAT):
   1046                        vertexShaderSrc +=
   1047                        '\tcoord = vec2(a_0);\n';
   1048                        break;
   1049 
   1050                    case (glsVertexArrayTests.deArray.OutputType.VEC2):
   1051                        vertexShaderSrc +=
   1052                        '\tcoord = a_0.xy;\n';
   1053                        break;
   1054 
   1055                    case (glsVertexArrayTests.deArray.OutputType.VEC3):
   1056                        vertexShaderSrc +=
   1057                        '\tcoord = a_0.xy;\n' +
   1058                        '\tcoord.x = coord.x + a_0.z;\n';
   1059                        break;
   1060 
   1061                    case (glsVertexArrayTests.deArray.OutputType.VEC4):
   1062                        vertexShaderSrc +=
   1063                        '\tcoord = a_0.xy;\n' +
   1064                        '\tcoord += a_0.zw;\n';
   1065                        break;
   1066 
   1067                    case (glsVertexArrayTests.deArray.OutputType.IVEC2):
   1068                    case (glsVertexArrayTests.deArray.OutputType.UVEC2):
   1069                        vertexShaderSrc +=
   1070                        '\tcoord = vec2(a_0.xy);\n';
   1071                        break;
   1072 
   1073                    case (glsVertexArrayTests.deArray.OutputType.IVEC3):
   1074                    case (glsVertexArrayTests.deArray.OutputType.UVEC3):
   1075                        vertexShaderSrc +=
   1076                        '\tcoord = vec2(a_0.xy);\n' +
   1077                        '\tcoord.x = coord.x + float(a_0.z);\n';
   1078                        break;
   1079 
   1080                    case (glsVertexArrayTests.deArray.OutputType.IVEC4):
   1081                    case (glsVertexArrayTests.deArray.OutputType.UVEC4):
   1082                        vertexShaderSrc +=
   1083                        '\tcoord = vec2(a_0.xy);\n' +
   1084                        '\tcoord += vec2(a_0.zw);\n';
   1085                        break;
   1086 
   1087                    default:
   1088                        throw new Error('Invalid output type');
   1089                        break;
   1090                }
   1091                continue;
   1092            }
   1093 
   1094            switch (arrays[arrayNdx].getOutputType()) {
   1095                case (glsVertexArrayTests.deArray.OutputType.FLOAT):
   1096                    vertexShaderSrc +=
   1097                    '\tcolor = color * a_' + arrays[arrayNdx].getAttribNdx() + ';\n';
   1098                    break;
   1099 
   1100                case (glsVertexArrayTests.deArray.OutputType.VEC2):
   1101                    vertexShaderSrc +=
   1102                    '\tcolor.rg = color.rg * a_' + arrays[arrayNdx].getAttribNdx() + '.xy;\n';
   1103                    break;
   1104 
   1105                case (glsVertexArrayTests.deArray.OutputType.VEC3):
   1106                    vertexShaderSrc +=
   1107                    '\tcolor = color.rgb * a_' + arrays[arrayNdx].getAttribNdx() + '.xyz;\n';
   1108                    break;
   1109 
   1110                case (glsVertexArrayTests.deArray.OutputType.VEC4):
   1111                    vertexShaderSrc +=
   1112                    '\tcolor = color.rgb * a_' + arrays[arrayNdx].getAttribNdx() + '.xyz * a_' + arrays[arrayNdx].getAttribNdx() + '.w;\n';
   1113                    break;
   1114 
   1115                default:
   1116                    throw new Error('Invalid output type');
   1117                    break;
   1118            }
   1119        }
   1120 
   1121        vertexShaderSrc +=
   1122        '\tv_color = vec4(u_colorScale * color, 1.0);\n' +
   1123        '\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n' +
   1124        '}\n';
   1125 
   1126        return vertexShaderSrc;
   1127    };
   1128 
   1129    /**
   1130     * @return {string}
   1131     */
   1132    glsVertexArrayTests.ContextShaderProgram.prototype.genFragmentSource = function() {
   1133        var params = [];
   1134 
   1135        params['VTX_IN'] = 'in';
   1136        params['VTX_OUT'] = 'out';
   1137        params['FRAG_IN'] = 'in';
   1138        params['FRAG_COLOR'] = 'dEQP_FragColor';
   1139        params['VTX_HDR'] = '#version 300 es\n';
   1140        params['FRAG_HDR'] = '#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n';
   1141 
   1142        /* TODO: Check if glsl supported version check function is needed.*/
   1143 
   1144        var fragmentShaderSrc = params['FRAG_HDR'] +
   1145        params['FRAG_IN'] + ' mediump vec4 v_color;\n' +
   1146        'void main(void)\n' +
   1147        ' {\n' +
   1148        '\t' + params['FRAG_COLOR'] + ' = v_color;\n' +
   1149        '}\n';
   1150 
   1151        return fragmentShaderSrc;
   1152    };
   1153 
   1154    /**
   1155     * @param {glsVertexArrayTests.deArray.OutputType} type
   1156     * @return {rrGenericVector.GenericVecType}
   1157     */
   1158    glsVertexArrayTests.ContextShaderProgram.prototype.mapOutputType = function(type) {
   1159        switch (type) {
   1160            case (glsVertexArrayTests.deArray.OutputType.FLOAT):
   1161            case (glsVertexArrayTests.deArray.OutputType.VEC2):
   1162            case (glsVertexArrayTests.deArray.OutputType.VEC3):
   1163            case (glsVertexArrayTests.deArray.OutputType.VEC4):
   1164                return rrGenericVector.GenericVecType.FLOAT;
   1165 
   1166            case (glsVertexArrayTests.deArray.OutputType.INT):
   1167            case (glsVertexArrayTests.deArray.OutputType.IVEC2):
   1168            case (glsVertexArrayTests.deArray.OutputType.IVEC3):
   1169            case (glsVertexArrayTests.deArray.OutputType.IVEC4):
   1170                return rrGenericVector.GenericVecType.INT32;
   1171 
   1172            case (glsVertexArrayTests.deArray.OutputType.UINT):
   1173            case (glsVertexArrayTests.deArray.OutputType.UVEC2):
   1174            case (glsVertexArrayTests.deArray.OutputType.UVEC3):
   1175            case (glsVertexArrayTests.deArray.OutputType.UVEC4):
   1176                return rrGenericVector.GenericVecType.UINT32;
   1177 
   1178            default:
   1179                throw new Error('Invalid output type');
   1180        }
   1181    };
   1182 
   1183    /**
   1184     * @param {glsVertexArrayTests.deArray.OutputType} type
   1185     * @return {number}
   1186     */
   1187    glsVertexArrayTests.ContextShaderProgram.prototype.getComponentCount = function(type) {
   1188        switch (type) {
   1189            case (glsVertexArrayTests.deArray.OutputType.FLOAT):
   1190            case (glsVertexArrayTests.deArray.OutputType.INT):
   1191            case (glsVertexArrayTests.deArray.OutputType.UINT):
   1192                return 1;
   1193 
   1194            case (glsVertexArrayTests.deArray.OutputType.VEC2):
   1195            case (glsVertexArrayTests.deArray.OutputType.IVEC2):
   1196            case (glsVertexArrayTests.deArray.OutputType.UVEC2):
   1197                return 2;
   1198 
   1199            case (glsVertexArrayTests.deArray.OutputType.VEC3):
   1200            case (glsVertexArrayTests.deArray.OutputType.IVEC3):
   1201            case (glsVertexArrayTests.deArray.OutputType.UVEC3):
   1202                return 3;
   1203 
   1204            case (glsVertexArrayTests.deArray.OutputType.VEC4):
   1205            case (glsVertexArrayTests.deArray.OutputType.IVEC4):
   1206            case (glsVertexArrayTests.deArray.OutputType.UVEC4):
   1207                return 4;
   1208 
   1209            default:
   1210                throw new Error('Invalid output type');
   1211        }
   1212    };
   1213 
   1214    /**
   1215     * @param {WebGLRenderingContextBase | sglrReferenceContext.ReferenceContext} ctx
   1216     * @param {Array<glsVertexArrayTests.ContextArray>} arrays
   1217     * @return {sglrShaderProgram.ShaderProgramDeclaration}
   1218     */
   1219    glsVertexArrayTests.ContextShaderProgram.prototype.createProgramDeclaration = function(ctx, arrays) {
   1220        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var decl = new sglrShaderProgram.ShaderProgramDeclaration();
   1221 
   1222        for (var arrayNdx = 0; arrayNdx < arrays.length; arrayNdx++)
   1223            decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_' + arrayNdx, this.mapOutputType(arrays[arrayNdx].getOutputType())));
   1224 
   1225        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
   1226        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
   1227 
   1228        decl.pushVertexSource(new sglrShaderProgram.VertexSource(this.genVertexSource(/*ctx,*/ arrays))); //TODO: Check if we need to review the support of a given GLSL version (we'd need the ctx)
   1229        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(this.genFragmentSource(/*ctx*/)));
   1230 
   1231        decl.pushUniform(new sglrShaderProgram.Uniform('u_coordScale', gluShaderUtil.DataType.FLOAT));
   1232        decl.pushUniform(new sglrShaderProgram.Uniform('u_colorScale', gluShaderUtil.DataType.FLOAT));
   1233 
   1234        return decl;
   1235    };
   1236 
   1237    /**
   1238     * glsVertexArrayTests.GLValue class
   1239     * @constructor
   1240     */
   1241    glsVertexArrayTests.GLValue = function() {
   1242        /** @type {goog.NumberArray} */ this.m_value = [0];
   1243        /** @type {glsVertexArrayTests.deArray.InputType} */ this.m_type;
   1244    };
   1245 
   1246    /**
   1247     * @param {Uint8Array} dst
   1248     * @param {glsVertexArrayTests.GLValue} val
   1249     */
   1250    glsVertexArrayTests.copyGLValueToArray = function(dst, val) {
   1251        /** @type {Uint8Array} */ var val8 = new Uint8Array(val.m_value.buffer); // TODO: Fix encapsulation issue
   1252        dst.set(val8);
   1253    };
   1254 
   1255    /**
   1256     * @param {Uint8Array} dst
   1257     * @param {goog.NumberArray} src
   1258     */
   1259    glsVertexArrayTests.copyArray = function(dst, src) {
   1260        /** @type {Uint8Array} */ var src8 = new Uint8Array(src.buffer).subarray(src.byteOffset, src.byteOffset + src.byteLength); // TODO: Fix encapsulation issue
   1261        dst.set(src8);
   1262    };
   1263 
   1264    /**
   1265     * typeToTypedArray function. Determines which type of array will store the value, and stores it.
   1266     * @param {number} value
   1267     * @param {glsVertexArrayTests.deArray.InputType} type
   1268     */
   1269    glsVertexArrayTests.GLValue.typeToTypedArray = function(value, type) {
   1270        var array;
   1271 
   1272        switch (type) {
   1273            case glsVertexArrayTests.deArray.InputType.FLOAT:
   1274                array = new Float32Array(1);
   1275                break;
   1276            /*case glsVertexArrayTests.deArray.InputType.FIXED:
   1277                array = new Int32Array(1);
   1278                break;
   1279            case glsVertexArrayTests.deArray.InputType.DOUBLE:
   1280                array = new Float32Array(1); // 64-bit?
   1281                break;*/
   1282 
   1283            case glsVertexArrayTests.deArray.InputType.BYTE:
   1284                array = new Int8Array(1);
   1285                break;
   1286            case glsVertexArrayTests.deArray.InputType.SHORT:
   1287                array = new Int16Array(1);
   1288                break;
   1289 
   1290            case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
   1291                array = new Uint8Array(1);
   1292                break;
   1293            case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
   1294                array = new Uint16Array(1);
   1295                break;
   1296 
   1297            case glsVertexArrayTests.deArray.InputType.INT:
   1298                array = new Int32Array(1);
   1299                break;
   1300            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
   1301                array = new Uint32Array(1);
   1302                break;
   1303            case glsVertexArrayTests.deArray.InputType.HALF:
   1304                array = new Uint16Array(1);
   1305                value = glsVertexArrayTests.GLValue.floatToHalf(value);
   1306                break;
   1307            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10:
   1308                array = new Uint32Array(1);
   1309                break;
   1310            case glsVertexArrayTests.deArray.InputType.INT_2_10_10_10:
   1311                array = new Int32Array(1);
   1312                break;
   1313            default:
   1314                throw new Error('glsVertexArrayTests.GLValue.typeToTypedArray - Invalid InputType');
   1315        }
   1316 
   1317        array[0] = value;
   1318        return array;
   1319    };
   1320 
   1321    /**
   1322     * glsVertexArrayTests.GLValue.create
   1323     * @param {number} value
   1324     * @param {glsVertexArrayTests.deArray.InputType} type
   1325     */
   1326    glsVertexArrayTests.GLValue.create = function(value, type) {
   1327        var v = new glsVertexArrayTests.GLValue();
   1328        v.m_value = glsVertexArrayTests.GLValue.typeToTypedArray(value, type);
   1329        v.m_type = type;
   1330        return v;
   1331    };
   1332 
   1333    /**
   1334     * glsVertexArrayTests.GLValue.halfToFloat
   1335     * @param {number} value
   1336     * @return {number}
   1337     */
   1338    glsVertexArrayTests.GLValue.halfToFloat = function(value) {
   1339        return tcuFloat.halfFloatToNumberNoDenorm(value);
   1340    };
   1341 
   1342    /**
   1343     * @param {number} f
   1344     * @return {number}
   1345     */
   1346    glsVertexArrayTests.GLValue.floatToHalf = function(f) {
   1347        // No denorm support.
   1348        return tcuFloat.numberToHalfFloatNoDenorm(f);
   1349    };
   1350 
   1351    /**
   1352     * glsVertexArrayTests.GLValue.getMaxValue
   1353     * @param {glsVertexArrayTests.deArray.InputType} type
   1354     * @return {glsVertexArrayTests.GLValue}
   1355     */
   1356    glsVertexArrayTests.GLValue.getMaxValue = function(type) {
   1357        var value;
   1358 
   1359        switch (type) {
   1360            case glsVertexArrayTests.deArray.InputType.FLOAT:
   1361                value = 127;
   1362                break;
   1363            /*case glsVertexArrayTests.deArray.InputType.FIXED:
   1364                value = 32760;
   1365                break;
   1366            case glsVertexArrayTests.deArray.InputType.DOUBLE:
   1367                value = 127;
   1368                break;*/
   1369            case glsVertexArrayTests.deArray.InputType.BYTE:
   1370                value = 127;
   1371                break;
   1372            case glsVertexArrayTests.deArray.InputType.SHORT:
   1373                value = 32760;
   1374                break;
   1375            case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
   1376                value = 255;
   1377                break;
   1378            case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
   1379                value = 65530;
   1380                break;
   1381            case glsVertexArrayTests.deArray.InputType.INT:
   1382                value = 2147483647;
   1383                break;
   1384            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
   1385                value = 4294967295;
   1386                break;
   1387            case glsVertexArrayTests.deArray.InputType.HALF:
   1388                value = 256;
   1389                break;
   1390            default: //Original code returns garbage-filled GLValues
   1391                return new glsVertexArrayTests.GLValue();
   1392        }
   1393 
   1394        return glsVertexArrayTests.GLValue.create(value, type);
   1395    };
   1396 
   1397    /**
   1398     * glsVertexArrayTests.GLValue.getMinValue
   1399     * @param {glsVertexArrayTests.deArray.InputType} type
   1400     * @return {glsVertexArrayTests.GLValue}
   1401     */
   1402    glsVertexArrayTests.GLValue.getMinValue = function(type) {
   1403        var value;
   1404 
   1405        switch (type) {
   1406            case glsVertexArrayTests.deArray.InputType.FLOAT:
   1407                value = -127;
   1408                break;
   1409            /*case glsVertexArrayTests.deArray.InputType.FIXED:
   1410                value = -32760;
   1411                break;
   1412            case glsVertexArrayTests.deArray.InputType.DOUBLE:
   1413                value = -127;
   1414                break;*/
   1415            case glsVertexArrayTests.deArray.InputType.BYTE:
   1416                value = -127;
   1417                break;
   1418            case glsVertexArrayTests.deArray.InputType.SHORT:
   1419                value = -32760;
   1420                break;
   1421            case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
   1422                value = 0;
   1423                break;
   1424            case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
   1425                value = 0;
   1426                break;
   1427            case glsVertexArrayTests.deArray.InputType.INT:
   1428                value = -2147483647;
   1429                break;
   1430            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
   1431                value = 0;
   1432                break;
   1433            case glsVertexArrayTests.deArray.InputType.HALF:
   1434                value = -256;
   1435                break;
   1436 
   1437            default: //Original code returns garbage-filled GLValues
   1438                return new glsVertexArrayTests.GLValue();
   1439        }
   1440 
   1441        return glsVertexArrayTests.GLValue.create(value, type);
   1442    };
   1443 
   1444    /**
   1445     * glsVertexArrayTests.GLValue.getRandom
   1446     * @param {deRandom.Random} rnd
   1447     * @param {glsVertexArrayTests.GLValue} min
   1448     * @param {glsVertexArrayTests.GLValue} max
   1449     * @return {glsVertexArrayTests.GLValue}
   1450     */
   1451    glsVertexArrayTests.GLValue.getRandom = function(rnd, min, max) {
   1452        DE_ASSERT(min.getType() == max.getType());
   1453 
   1454        var minv = min.interpret();
   1455        var maxv = max.interpret();
   1456        var type = min.getType();
   1457        var value;
   1458 
   1459        if (maxv < minv)
   1460            return min;
   1461 
   1462        switch (type) {
   1463            case glsVertexArrayTests.deArray.InputType.FLOAT:
   1464            //case glsVertexArrayTests.deArray.InputType.DOUBLE:
   1465            case glsVertexArrayTests.deArray.InputType.HALF: {
   1466                return glsVertexArrayTests.GLValue.create(minv + rnd.getFloat() * (maxv - minv), type);
   1467                break;
   1468            }
   1469 
   1470            /*case glsVertexArrayTests.deArray.InputType.FIXED: {
   1471                return minv == maxv ? min : glsVertexArrayTests.GLValue.create(minv + rnd.getInt() % (maxv - minv), type);
   1472                break;
   1473            }*/
   1474 
   1475            case glsVertexArrayTests.deArray.InputType.SHORT:
   1476            case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
   1477            case glsVertexArrayTests.deArray.InputType.BYTE:
   1478            case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
   1479            case glsVertexArrayTests.deArray.InputType.INT:
   1480            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT: {
   1481                return glsVertexArrayTests.GLValue.create(minv + rnd.getInt() % (maxv - minv), type);
   1482                break;
   1483            }
   1484 
   1485            default:
   1486                throw new Error('glsVertexArrayTests.GLValue.getRandom - Invalid input type');
   1487                break;
   1488        }
   1489    };
   1490 
   1491    // Minimum difference required between coordinates
   1492 
   1493    /**
   1494     * @param {glsVertexArrayTests.deArray.InputType} type
   1495     * @return {glsVertexArrayTests.GLValue}
   1496     */
   1497    glsVertexArrayTests.GLValue.minValue = function(type) {
   1498        switch (type) {
   1499            case glsVertexArrayTests.deArray.InputType.FLOAT:
   1500            case glsVertexArrayTests.deArray.InputType.BYTE:
   1501            case glsVertexArrayTests.deArray.InputType.HALF:
   1502            //case glsVertexArrayTests.deArray.InputType.DOUBLE:
   1503                return glsVertexArrayTests.GLValue.create(4, type);
   1504            case glsVertexArrayTests.deArray.InputType.SHORT:
   1505            case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
   1506                return glsVertexArrayTests.GLValue.create(4 * 256, type);
   1507            case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
   1508                return glsVertexArrayTests.GLValue.create(4 * 2, type);
   1509            /*case glsVertexArrayTests.deArray.InputType.FIXED:
   1510                return glsVertexArrayTests.GLValue.create(4 * 512, type);*/
   1511            case glsVertexArrayTests.deArray.InputType.INT:
   1512            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
   1513                return glsVertexArrayTests.GLValue.create(4 * 16777216, type);
   1514 
   1515            default:
   1516                throw new Error('glsVertexArrayTests.GLValue.minValue - Invalid input type');
   1517        }
   1518    };
   1519 
   1520    /**
   1521     * @param {glsVertexArrayTests.GLValue} val
   1522     * @return {glsVertexArrayTests.GLValue}
   1523     */
   1524    glsVertexArrayTests.GLValue.abs = function(val) {
   1525        var type = val.getType();
   1526        switch (type) {
   1527            //case glsVertexArrayTests.deArray.InputType.FIXED:
   1528            case glsVertexArrayTests.deArray.InputType.SHORT:
   1529                return glsVertexArrayTests.GLValue.create(0x7FFF & val.getValue(), type);
   1530            case glsVertexArrayTests.deArray.InputType.BYTE:
   1531                return glsVertexArrayTests.GLValue.create(0x7F & val.getValue(), type);
   1532            case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
   1533            case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
   1534            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
   1535                return val;
   1536            case glsVertexArrayTests.deArray.InputType.FLOAT:
   1537            case glsVertexArrayTests.deArray.InputType.HALF:
   1538            //case glsVertexArrayTests.deArray.InputType.DOUBLE:
   1539                return glsVertexArrayTests.GLValue.create(Math.abs(val.interpret()), type);
   1540            case glsVertexArrayTests.deArray.InputType.INT:
   1541                return glsVertexArrayTests.GLValue.create(0x7FFFFFFF & val.getValue(), type);
   1542            default:
   1543                throw new Error('glsVertexArrayTests.GLValue.abs - Invalid input type');
   1544        }
   1545    };
   1546 
   1547    /**
   1548     * @return {glsVertexArrayTests.deArray.InputType}
   1549     */
   1550    glsVertexArrayTests.GLValue.prototype.getType = function() {
   1551        return this.m_type;
   1552    };
   1553 
   1554    /**
   1555     * glsVertexArrayTests.GLValue.toFloat
   1556     * @return {number}
   1557     */
   1558    glsVertexArrayTests.GLValue.prototype.toFloat = function() {
   1559        return this.interpret();
   1560    };
   1561 
   1562    /**
   1563     * glsVertexArrayTests.GLValue.getValue
   1564     * @return {number}
   1565     */
   1566    glsVertexArrayTests.GLValue.prototype.getValue = function() {
   1567        return this.m_value[0];
   1568    };
   1569 
   1570    /**
   1571     * interpret function. Returns the m_value as a quantity so arithmetic operations can be performed on it
   1572     * Only some types require this.
   1573     * @return {number}
   1574     */
   1575    glsVertexArrayTests.GLValue.prototype.interpret = function() {
   1576        if (this.m_type == glsVertexArrayTests.deArray.InputType.HALF)
   1577            return glsVertexArrayTests.GLValue.halfToFloat(this.m_value[0]);
   1578        /*else if (this.m_type == glsVertexArrayTests.deArray.InputType.FIXED) {
   1579            var maxValue = 65536;
   1580            return Math.floor((2 * this.m_value[0] + 1) / (maxValue - 1));
   1581        }*/
   1582 
   1583        return this.m_value[0];
   1584    };
   1585 
   1586    /**
   1587     * @param {glsVertexArrayTests.GLValue} other
   1588     * @return {glsVertexArrayTests.GLValue}
   1589     */
   1590    glsVertexArrayTests.GLValue.prototype.add = function(other) {
   1591        return glsVertexArrayTests.GLValue.create(this.interpret() + other.interpret(), this.m_type);
   1592    };
   1593 
   1594    /**
   1595     * @param {glsVertexArrayTests.GLValue} other
   1596     * @return {glsVertexArrayTests.GLValue}
   1597     */
   1598    glsVertexArrayTests.GLValue.prototype.mul = function(other) {
   1599        return glsVertexArrayTests.GLValue.create(this.interpret() * other.interpret(), this.m_type);
   1600    };
   1601 
   1602    /**
   1603     * @param {glsVertexArrayTests.GLValue} other
   1604     * @return {glsVertexArrayTests.GLValue}
   1605     */
   1606    glsVertexArrayTests.GLValue.prototype.div = function(other) {
   1607        return glsVertexArrayTests.GLValue.create(this.interpret() / other.interpret(), this.m_type);
   1608    };
   1609 
   1610    /**
   1611     * @param {glsVertexArrayTests.GLValue} other
   1612     * @return {glsVertexArrayTests.GLValue}
   1613     */
   1614    glsVertexArrayTests.GLValue.prototype.sub = function(other) {
   1615        return glsVertexArrayTests.GLValue.create(this.interpret() - other.interpret(), this.m_type);
   1616    };
   1617 
   1618    /**
   1619     * @param {glsVertexArrayTests.GLValue} other
   1620     * @return {glsVertexArrayTests.GLValue}
   1621     */
   1622    glsVertexArrayTests.GLValue.prototype.addToSelf = function(other) {
   1623        this.m_value[0] = this.interpret() + other.interpret();
   1624        return this;
   1625    };
   1626 
   1627    /**
   1628     * @param {glsVertexArrayTests.GLValue} other
   1629     * @return {glsVertexArrayTests.GLValue}
   1630     */
   1631    glsVertexArrayTests.GLValue.prototype.subToSelf = function(other) {
   1632        this.m_value[0] = this.interpret() - other.interpret();
   1633        return this;
   1634    };
   1635 
   1636    /**
   1637     * @param {glsVertexArrayTests.GLValue} other
   1638     * @return {glsVertexArrayTests.GLValue}
   1639     */
   1640    glsVertexArrayTests.GLValue.prototype.mulToSelf = function(other) {
   1641        this.m_value[0] = this.interpret() * other.interpret();
   1642        return this;
   1643    };
   1644 
   1645    /**
   1646     * @param {glsVertexArrayTests.GLValue} other
   1647     * @return {glsVertexArrayTests.GLValue}
   1648     */
   1649    glsVertexArrayTests.GLValue.prototype.divToSelf = function(other) {
   1650        this.m_value[0] = this.interpret() / other.interpret();
   1651        return this;
   1652    };
   1653 
   1654    /**
   1655     * @param {glsVertexArrayTests.GLValue} other
   1656     * @return {boolean}
   1657     */
   1658    glsVertexArrayTests.GLValue.prototype.equals = function(other) {
   1659        return this.m_value[0] == other.getValue();
   1660    };
   1661 
   1662    /**
   1663     * @param {glsVertexArrayTests.GLValue} other
   1664     * @return {boolean}
   1665     */
   1666    glsVertexArrayTests.GLValue.prototype.lessThan = function(other) {
   1667        return this.interpret() < other.interpret();
   1668    };
   1669 
   1670    /**
   1671     * @param {glsVertexArrayTests.GLValue} other
   1672     * @return {boolean}
   1673     */
   1674    glsVertexArrayTests.GLValue.prototype.greaterThan = function(other) {
   1675        return this.interpret() > other.interpret();
   1676    };
   1677 
   1678    /**
   1679     * @param {glsVertexArrayTests.GLValue} other
   1680     * @return {boolean}
   1681     */
   1682    glsVertexArrayTests.GLValue.prototype.lessOrEqualThan = function(other) {
   1683        return this.interpret() <= other.interpret();
   1684    };
   1685 
   1686    /**
   1687     * @param {glsVertexArrayTests.GLValue} other
   1688     * @return {boolean}
   1689     */
   1690    glsVertexArrayTests.GLValue.prototype.greaterOrEqualThan = function(other) {
   1691        return this.interpret() >= other.interpret();
   1692    };
   1693 
   1694    /**
   1695     * glsVertexArrayTests.RandomArrayGenerator class. Contains static methods only
   1696     */
   1697    glsVertexArrayTests.RandomArrayGenerator = function() {};
   1698 
   1699    /**
   1700     * glsVertexArrayTests.RandomArrayGenerator.setData
   1701     * @param {Uint8Array} data
   1702     * @param {glsVertexArrayTests.deArray.InputType} type
   1703     * @param {deRandom.Random} rnd
   1704     * @param {glsVertexArrayTests.GLValue} min
   1705     * @param {glsVertexArrayTests.GLValue} max
   1706     */
   1707    glsVertexArrayTests.RandomArrayGenerator.setData = function(data, type, rnd, min, max) {
   1708        // Parameter type is not necessary, but we'll use it to assert the created glsVertexArrayTests.GLValue is of the correct type.
   1709        /** @type {glsVertexArrayTests.GLValue} */ var value = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
   1710        DE_ASSERT(value.getType() == type);
   1711 
   1712        glsVertexArrayTests.copyGLValueToArray(data, value);
   1713    };
   1714 
   1715    /**
   1716     * generateArray
   1717     * @param {number} seed
   1718     * @param {glsVertexArrayTests.GLValue} min
   1719     * @param {glsVertexArrayTests.GLValue} max
   1720     * @param {number} count
   1721     * @param {number} componentCount
   1722     * @param {number} stride
   1723     * @param {glsVertexArrayTests.deArray.InputType} type
   1724     * @return {ArrayBuffer}
   1725     */
   1726    glsVertexArrayTests.RandomArrayGenerator.generateArray = function(seed, min, max, count, componentCount, stride, type) {
   1727        /** @type {ArrayBuffer} */ var data;
   1728        /** @type {Uint8Array} */ var data8;
   1729 
   1730        var rnd = new deRandom.Random(seed);
   1731 
   1732        if (stride == 0)
   1733            stride = componentCount * glsVertexArrayTests.deArray.inputTypeSize(type);
   1734 
   1735        data = new ArrayBuffer(stride * count);
   1736        data8 = new Uint8Array(data);
   1737 
   1738        for (var vertexNdx = 0; vertexNdx < count; vertexNdx++) {
   1739            for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
   1740                glsVertexArrayTests.RandomArrayGenerator.setData(data8.subarray(vertexNdx * stride + glsVertexArrayTests.deArray.inputTypeSize(type) * componentNdx), type, rnd, min, max);
   1741            }
   1742        }
   1743 
   1744        return data;
   1745    };
   1746 
   1747    /* {
   1748        static char*    generateQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, glsVertexArrayTests.GLValue min, glsVertexArrayTests.GLValue max);
   1749        static char*    generatePerQuad (int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, glsVertexArrayTests.GLValue min, glsVertexArrayTests.GLValue max);
   1750 
   1751    private:
   1752        template<typename T>
   1753        static char*    createQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max);
   1754        template<typename T>
   1755        static char*    createPerQuads (int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max);
   1756        static char*    createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive);
   1757    };*/
   1758 
   1759    /**
   1760     * @param {number} seed
   1761     * @param {number} count
   1762     * @param {number} componentCount
   1763     * @param {number} offset
   1764     * @param {number} stride
   1765     * @param {glsVertexArrayTests.deArray.Primitive} primitive
   1766     * @param {glsVertexArrayTests.deArray.InputType} type
   1767     * @param {glsVertexArrayTests.GLValue} min
   1768     * @param {glsVertexArrayTests.GLValue} max
   1769     * @param {number} scale Coordinate scaling factor
   1770     * @return {ArrayBuffer}
   1771     */
   1772    glsVertexArrayTests.RandomArrayGenerator.generateQuads = function(seed, count, componentCount, offset, stride, primitive, type, min, max, scale) {
   1773        /** @type {ArrayBuffer} */ var data;
   1774 
   1775        switch (type) {
   1776            case glsVertexArrayTests.deArray.InputType.FLOAT:
   1777            /*case glsVertexArrayTests.deArray.InputType.FIXED:
   1778            case glsVertexArrayTests.deArray.InputType.DOUBLE:*/
   1779            case glsVertexArrayTests.deArray.InputType.BYTE:
   1780            case glsVertexArrayTests.deArray.InputType.SHORT:
   1781            case glsVertexArrayTests.deArray.InputType.UNSIGNED_BYTE:
   1782            case glsVertexArrayTests.deArray.InputType.UNSIGNED_SHORT:
   1783            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT:
   1784            case glsVertexArrayTests.deArray.InputType.INT:
   1785            case glsVertexArrayTests.deArray.InputType.HALF:
   1786                data = glsVertexArrayTests.RandomArrayGenerator.createQuads(seed, count, componentCount, offset, stride, primitive, min, max, scale);
   1787                break;
   1788 
   1789            case glsVertexArrayTests.deArray.InputType.INT_2_10_10_10:
   1790            case glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10:
   1791                data = glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked(seed, count, componentCount, offset, stride, primitive);
   1792                break;
   1793 
   1794            default:
   1795                throw new Error('glsVertexArrayTests.RandomArrayGenerator.generateQuads - Invalid input type');
   1796                break;
   1797        }
   1798 
   1799        return data;
   1800    };
   1801 
   1802    /**
   1803     * @param {number} seed
   1804     * @param {number} count
   1805     * @param {number} componentCount
   1806     * @param {number} offset
   1807     * @param {number} stride
   1808     * @param {glsVertexArrayTests.deArray.Primitive} primitive
   1809     * @return {ArrayBuffer}
   1810     */
   1811    glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked = function(seed, count, componentCount, offset, stride, primitive) {
   1812        DE_ASSERT(componentCount == 4);
   1813 
   1814        /** @type {number} */ var quadStride = 0;
   1815 
   1816        if (stride == 0)
   1817            stride = deMath.INT32_SIZE;
   1818 
   1819        switch (primitive) {
   1820            case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
   1821                quadStride = stride * 6;
   1822                break;
   1823 
   1824            default:
   1825                throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked - Invalid primitive');
   1826                break;
   1827        }
   1828 
   1829        /** @type {ArrayBuffer} */ var _data = new ArrayBuffer(offset + quadStride * (count - 1) + stride * 5 + componentCount * glsVertexArrayTests.deArray.inputTypeSize(glsVertexArrayTests.deArray.InputType.INT_2_10_10_10)); // last element must be fully in the array
   1830        /** @type {Uint8Array} */ var resultData = new Uint8Array(_data).subarray(offset);
   1831 
   1832        /** @type {number} */ var max = 1024;
   1833        /** @type {number} */ var min = 10;
   1834        /** @type {number} */ var max2 = 4;
   1835 
   1836        var rnd = new deRandom.Random(seed);
   1837 
   1838        switch (primitive) {
   1839            case glsVertexArrayTests.deArray.Primitive.TRIANGLES: {
   1840                for (var quadNdx = 0; quadNdx < count; quadNdx++) {
   1841                    /** @type {number} */ var x1 = min + rnd.getInt() % (max - min);
   1842                    /** @type {number} */ var x2 = min + rnd.getInt() % (max - x1);
   1843 
   1844                    /** @type {number} */ var y1 = min + rnd.getInt() % (max - min);
   1845                    /** @type {number} */ var y2 = min + rnd.getInt() % (max - y1);
   1846 
   1847                    /** @type {number} */ var z = min + rnd.getInt() % (max - min);
   1848                    /** @type {number} */ var w = rnd.getInt() % max2;
   1849 
   1850                    /** @type {number} */ var val1 = (w << 30) | (z << 20) | (y1 << 10) | x1;
   1851                    /** @type {number} */ var val2 = (w << 30) | (z << 20) | (y1 << 10) | x2;
   1852                    /** @type {number} */ var val3 = (w << 30) | (z << 20) | (y2 << 10) | x1;
   1853 
   1854                    /** @type {number} */ var val4 = (w << 30) | (z << 20) | (y2 << 10) | x1;
   1855                    /** @type {number} */ var val5 = (w << 30) | (z << 20) | (y1 << 10) | x2;
   1856                    /** @type {number} */ var val6 = (w << 30) | (z << 20) | (y2 << 10) | x2;
   1857 
   1858                    glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 0), new Uint32Array([val1]));
   1859                    glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 1), new Uint32Array([val2]));
   1860                    glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 2), new Uint32Array([val3]));
   1861                    glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 3), new Uint32Array([val4]));
   1862                    glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 4), new Uint32Array([val5]));
   1863                    glsVertexArrayTests.copyArray(resultData.subarray(quadNdx * quadStride + stride * 5), new Uint32Array([val6]));
   1864                }
   1865 
   1866                break;
   1867            }
   1868 
   1869            default:
   1870                throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuadsPacked - Invalid primitive');
   1871                break;
   1872        }
   1873 
   1874        return _data;
   1875    };
   1876 
   1877    /**
   1878     * @param {number} seed
   1879     * @param {number} count
   1880     * @param {number} componentCount
   1881     * @param {number} offset
   1882     * @param {number} stride
   1883     * @param {glsVertexArrayTests.deArray.Primitive} primitive
   1884     * @param {glsVertexArrayTests.GLValue} min
   1885     * @param {glsVertexArrayTests.GLValue} max
   1886     * @param {number} scale Coordinate scaling factor
   1887     * @return {ArrayBuffer}
   1888     */
   1889    glsVertexArrayTests.RandomArrayGenerator.createQuads = function(seed, count, componentCount, offset, stride, primitive, min, max, scale) {
   1890        var componentStride = min.m_value.byteLength; //TODO: Fix encapsulation issue
   1891        var quadStride = 0;
   1892        var type = min.getType(); //Instead of using the template parameter.
   1893 
   1894        if (stride == 0)
   1895            stride = componentCount * componentStride;
   1896        DE_ASSERT(stride >= componentCount * componentStride);
   1897 
   1898        switch (primitive) {
   1899            case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
   1900                quadStride = stride * 6;
   1901                break;
   1902 
   1903            default:
   1904                throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuads - Invalid primitive');
   1905                break;
   1906        }
   1907 
   1908        /** @type {ArrayBuffer} */ var _data = new ArrayBuffer(offset + quadStride * count);
   1909        /** @type {Uint8Array} */ var resultData = new Uint8Array(_data).subarray(offset);
   1910 
   1911        var rnd = new deRandom.Random(seed);
   1912 
   1913        switch (primitive) {
   1914            case glsVertexArrayTests.deArray.Primitive.TRIANGLES: {
   1915                for (var quadNdx = 0; quadNdx < count; ++quadNdx) {
   1916                    /** @type {glsVertexArrayTests.GLValue} */ var x1 = null;
   1917                    /** @type {glsVertexArrayTests.GLValue} */ var x2 = null;
   1918                    /** @type {glsVertexArrayTests.GLValue} */ var y1 = null;
   1919                    /** @type {glsVertexArrayTests.GLValue} */ var y2 = null;
   1920                    /** @type {glsVertexArrayTests.GLValue} */ var z = null;
   1921                    /** @type {glsVertexArrayTests.GLValue} */ var w = null;
   1922 
   1923                    // attempt to find a good (i.e not extremely small) quad
   1924                    for (var attemptNdx = 0; attemptNdx < 4; ++attemptNdx) {
   1925                        x1 = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
   1926                        x2 = glsVertexArrayTests.GLValue.getRandom(rnd, glsVertexArrayTests.GLValue.minValue(type), glsVertexArrayTests.GLValue.abs(max.sub(x1)));
   1927 
   1928                        y1 = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
   1929                        y2 = glsVertexArrayTests.GLValue.getRandom(rnd, glsVertexArrayTests.GLValue.minValue(type), glsVertexArrayTests.GLValue.abs(max.sub(y1)));
   1930 
   1931                        z = (componentCount > 2) ? (glsVertexArrayTests.GLValue.getRandom(rnd, min, max)) : (glsVertexArrayTests.GLValue.create(0, type));
   1932                        w = (componentCount > 3) ? (glsVertexArrayTests.GLValue.getRandom(rnd, min, max)) : (glsVertexArrayTests.GLValue.create(1, type));
   1933 
   1934                        // no additional components, all is good
   1935                        if (componentCount <= 2)
   1936                            break;
   1937 
   1938                        // The result quad is too thin?
   1939                        if ((Math.abs(x2.interpret() + z.interpret()) < glsVertexArrayTests.GLValue.minValue(type).interpret()) ||
   1940                            (Math.abs(y2.interpret() + w.interpret()) < glsVertexArrayTests.GLValue.minValue(type).interpret()))
   1941                            continue;
   1942 
   1943                        // all ok
   1944                        break;
   1945                    }
   1946 
   1947                    x2 = x1.add(x2);
   1948                    y2 = y1.add(y2);
   1949 
   1950                    /**
   1951                     * Transform GL vertex coordinates so that after vertex shading the vertices will be rounded.
   1952                     * We want to avoid quads that cover a pixel partially
   1953                     */
   1954                    var round = function(pos, scale, offset, range) {
   1955                        // Perform the same transformation as the vertex shader
   1956                        var val = (pos.interpret() + offset) * scale;
   1957                        var half = range / 2;
   1958                        val = val * half + half;
   1959                        // Round it
   1960                        val = Math.round(val);
   1961                        // And reverse the vertex shading transformation
   1962                        val = (val - half) / half;
   1963                        val = val / scale - offset;
   1964                        return glsVertexArrayTests.GLValue.create(val, pos.m_type);
   1965                    };
   1966 
   1967                    var viewport = gl.getParameter(gl.VIEWPORT);
   1968                    var voffset = 0;
   1969                    if (componentCount > 2)
   1970                        voffset = z.interpret();
   1971                    x1 = round(x1, scale, voffset, viewport[2]);
   1972                    x2 = round(x2, scale, voffset, viewport[2]);
   1973                    voffset = 1;
   1974                    if (componentCount > 3)
   1975                        voffset = w.interpret();
   1976                    y1 = round(y1, scale, voffset, viewport[3]);
   1977                    y2 = round(y2, scale, voffset, viewport[3]);
   1978 
   1979                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride), x1);
   1980                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + componentStride), y1);
   1981 
   1982                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride), x2);
   1983                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride + componentStride), y1);
   1984 
   1985                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 2), x1);
   1986                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 2 + componentStride), y2);
   1987 
   1988                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 3), x1);
   1989                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 3 + componentStride), y2);
   1990 
   1991                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 4), x2);
   1992                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 4 + componentStride), y1);
   1993 
   1994                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 5), x2);
   1995                    glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * 5 + componentStride), y2);
   1996 
   1997                    if (componentCount > 2) {
   1998                        for (var i = 0; i < 6; i++)
   1999                            glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * i + componentStride * 2), z);
   2000                    }
   2001 
   2002                    if (componentCount > 3) {
   2003                        for (var i = 0; i < 6; i++)
   2004                            glsVertexArrayTests.copyGLValueToArray(resultData.subarray(quadNdx * quadStride + stride * i + componentStride * 3), w);
   2005                    }
   2006                }
   2007 
   2008                break;
   2009            }
   2010 
   2011            default:
   2012                throw new Error('glsVertexArrayTests.RandomArrayGenerator.createQuads - Invalid primitive');
   2013                break;
   2014        }
   2015 
   2016        return _data;
   2017    };
   2018 
   2019    /**
   2020     * @param {number} seed
   2021     * @param {number} count
   2022     * @param {number} componentCount
   2023     * @param {number} stride
   2024     * @param {glsVertexArrayTests.deArray.Primitive} primitive
   2025     * @param {glsVertexArrayTests.deArray.InputType} type
   2026     * @param {glsVertexArrayTests.GLValue} min
   2027     * @param {glsVertexArrayTests.GLValue} max
   2028     */
   2029    glsVertexArrayTests.RandomArrayGenerator.generatePerQuad = function(seed, count, componentCount, stride, primitive, type, min, max) {
   2030        /** @type {ArrayBuffer} */ var data = null;
   2031 
   2032        data = glsVertexArrayTests.RandomArrayGenerator.createPerQuads(seed, count, componentCount, stride, primitive, min, max);
   2033        return data;
   2034    };
   2035 
   2036    /**
   2037     * @param {number} seed
   2038     * @param {number} count
   2039     * @param {number} componentCount
   2040     * @param {number} stride
   2041     * @param {glsVertexArrayTests.deArray.Primitive} primitive
   2042     * @param {glsVertexArrayTests.GLValue} min
   2043     * @param {glsVertexArrayTests.GLValue} max
   2044     */
   2045    glsVertexArrayTests.RandomArrayGenerator.createPerQuads = function(seed, count, componentCount, stride, primitive, min, max) {
   2046        var rnd = new deRandom.Random(seed);
   2047 
   2048        var componentStride = min.m_value.byteLength; //TODO: Fix encapsulation issue.
   2049 
   2050        if (stride == 0)
   2051            stride = componentStride * componentCount;
   2052 
   2053        var quadStride = 0;
   2054 
   2055        switch (primitive) {
   2056            case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
   2057                quadStride = stride * 6;
   2058                break;
   2059 
   2060            default:
   2061                throw new Error('glsVertexArrayTests.RandomArrayGenerator.createPerQuads - Invalid primitive');
   2062                break;
   2063        }
   2064 
   2065        /** @type {ArrayBuffer} */ var data = new ArrayBuffer(count * quadStride);
   2066 
   2067        for (var quadNdx = 0; quadNdx < count; quadNdx++) {
   2068            for (var componentNdx = 0; componentNdx < componentCount; componentNdx++) {
   2069                /** @type {glsVertexArrayTests.GLValue} */ var val = glsVertexArrayTests.GLValue.getRandom(rnd, min, max);
   2070 
   2071                var data8 = new Uint8Array(data);
   2072                glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 0 + componentStride * componentNdx), val);
   2073                glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 1 + componentStride * componentNdx), val);
   2074                glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 2 + componentStride * componentNdx), val);
   2075                glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 3 + componentStride * componentNdx), val);
   2076                glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 4 + componentStride * componentNdx), val);
   2077                glsVertexArrayTests.copyGLValueToArray(data8.subarray(quadNdx * quadStride + stride * 5 + componentStride * componentNdx), val);
   2078            }
   2079        }
   2080 
   2081        return data;
   2082    };
   2083 
   2084    /**
   2085     * class glsVertexArrayTests.VertexArrayTest
   2086     * @constructor
   2087     * @extends {tcuTestCase.DeqpTest}
   2088     * @param {string} name
   2089     * @param {string} description
   2090     */
   2091    glsVertexArrayTests.VertexArrayTest = function(name, description) {
   2092        tcuTestCase.DeqpTest.call(this, name, description);
   2093 
   2094        var r = /** @type {number} */ (gl.getParameter(gl.RED_BITS));
   2095        var g = /** @type {number} */ (gl.getParameter(gl.GREEN_BITS));
   2096        var b = /** @type {number} */ (gl.getParameter(gl.BLUE_BITS));
   2097        var a = /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS));
   2098        this.m_pixelformat = new tcuPixelFormat.PixelFormat(r, g, b, a);
   2099 
   2100        /** @type {sglrReferenceContext.ReferenceContextBuffers} */ this.m_refBuffers = null;
   2101        /** @type {sglrReferenceContext.ReferenceContext} */ this.m_refContext = null;
   2102        /** @type {sglrGLContext.GLContext} */ this.m_glesContext = null;
   2103        /** @type {glsVertexArrayTests.ContextArrayPack} */ this.m_glArrayPack = null;
   2104        /** @type {glsVertexArrayTests.ContextArrayPack} */ this.m_rrArrayPack = null;
   2105        /** @type {boolean} */ this.m_isOk = false;
   2106        /** @type {number} */ this.m_maxDiffRed = Math.ceil(256.0 * (2.0 / (1 << this.m_pixelformat.redBits)));
   2107        /** @type {number} */ this.m_maxDiffGreen = Math.ceil(256.0 * (2.0 / (1 << this.m_pixelformat.greenBits)));
   2108        /** @type {number} */ this.m_maxDiffBlue = Math.ceil(256.0 * (2.0 / (1 << this.m_pixelformat.blueBits)));
   2109    };
   2110 
   2111    glsVertexArrayTests.VertexArrayTest.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
   2112    glsVertexArrayTests.VertexArrayTest.prototype.constructor = glsVertexArrayTests.VertexArrayTest;
   2113 
   2114    /**
   2115     * init
   2116     */
   2117    glsVertexArrayTests.VertexArrayTest.prototype.init = function() {
   2118        /** @type {number}*/ var renderTargetWidth = Math.min(512, canvas.width);
   2119        /** @type {number}*/ var renderTargetHeight = Math.min(512, canvas.height);
   2120        /** @type {sglrReferenceContext.ReferenceContextLimits} */ var limits = new sglrReferenceContext.ReferenceContextLimits(gl);
   2121 
   2122        this.m_glesContext = new sglrGLContext.GLContext(gl);
   2123        this.m_refBuffers = new sglrReferenceContext.ReferenceContextBuffers(this.m_pixelformat, 0, 0, renderTargetWidth, renderTargetHeight);
   2124        this.m_refContext = new sglrReferenceContext.ReferenceContext(limits, this.m_refBuffers.getColorbuffer(), this.m_refBuffers.getDepthbuffer(), this.m_refBuffers.getStencilbuffer());
   2125 
   2126        this.m_glArrayPack = new glsVertexArrayTests.ContextArrayPack(this.m_glesContext);
   2127        this.m_rrArrayPack = new glsVertexArrayTests.ContextArrayPack(this.m_refContext);
   2128    };
   2129 
   2130    /**
   2131     * compare
   2132     */
   2133    glsVertexArrayTests.VertexArrayTest.prototype.compare = function() {
   2134        /** @type {tcuSurface.Surface} */ var ref = this.m_rrArrayPack.getSurface();
   2135        /** @type {tcuSurface.Surface} */ var screen = this.m_glArrayPack.getSurface();
   2136 
   2137        if (/** @type {number} */ (this.m_glesContext.getParameter(gl.SAMPLES)) > 1) {
   2138            // \todo [mika] Improve compare when using multisampling
   2139            bufferedLogToConsole('Warning: Comparison of result from multisample render targets are not as strict as without multisampling. Might produce false positives!');
   2140            this.m_isOk = tcuImageCompare.fuzzyCompare('Compare Results', 'Compare Results', ref.getAccess(), screen.getAccess(), 1.5);
   2141        } else {
   2142            /** @type {tcuRGBA.RGBA} */ var threshold = tcuRGBA.newRGBAComponents(this.m_maxDiffRed, this.m_maxDiffGreen, this.m_maxDiffBlue, 255);
   2143            /** @type {tcuSurface.Surface} */ var error = new tcuSurface.Surface(ref.getWidth(), ref.getHeight());
   2144 
   2145            this.m_isOk = true;
   2146 
   2147            for (var y = 1; y < ref.getHeight() - 1; y++) {
   2148                for (var x = 1; x < ref.getWidth() - 1; x++) {
   2149                    /** @type {tcuRGBA.RGBA} */ var refPixel = tcuRGBA.newRGBAFromArray(ref.getPixel(x, y));
   2150                    /** @type {tcuRGBA.RGBA} */ var screenPixel = tcuRGBA.newRGBAFromArray(screen.getPixel(x, y));
   2151                    /** @type {boolean} */ var isOkPixel = false;
   2152 
   2153                    // Don't do comparisons for this pixel if it belongs to a one-pixel-thin part (i.e. it doesn't have similar-color neighbors in both x and y directions) in both result and reference.
   2154                    // This fixes some false negatives.
   2155                    /** @type {boolean} */ var refThin = (
   2156                        !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x - 1, y)), threshold) &&
   2157                        !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x + 1, y)), threshold)
   2158                    ) || (
   2159                        !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x, y - 1)), threshold) &&
   2160                        !tcuRGBA.compareThreshold(refPixel, tcuRGBA.newRGBAFromArray(ref.getPixel(x, y + 1)), threshold)
   2161                    );
   2162 
   2163                    /** @type {boolean} */ var screenThin = (
   2164                        !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x - 1, y)), threshold) &&
   2165                        !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x + 1, y)), threshold)
   2166                    ) || (
   2167                        !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x, y - 1)), threshold) &&
   2168                        !tcuRGBA.compareThreshold(screenPixel, tcuRGBA.newRGBAFromArray(screen.getPixel(x, y + 1)), threshold)
   2169                    );
   2170 
   2171                    if (refThin && screenThin)
   2172                        isOkPixel = true;
   2173                    else {
   2174                        //NOTE: This will ignore lines less than three pixels wide, so
   2175                        //even if there's a difference, the test will pass.
   2176                        for (var dy = -1; dy < 2 && !isOkPixel; dy++) {
   2177                            for (var dx = -1; dx < 2 && !isOkPixel; dx++) {
   2178                                // Check reference pixel against screen pixel
   2179                                /** @type {tcuRGBA.RGBA} */ var screenCmpPixel = tcuRGBA.newRGBAFromArray(screen.getPixel(x + dx, y + dy));
   2180                                /** @type {number} (8-bit) */ var r = Math.abs(refPixel.getRed() - screenCmpPixel.getRed());
   2181                                /** @type {number} (8-bit) */ var g = Math.abs(refPixel.getGreen() - screenCmpPixel.getGreen());
   2182                                /** @type {number} (8-bit) */ var b = Math.abs(refPixel.getBlue() - screenCmpPixel.getBlue());
   2183 
   2184                                if (r <= this.m_maxDiffRed && g <= this.m_maxDiffGreen && b <= this.m_maxDiffBlue)
   2185                                    isOkPixel = true;
   2186 
   2187                                // Check screen pixels against reference pixel
   2188                                /** @type {tcuRGBA.RGBA} */ var refCmpPixel = tcuRGBA.newRGBAFromArray(ref.getPixel(x + dx, y + dy));
   2189                                r = Math.abs(refCmpPixel.getRed() - screenPixel.getRed());
   2190                                g = Math.abs(refCmpPixel.getGreen() - screenPixel.getGreen());
   2191                                b = Math.abs(refCmpPixel.getBlue() - screenPixel.getBlue());
   2192 
   2193                                    if (r <= this.m_maxDiffRed && g <= this.m_maxDiffGreen && b <= this.m_maxDiffBlue)
   2194                                        isOkPixel = true;
   2195                            }
   2196                        }
   2197                    }
   2198 
   2199                    if (isOkPixel)
   2200                        error.setPixel(x, y,
   2201                            [tcuRGBA.newRGBAFromArray(screen.getPixel(x, y)).getRed(),
   2202                            (tcuRGBA.newRGBAFromArray(screen.getPixel(x, y)).getGreen() + 255) / 2,
   2203                            tcuRGBA.newRGBAFromArray(screen.getPixel(x, y)).getBlue(), 255]
   2204                        );
   2205                    else {
   2206                        error.setPixel(x, y, [255, 0, 0, 255]);
   2207                        this.m_isOk = false;
   2208                    }
   2209                }
   2210            }
   2211 
   2212            if (!this.m_isOk) {
   2213                debug('Image comparison failed, threshold = (' + this.m_maxDiffRed + ', ' + this.m_maxDiffGreen + ', ' + this.m_maxDiffBlue + ')');
   2214                //log << TestLog::ImageSet("Compare result", "Result of rendering");
   2215                tcuImageCompare.displayImages(screen.getAccess(), ref.getAccess(), error.getAccess());
   2216            } else {
   2217                //log << TestLog::ImageSet("Compare result", "Result of rendering")
   2218                tcuLogImage.logImage('Result', '', screen.getAccess());
   2219            }
   2220        }
   2221    };
   2222 
   2223    //TODO: Is this actually used? -> glsVertexArrayTests.VertexArrayTest& operator= (const glsVertexArrayTests.VertexArrayTest& other);
   2224 
   2225    /**
   2226     * glsVertexArrayTests.MultiVertexArrayTest class
   2227     * @constructor
   2228     * @extends {glsVertexArrayTests.VertexArrayTest}
   2229     * @param {glsVertexArrayTests.MultiVertexArrayTest.Spec} spec
   2230     * @param {string} name
   2231     * @param {string} desc
   2232     */
   2233    glsVertexArrayTests.MultiVertexArrayTest = function(spec, name, desc) {
   2234        glsVertexArrayTests.VertexArrayTest.call(this, name, desc);
   2235 
   2236        /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec} */ this.m_spec = spec;
   2237        /** @type {number} */ this.m_iteration = 0;
   2238    };
   2239 
   2240    glsVertexArrayTests.MultiVertexArrayTest.prototype = Object.create(glsVertexArrayTests.VertexArrayTest.prototype);
   2241    glsVertexArrayTests.MultiVertexArrayTest.prototype.constructor = glsVertexArrayTests.MultiVertexArrayTest;
   2242 
   2243    /**
   2244     * glsVertexArrayTests.MultiVertexArrayTest.Spec class
   2245     * @constructor
   2246     */
   2247    glsVertexArrayTests.MultiVertexArrayTest.Spec = function() {
   2248        /** @type {glsVertexArrayTests.deArray.Primitive} */ this.primitive;
   2249        /** @type {number} */ this.drawCount = 0;
   2250        /** @type {number} */ this.first = 0;
   2251        /** @type {Array<glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec>} */ this.arrays = [];
   2252    };
   2253 
   2254    /**
   2255     * glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec class
   2256     * @constructor
   2257     * @param {glsVertexArrayTests.deArray.InputType} inputType_
   2258     * @param {glsVertexArrayTests.deArray.OutputType} outputType_
   2259     * @param {glsVertexArrayTests.deArray.Storage} storage_
   2260     * @param {glsVertexArrayTests.deArray.Usage} usage_
   2261     * @param {number} componentCount_
   2262     * @param {number} offset_
   2263     * @param {number} stride_
   2264     * @param {boolean} normalize_
   2265     * @param {glsVertexArrayTests.GLValue} min_
   2266     * @param {glsVertexArrayTests.GLValue} max_
   2267     */
   2268    glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec = function(inputType_, outputType_, storage_, usage_, componentCount_, offset_, stride_, normalize_, min_, max_) {
   2269        this.inputType = inputType_;
   2270        this.outputType = outputType_;
   2271        this.storage = storage_;
   2272        this.usage = usage_;
   2273        this.componentCount = componentCount_;
   2274        this.offset = offset_;
   2275        /** @type {number} */ this.stride = stride_;
   2276        this.normalize = normalize_;
   2277        this.min = min_;
   2278        this.max = max_;
   2279    };
   2280 
   2281    /**
   2282     * getName
   2283     * @return {string}
   2284     */
   2285    glsVertexArrayTests.MultiVertexArrayTest.Spec.prototype.getName = function() {
   2286        var name = '';
   2287 
   2288        for (var ndx = 0; ndx < this.arrays.length; ++ndx) {
   2289            /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var array = this.arrays[ndx];
   2290 
   2291            if (this.arrays.length > 1)
   2292                name += 'array' + ndx + '_';
   2293 
   2294            name += glsVertexArrayTests.deArray.storageToString(array.storage) + '_' +
   2295            array.offset + '_' +
   2296            array.stride + '_' +
   2297            glsVertexArrayTests.deArray.inputTypeToString(array.inputType);
   2298 
   2299            if (array.inputType != glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 && array.inputType != glsVertexArrayTests.deArray.InputType.INT_2_10_10_10)
   2300                name += array.componentCount;
   2301            name += '_' +
   2302            (array.normalize ? 'normalized_' : '') +
   2303            glsVertexArrayTests.deArray.outputTypeToString(array.outputType) + '_' +
   2304            glsVertexArrayTests.deArray.usageTypeToString(array.usage) + '_';
   2305        }
   2306 
   2307        if (this.first)
   2308            name += 'first' + this.first + '_';
   2309 
   2310        switch (this.primitive) {
   2311            case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
   2312                name += 'quads_';
   2313                break;
   2314            case glsVertexArrayTests.deArray.Primitive.POINTS:
   2315                name += 'points_';
   2316                break;
   2317 
   2318            default:
   2319                throw new Error('glsVertexArrayTests.MultiVertexArrayTest.Spec.getName - Invalid primitive type');
   2320                break;
   2321        }
   2322 
   2323        name += this.drawCount;
   2324 
   2325        return name;
   2326    };
   2327 
   2328    /**
   2329     * getName
   2330     * @return {string}
   2331     */
   2332    glsVertexArrayTests.MultiVertexArrayTest.Spec.prototype.getDesc = function() {
   2333        var desc = '';
   2334 
   2335        for (var ndx = 0; ndx < this.arrays.length; ++ndx) {
   2336            /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var array = this.arrays[ndx];
   2337 
   2338            desc += 'Array ' + ndx + ': ' +
   2339            'Storage in ' + glsVertexArrayTests.deArray.storageToString(array.storage) + ', ' +
   2340            'stride ' + array.stride + ', ' +
   2341            'input datatype ' + glsVertexArrayTests.deArray.inputTypeToString(array.inputType) + ', ' +
   2342            'input component count ' + array.componentCount + ', ' +
   2343            (array.normalize ? 'normalized, ' : '') +
   2344            'used as ' + glsVertexArrayTests.deArray.outputTypeToString(array.outputType) + ', ';
   2345        }
   2346 
   2347        desc += 'drawArrays(), ' +
   2348        'first ' + this.first + ', ' +
   2349        this.drawCount;
   2350 
   2351        switch (this.primitive) {
   2352            case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
   2353                desc += 'quads ';
   2354                break;
   2355            case glsVertexArrayTests.deArray.Primitive.POINTS:
   2356                desc += 'points';
   2357                break;
   2358 
   2359            default:
   2360                throw new Error('glsVertexArrayTests.MultiVertexArrayTest.Spec.getDesc - Invalid primitive type');
   2361                break;
   2362        }
   2363 
   2364        return desc;
   2365    };
   2366 
   2367    /**
   2368     * iterate
   2369     * @return {tcuTestCase.IterateResult}
   2370     */
   2371    glsVertexArrayTests.MultiVertexArrayTest.prototype.iterate = function() {
   2372        if (this.m_iteration == 0) {
   2373            var primitiveSize = (this.m_spec.primitive == glsVertexArrayTests.deArray.Primitive.TRIANGLES) ? (6) : (1); // in non-indexed draw Triangles means rectangles
   2374            var coordScale = 1.0;
   2375            var colorScale = 1.0;
   2376            var useVao = true; // WebGL, WebGL 2.0 - gl.getType().getProfile() == glu::PROFILE_CORE;
   2377 
   2378            // Log info
   2379            bufferedLogToConsole(this.m_spec.getDesc());
   2380 
   2381            // Color and Coord scale
   2382 
   2383            // First array is always position
   2384            /** @type {glsVertexArrayTests.MultiVertexArrayTest.Spec.ArraySpec} */ var arraySpec = this.m_spec.arrays[0];
   2385            if (arraySpec.inputType == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10) {
   2386                if (arraySpec.normalize)
   2387                    coordScale = 1;
   2388                else
   2389                    coordScale = 1 / 1024;
   2390            } else if (arraySpec.inputType == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10) {
   2391                if (arraySpec.normalize)
   2392                    coordScale = 1.0;
   2393                else
   2394                    coordScale = 1.0 / 512.0;
   2395            } else
   2396                coordScale = arraySpec.normalize && !glsVertexArrayTests.inputTypeIsFloatType(arraySpec.inputType) ? 1.0 : 0.9 / arraySpec.max.toFloat();
   2397 
   2398            if (arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.VEC3 || arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.VEC4 ||
   2399                arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.IVEC3 || arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.IVEC4 ||
   2400                arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.UVEC3 || arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.UVEC4)
   2401                coordScale = coordScale * 0.5;
   2402 
   2403            // And other arrays are color-like
   2404            for (var arrayNdx = 1; arrayNdx < this.m_spec.arrays.length; arrayNdx++) {
   2405                arraySpec = this.m_spec.arrays[arrayNdx];
   2406 
   2407                colorScale *= (arraySpec.normalize && !glsVertexArrayTests.inputTypeIsFloatType(arraySpec.inputType) ? 1.0 : 1.0 / arraySpec.max.toFloat());
   2408                if (arraySpec.outputType == glsVertexArrayTests.deArray.OutputType.VEC4)
   2409                    colorScale *= (arraySpec.normalize && !glsVertexArrayTests.inputTypeIsFloatType(arraySpec.inputType) ? 1.0 : 1.0 / arraySpec.max.toFloat());
   2410            }
   2411 
   2412            // Data
   2413 
   2414            for (var arrayNdx = 0; arrayNdx < this.m_spec.arrays.length; arrayNdx++) {
   2415                arraySpec = this.m_spec.arrays[arrayNdx];
   2416                /** @type {number} */ var seed = arraySpec.inputType + 10 * arraySpec.outputType + 100 * arraySpec.storage + 1000 * this.m_spec.primitive + 10000 * arraySpec.usage + this.m_spec.drawCount + 12 * arraySpec.componentCount + arraySpec.stride + arraySpec.normalize;
   2417                /** @type {ArrayBuffer} */ var data = null;
   2418                /** @type {number} */ var stride = arraySpec.stride == 0 ? arraySpec.componentCount * glsVertexArrayTests.deArray.inputTypeSize(arraySpec.inputType) : arraySpec.stride;
   2419                /** @type {number} */ var bufferSize = arraySpec.offset + stride * (this.m_spec.drawCount * primitiveSize - 1) + arraySpec.componentCount * glsVertexArrayTests.deArray.inputTypeSize(arraySpec.inputType);
   2420 
   2421                switch (this.m_spec.primitive) {
   2422                    //          case glsVertexArrayTests.deArray.Primitive.POINTS:
   2423                    //              data = glsVertexArrayTests.RandomArrayGenerator.generateArray(seed, arraySpec.min, arraySpec.max, arraySpec.count, arraySpec.componentCount, arraySpec.stride, arraySpec.inputType);
   2424                    //              break;
   2425                    case glsVertexArrayTests.deArray.Primitive.TRIANGLES:
   2426                        if (arrayNdx == 0) {
   2427                            data = glsVertexArrayTests.RandomArrayGenerator.generateQuads(seed, this.m_spec.drawCount, arraySpec.componentCount, arraySpec.offset, arraySpec.stride, this.m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max, coordScale);
   2428                        } else {
   2429                            DE_ASSERT(arraySpec.offset == 0); // \note [jarkko] it just hasn't been implemented
   2430                            data = glsVertexArrayTests.RandomArrayGenerator.generatePerQuad(seed, this.m_spec.drawCount, arraySpec.componentCount, arraySpec.stride, this.m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max);
   2431                        }
   2432                        break;
   2433 
   2434                    default:
   2435                        throw new Error('glsVertexArrayTests.MultiVertexArrayTest.prototype.iterate - Invalid primitive type');
   2436                        break;
   2437                }
   2438 
   2439                this.m_glArrayPack.newArray(arraySpec.storage);
   2440                this.m_rrArrayPack.newArray(arraySpec.storage);
   2441 
   2442                this.m_glArrayPack.getArray(arrayNdx).data(glsVertexArrayTests.deArray.Target.ARRAY, bufferSize, new Uint8Array(data), arraySpec.usage);
   2443                this.m_rrArrayPack.getArray(arrayNdx).data(glsVertexArrayTests.deArray.Target.ARRAY, bufferSize, new Uint8Array(data), arraySpec.usage);
   2444 
   2445                this.m_glArrayPack.getArray(arrayNdx).bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
   2446                this.m_rrArrayPack.getArray(arrayNdx).bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
   2447            }
   2448 
   2449            try {
   2450                this.m_glArrayPack.render(this.m_spec.primitive, this.m_spec.first, this.m_spec.drawCount * primitiveSize, useVao, coordScale, colorScale);
   2451                this.m_rrArrayPack.render(this.m_spec.primitive, this.m_spec.first, this.m_spec.drawCount * primitiveSize, useVao, coordScale, colorScale);
   2452            }
   2453            catch (err) {
   2454                // GL Errors are ok if the mode is not properly aligned
   2455 
   2456                bufferedLogToConsole('Got error: ' + err.message);
   2457 
   2458                if (this.isUnalignedBufferOffsetTest())
   2459                    testFailedOptions('Failed to draw with unaligned buffers', false); // TODO: QP_TEST_RESULT_COMPATIBILITY_WARNING
   2460                else if (this.isUnalignedBufferStrideTest())
   2461                    testFailedOptions('Failed to draw with unaligned stride', false); // QP_TEST_RESULT_COMPATIBILITY_WARNING
   2462                else
   2463                    throw new Error(err.message);
   2464 
   2465                return tcuTestCase.IterateResult.STOP;
   2466            }
   2467 
   2468            this.m_iteration++;
   2469            return tcuTestCase.IterateResult.CONTINUE;
   2470        } else if (this.m_iteration == 1) {
   2471            this.compare();
   2472 
   2473            if (this.m_isOk) {
   2474                testPassedOptions('', true);
   2475            } else {
   2476                if (this.isUnalignedBufferOffsetTest())
   2477                    testFailedOptions('Failed to draw with unaligned buffers', false); // QP_TEST_RESULT_COMPATIBILITY_WARNING
   2478                else if (this.isUnalignedBufferStrideTest())
   2479                    testFailedOptions('Failed to draw with unaligned stride', false); // QP_TEST_RESULT_COMPATIBILITY_WARNING
   2480                else
   2481                    testFailedOptions('Image comparison failed', false);
   2482            }
   2483 
   2484            this.m_iteration++;
   2485            return tcuTestCase.IterateResult.STOP;
   2486        } else {
   2487            testFailedOptions('glsVertexArrayTests.MultiVertexArrayTest.iterate - Invalid iteration stage', false);
   2488            return tcuTestCase.IterateResult.STOP;
   2489        }
   2490    };
   2491 
   2492    /**
   2493     * isUnalignedBufferOffsetTest
   2494     * @return {boolean}
   2495     */
   2496    glsVertexArrayTests.MultiVertexArrayTest.prototype.isUnalignedBufferOffsetTest = function() {
   2497        // Buffer offsets should be data type size aligned
   2498        for (var i = 0; i < this.m_spec.arrays.length; ++i) {
   2499            if (this.m_spec.arrays[i].storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
   2500                /** @type {boolean} */ var inputTypePacked = this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 || this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10;
   2501 
   2502                /** @type {number} */ var dataTypeSize = glsVertexArrayTests.deArray.inputTypeSize(this.m_spec.arrays[i].inputType);
   2503                if (inputTypePacked)
   2504                    dataTypeSize = 4;
   2505 
   2506                if (this.m_spec.arrays[i].offset % dataTypeSize != 0)
   2507                    return true;
   2508            }
   2509        }
   2510        return false;
   2511    };
   2512 
   2513    /**
   2514     * isUnalignedBufferStrideTest
   2515     * @return {boolean}
   2516     */
   2517    glsVertexArrayTests.MultiVertexArrayTest.prototype.isUnalignedBufferStrideTest = function() {
   2518        // Buffer strides should be data type size aligned
   2519        for (var i = 0; i < this.m_spec.arrays.length; ++i) {
   2520            if (this.m_spec.arrays[i].storage == glsVertexArrayTests.deArray.Storage.BUFFER) {
   2521                /** @type {boolean} */ var inputTypePacked = this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.UNSIGNED_INT_2_10_10_10 || this.m_spec.arrays[i].inputType == glsVertexArrayTests.deArray.InputType.INT_2_10_10_10;
   2522 
   2523                /** @type {number} */ var dataTypeSize = glsVertexArrayTests.deArray.inputTypeSize(this.m_spec.arrays[i].inputType);
   2524                if (inputTypePacked)
   2525                    dataTypeSize = 4;
   2526 
   2527                if (this.m_spec.arrays[i].stride % dataTypeSize != 0)
   2528                    return true;
   2529            }
   2530        }
   2531        return false;
   2532    };
   2533 
   2534 });