tor-browser

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

es3fShaderBuiltinVarTests.js (52694B)


      1 /*-------------------------------------------------------------------------
      2 * drawElements Quality Program OpenGL ES Utilities
      3 * ------------------------------------------------
      4 *
      5 * Copyright 2014 The Android Open Source Project
      6 *
      7 * Licensed under the Apache License, Version 2.0 (the "License");
      8 * you may not use this file except in compliance with the License.
      9 * You may obtain a copy of the License at
     10 *
     11 *      http://www.apache.org/licenses/LICENSE-2.0
     12 *
     13 * Unless required by applicable law or agreed to in writing, software
     14 * distributed under the License is distributed on an "AS IS" BASIS,
     15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16 * See the License for the specific language governing permissions and
     17 * limitations under the License.
     18 *
     19 */
     20 
     21 'use strict';
     22 goog.provide('functional.gles3.es3fShaderBuiltinVarTests');
     23 goog.require('framework.delibs.debase.deMath');
     24 goog.require('framework.delibs.debase.deRandom');
     25 goog.require('framework.delibs.debase.deString');
     26 goog.require('framework.common.tcuImageCompare');
     27 goog.require('framework.common.tcuLogImage');
     28 goog.require('framework.common.tcuPixelFormat');
     29 goog.require('framework.common.tcuRGBA');
     30 goog.require('framework.common.tcuSurface');
     31 goog.require('framework.common.tcuTestCase');
     32 goog.require('framework.common.tcuTexture');
     33 goog.require('framework.opengl.gluDrawUtil');
     34 goog.require('framework.opengl.gluShaderProgram');
     35 goog.require('framework.opengl.gluShaderUtil');
     36 goog.require('framework.opengl.gluVarType');
     37 goog.require('framework.opengl.simplereference.sglrReferenceContext');
     38 goog.require('framework.opengl.simplereference.sglrShaderProgram');
     39 goog.require('framework.referencerenderer.rrFragmentOperations');
     40 goog.require('framework.referencerenderer.rrGenericVector');
     41 goog.require('framework.referencerenderer.rrMultisamplePixelBufferAccess');
     42 goog.require('framework.referencerenderer.rrRenderer');
     43 goog.require('framework.referencerenderer.rrRenderState');
     44 goog.require('framework.referencerenderer.rrShadingContext');
     45 goog.require('framework.referencerenderer.rrVertexAttrib');
     46 goog.require('framework.referencerenderer.rrVertexPacket');
     47 goog.require('modules.shared.glsShaderRenderCase');
     48 goog.require('modules.shared.glsShaderExecUtil');
     49 
     50 goog.scope(function() {
     51    var es3fShaderBuiltinVarTests = functional.gles3.es3fShaderBuiltinVarTests;
     52    var deMath = framework.delibs.debase.deMath;
     53    var deString = framework.delibs.debase.deString;
     54    var deRandom = framework.delibs.debase.deRandom;
     55    var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
     56    var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
     57    var gluShaderProgram = framework.opengl.gluShaderProgram;
     58    var gluShaderUtil = framework.opengl.gluShaderUtil;
     59    var gluDrawUtil = framework.opengl.gluDrawUtil;
     60    var gluVarType = framework.opengl.gluVarType;
     61    var tcuPixelFormat = framework.common.tcuPixelFormat;
     62    var tcuSurface = framework.common.tcuSurface;
     63    var tcuTexture = framework.common.tcuTexture;
     64    var tcuLogImage = framework.common.tcuLogImage;
     65    var tcuTestCase = framework.common.tcuTestCase;
     66    var tcuImageCompare = framework.common.tcuImageCompare;
     67    var tcuRGBA = framework.common.tcuRGBA;
     68    var rrGenericVector = framework.referencerenderer.rrGenericVector;
     69    var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
     70    var rrMultisamplePixelBufferAccess = framework.referencerenderer.rrMultisamplePixelBufferAccess;
     71    var rrRenderer = framework.referencerenderer.rrRenderer;
     72    var rrRenderState = framework.referencerenderer.rrRenderState;
     73    var rrShadingContext = framework.referencerenderer.rrShadingContext;
     74    var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
     75    var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
     76    var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
     77    var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
     78 
     79    /** @typedef {function():number} */ es3fShaderBuiltinVarTests.GetConstantValueFunc;
     80 
     81    /**
     82     * @param {number} pname
     83     * @return {number} getParameter returns values of any kind
     84     */
     85    es3fShaderBuiltinVarTests.getInteger = function(pname) {
     86        return /** @type {number} */ (gl.getParameter(pname));
     87    };
     88 
     89    /**
     90     * @param {number} pname
     91     * @return {number} forcing number
     92     */
     93    es3fShaderBuiltinVarTests.getVectorsFromComps = function(pname) {
     94        var value = /** @type {number} */ (gl.getParameter(pname));
     95        assertMsgOptions(value%4 === 0, 'Expected value to be divisible by 4.', false, true);
     96        return value / 4;
     97    };
     98 
     99    /**
    100     * @constructor
    101     * @extends {tcuTestCase.DeqpTest}
    102     * @param {string} name
    103     * @param {string} desc
    104     * @param {string} varName
    105     * @param {es3fShaderBuiltinVarTests.GetConstantValueFunc} getValue
    106     * @param {gluShaderProgram.shaderType} shaderType
    107     */
    108    es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase = function(name, desc, varName, getValue, shaderType) {
    109        tcuTestCase.DeqpTest.call(this, name, desc);
    110        /** @type {string} */ this.m_varName = varName;
    111        /** @type {es3fShaderBuiltinVarTests.GetConstantValueFunc} */ this.m_getValue = getValue;
    112        /** @type {gluShaderProgram.shaderType} */ this.m_shaderType = shaderType;
    113    };
    114 
    115    es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    116    es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.constructor = es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase;
    117 
    118    es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.deinit = function() {
    119        // an attempt to cleanup the GL state when the test fails
    120        bufferedLogToConsole('ShaderBuildInConstantCase.deinit()');
    121        gl.useProgram(null);
    122        gl.bindBuffer(gl.ARRAY_BUFFER, null);
    123        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    124        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    125        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    126    };
    127 
    128    /**
    129     * @param {gluShaderProgram.shaderType} shaderType
    130     * @param {string} varName
    131     * @return {glsShaderExecUtil.ShaderExecutor}
    132     */
    133    es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.createGetConstantExecutor = function(shaderType, varName) {
    134        /** @type {glsShaderExecUtil.ShaderSpec} */ var shaderSpec = new glsShaderExecUtil.ShaderSpec();
    135        shaderSpec.version = gluShaderUtil.GLSLVersion.V300_ES;
    136        shaderSpec.source = 'result = ' + varName + ';\n';
    137        shaderSpec.outputs.push(new glsShaderExecUtil.Symbol('result',
    138            gluVarType.newTypeBasic(gluShaderUtil.DataType.INT, gluShaderUtil.precision.PRECISION_HIGHP)));
    139        return glsShaderExecUtil.createExecutor(shaderType, shaderSpec);
    140 
    141    };
    142 
    143    /**
    144     * @return {tcuTestCase.IterateResult}
    145     */
    146    es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase.prototype.iterate = function() {
    147        /** @type {glsShaderExecUtil.ShaderExecutor} */
    148         var shaderExecutor = this.createGetConstantExecutor(this.m_shaderType, this.m_varName);
    149        /** @type {number} */ var reference = this.m_getValue();
    150        /** @type {goog.NumberArray} */ var shaderExecutorResult;
    151        /** @type {number} */ var result;
    152 
    153        if (!shaderExecutor.isOk())
    154            assertMsgOptions(false, 'Compile failed', false, true);
    155 
    156        shaderExecutor.useProgram();
    157 
    158        shaderExecutorResult = shaderExecutor.execute(1, null);
    159        result = new Int32Array(shaderExecutorResult[0].buffer)[0];
    160 
    161        bufferedLogToConsole(this.m_varName + ' = ' + result);
    162 
    163        if (result != reference) {
    164            bufferedLogToConsole('ERROR: Expected ' + this.m_varName + ' = ' + reference + '\n' +
    165                'Test shader:' + shaderExecutor.m_program.getProgramInfo().infoLog);
    166            testFailedOptions('Invalid builtin constant value', false);
    167        } else
    168            testPassedOptions('Pass', true);
    169 
    170        return tcuTestCase.IterateResult.STOP;
    171    };
    172 
    173    /**
    174     * @struct
    175     * @constructor
    176     * @param {number=} near
    177     * @param {number=} far
    178     */
    179    es3fShaderBuiltinVarTests.DepthRangeParams = function(near, far) {
    180        /** @type {number} */ this.zNear = near === undefined ? 0.0 : near;
    181        /** @type {number} */ this.zFar = far === undefined ? 1.0 : far;
    182    };
    183 
    184    /**
    185     * @constructor
    186     * @extends {glsShaderRenderCase.ShaderEvaluator}
    187     * @param {es3fShaderBuiltinVarTests.DepthRangeParams} params
    188     */
    189    es3fShaderBuiltinVarTests.DepthRangeEvaluator = function(params) {
    190        /** @type {es3fShaderBuiltinVarTests.DepthRangeParams} */ this.m_params = params;
    191    };
    192 
    193    es3fShaderBuiltinVarTests.DepthRangeEvaluator.prototype = Object.create(glsShaderRenderCase.ShaderEvaluator.prototype);
    194    es3fShaderBuiltinVarTests.DepthRangeEvaluator.prototype.constructor = es3fShaderBuiltinVarTests.DepthRangeEvaluator;
    195 
    196    /**
    197     * @param {glsShaderRenderCase.ShaderEvalContext} c
    198     */
    199    es3fShaderBuiltinVarTests.DepthRangeEvaluator.prototype.evaluate = function(c) {
    200        /** @type {number} */ var zNear = deMath.clamp(this.m_params.zNear, 0.0, 1.0);
    201        /** @type {number} */ var zFar = deMath.clamp(this.m_params.zFar, 0.0, 1.0);
    202        /** @type {number} */ var diff = zFar - zNear;
    203        c.color[0] = zNear;
    204        c.color[1] = zFar;
    205        c.color[2] = diff * 0.5 + 0.5;
    206    };
    207 
    208    /**
    209     * @constructor
    210     * @extends {glsShaderRenderCase.ShaderRenderCase}
    211     * @param {string} name
    212     * @param {string} desc
    213     * @param {boolean} isVertexCase
    214     */
    215    es3fShaderBuiltinVarTests.ShaderDepthRangeTest = function(name, desc, isVertexCase) {
    216        glsShaderRenderCase.ShaderRenderCase.call(this, name, desc, isVertexCase);
    217        /** @type {es3fShaderBuiltinVarTests.DepthRangeParams} */ this.m_depthRange = new es3fShaderBuiltinVarTests.DepthRangeParams();
    218        /** @type {es3fShaderBuiltinVarTests.DepthRangeEvaluator} */ this.m_evaluator = new es3fShaderBuiltinVarTests.DepthRangeEvaluator(this.m_depthRange);
    219        /** @type {number} */ this.m_iterNdx = 0;
    220    };
    221 
    222    es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
    223    es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype.constructor = es3fShaderBuiltinVarTests.ShaderDepthRangeTest;
    224 
    225    es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype.init = function() {
    226        /** @type {string} */ var defaultVertSrc = '' +
    227            '#version 300 es\n' +
    228            'in highp vec4 a_position;\n' +
    229            'void main (void)\n' +
    230            '{\n' +
    231            ' gl_Position = a_position;\n' +
    232            '}\n';
    233        /** @type {string} */ var defaultFragSrc = '' +
    234            '#version 300 es\n' +
    235            'in mediump vec4 v_color;\n' +
    236            'layout(location = 0) out mediump vec4 o_color;\n\n' +
    237            'void main (void)\n' +
    238            '{\n' +
    239            ' o_color = v_color;\n' +
    240            '}\n';
    241 
    242        // Construct shader.
    243        /** @type {string} */ var src = '#version 300 es\n';
    244        if (this.m_isVertexCase)
    245            src += 'in highp vec4 a_position;\n' +
    246                   'out mediump vec4 v_color;\n';
    247        else
    248            src += 'layout(location = 0) out mediump vec4 o_color;\n';
    249 
    250        src += 'void main (void)\n{\n' +
    251               '\t' + (this.m_isVertexCase ? 'v_color' : 'o_color') + ' = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff*0.5 + 0.5, 1.0);\n';
    252 
    253        if (this.m_isVertexCase)
    254            src += '\tgl_Position = a_position;\n';
    255 
    256        src += '}\n';
    257 
    258        this.m_vertShaderSource = this.m_isVertexCase ? src : defaultVertSrc;
    259        this.m_fragShaderSource = this.m_isVertexCase ? defaultFragSrc : src;
    260 
    261        this.postinit();
    262    };
    263 
    264    /**
    265     * @return {tcuTestCase.IterateResult}
    266     */
    267    es3fShaderBuiltinVarTests.ShaderDepthRangeTest.prototype.iterate = function() {
    268        /** @type {Array<es3fShaderBuiltinVarTests.DepthRangeParams>} */ var cases = [
    269            new es3fShaderBuiltinVarTests.DepthRangeParams(0.0, 1.0)
    270        ];
    271 
    272        this.m_depthRange = cases[this.m_iterNdx];
    273        bufferedLogToConsole('gl.depthRange(' + this.m_depthRange.zNear + ', ' + this.m_depthRange.zFar + ')');
    274        gl.depthRange(this.m_depthRange.zNear, this.m_depthRange.zFar);
    275 
    276        this.postiterate();
    277        this.m_iterNdx += 1;
    278 
    279        if (this.m_iterNdx == cases.length)
    280            return tcuTestCase.IterateResult.STOP;
    281        else
    282            return tcuTestCase.IterateResult.CONTINUE;
    283    };
    284 
    285    /**
    286     * @constructor
    287     * @extends {tcuTestCase.DeqpTest}
    288     */
    289    es3fShaderBuiltinVarTests.FragCoordXYZCase = function() {
    290        tcuTestCase.DeqpTest.call(this, 'fragcoord_xyz', 'gl_FragCoord.xyz Test');
    291    };
    292 
    293    es3fShaderBuiltinVarTests.FragCoordXYZCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    294    es3fShaderBuiltinVarTests.FragCoordXYZCase.prototype.constructor = es3fShaderBuiltinVarTests.FragCoordXYZCase;
    295 
    296    es3fShaderBuiltinVarTests.FragCoordXYZCase.prototype.iterate = function() {
    297        /** @type {number} */ var width = gl.drawingBufferWidth;
    298        /** @type {number} */ var height = gl.drawingBufferHeight;
    299        /** @type {Array<number>} */ var threshold = deMath.add([1, 1, 1, 1], tcuPixelFormat.PixelFormatFromContext(gl).getColorThreshold());
    300        /** @type {Array<number>} */ var scale = [1. / width, 1. / height, 1.0];
    301 
    302        /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
    303        /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
    304 
    305        /** @type {string} */ var vtxSource = '' +
    306            '#version 300 es\n' +
    307            'in highp vec4 a_position;\n' +
    308            'void main (void)\n' +
    309            '{\n' +
    310            ' gl_Position = a_position;\n' +
    311            '}\n';
    312        /** @type {string} */ var fragSource = '' +
    313            '#version 300 es\n' +
    314            'uniform highp vec3 u_scale;\n' +
    315            'layout(location = 0) out mediump vec4 o_color;\n' +
    316            'void main (void)\n' +
    317            '{\n' +
    318            ' o_color = vec4(gl_FragCoord.xyz*u_scale, 1.0);\n' +
    319            '}\n';
    320        /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
    321 
    322        bufferedLogToConsole(program.getProgramInfo().infoLog);
    323 
    324        if (!program.isOk())
    325            throw new Error('Compile failed');
    326 
    327        // Draw with GL.
    328        /** @type {Array<number>} */ var positions = [
    329            -1.0, 1.0, -1.0, 1.0,
    330            -1.0, -1.0, 0.0, 1.0,
    331             1.0, 1.0, 0.0, 1.0,
    332             1.0, -1.0, 1.0, 1.0
    333        ];
    334        /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
    335 
    336        /** @type {WebGLUniformLocation} */ var scaleLoc = gl.getUniformLocation(program.getProgram(), 'u_scale');
    337        /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions);
    338 
    339        gl.useProgram(program.getProgram());
    340        gl.uniform3fv(scaleLoc, scale);
    341 
    342        gl.viewport(0, 0, width, height);
    343        gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indices));
    344 
    345        testImg.readViewport(gl, [0, 0, width, height]);
    346 
    347        // Draw reference
    348        for (var y = 0; y < refImg.getHeight(); y++) {
    349            for (var x = 0; x < refImg.getWidth(); x++) {
    350                /** @type {number} */ var xf = (x + .5) / refImg.getWidth();
    351                /** @type {number} */ var yf = (refImg.getHeight() - y - 1 + .5) / refImg.getHeight();
    352                /** @type {number} */ var z = (xf + yf) / 2.0;
    353                /** @type {Array<number>} */ var fragCoord = [x + .5, y + .5, z];
    354                /** @type {Array<number>} */ var scaledFC = deMath.multiply(fragCoord, scale);
    355                /** @type {Array<number>} */
    356                var color = [
    357                    deMath.clamp(Math.floor(scaledFC[0] * 255 + 0.5), 0, 255),
    358                    deMath.clamp(Math.floor(scaledFC[1] * 255 + 0.5), 0, 255),
    359                    deMath.clamp(Math.floor(scaledFC[2] * 255 + 0.5), 0, 255),
    360                    255];
    361                refImg.setPixel(x, y, color);
    362            }
    363        }
    364 
    365        // Compare
    366        /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', refImg, testImg, threshold);
    367 
    368        if (!isOk)
    369            testFailedOptions('Image comparison failed', false);
    370        else
    371            testPassedOptions('Pass', true);
    372 
    373        return tcuTestCase.IterateResult.STOP;
    374    };
    375 
    376    /**
    377     * @param {Array<number>} s
    378     * @param {Array<number>} w
    379     * @param {number} nx
    380     * @param {number} ny
    381     * @return {number}
    382     */
    383    es3fShaderBuiltinVarTests.projectedTriInterpolate = function(s, w, nx, ny) {
    384        return (s[0] * (1.0 - nx - ny)/w[0] + s[1] * ny / w[1] + s[2] * nx / w[2]) / ((1.0 - nx - ny) / w[0] + ny / w[1] + nx / w[2]);
    385    };
    386 
    387    /**
    388     * @constructor
    389     * @extends {tcuTestCase.DeqpTest}
    390     */
    391    es3fShaderBuiltinVarTests.FragCoordWCase = function() {
    392        tcuTestCase.DeqpTest.call(this, 'fragcoord_w', 'gl_FragCoord.w Test');
    393    };
    394 
    395    es3fShaderBuiltinVarTests.FragCoordWCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    396    es3fShaderBuiltinVarTests.FragCoordWCase.prototype.constructor = es3fShaderBuiltinVarTests.FragCoordWCase;
    397 
    398    /**
    399     * @return {tcuTestCase.IterateResult}
    400     */
    401    es3fShaderBuiltinVarTests.FragCoordWCase.prototype.iterate = function() {
    402        /** @type {number} */ var width = gl.drawingBufferWidth;
    403        /** @type {number} */ var height = gl.drawingBufferHeight;
    404        /** @type {Array<number>} */ var threshold = deMath.add([1, 1, 1, 1], tcuPixelFormat.PixelFormatFromContext(gl).getColorThreshold());
    405 
    406        /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
    407        /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
    408 
    409        /** @type {Array<number>} */ var w = [1.7, 2.0, 1.2, 1.0];
    410 
    411        /** @type {string} */ var vtxSource = '#version 300 es\n' +
    412            'in highp vec4 a_position;\n' +
    413            'void main (void)\n' +
    414            '{\n' +
    415            ' gl_Position = a_position;\n' +
    416            '}\n';
    417 
    418        /** @type {string} */ var fragSource = '#version 300 es\n' +
    419            'layout(location = 0) out mediump vec4 o_color;\n' +
    420            'void main (void)\n' +
    421            '{\n' +
    422            ' o_color = vec4(0.0, 1.0/gl_FragCoord.w - 1.0, 0.0, 1.0);\n' +
    423            '}\n';
    424 
    425        /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
    426        bufferedLogToConsole(program.getProgramInfo().infoLog);
    427 
    428        if (!program.isOk())
    429            throw new Error('Compile failed');
    430 
    431        // Draw with GL.
    432        /** @type {Array<number>} */ var positions = [
    433            -w[0], w[0], 0.0, w[0],
    434            -w[1], -w[1], 0.0, w[1],
    435            w[2], w[2], 0.0, w[2],
    436            w[3], -w[3], 0.0, w[3]
    437        ];
    438        /** @type {Array<number>} */ var indices = [0, 1, 2, 2, 1, 3];
    439 
    440        /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions);
    441        gl.useProgram(program.getProgram());
    442 
    443        gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indices));
    444        testImg.readViewport(gl, [0, 0, width, height]);
    445 
    446        // Draw reference
    447        for (var y = 0; y < refImg.getHeight(); y++) {
    448            for (var x = 0; x < refImg.getWidth(); x++) {
    449                /** @type {number} */ var xf = (x + 0.5) / refImg.getWidth();
    450                /** @type {number} */ var yf = (refImg.getHeight() - y - 1 + 0.5) / refImg.getHeight();
    451                /** @type {number} */ var oow = ((xf + yf) < 1.0) ?
    452                                                es3fShaderBuiltinVarTests.projectedTriInterpolate([w[0], w[1], w[2]], [w[0], w[1], w[2]], xf, yf) :
    453                                                es3fShaderBuiltinVarTests.projectedTriInterpolate([w[3], w[2], w[1]], [w[3], w[2], w[1]], 1.0 - xf, 1.0 - yf);
    454                /** @type {Array<number>} */
    455                var color = [
    456                    0,
    457                    deMath.clamp(Math.floor((oow - 1.0) * 255 + 0.5), 0, 255),
    458                    0,
    459                    255];
    460                refImg.setPixel(x, y, color);
    461            }
    462        }
    463 
    464        // Compare
    465        /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', refImg, testImg, threshold);
    466 
    467        if (!isOk) {
    468            testFailedOptions('Image comparison failed', false);
    469        } else
    470            testPassedOptions('Pass', true);
    471 
    472        return tcuTestCase.IterateResult.STOP;
    473    };
    474 
    475    /**
    476     * @constructor
    477     * @extends {tcuTestCase.DeqpTest}
    478     */
    479    es3fShaderBuiltinVarTests.PointCoordCase = function() {
    480        tcuTestCase.DeqpTest.call(this, 'pointcoord', 'gl_PointCoord Test');
    481    };
    482 
    483    es3fShaderBuiltinVarTests.PointCoordCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    484    es3fShaderBuiltinVarTests.PointCoordCase.prototype.constructor = es3fShaderBuiltinVarTests.PointCoordCase;
    485 
    486    /**
    487     * @return {tcuTestCase.IterateResult}
    488     */
    489    es3fShaderBuiltinVarTests.PointCoordCase.prototype.iterate = function() {
    490        /** @type {number} */ var width = Math.min(256, gl.drawingBufferWidth);
    491        /** @type {number} */ var height = Math.min(256, gl.drawingBufferHeight);
    492        /** @type {number} */ var threshold = 0.02;
    493 
    494        /** @type {number} */ var numPoints = 8;
    495 
    496        /** @type {Array<number>} */ var coords = [];
    497        /** @type {Array<number>} */ var pointSizeRange = [0.0, 0.0];
    498        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0x145fa);
    499        /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
    500        /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
    501 
    502        pointSizeRange = /** @type {Array<number>} */ (gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE));
    503 
    504        if (pointSizeRange[0] <= 0.0 || pointSizeRange[1] <= 0.0 || pointSizeRange[1] < pointSizeRange[0])
    505            throw new Error('Invalid gl.ALIASED_POINT_SIZE_RANGE');
    506 
    507        // Compute coordinates.
    508        for (var i = 0; i < numPoints; i++)
    509            coords.push([
    510                rnd.getFloat(-0.9, 0.9),
    511                rnd.getFloat(-0.9, 0.9),
    512                rnd.getFloat(pointSizeRange[0], pointSizeRange[1])
    513            ]);
    514 
    515        /** @type {string} */ var vtxSource = '#version 300 es\n' +
    516            'in highp vec3 a_positionSize;\n' +
    517            'void main (void)\n' +
    518            '{\n' +
    519            ' gl_Position = vec4(a_positionSize.xy, 0.0, 1.0);\n' +
    520            ' gl_PointSize = a_positionSize.z;\n' +
    521            '}\n';
    522 
    523        /** @type {string} */ var fragSource = '#version 300 es\n' +
    524            'layout(location = 0) out mediump vec4 o_color;\n' +
    525            'void main (void)\n' +
    526            '{\n' +
    527            ' o_color = vec4(gl_PointCoord, 0.0, 1.0);\n' +
    528            '}\n';
    529 
    530        /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
    531        bufferedLogToConsole(program.getProgramInfo().infoLog);
    532 
    533        if (!program.isOk())
    534            throw new Error('Compile failed');
    535 
    536        // Draw with GL.
    537        var newCoords = [].concat.apply([], coords);
    538 
    539        // /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_positionSize', 3, coords.length, 0, coords);
    540        /** @type {gluDrawUtil.VertexArrayBinding} */
    541        var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_positionSize', 3, coords.length, 12, newCoords);
    542        /** @type {number} */ var viewportX = rnd.getInt(0, gl.drawingBufferWidth - width);
    543        /** @type {number} */ var viewportY = rnd.getInt(0, gl.drawingBufferHeight - height);
    544 
    545        gl.viewport(viewportX, viewportY, width, height);
    546        gl.clearColor(0.0, 0.0, 0.0, 1.0);
    547        gl.clear(gl.COLOR_BUFFER_BIT);
    548 
    549        gl.useProgram(program.getProgram());
    550 
    551        gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.pointsFromElements(coords.length));
    552        testImg.readViewport(gl, [viewportX, viewportY, width, height]);
    553 
    554        // Draw reference
    555        refImg.getAccess().clear([0.0, 0.0, 0.0, 1.0]);
    556        for (var i = 0; i < coords.length; i++) {
    557            /** @type {number} */ var x0 = Math.round(width * (coords[i][0] * 0.5 + 0.5) - coords[i][2] * 0.5);
    558            /** @type {number} */ var y0 = Math.round(height*  (coords[i][1] * 0.5 + 0.5) - coords[i][2] * 0.5);
    559            /** @type {number} */ var x1 = Math.round(width * (coords[i][0] * 0.5 + 0.5) + coords[i][2] * 0.5);
    560            /** @type {number} */ var y1 = Math.round(height * (coords[i][1] * 0.5 + 0.5) + coords[i][2] * 0.5);
    561            /** @type {number} */ var w = x1 - x0;
    562            /** @type {number} */ var h = y1 - y0;
    563 
    564            for (var yo = 0; yo < h; yo++) {
    565                for (var xo = 0; xo < w; xo++) {
    566                    /** @type {number} */ var xf = (xo + 0.5) / w;
    567                    /** @type {number} */ var yf = ((h - yo - 1) + 0.5) / h;
    568                    /** @type {number} */ var dx = x0 + xo;
    569                    /** @type {number} */ var dy = y0 + yo;
    570                    /** @type {Array<number>} */
    571                    var color = [
    572                        deMath.clamp(Math.floor(xf * 255 + 0.5), 0, 255),
    573                        deMath.clamp(Math.floor(yf * 255 + 0.5), 0, 255),
    574                        0,
    575                        255];
    576                    if (deMath.deInBounds32(dx, 0, refImg.getWidth()) && deMath.deInBounds32(dy, 0, refImg.getHeight()))
    577                        refImg.setPixel(dx, dy, color);
    578                }
    579            }
    580        }
    581 
    582        // Compare
    583        /** @type {boolean} */ var isOk = tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', refImg.getAccess(), testImg.getAccess(), threshold);
    584 
    585        if (!isOk) {
    586            testFailedOptions('Image comparison failed', false);
    587        } else
    588            testPassedOptions('Pass', true);
    589 
    590        return tcuTestCase.IterateResult.STOP;
    591    };
    592 
    593    /**
    594     * @constructor
    595     * @extends {tcuTestCase.DeqpTest}
    596     */
    597    es3fShaderBuiltinVarTests.FrontFacingCase = function() {
    598        tcuTestCase.DeqpTest.call(this, 'frontfacing', 'gl_FrontFacing Test');
    599    };
    600 
    601    es3fShaderBuiltinVarTests.FrontFacingCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    602    es3fShaderBuiltinVarTests.FrontFacingCase.prototype.constructor = es3fShaderBuiltinVarTests.FrontFacingCase;
    603 
    604    /**
    605     * @return {tcuTestCase.IterateResult}
    606     */
    607    es3fShaderBuiltinVarTests.FrontFacingCase.prototype.iterate = function() {
    608        // Test case renders two adjecent quads, where left is has front-facing
    609        // triagles and right back-facing. Color is selected based on gl_FrontFacing
    610        // value.
    611        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0x89f2c);
    612        /** @type {number} */ var width = Math.min(64, gl.drawingBufferWidth);
    613        /** @type {number} */ var height = Math.min(64, gl.drawingBufferHeight);
    614        /** @type {number} */ var viewportX = rnd.getInt(0, gl.drawingBufferWidth - width);
    615        /** @type {number} */ var viewportY = rnd.getInt(0, gl.drawingBufferHeight - height);
    616        /** @type {Array<number>} */ var threshold = deMath.add([1, 1, 1, 1], tcuPixelFormat.PixelFormatFromContext(gl).getColorThreshold());
    617 
    618        /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(width, height);
    619        /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(width, height);
    620 
    621        /** @type {string} */ var vtxSource = '#version 300 es\n' +
    622            'in highp vec4 a_position;\n' +
    623            'void main (void)\n' +
    624            '{\n' +
    625            ' gl_Position = a_position;\n' +
    626            '}\n';
    627 
    628        /** @type {string} */ var fragSource = '#version 300 es\n' +
    629            'layout(location = 0) out mediump vec4 o_color;\n' +
    630            'void main (void)\n' +
    631            '{\n' +
    632            ' if (gl_FrontFacing)\n' +
    633            ' o_color = vec4(0.0, 1.0, 0.0, 1.0);\n' +
    634            ' else\n' +
    635            ' o_color = vec4(0.0, 0.0, 1.0, 1.0);\n' +
    636            '}\n';
    637 
    638        /** @type {gluShaderProgram.ShaderProgram} */ var program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
    639 
    640        bufferedLogToConsole(program.getProgramInfo().infoLog);
    641 
    642        if (!program.isOk())
    643            throw new Error('Compile failed');
    644 
    645        // Draw with GL.
    646        /** @type {Array<number>} */ var positions = [
    647            -1.0, 1.0, 0.0, 1.0,
    648            -1.0, -1.0, 0.0, 1.0,
    649            1.0, 1.0, 0.0, 1.0,
    650            1.0, -1.0, 0.0, 1.0
    651        ];
    652 
    653        /** @type {Array<number>} */ var indicesCCW = [0, 1, 2, 2, 1, 3];
    654        /** @type {Array<number>} */ var indicesCW = [2, 1, 0, 3, 1, 2];
    655 
    656        /** @type {gluDrawUtil.VertexArrayBinding} */ var posBinding = gluDrawUtil.newFloatVertexArrayBinding('a_position', 4, 4, 0, positions);
    657 
    658        gl.useProgram(program.getProgram());
    659 
    660        gl.viewport(viewportX, viewportY, Math.floor(width / 2), height);
    661 
    662        gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indicesCCW));
    663 
    664        gl.viewport(viewportX + Math.floor(width / 2), viewportY, width - Math.floor(width / 2), height);
    665        gluDrawUtil.draw(gl, program.getProgram(), [posBinding], gluDrawUtil.triangles(indicesCW));
    666        testImg.readViewport(gl, [viewportX, viewportY, width, height]);
    667        // Draw reference
    668        for (var y = 0; y < refImg.getHeight(); y++) {
    669            for (var x = 0; x < Math.floor(refImg.getWidth() / 2); x++)
    670                refImg.setPixel(x, y, tcuRGBA.RGBA.green.toIVec());
    671 
    672            for (var x = Math.floor(refImg.getWidth() / 2); x < refImg.getWidth(); x++)
    673                refImg.setPixel(x, y, tcuRGBA.RGBA.blue.toIVec());
    674        }
    675 
    676        // Compare
    677        /** @type {boolean} */ var isOk = tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', refImg, testImg, threshold);
    678 
    679        if (!isOk) {
    680            testFailedOptions('Image comparison failed', false);
    681        } else
    682            testPassedOptions('Pass', true);
    683 
    684        return tcuTestCase.IterateResult.STOP;
    685    };
    686 
    687    /**
    688     * @constructor
    689     * @extends {tcuTestCase.DeqpTest}
    690     */
    691    es3fShaderBuiltinVarTests.VertexIDCase = function() {
    692        tcuTestCase.DeqpTest.call(this, 'vertex_id', 'gl_VertexID Test');
    693        /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null;
    694        /** @type {WebGLBuffer} */ this.m_positionBuffer = null;
    695        /** @type {WebGLBuffer} */ this.m_elementBuffer = null;
    696        /** @type {number} */ this.m_viewportW = 0;
    697        /** @type {number} */ this.m_viewportH = 0;
    698        /** @type {number} */ this.m_iterNdx = 0;
    699        /** @type {Array<Array<number>>} */ this.m_positions = [];
    700        /** @type {Array<Array<number>>} */ this.m_colors = [];
    701    };
    702 
    703    es3fShaderBuiltinVarTests.VertexIDCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    704    es3fShaderBuiltinVarTests.VertexIDCase.prototype.constructor = es3fShaderBuiltinVarTests.VertexIDCase;
    705 
    706    es3fShaderBuiltinVarTests.VertexIDCase.MAX_VERTICES = 24; //!< 8 triangles, totals 24 vertices
    707 
    708    es3fShaderBuiltinVarTests.VertexIDCase.prototype.init = function() {
    709        /** @type {number} */ var width = gl.drawingBufferWidth;
    710        /** @type {number} */ var height = gl.drawingBufferHeight;
    711 
    712        /** @type {number} */ var quadWidth = 32;
    713        /** @type {number} */ var quadHeight = 32;
    714 
    715        if (width < quadWidth)
    716            throw new Error('Too small render target');
    717 
    718        /** @type {number} */ var maxQuadsX = Math.floor(width / quadWidth);
    719        /** @type {number} */ var numVertices = es3fShaderBuiltinVarTests.VertexIDCase.MAX_VERTICES;
    720 
    721        /** @type {number} */ var numQuads = Math.floor(numVertices / 6) + (numVertices % 6 != 0 ? 1 : 0);
    722        /** @type {number} */ var viewportW = Math.min(numQuads, maxQuadsX)*quadWidth;
    723        /** @type {number} */ var viewportH = (Math.floor(numQuads/maxQuadsX) + (numQuads % maxQuadsX != 0 ? 1 : 0)) * quadHeight;
    724 
    725        if (viewportH > height)
    726            throw new Error('Too small render target');
    727 
    728        assertMsgOptions(viewportW <= width && viewportH <= height, 'Unexpected viewport dimensions.', false, true);
    729 
    730        assertMsgOptions(!this.m_program, 'Program should not be defined at this point.', false, true);
    731 
    732        /** @type {string} */ var vtxSource = '#version 300 es\n' +
    733            'in highp vec4 a_position;\n' +
    734            'out mediump vec4 v_color;\n' +
    735            'uniform highp vec4 u_colors[24];\n' +
    736            'void main (void)\n' +
    737            '{\n' +
    738            ' gl_Position = a_position;\n' +
    739            ' v_color = u_colors[gl_VertexID];\n' +
    740            '}\n';
    741 
    742        /** @type {string} */ var fragSource = '#version 300 es\n' +
    743            'in mediump vec4 v_color;\n' +
    744            'layout(location = 0) out mediump vec4 o_color;\n' +
    745            'void main (void)\n' +
    746            '{\n' +
    747            ' o_color = v_color;\n' +
    748            '}\n';
    749 
    750        this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vtxSource, fragSource));
    751        bufferedLogToConsole(this.m_program.getProgramInfo().infoLog);
    752 
    753        if (!this.m_program.isOk()) {
    754            this.m_program = null;
    755            throw new Error('Compile failed');
    756        }
    757 
    758        this.m_positionBuffer = gl.createBuffer();
    759        this.m_elementBuffer = gl.createBuffer();
    760 
    761        // Set colors (in dynamic memory to save static data space).
    762        this.m_colors[0] = [0.0, 0.0, 0.0, 1.0];
    763        this.m_colors[1] = [0.5, 1.0, 0.5, 1.0];
    764        this.m_colors[2] = [0.0, 0.5, 1.0, 1.0];
    765        this.m_colors[3] = [0.0, 1.0, 0.0, 1.0];
    766        this.m_colors[4] = [0.0, 1.0, 1.0, 1.0];
    767        this.m_colors[5] = [0.5, 0.0, 0.0, 1.0];
    768        this.m_colors[6] = [0.5, 0.0, 1.0, 1.0];
    769        this.m_colors[7] = [0.5, 0.0, 0.5, 1.0];
    770        this.m_colors[8] = [1.0, 0.0, 0.0, 1.0];
    771        this.m_colors[9] = [0.5, 1.0, 0.0, 1.0];
    772        this.m_colors[10] = [0.0, 0.5, 0.0, 1.0];
    773        this.m_colors[11] = [0.5, 1.0, 1.0, 1.0];
    774        this.m_colors[12] = [0.0, 0.0, 1.0, 1.0];
    775        this.m_colors[13] = [1.0, 0.0, 0.5, 1.0];
    776        this.m_colors[14] = [0.0, 0.5, 0.5, 1.0];
    777        this.m_colors[15] = [1.0, 1.0, 0.5, 1.0];
    778        this.m_colors[16] = [1.0, 0.0, 1.0, 1.0];
    779        this.m_colors[17] = [1.0, 0.5, 0.0, 1.0];
    780        this.m_colors[18] = [0.0, 1.0, 0.5, 1.0];
    781        this.m_colors[19] = [1.0, 0.5, 1.0, 1.0];
    782        this.m_colors[20] = [1.0, 1.0, 0.0, 1.0];
    783        this.m_colors[21] = [1.0, 0.5, 0.5, 1.0];
    784        this.m_colors[22] = [0.0, 0.0, 0.5, 1.0];
    785        this.m_colors[23] = [1.0, 1.0, 1.0, 1.0];
    786 
    787        // Compute positions.
    788        assertMsgOptions(numVertices % 3 == 0, 'Number of vertices should be multiple of 3.', false, true);
    789 
    790        for (var vtxNdx = 0; vtxNdx < numVertices; vtxNdx += 3) {
    791            /** @type {number} */ var h = 2.0 * quadHeight / viewportH;
    792            /** @type {number} */ var w = 2.0 * quadWidth / viewportW;
    793 
    794            /** @type {number} */ var triNdx = Math.floor(vtxNdx / 3);
    795            /** @type {number} */ var quadNdx = Math.floor(triNdx / 2);
    796            /** @type {number} */ var quadY = Math.floor(quadNdx / maxQuadsX);
    797            /** @type {number} */ var quadX = quadNdx % maxQuadsX;
    798 
    799            /** @type {number} */ var x0 = -1.0 + quadX * w;
    800            /** @type {number} */ var y0 = -1.0 + quadY * h;
    801 
    802            if (triNdx % 2 === 0) {
    803                this.m_positions[vtxNdx + 0] = [x0, y0, 0.0, 1.0];
    804                this.m_positions[vtxNdx + 1] = [x0+w, y0+h, 0.0, 1.0];
    805                this.m_positions[vtxNdx + 2] = [x0, y0+h, 0.0, 1.0];
    806            } else {
    807                this.m_positions[vtxNdx + 0] = [x0 + w, y0 + h, 0.0, 1.0];
    808                this.m_positions[vtxNdx + 1] = [x0, y0, 0.0, 1.0];
    809                this.m_positions[vtxNdx + 2] = [x0+w, y0, 0.0, 1.0];
    810            }
    811        }
    812 
    813        this.m_viewportW = viewportW;
    814        this.m_viewportH = viewportH;
    815        this.m_iterNdx = 0;
    816 
    817    };
    818 
    819    es3fShaderBuiltinVarTests.VertexIDCase.prototype.deinit = function() {
    820        this.m_program = null;
    821 
    822        if (this.m_positionBuffer) {
    823            gl.deleteBuffer(this.m_positionBuffer);
    824            this.m_positionBuffer = null;
    825        }
    826 
    827        if (this.m_elementBuffer) {
    828            gl.deleteBuffer(this.m_elementBuffer);
    829            this.m_elementBuffer = null;
    830        }
    831 
    832        this.m_positions = [];
    833        this.m_colors = [];
    834    };
    835 
    836    /**
    837     * @constructor
    838     * @extends {sglrShaderProgram.ShaderProgram}
    839     */
    840    es3fShaderBuiltinVarTests.VertexIDReferenceShader = function() {
    841        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */ var declaration = new sglrShaderProgram.ShaderProgramDeclaration();
    842        declaration.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('', rrGenericVector.GenericVecType.FLOAT));
    843        declaration.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('', rrGenericVector.GenericVecType.FLOAT));
    844        declaration.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT, new sglrShaderProgram.VaryingFlags()));
    845        declaration.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(rrGenericVector.GenericVecType.FLOAT));
    846        declaration.pushVertexSource(new sglrShaderProgram.VertexSource('')); // ShaderProgram fails if we don't push a source, even though GLSL source is not used
    847        declaration.pushFragmentSource(new sglrShaderProgram.FragmentSource(''));
    848        sglrShaderProgram.ShaderProgram.call(this, declaration);
    849    };
    850 
    851    es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    852    es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype.constructor = es3fShaderBuiltinVarTests.VertexIDReferenceShader;
    853 
    854    /** @const {number} */ es3fShaderBuiltinVarTests.VertexIDReferenceShader.VARYINGLOC_COLOR = 0;
    855 
    856    /**
    857     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    858     * @param {Array<rrVertexPacket.VertexPacket>} packets
    859     */
    860    es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype.shadeVertices = function(inputs, packets) {
    861        for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx) {
    862            /** @type {number} */ var positionAttrLoc = 0;
    863            /** @type {number} */ var colorAttrLoc = 1;
    864 
    865            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    866 
    867            // Transform to position
    868            packet.position = rrVertexAttrib.readVertexAttrib(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    869 
    870            // Pass color to FS
    871            packet.outputs[es3fShaderBuiltinVarTests.VertexIDReferenceShader.VARYINGLOC_COLOR] = rrVertexAttrib.readVertexAttrib(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    872        }
    873    };
    874 
    875    /**
    876     * @param {Array<rrFragmentOperations.Fragment>} packets
    877     * @param {rrShadingContext.FragmentShadingContext} context
    878     */
    879    es3fShaderBuiltinVarTests.VertexIDReferenceShader.prototype.shadeFragments = function(packets, context) {
    880        for (var packetNdx = 0; packetNdx < packets.length; ++packetNdx) {
    881            /** @type {rrFragmentOperations.Fragment} */ var packet = packets[packetNdx];
    882            packet.value = rrShadingContext.readVarying(packet, context, es3fShaderBuiltinVarTests.VertexIDReferenceShader.VARYINGLOC_COLOR);
    883        }
    884    };
    885 
    886    /**
    887     * @param {tcuTexture.PixelBufferAccess} dst
    888     * @param {Array<number>} indices
    889     * @param {goog.NumberArray} positions
    890     * @param {goog.NumberArray} colors
    891     */
    892    es3fShaderBuiltinVarTests.VertexIDCase.prototype.renderReference = function(dst, indices, positions, colors) {
    893        /** @type {rrRenderState.RenderState} */
    894        var referenceState = new rrRenderState.RenderState(
    895            new rrRenderState.ViewportState(rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(dst))
    896        );
    897 
    898        /** @type {rrRenderer.RenderTarget} */
    899        var referenceTarget = new rrRenderer.RenderTarget(
    900            rrMultisamplePixelBufferAccess.MultisamplePixelBufferAccess.fromSinglesampleAccess(dst)
    901        );
    902 
    903        /** @type {es3fShaderBuiltinVarTests.VertexIDReferenceShader} */
    904        var referenceShaderProgram = new es3fShaderBuiltinVarTests.VertexIDReferenceShader();
    905 
    906        /** @type {Array<rrVertexAttrib.VertexAttrib>} */ var attribs = [];
    907        attribs[0] = new rrVertexAttrib.VertexAttrib();
    908        attribs[0].type = rrVertexAttrib.VertexAttribType.FLOAT;
    909        attribs[0].size = 4;
    910        attribs[0].stride = 0;
    911        attribs[0].instanceDivisor = 0;
    912        attribs[0].pointer = positions.buffer;
    913 
    914        attribs[1] = new rrVertexAttrib.VertexAttrib();
    915        attribs[1].type = rrVertexAttrib.VertexAttribType.FLOAT;
    916        attribs[1].size = 4;
    917        attribs[1].stride = 0;
    918        attribs[1].instanceDivisor = 0;
    919        attribs[1].pointer = colors.buffer;
    920        rrRenderer.drawTriangles(referenceState, referenceTarget, referenceShaderProgram,
    921            attribs, rrRenderer.PrimitiveType.TRIANGLES, 0, indices.length, /*instanceID = */ 0);
    922    };
    923 
    924    /**
    925     * @return {tcuTestCase.IterateResult}
    926     */
    927    es3fShaderBuiltinVarTests.VertexIDCase.prototype.iterate = function() {
    928        /** @type {number} */ var width = gl.drawingBufferWidth;
    929        /** @type {number} */ var height = gl.drawingBufferHeight;
    930        /** @type {number} */ var viewportW = this.m_viewportW;
    931        /** @type {number} */ var viewportH = this.m_viewportH;
    932 
    933        /** @type {number} */ var threshold = 0.02;
    934 
    935        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(0xcf23ab1 ^ deString.deStringHash(this.m_iterNdx.toString()));
    936        /** @type {tcuSurface.Surface} */ var refImg = new tcuSurface.Surface(viewportW, viewportH);
    937        /** @type {tcuSurface.Surface} */ var testImg = new tcuSurface.Surface(viewportW, viewportH);
    938 
    939        /** @type {number} */ var viewportX = rnd.getInt(0, width - viewportW);
    940        /** @type {number} */ var viewportY = rnd.getInt(0, height - viewportH);
    941 
    942        /** @type {number} */ var posLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
    943        /** @type {WebGLUniformLocation} */ var colorsLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_colors[0]');
    944        /** @type {Array<number>} */ var clearColor = [0.0, 0.0, 0.0, 1.0];
    945        /** @type {Array<number>} */ var indices = [];
    946        /** @type {Array<Array<number>>} */ var mappedPos = [];
    947        /** @type {goog.NumberArray} */ var flatColorArray;
    948        /** @type {goog.NumberArray} */ var flatPosArray;
    949        // Setup common state.
    950        gl.viewport(viewportX, viewportY, viewportW, viewportH);
    951        gl.useProgram(this.m_program.getProgram());
    952        gl.bindBuffer(gl.ARRAY_BUFFER, this.m_positionBuffer);
    953        gl.enableVertexAttribArray(posLoc);
    954        gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0);
    955        gl.uniform4fv(colorsLoc, [].concat.apply([], this.m_colors));
    956 
    957        // Clear render target to black.
    958        gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
    959        gl.clear(gl.COLOR_BUFFER_BIT);
    960 
    961        refImg.getAccess().clear(clearColor);
    962 
    963        if (this.m_iterNdx === 0) {
    964            bufferedLogToConsole('Iter0: glDrawArrays()');
    965 
    966            flatPosArray = new Float32Array([].concat.apply([], this.m_positions));
    967            flatColorArray = new Float32Array([].concat.apply([], this.m_colors));
    968            gl.bufferData(gl.ARRAY_BUFFER, flatPosArray.buffer, gl.DYNAMIC_DRAW);
    969            gl.drawArrays(gl.TRIANGLES, 0, Math.floor(flatPosArray.length / 4));
    970 
    971            //glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
    972            testImg.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
    973            // Reference indices
    974            for (var ndx = 0; ndx < this.m_positions.length; ndx++)
    975                indices.push(ndx);
    976 
    977            this.renderReference(refImg.getAccess(), indices, flatPosArray, flatColorArray);
    978        } else if (this.m_iterNdx === 1) {
    979            bufferedLogToConsole('Iter1: glDrawElements(), indices in buffer');
    980 
    981            // Compute initial indices and suffle
    982            for (var ndx = 0; ndx < this.m_positions.length; ndx++)
    983                indices.push(ndx);
    984            // deRandom.shuffle(rnd, indices);
    985            // \note [2015-08-05 dag] The original test shuffles the indices array but the reference renderer cannot handle triangles with sides not parallel to the axes.
    986 
    987            // Use indices to re-map positions.
    988            for (var ndx = 0; ndx < indices.length; ndx++)
    989                mappedPos[indices[ndx]] = this.m_positions[ndx];
    990 
    991            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.m_elementBuffer);
    992            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, (new Uint16Array(indices)).buffer, gl.DYNAMIC_DRAW);
    993 
    994            flatPosArray = new Float32Array([].concat.apply([], mappedPos));
    995            flatColorArray = new Float32Array([].concat.apply([], this.m_colors));
    996            gl.bufferData(gl.ARRAY_BUFFER, flatPosArray.buffer, gl.DYNAMIC_DRAW);
    997            gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
    998 
    999            //glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
   1000            testImg.readViewport(gl, [viewportX, viewportY, viewportW, viewportH]);
   1001            refImg.getAccess().clear(clearColor);
   1002            this.renderReference(refImg.getAccess(), indices, flatPosArray, flatColorArray);
   1003        } else
   1004            throw new Error('Iteration count exceeded.');
   1005 
   1006        if (!tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', refImg.getAccess(), testImg.getAccess(), threshold))
   1007            testFailedOptions('Image comparison failed', false);
   1008        else
   1009            testPassedOptions('Pass', true);
   1010 
   1011        this.m_iterNdx += 1;
   1012        return (this.m_iterNdx < 2) ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
   1013    };
   1014 
   1015    /**
   1016     * @constructor
   1017     * @extends {tcuTestCase.DeqpTest}
   1018     */
   1019    es3fShaderBuiltinVarTests.ShaderBuiltinVarTests = function() {
   1020        tcuTestCase.DeqpTest.call(this, 'builtin_variable', 'Built-in Variable Tests');
   1021    };
   1022 
   1023    es3fShaderBuiltinVarTests.ShaderBuiltinVarTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
   1024    es3fShaderBuiltinVarTests.ShaderBuiltinVarTests.prototype.constructor = es3fShaderBuiltinVarTests.ShaderBuiltinVarTests;
   1025 
   1026    es3fShaderBuiltinVarTests.ShaderBuiltinVarTests.prototype.init = function() {
   1027        var testGroup = tcuTestCase.runner.testCases;
   1028        // Builtin constants.
   1029        /**
   1030         * @struct
   1031         * @constructor
   1032         * @param {string} caseName
   1033         * @param {string} varName
   1034         * @param {es3fShaderBuiltinVarTests.GetConstantValueFunc} getValue
   1035         */
   1036        var BuiltinConstant = function(caseName, varName, getValue) {
   1037            /** @type {string} */ this.caseName = caseName;
   1038            /** @type {string} */ this.varName = varName;
   1039            /** @type {es3fShaderBuiltinVarTests.GetConstantValueFunc} */ this.getValue = getValue;
   1040 
   1041        };
   1042 
   1043        /** @type {Array<BuiltinConstant>} */ var builtinConstants = [
   1044            // GLES 2.
   1045 
   1046            new BuiltinConstant('max_vertex_attribs', 'gl_MaxVertexAttribs', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_VERTEX_ATTRIBS); }),
   1047            new BuiltinConstant('max_vertex_uniform_vectors', 'gl_MaxVertexUniformVectors', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_VERTEX_UNIFORM_VECTORS); }),
   1048            new BuiltinConstant('max_fragment_uniform_vectors', 'gl_MaxFragmentUniformVectors', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_FRAGMENT_UNIFORM_VECTORS); }),
   1049            new BuiltinConstant('max_texture_image_units', 'gl_MaxTextureImageUnits', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_TEXTURE_IMAGE_UNITS); }),
   1050            new BuiltinConstant('max_vertex_texture_image_units', 'gl_MaxVertexTextureImageUnits', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS); }),
   1051            new BuiltinConstant('max_combined_texture_image_units', 'gl_MaxCombinedTextureImageUnits', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS); }),
   1052            new BuiltinConstant('max_draw_buffers', 'gl_MaxDrawBuffers', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_DRAW_BUFFERS); }),
   1053 
   1054            // GLES 3.
   1055 
   1056            new BuiltinConstant('max_vertex_output_vectors', 'gl_MaxVertexOutputVectors', function() { return es3fShaderBuiltinVarTests.getVectorsFromComps(gl.MAX_VERTEX_OUTPUT_COMPONENTS); }),
   1057            new BuiltinConstant('max_fragment_input_vectors', 'gl_MaxFragmentInputVectors', function() { return es3fShaderBuiltinVarTests.getVectorsFromComps(gl.MAX_FRAGMENT_INPUT_COMPONENTS); }),
   1058            new BuiltinConstant('min_program_texel_offset', 'gl_MinProgramTexelOffset', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MIN_PROGRAM_TEXEL_OFFSET); }),
   1059            new BuiltinConstant('max_program_texel_offset', 'gl_MaxProgramTexelOffset', function() { return es3fShaderBuiltinVarTests.getInteger(gl.MAX_PROGRAM_TEXEL_OFFSET); })
   1060        ];
   1061 
   1062        for (var ndx = 0; ndx < builtinConstants.length; ndx++) {
   1063            /** @type {string} */ var caseName = builtinConstants[ndx].caseName;
   1064            /** @type {string} */ var varName = builtinConstants[ndx].varName;
   1065            /** @type {es3fShaderBuiltinVarTests.GetConstantValueFunc} */ var getValue = builtinConstants[ndx].getValue;
   1066 
   1067            testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase(caseName + '_vertex', varName, varName, getValue, gluShaderProgram.shaderType.VERTEX));
   1068            testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderBuiltinConstantCase(caseName + '_fragment', varName, varName, getValue, gluShaderProgram.shaderType.FRAGMENT));
   1069        }
   1070 
   1071        testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderDepthRangeTest('depth_range_vertex', 'gl_DepthRange', true));
   1072        testGroup.addChild(new es3fShaderBuiltinVarTests.ShaderDepthRangeTest('depth_range_fragment', 'gl_DepthRange', false));
   1073 
   1074        // Vertex shader builtin variables.
   1075        testGroup.addChild(new es3fShaderBuiltinVarTests.VertexIDCase());
   1076        // \todo [2013-03-20 pyry] gl_InstanceID -- tested in instancing tests quite thoroughly.
   1077 
   1078        // Fragment shader builtin variables.
   1079        testGroup.addChild(new es3fShaderBuiltinVarTests.FragCoordXYZCase());
   1080        testGroup.addChild(new es3fShaderBuiltinVarTests.FragCoordWCase());
   1081        testGroup.addChild(new es3fShaderBuiltinVarTests.PointCoordCase());
   1082        testGroup.addChild(new es3fShaderBuiltinVarTests.FrontFacingCase());
   1083    };
   1084 
   1085    /**
   1086    * Run test
   1087    * @param {WebGL2RenderingContext} context
   1088    */
   1089    es3fShaderBuiltinVarTests.run = function(context) {
   1090        gl = context;
   1091        //Set up Test Root parameters
   1092        var state = tcuTestCase.runner;
   1093        state.setRoot(new es3fShaderBuiltinVarTests.ShaderBuiltinVarTests());
   1094 
   1095        //Set up name and description of this test series.
   1096        setCurrentTestName(state.testCases.fullName());
   1097        description(state.testCases.getDescription());
   1098 
   1099        try {
   1100            //Run test cases
   1101            tcuTestCase.runTestCases();
   1102        }
   1103        catch (err) {
   1104            testFailedOptions('Failed to es3fShaderBuiltinVarTests.run tests', false);
   1105            tcuTestCase.runner.terminate();
   1106        }
   1107    };
   1108 
   1109 });