tor-browser

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

es3fFboTestUtil.js (63935B)


      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.es3fFboTestUtil');
     23 goog.require('framework.common.tcuMatrix');
     24 goog.require('framework.common.tcuRGBA');
     25 goog.require('framework.common.tcuSurface');
     26 goog.require('framework.common.tcuTexture');
     27 goog.require('framework.common.tcuTextureUtil');
     28 goog.require('framework.delibs.debase.deMath');
     29 goog.require('framework.opengl.gluShaderUtil');
     30 goog.require('framework.opengl.gluTextureUtil');
     31 goog.require('framework.opengl.simplereference.sglrGLContext');
     32 goog.require('framework.opengl.simplereference.sglrReferenceContext');
     33 goog.require('framework.opengl.simplereference.sglrShaderProgram');
     34 goog.require('framework.referencerenderer.rrFragmentOperations');
     35 goog.require('framework.referencerenderer.rrGenericVector');
     36 goog.require('framework.referencerenderer.rrShadingContext');
     37 goog.require('framework.referencerenderer.rrVertexAttrib');
     38 goog.require('framework.referencerenderer.rrVertexPacket');
     39 
     40 goog.scope(function() {
     41 
     42 var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
     43 var tcuTexture = framework.common.tcuTexture;
     44 var tcuTextureUtil = framework.common.tcuTextureUtil;
     45 var tcuRGBA = framework.common.tcuRGBA;
     46 var gluTextureUtil = framework.opengl.gluTextureUtil;
     47 var deMath = framework.delibs.debase.deMath;
     48 var rrShadingContext = framework.referencerenderer.rrShadingContext;
     49 var rrVertexPacket = framework.referencerenderer.rrVertexPacket;
     50 var rrVertexAttrib = framework.referencerenderer.rrVertexAttrib;
     51 var gluShaderUtil = framework.opengl.gluShaderUtil;
     52 var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
     53 var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
     54 var sglrShaderProgram = framework.opengl.simplereference.sglrShaderProgram;
     55 var rrGenericVector = framework.referencerenderer.rrGenericVector;
     56 var tcuMatrix = framework.common.tcuMatrix;
     57 var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations;
     58 var tcuSurface = framework.common.tcuSurface;
     59 
     60 var DE_ASSERT = function(x) {
     61    if (!x)
     62        throw new Error('Assert failed');
     63 };
     64 
     65 /**
     66 * Defines the exception type for a test failure.
     67 * @constructor
     68 * @param {number} reason The error code.
     69 */
     70 es3fFboTestUtil.FboIncompleteException = function(reason) {
     71   this.reason = reason;
     72   this.name = 'es3fFboTestUtil.FboIncompleteException';
     73 };
     74 
     75 /** @typedef { (WebGL2RenderingContext|sglrReferenceContext.ReferenceContext)} */
     76 es3fFboTestUtil.Context;
     77 
     78 es3fFboTestUtil.FboIncompleteException.prototype.getReason = function() {return this.reason; };
     79 
     80    /**
     81     * @param {gluShaderUtil.DataType} type
     82     * @return {rrGenericVector.GenericVecType}
     83     */
     84    es3fFboTestUtil.mapDataTypeToGenericVecType = function(type) {
     85        switch (type) {
     86            case gluShaderUtil.DataType.FLOAT_VEC4: return rrGenericVector.GenericVecType.FLOAT;
     87            case gluShaderUtil.DataType.INT_VEC4: return rrGenericVector.GenericVecType.INT32;
     88            case gluShaderUtil.DataType.UINT_VEC4: return rrGenericVector.GenericVecType.UINT32;
     89            default:
     90                throw new Error('Unrecognized type: ' + type);
     91        }
     92    };
     93 
     94    /**
     95     * @param {Array<number>} input
     96     * @param {{max: number, min: number}} type min, max information
     97     * @return {Array<number>}
     98     */
     99    es3fFboTestUtil.castVectorSaturate = function(input, type) {
    100        return [
    101            (input[0] + 0.5 >= type.max) ? (type.max) : ((input[0] - 0.5 <= type.min) ? (type.min) : Math.round(input[0])),
    102            (input[1] + 0.5 >= type.max) ? (type.max) : ((input[1] - 0.5 <= type.min) ? (type.min) : Math.round(input[1])),
    103            (input[2] + 0.5 >= type.max) ? (type.max) : ((input[2] - 0.5 <= type.min) ? (type.min) : Math.round(input[2])),
    104            (input[3] + 0.5 >= type.max) ? (type.max) : ((input[3] - 0.5 <= type.min) ? (type.min) : Math.round(input[3]))
    105        ];
    106    };
    107 
    108    /**
    109     * es3fFboTestUtil.FlatColorShader inherits from sglrShaderProgram
    110     * @constructor
    111     * @extends {sglrShaderProgram.ShaderProgram}
    112     * @param {gluShaderUtil.DataType} outputType
    113     * @param {number=} pointSize
    114     */
    115    es3fFboTestUtil.FlatColorShader = function(outputType, pointSize) {
    116        pointSize = pointSize || 1;
    117        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
    118        var decl = new sglrShaderProgram.ShaderProgramDeclaration();
    119        /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
    120 
    121        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
    122        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
    123        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
    124        decl.pushUniform(new sglrShaderProgram.Uniform('u_color', gluShaderUtil.DataType.FLOAT_VEC4));
    125        decl.pushVertexSource(new sglrShaderProgram.VertexSource(
    126            '#version 300 es\n' +
    127            'in highp vec4 a_position;\n' +
    128            'void main (void)\n' +
    129            '{\n' +
    130            ' gl_Position = a_position;\n' +
    131            ' gl_PointSize = ' + pointSize + '.0;\n' +
    132            '}\n'));
    133        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
    134            '#version 300 es\n' +
    135            'uniform highp vec4 u_color;\n' +
    136            'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
    137            'void main (void)\n' +
    138            '{\n' +
    139            ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(u_color);\n' +
    140            '}\n'));
    141        sglrShaderProgram.ShaderProgram.call(this, decl);
    142        this.m_pointSize = pointSize;
    143    };
    144 
    145    es3fFboTestUtil.FlatColorShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    146    es3fFboTestUtil.FlatColorShader.prototype.constructor = es3fFboTestUtil.FlatColorShader;
    147 
    148    /**
    149     * @param {(WebGL2RenderingContext|sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext)} context
    150     * @param program GL program object
    151     * @param {Array<number>} color
    152     */
    153    es3fFboTestUtil.FlatColorShader.prototype.setColor = function(context, program, color) {
    154        /** @type {number} */ var location = context.getUniformLocation(program, 'u_color');
    155 
    156        context.useProgram(program);
    157        context.uniform4fv(location, color);
    158    };
    159 
    160    /**
    161     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    162     * @param {Array<rrVertexPacket.VertexPacket>} packets
    163     * @param {number} numPackets
    164     */
    165    es3fFboTestUtil.FlatColorShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
    166        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    167            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    168            packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    169            packet.pointSize = this.m_pointSize;
    170        }
    171    };
    172 
    173    /**
    174     * @param {Array<rrFragmentOperations.Fragment>} packet
    175     * @param {rrShadingContext.FragmentShadingContext} context
    176     */
    177    es3fFboTestUtil.FlatColorShader.prototype.shadeFragments = function(packet, context) {
    178        var numPackets = packet.length;
    179        /** @const {Array<number>} */ var color = this.m_uniforms[0].value;
    180        /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
    181        /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
    182 
    183        if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4) {
    184            for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    185                packet[packetNdx].value = color;
    186        } else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4) {
    187            for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    188                packet[packetNdx].value = icolor;
    189        } else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4) {
    190            for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx)
    191                packet[packetNdx].value = uicolor;
    192        } else
    193            throw new Error('Invalid output type: ' + this.m_outputType);
    194    };
    195 
    196    /**
    197     * es3fFboTestUtil.GradientShader inherits from sglrShaderProgram
    198     * @constructor
    199     * @extends {sglrShaderProgram.ShaderProgram}
    200     * @param {gluShaderUtil.DataType} outputType
    201     */
    202    es3fFboTestUtil.GradientShader = function(outputType) {
    203        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
    204        var decl = new sglrShaderProgram.ShaderProgramDeclaration();
    205        /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
    206        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
    207        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
    208        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
    209        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
    210        decl.pushUniform(new sglrShaderProgram.Uniform('u_gradientMin', gluShaderUtil.DataType.FLOAT_VEC4));
    211        decl.pushUniform(new sglrShaderProgram.Uniform('u_gradientMax', gluShaderUtil.DataType.FLOAT_VEC4));
    212        decl.pushVertexSource(new sglrShaderProgram.VertexSource(
    213            '#version 300 es\n' +
    214            'in highp vec4 a_position;\n' +
    215            'in highp vec4 a_coord;\n' +
    216            'out highp vec4 v_coord;\n' +
    217            'void main (void)\n' +
    218            '{\n' +
    219            ' gl_Position = a_position;\n' +
    220            ' v_coord = a_coord;\n' +
    221            '}\n'));
    222        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
    223            '#version 300 es\n' +
    224            'in highp vec4 v_coord;\n' +
    225            'uniform highp vec4 u_gradientMin;\n' +
    226            'uniform highp vec4 u_gradientMax;\n' +
    227            'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
    228            'void main (void)\n' +
    229            '{\n' +
    230            ' highp float x = v_coord.x;\n' +
    231            ' highp float y = v_coord.y;\n' +
    232            ' highp float f0 = (x + y) * 0.5;\n' +
    233            ' highp float f1 = 0.5 + (x - y) * 0.5;\n' +
    234            ' highp vec4 fv = vec4(f0, f1, 1.0f-f0, 1.0f-f1);\n' +
    235            ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(u_gradientMin + (u_gradientMax-u_gradientMin)*fv);\n' +
    236            '}\n'));
    237        sglrShaderProgram.ShaderProgram.call(this, decl);
    238    };
    239 
    240    es3fFboTestUtil.GradientShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    241    es3fFboTestUtil.GradientShader.prototype.constructor = es3fFboTestUtil.GradientShader;
    242 
    243    /**
    244     * @param {es3fFboTestUtil.Context} ctx GL-like context
    245     * @param program GL program
    246     * @param {Array<number>} gradientMin
    247     * @param {Array<number>} gradientMax
    248     */
    249    es3fFboTestUtil.GradientShader.prototype.setGradient = function(ctx, program, gradientMin, gradientMax) {
    250        ctx.useProgram(program);
    251        ctx.uniform4fv(ctx.getUniformLocation(program, 'u_gradientMin'), gradientMin);
    252        ctx.uniform4fv(ctx.getUniformLocation(program, 'u_gradientMax'), gradientMax);
    253    };
    254 
    255    /**
    256     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    257     * @param {Array<rrVertexPacket.VertexPacket>} packets
    258     * @param {number} numPackets
    259     */
    260    es3fFboTestUtil.GradientShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
    261        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    262            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    263 
    264            packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    265            packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    266        }
    267    };
    268 
    269    /**
    270     * @param {Array<rrFragmentOperations.Fragment>} packet
    271     * @param {rrShadingContext.FragmentShadingContext} context
    272     */
    273    es3fFboTestUtil.GradientShader.prototype.shadeFragments = function(packet, context) {
    274        var numPackets = packet.length;
    275        /** @const {Array<number>} */ var gradientMin = this.m_uniforms[0].value;
    276        /** @const {Array<number>} */ var gradientMax = this.m_uniforms[1].value;
    277 
    278        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    279            /** @const {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
    280            /** @const {number} */ var x = coord[0];
    281            /** @const {number} */ var y = coord[1];
    282            /** @const {number} */ var f0 = (x + y) * 0.5;
    283            /** @const {number} */ var f1 = 0.5 + (x - y) * 0.5;
    284            /** @const {Array<number>} */ var fv = [f0, f1, 1.0 - f0, 1.0 - f1];
    285 
    286            /** @const {Array<number>} */ var color = deMath.add(gradientMin, deMath.multiply(deMath.subtract(gradientMax, gradientMin), fv));
    287            /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
    288            /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
    289 
    290            if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
    291                packet[packetNdx].value = color;
    292            else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
    293                packet[packetNdx].value = icolor;
    294            else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
    295                packet[packetNdx].value = uicolor;
    296            else
    297                throw new Error('Invalid output type: ' + this.m_outputType);
    298        }
    299    };
    300 
    301    /**
    302    * @param {Array<gluShaderUtil.DataType>} samplerTypes
    303    * @param {gluShaderUtil.DataType} outputType
    304    * @return {string}
    305     */
    306    es3fFboTestUtil.genTexFragmentShader = function(samplerTypes, outputType) {
    307        /** @type {string} */ var precision = 'highp';
    308        /** @type {string} */ var src = '';
    309 
    310        src = '#version 300 es\n' +
    311              'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color0;\n' +
    312              'in highp vec2 v_coord;\n';
    313 
    314        for (var samplerNdx = 0; samplerNdx < samplerTypes.length; samplerNdx++) {
    315            src += 'uniform ' + precision + ' ' + gluShaderUtil.getDataTypeName(samplerTypes[samplerNdx]) + ' u_sampler' + samplerNdx + ';\n' +
    316                   'uniform ' + precision + ' vec4 u_texScale' + samplerNdx + ';\n' +
    317                   'uniform ' + precision + ' vec4 u_texBias' + samplerNdx + ';\n';
    318        }
    319 
    320        // Output scale & bias
    321        src += 'uniform ' + precision + ' vec4 u_outScale0;\n' +
    322               'uniform ' + precision + ' vec4 u_outBias0;\n';
    323 
    324        src += '\n' +
    325               'void main (void)\n' +
    326               '{\n' +
    327               ' ' + precision + ' vec4 out0 = vec4(0.0);\n';
    328 
    329        // Texture input fetch and combine.
    330        for (var inNdx = 0; inNdx < samplerTypes.length; inNdx++)
    331            src += '\tout0 += vec4(' +
    332                   'texture(u_sampler' + inNdx + ', v_coord)) * u_texScale' + inNdx + ' + u_texBias' + inNdx + ';\n';
    333 
    334        // Write output.
    335        src += ' o_color0 = ' + gluShaderUtil.getDataTypeName(outputType) + '(out0 * u_outScale0 + u_outBias0);\n' +
    336               '}\n';
    337 
    338        return src;
    339    };
    340 
    341    /**
    342     * @param {Array<gluShaderUtil.DataType>} samplerTypes
    343     * @param {gluShaderUtil.DataType} outputType
    344     * @return {sglrShaderProgram.ShaderProgramDeclaration}
    345     */
    346    es3fFboTestUtil.genTexture2DShaderDecl = function(samplerTypes, outputType) {
    347        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
    348        var decl = new sglrShaderProgram.ShaderProgramDeclaration();
    349 
    350        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
    351        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
    352        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
    353        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
    354 
    355        decl.pushVertexSource(new sglrShaderProgram.VertexSource(
    356            '#version 300 es\n' +
    357            'in highp vec4 a_position;\n' +
    358            'in highp vec2 a_coord;\n' +
    359            'out highp vec2 v_coord;\n' +
    360            'void main(void)\n' +
    361            '{\n' +
    362            ' gl_Position = a_position;\n' +
    363            ' v_coord = a_coord;\n' +
    364            '}\n'));
    365 
    366        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(es3fFboTestUtil.genTexFragmentShader(samplerTypes, outputType)));
    367 
    368        decl.pushUniform(new sglrShaderProgram.Uniform('u_outScale0', gluShaderUtil.DataType.FLOAT_VEC4));
    369        decl.pushUniform(new sglrShaderProgram.Uniform('u_outBias0', gluShaderUtil.DataType.FLOAT_VEC4));
    370 
    371        for (var ndx = 0; ndx < samplerTypes.length; ++ndx) {
    372            decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler' + ndx, samplerTypes[ndx]));
    373            decl.pushUniform(new sglrShaderProgram.Uniform('u_texScale' + ndx, gluShaderUtil.DataType.FLOAT_VEC4));
    374            decl.pushUniform(new sglrShaderProgram.Uniform('u_texBias' + ndx, gluShaderUtil.DataType.FLOAT_VEC4));
    375        }
    376 
    377        return decl;
    378    };
    379 
    380    /**
    381     * For use in es3fFboTestUtil.Texture2DShader
    382     * @constructor
    383     */
    384    es3fFboTestUtil.Input = function() {
    385        /** @type {number} */ this.unitNdx;
    386        /** @type {Array<number>} */ this.scale;
    387        /** @type {Array<number>} */ this.bias;
    388    };
    389 
    390    /**
    391     * es3fFboTestUtil.Texture2DShader inherits from sglrShaderProgram
    392     * @constructor
    393     * @extends {sglrShaderProgram.ShaderProgram}
    394     * @param {Array<gluShaderUtil.DataType>} samplerTypes
    395     * @param {gluShaderUtil.DataType} outputType
    396     * @param {Array<number>=} outScale - default [1.0, 1.0, 1.0, 1.0]
    397     * @param {Array<number>=} outBias - default [0.0, 0.0, 0.0, 0.0]
    398     */
    399    es3fFboTestUtil.Texture2DShader = function(samplerTypes, outputType, outScale, outBias) {
    400        if (outScale === undefined) outScale = [1.0, 1.0, 1.0, 1.0];
    401        if (outBias === undefined) outBias = [0.0, 0.0, 0.0, 0.0];
    402        sglrShaderProgram.ShaderProgram.call(this, es3fFboTestUtil.genTexture2DShaderDecl(samplerTypes, outputType));
    403        /** @type {Array<es3fFboTestUtil.Input>} */ this.m_inputs = [];
    404        /** @type {Array<number>} */ this.m_outScale = outScale;
    405        /** @type {Array<number>} */ this.m_outBias = outBias;
    406        /** @const {gluShaderUtil.DataType} */ this.m_outputType = outputType;
    407        for (var ndx = 0; ndx < samplerTypes.length; ndx++) {
    408            var input = new es3fFboTestUtil.Input();
    409            input.unitNdx = ndx;
    410            input.scale = [1.0, 1.0, 1.0, 1.0];
    411            input.bias = [0.0, 0.0, 0.0, 0.0];
    412            this.m_inputs[ndx] = input;
    413        }
    414    };
    415 
    416    es3fFboTestUtil.Texture2DShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    417    es3fFboTestUtil.Texture2DShader.prototype.constructor = es3fFboTestUtil.Texture2DShader;
    418 
    419    /**
    420     * @param {number} inputNdx
    421     * @param {number} unitNdx
    422     */
    423    es3fFboTestUtil.Texture2DShader.prototype.setUnit = function(inputNdx, unitNdx) {
    424        this.m_inputs[inputNdx].unitNdx = unitNdx;
    425    };
    426 
    427    /**
    428     * @param {number} inputNdx
    429     * @param {Array<number>} scale
    430     * @param {Array<number>} bias
    431     */
    432    es3fFboTestUtil.Texture2DShader.prototype.setTexScaleBias = function(inputNdx, scale, bias) {
    433        this.m_inputs[inputNdx].scale = scale;
    434        this.m_inputs[inputNdx].bias = bias;
    435    };
    436 
    437    /**
    438     * @param {Array<number>} scale
    439     * @param {Array<number>} bias
    440     */
    441    es3fFboTestUtil.Texture2DShader.prototype.setOutScaleBias = function(scale, bias) {
    442        this.m_outScale = scale;
    443        this.m_outBias = bias;
    444    };
    445 
    446    /**
    447     * @param context GL-like context
    448     * @param program
    449     */
    450    es3fFboTestUtil.Texture2DShader.prototype.setUniforms = function(context, program) {
    451        context.useProgram(program);
    452 
    453        for (var texNdx = 0; texNdx < this.m_inputs.length; texNdx++) {
    454            /** @type {string} */ var samplerName = 'u_sampler' + texNdx;
    455            /** @type {string} */ var scaleName = 'u_texScale' + texNdx;
    456            /** @type {string} */ var biasName = 'u_texBias' + texNdx;
    457 
    458            context.uniform1i(context.getUniformLocation(program, samplerName), this.m_inputs[texNdx].unitNdx);
    459            context.uniform4fv(context.getUniformLocation(program, scaleName), this.m_inputs[texNdx].scale);
    460            context.uniform4fv(context.getUniformLocation(program, biasName), this.m_inputs[texNdx].bias);
    461        }
    462 
    463        context.uniform4fv(context.getUniformLocation(program, 'u_outScale0'), this.m_outScale);
    464        context.uniform4fv(context.getUniformLocation(program, 'u_outBias0'), this.m_outBias);
    465    };
    466 
    467    /**
    468     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    469     * @param {Array<rrVertexPacket.VertexPacket>} packets
    470     * @param {number} numPackets
    471     */
    472    es3fFboTestUtil.Texture2DShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
    473        // TODO: implement rrVertexAttrib.readVertexAttribFloat
    474        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    475            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    476            packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    477            packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    478        }
    479    };
    480 
    481    /**
    482     * @param {Array<rrFragmentOperations.Fragment>} packet
    483     * @param {rrShadingContext.FragmentShadingContext} context
    484     */
    485    es3fFboTestUtil.Texture2DShader.prototype.shadeFragments = function(packet, context) {
    486        var numPackets = packet.length;
    487        /** @type {Array<number>} */ var outScale = this.m_uniforms[0].value;
    488        /** @type {Array<number>} */ var outBias = this.m_uniforms[1].value;
    489        var texCoords = [];
    490        var colors = [];
    491 
    492        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    493            // setup tex coords
    494                /** @const {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
    495                texCoords = [coord[0], coord[1]];
    496 
    497            // clear result
    498            colors = [0.0, 0.0, 0.0, 0.0];
    499 
    500            // sample each texture
    501            for (var ndx = 0; ndx < this.m_inputs.length; ndx++) {
    502                var tex = this.m_uniforms[2 + ndx * 3].sampler;
    503                var ratioX = tex.m_view.getWidth() / context.getWidth();
    504                var ratioY = tex.m_view.getHeight() / context.getHeight();
    505                var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
    506 
    507                /** @const {Array<number>} */ var scale = this.m_uniforms[2 + ndx * 3 + 1].value;
    508                /** @const {Array<number>} */ var bias = this.m_uniforms[2 + ndx * 3 + 2].value;
    509 
    510                var tmpColors = tex.sample(texCoords, lod);
    511 
    512                colors = deMath.add(colors, deMath.add(deMath.multiply(tmpColors, scale), bias));
    513            }
    514 
    515            // write out
    516            /** @const {Array<number>} */ var color = deMath.add(deMath.multiply(colors, outScale), outBias);
    517            /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
    518            /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
    519 
    520            if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
    521                packet[packetNdx].value = color;
    522            else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
    523                packet[packetNdx].value = icolor;
    524            else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
    525                packet[packetNdx].value = uicolor;
    526        }
    527    };
    528 
    529    /**
    530     * es3fFboTestUtil.TextureCubeShader inherits from sglrShaderProgram
    531     * @constructor
    532     * @extends {sglrShaderProgram.ShaderProgram}
    533     * @param {gluShaderUtil.DataType} samplerType
    534     * @param {gluShaderUtil.DataType} outputType
    535     */
    536    es3fFboTestUtil.TextureCubeShader = function(samplerType, outputType) {
    537        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
    538        var decl = new sglrShaderProgram.ShaderProgramDeclaration();
    539        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
    540        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
    541        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
    542        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
    543        decl.pushUniform(new sglrShaderProgram.Uniform('u_coordMat', gluShaderUtil.DataType.FLOAT_MAT3));
    544        decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler0', samplerType));
    545        decl.pushUniform(new sglrShaderProgram.Uniform('u_scale', gluShaderUtil.DataType.FLOAT_VEC4));
    546        decl.pushUniform(new sglrShaderProgram.Uniform('u_bias', gluShaderUtil.DataType.FLOAT_VEC4));
    547        decl.pushVertexSource(new sglrShaderProgram.VertexSource(
    548            '#version 300 es\n' +
    549            'in highp vec4 a_position;\n' +
    550            'in mediump vec2 a_coord;\n' +
    551            'uniform mat3 u_coordMat;\n' +
    552            'out mediump vec3 v_coord;\n' +
    553            'void main (void)\n' +
    554            '{\n' +
    555            ' gl_Position = a_position;\n' +
    556            ' v_coord = u_coordMat * vec3(a_coord, 1.0);\n' +
    557            '}\n'));
    558        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
    559            '#version 300 es\n' +
    560            'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler0;\n' +
    561            'uniform highp vec4 u_scale;\n' +
    562            'uniform highp vec4 u_bias;\n' +
    563            'in mediump vec3 v_coord;\n' +
    564            'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
    565            'void main (void)\n' +
    566            '{\n' +
    567            ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(vec4(texture(u_sampler0, v_coord)) * u_scale + u_bias);\n' +
    568            '}\n'));
    569        sglrShaderProgram.ShaderProgram.call(this, decl);
    570        /** @type {Array<number>} */ this.m_texScale = [1.0, 1.0, 1.0, 1.0];
    571        /** @type {Array<number>} */ this.m_texBias = [0.0, 0.0, 0.0, 0.0];
    572        /** @type {tcuMatrix.Mat3} */ this.m_coordMat;
    573        /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
    574    };
    575 
    576    es3fFboTestUtil.TextureCubeShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    577    es3fFboTestUtil.TextureCubeShader.prototype.constructor = es3fFboTestUtil.TextureCubeShader;
    578 
    579    /**
    580     * @param {tcuTexture.CubeFace} face
    581     */
    582    es3fFboTestUtil.TextureCubeShader.prototype.setFace = function(face) {
    583        /** @const {Array<Array<number>>} */ var s_cubeTransforms = [
    584            // Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
    585            [0, 0, -1,
    586             0, -2, 1,
    587             2, 0, -1],
    588            // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
    589            [0, 0, 1,
    590             0, -2, 1,
    591            -2, 0, 1],
    592            // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
    593            [2, 0, -1,
    594             0, 0, -1,
    595             0, -2, 1],
    596            // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
    597            [2, 0, -1,
    598             0, 0, 1,
    599             0, 2, -1],
    600            // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
    601            [-2, 0, 1,
    602             0, -2, 1,
    603              0, 0, -1],
    604            // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
    605            [2, 0, -1,
    606             0, -2, 1,
    607             0, 0, 1]];
    608        this.m_coordMat = /** @type {tcuMatrix.Mat3} */ (tcuMatrix.matrixFromArray(3, 3, s_cubeTransforms[face]));
    609    };
    610 
    611    /**
    612     * @param {Array<number>} scale
    613     * @param {Array<number>} bias
    614     */
    615    es3fFboTestUtil.TextureCubeShader.prototype.setTexScaleBias = function(scale, bias) {
    616        this.m_texScale = scale;
    617        this.m_texBias = bias;
    618    };
    619 
    620    /**
    621     * @param ctx GL-like context
    622     * @param program
    623     */
    624    es3fFboTestUtil.TextureCubeShader.prototype.setUniforms = function(ctx, program) {
    625        ctx.useProgram(program);
    626 
    627        ctx.uniform1i(ctx.getUniformLocation(program, 'u_sampler0'), 0);
    628        ctx.uniformMatrix3fv(ctx.getUniformLocation(program, 'u_coordMat'), false, this.m_coordMat.getColumnMajorData());
    629        ctx.uniform4fv(ctx.getUniformLocation(program, 'u_scale'), this.m_texScale);
    630        ctx.uniform4fv(ctx.getUniformLocation(program, 'u_bias'), this.m_texBias);
    631    };
    632 
    633    /**
    634     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    635     * @param {Array<rrVertexPacket.VertexPacket>} packets
    636     * @param {number} numPackets
    637     */
    638    es3fFboTestUtil.TextureCubeShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
    639    /** @type {tcuMatrix.Matrix} */ var texCoordMat = tcuMatrix.matrixFromArray(3, 3, this.m_uniforms[0].value);
    640 
    641        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    642            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    643            var x = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT)[0];
    644            var y = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT)[1];
    645            /** @type {Array<number>} */ var a_coord = [x, y];
    646            /** @type {Array<number>} */ var v_coord = tcuMatrix.multiplyMatVec(texCoordMat, [a_coord[0], a_coord[1], 1.0]);
    647 
    648            packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    649            packet.outputs[0] = [v_coord[0], v_coord[1], v_coord[2], 0.0];
    650        }
    651    };
    652 
    653    /**
    654     * @param {Array<rrFragmentOperations.Fragment>} packet
    655     * @param {rrShadingContext.FragmentShadingContext} context
    656     */
    657    es3fFboTestUtil.TextureCubeShader.prototype.shadeFragments = function(packet, context) {
    658        var numPackets = packet.length;
    659        /** @const {Array<number>} */ var texScale = this.m_uniforms[2].value;
    660        /** @const {Array<number>} */ var texBias = this.m_uniforms[3].value;
    661 
    662        var texCoords = [];
    663        var colors = [];
    664 
    665        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    666            var tex = this.m_uniforms[1].sampler;
    667            var ratioX = tex.m_view.getSize() / context.getWidth();
    668            var ratioY = tex.m_view.getSize() / context.getHeight();
    669            var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
    670 
    671            var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
    672            texCoords = [coord[0], coord[1], coord[2]];
    673 
    674            colors = tex.sample(texCoords, lod);
    675 
    676            var color = deMath.add(deMath.multiply(colors, texScale), texBias);
    677            var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
    678            var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
    679 
    680            if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
    681                packet[packetNdx].value = color;
    682            else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
    683                packet[packetNdx].value = icolor;
    684            else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
    685                packet[packetNdx].value = uicolor;
    686        }
    687    };
    688 
    689    /**
    690     * es3fFboTestUtil.Texture2DArrayShader inherits from sglrShaderProgram
    691     * @constructor
    692     * @extends {sglrShaderProgram.ShaderProgram}
    693     * @param {gluShaderUtil.DataType} samplerType
    694     * @param {gluShaderUtil.DataType} outputType
    695     */
    696    es3fFboTestUtil.Texture2DArrayShader = function(samplerType, outputType) {
    697        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
    698        var decl = new sglrShaderProgram.ShaderProgramDeclaration();
    699        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
    700        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
    701        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
    702        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
    703        decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler0', samplerType));
    704        decl.pushUniform(new sglrShaderProgram.Uniform('u_scale', gluShaderUtil.DataType.FLOAT_VEC4));
    705        decl.pushUniform(new sglrShaderProgram.Uniform('u_bias', gluShaderUtil.DataType.FLOAT_VEC4));
    706        decl.pushUniform(new sglrShaderProgram.Uniform('u_layer', gluShaderUtil.DataType.INT));
    707        decl.pushVertexSource(new sglrShaderProgram.VertexSource(
    708                '#version 300 es\n' +
    709                'in highp vec4 a_position;\n' +
    710                'in highp vec2 a_coord;\n' +
    711                'out highp vec2 v_coord;\n' +
    712                'void main (void)\n' +
    713                '{\n' +
    714                ' gl_Position = a_position;\n' +
    715                ' v_coord = a_coord;\n' +
    716                '}\n'));
    717        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
    718                '#version 300 es\n' +
    719                'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler0;\n' +
    720                'uniform highp vec4 u_scale;\n' +
    721                'uniform highp vec4 u_bias;\n' +
    722                'uniform highp int u_layer;\n' +
    723                'in highp vec2 v_coord;\n' +
    724                'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
    725                'void main (void)\n' +
    726                '{\n' +
    727                ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(vec4(texture(u_sampler0, vec3(v_coord, u_layer))) * u_scale + u_bias);\n' +
    728                '}\n'));
    729        sglrShaderProgram.ShaderProgram.call(this, decl);
    730        /** @type {Array<number>} */ this.m_texScale = [1.0, 1.0, 1.0, 1.0];
    731        /** @type {Array<number>} */ this.m_texBias = [0.0, 0.0, 0.0, 0.0];
    732        /** @type {number} */ this.m_layer = 0;
    733        /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
    734    };
    735 
    736    es3fFboTestUtil.Texture2DArrayShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    737    es3fFboTestUtil.Texture2DArrayShader.prototype.constructor = es3fFboTestUtil.Texture2DArrayShader;
    738 
    739    /**
    740     * @param {number} layer
    741     */
    742    es3fFboTestUtil.Texture2DArrayShader.prototype.setLayer = function(layer) {
    743        this.m_layer = layer;
    744    };
    745    /**
    746     * @param {Array<number>} scale
    747     * @param {Array<number>} bias
    748     */
    749    es3fFboTestUtil.Texture2DArrayShader.prototype.setTexScaleBias = function(scale, bias) {
    750        this.m_texScale = scale;
    751        this.m_texBias = bias;
    752    };
    753    /**
    754     * @param {es3fFboTestUtil.Context} ctx GL-like context
    755     * @param program
    756     */
    757    es3fFboTestUtil.Texture2DArrayShader.prototype.setUniforms = function(ctx, program) {
    758        ctx.useProgram(program);
    759 
    760        ctx.uniform1i(ctx.getUniformLocation(program, 'u_sampler0'), 0);
    761        ctx.uniform1i(ctx.getUniformLocation(program, 'u_layer'), this.m_layer);
    762        ctx.uniform4fv(ctx.getUniformLocation(program, 'u_scale'), this.m_texScale);
    763        ctx.uniform4fv(ctx.getUniformLocation(program, 'u_bias'), this.m_texBias);
    764    };
    765 
    766    /**
    767     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    768     * @param {Array<rrVertexPacket.VertexPacket>} packets
    769     * @param {number} numPackets
    770     */
    771    es3fFboTestUtil.Texture2DArrayShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
    772        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    773            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    774 
    775            packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    776            packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    777        }
    778    };
    779 
    780    /**
    781     * @param {Array<rrFragmentOperations.Fragment>} packet
    782     * @param {rrShadingContext.FragmentShadingContext} context
    783     */
    784    es3fFboTestUtil.Texture2DArrayShader.prototype.shadeFragments = function(packet, context) {
    785        var numPackets = packet.length;
    786        /** @const {Array<number>} */ var texScale = this.m_uniforms[1].value;
    787        /** @const {Array<number>} */ var texBias = this.m_uniforms[2].value;
    788        /** @const {number} */ var layer = this.m_uniforms[3].value[0];
    789 
    790        var texCoords = [];
    791        var colors = [];
    792 
    793        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    794            var tex = this.m_uniforms[0].sampler;
    795            var ratioX = tex.m_view.getWidth() / context.getWidth();
    796            var ratioY = tex.m_view.getHeight() / context.getHeight();
    797            var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
    798 
    799            /** @const {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
    800            texCoords = [coord[0], coord[1], layer];
    801 
    802            colors = tex.sample(texCoords, lod);
    803 
    804            /** @const {Array<number>} */ var color = deMath.add(deMath.multiply(colors, texScale), texBias);
    805            /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
    806            /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
    807 
    808            if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
    809                packet[packetNdx].value = color;
    810            else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
    811                packet[packetNdx].value = icolor;
    812            else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
    813                packet[packetNdx].value = uicolor;
    814        }
    815    };
    816 
    817    /**
    818     * es3fFboTestUtil.Texture3DShader inherits from sglrShaderProgram
    819     * @constructor
    820     * @extends {sglrShaderProgram.ShaderProgram}
    821     * @param {gluShaderUtil.DataType} samplerType
    822     * @param {gluShaderUtil.DataType} outputType
    823     */
    824    es3fFboTestUtil.Texture3DShader = function(samplerType, outputType) {
    825        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
    826        var decl = new sglrShaderProgram.ShaderProgramDeclaration();
    827        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
    828        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
    829        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
    830        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
    831        decl.pushUniform(new sglrShaderProgram.Uniform('u_sampler0', samplerType));
    832        decl.pushUniform(new sglrShaderProgram.Uniform('u_scale', gluShaderUtil.DataType.FLOAT_VEC4));
    833        decl.pushUniform(new sglrShaderProgram.Uniform('u_bias', gluShaderUtil.DataType.FLOAT_VEC4));
    834        decl.pushUniform(new sglrShaderProgram.Uniform('u_depth', gluShaderUtil.DataType.FLOAT));
    835        decl.pushVertexSource(new sglrShaderProgram.VertexSource(
    836            '#version 300 es\n' +
    837            'in highp vec4 a_position;\n' +
    838            'in highp vec2 a_coord;\n' +
    839            'out highp vec2 v_coord;\n' +
    840            'void main (void)\n' +
    841            '{\n' +
    842            ' gl_Position = a_position;\n' +
    843            ' v_coord = a_coord;\n' +
    844            '}\n'));
    845        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
    846            '#version 300 es\n' +
    847            'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler0;\n' +
    848            'uniform highp vec4 u_scale;\n' +
    849            'uniform highp vec4 u_bias;\n' +
    850            'uniform highp float u_depth;\n' +
    851            'in highp vec2 v_coord;\n' +
    852            'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
    853            'void main (void)\n' +
    854            '{\n' +
    855            ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(vec4(texture(u_sampler0, vec3(v_coord, u_depth))) * u_scale + u_bias);\n' +
    856            '}\n'));
    857        sglrShaderProgram.ShaderProgram.call(this, decl);
    858        /** @type {Array<number>} */ this.m_texScale = [1.0, 1.0, 1.0, 1.0];
    859        /** @type {Array<number>} */ this.m_texBias = [0.0, 0.0, 0.0, 0.0];
    860        /** @type {number} */ this.m_depth = 0.0;
    861        /** @type {gluShaderUtil.DataType} */ this.m_outputType = outputType;
    862    };
    863 
    864    es3fFboTestUtil.Texture3DShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    865    es3fFboTestUtil.Texture3DShader.prototype.constructor = es3fFboTestUtil.Texture3DShader;
    866 
    867    /**
    868     * @param {number} depth
    869     */
    870    es3fFboTestUtil.Texture3DShader.prototype.setDepth = function(depth) {
    871        this.m_depth = depth;
    872    };
    873 
    874    /**
    875     * @param {Array<number>} scale
    876     * @param {Array<number>} bias
    877     */
    878    es3fFboTestUtil.Texture3DShader.prototype.setTexScaleBias = function(scale, bias) {
    879        this.m_texScale = scale;
    880        this.m_texBias = bias;
    881    };
    882 
    883    /**
    884     * @param context GL-like context
    885     * @param program
    886     */
    887    es3fFboTestUtil.Texture3DShader.prototype.setUniforms = function(context, program) {
    888        context.useProgram(program);
    889        context.uniform1i(context.getUniformLocation(program, 'u_sampler0'), 0);
    890        context.uniform1f(context.getUniformLocation(program, 'u_depth'), this.m_depth);
    891        context.uniform4fv(context.getUniformLocation(program, 'u_scale'), this.m_texScale);
    892        context.uniform4fv(context.getUniformLocation(program, 'u_bias'), this.m_texBias);
    893    };
    894 
    895    /**
    896     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
    897     * @param {Array<rrVertexPacket.VertexPacket>} packets
    898     * @param {number} numPackets
    899     */
    900    es3fFboTestUtil.Texture3DShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
    901        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    902            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
    903 
    904            packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    905            packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
    906        }
    907    };
    908 
    909    /**
    910     * @param {Array<rrFragmentOperations.Fragment>} packet
    911     * @param {rrShadingContext.FragmentShadingContext} context
    912     */
    913    es3fFboTestUtil.Texture3DShader.prototype.shadeFragments = function(packet, context) {
    914        var numPackets = packet.length;
    915        /** @const {Array<number>} */ var texScale = this.m_uniforms[1].value;
    916        /** @const {Array<number>} */ var texBias = this.m_uniforms[2].value;
    917        /** @const {number} */ var depth = this.m_uniforms[3].value[0];
    918 
    919        var texCoords = [];
    920        var colors = [];
    921 
    922        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
    923            var tex = this.m_uniforms[0].sampler;
    924            var ratioX = tex.m_view.getWidth() / context.getWidth();
    925            var ratioY = tex.m_view.getHeight() / context.getHeight();
    926            // TODO: what to do with Z coordinate?
    927            var lod = Math.floor(Math.log2(Math.max(ratioX, ratioY)));
    928 
    929            var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
    930            texCoords = [coord[0], coord[1], depth];
    931 
    932            colors = tex.sample(texCoords, lod);
    933 
    934            /** @const {Array<number>} */ var color = deMath.add(deMath.multiply(colors, texScale), texBias);
    935            /** @const {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
    936            /** @const {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
    937 
    938            if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
    939                packet[packetNdx].value = color;
    940            else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
    941                packet[packetNdx].value = icolor;
    942            else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
    943                packet[packetNdx].value = uicolor;
    944        }
    945    };
    946 
    947    /**
    948     * es3fFboTestUtil.DepthGradientShader inherits from sglrShaderProgram
    949     * @constructor
    950     * @extends {sglrShaderProgram.ShaderProgram}
    951     * @param {gluShaderUtil.DataType} outputType
    952     */
    953    es3fFboTestUtil.DepthGradientShader = function(outputType) {
    954        /** @type {sglrShaderProgram.ShaderProgramDeclaration} */
    955        var decl = new sglrShaderProgram.ShaderProgramDeclaration();
    956        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_position', rrGenericVector.GenericVecType.FLOAT));
    957        decl.pushVertexAttribute(new sglrShaderProgram.VertexAttribute('a_coord', rrGenericVector.GenericVecType.FLOAT));
    958        decl.pushVertexToFragmentVarying(new sglrShaderProgram.VertexToFragmentVarying(rrGenericVector.GenericVecType.FLOAT));
    959        decl.pushFragmentOutput(new sglrShaderProgram.FragmentOutput(es3fFboTestUtil.mapDataTypeToGenericVecType(outputType)));
    960        decl.pushUniform(new sglrShaderProgram.Uniform('u_maxGradient', gluShaderUtil.DataType.FLOAT));
    961        decl.pushUniform(new sglrShaderProgram.Uniform('u_minGradient', gluShaderUtil.DataType.FLOAT));
    962        decl.pushUniform(new sglrShaderProgram.Uniform('u_color', gluShaderUtil.DataType.FLOAT_VEC4));
    963        decl.pushVertexSource(new sglrShaderProgram.VertexSource(
    964                '#version 300 es\n' +
    965                'in highp vec4 a_position;\n' +
    966                'in highp vec4 a_coord;\n' +
    967                'out highp vec4 v_coord;\n' +
    968                'void main (void)\n' +
    969                '{\n' +
    970                ' gl_Position = a_position;\n' +
    971                ' v_coord = a_coord;\n' +
    972                '}\n'));
    973        decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(
    974                    '#version 300 es\n' +
    975                    'in highp vec4 v_coord;\n' +
    976                    'uniform highp float u_minGradient;\n' +
    977                    'uniform highp float u_maxGradient;\n' +
    978                    'uniform highp vec4 u_color;\n' +
    979                    'layout(location = 0) out highp ' + gluShaderUtil.getDataTypeName(outputType) + ' o_color;\n' +
    980                    'void main (void)\n' +
    981                    '{\n' +
    982                    ' highp float x = v_coord.x;\n' +
    983                    ' highp float y = v_coord.y;\n' +
    984                    ' highp float f0 = (x + y) * 0.5;\n' +
    985                    ' gl_FragDepth = u_minGradient + (u_maxGradient-u_minGradient)*f0;\n' +
    986                    ' o_color = ' + gluShaderUtil.getDataTypeName(outputType) + '(u_color);\n' +
    987                    '}\n'));
    988        this.m_outputType = outputType;
    989        sglrShaderProgram.ShaderProgram.call(this, decl);
    990        /** @const {sglrShaderProgram.Uniform} */ this.u_minGradient = this.getUniformByName('u_minGradient');
    991        /** @const {sglrShaderProgram.Uniform} */ this.u_maxGradient = this.getUniformByName('u_maxGradient');
    992        /** @const {sglrShaderProgram.Uniform} */ this.u_color = this.getUniformByName('u_color');
    993    };
    994 
    995    es3fFboTestUtil.DepthGradientShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
    996    es3fFboTestUtil.DepthGradientShader.prototype.constructor = es3fFboTestUtil.DepthGradientShader;
    997 
    998    /**
    999     * @param ctx GL-like context
   1000     * @param program
   1001     * @param {number} gradientMin
   1002     * @param {number} gradientMax
   1003     * @param {Array<number>} color
   1004     */
   1005    es3fFboTestUtil.DepthGradientShader.prototype.setUniforms = function(ctx, program, gradientMin, gradientMax, color) {
   1006        ctx.useProgram(program);
   1007        ctx.uniform1fv(ctx.getUniformLocation(program, 'u_minGradient'), [gradientMin]);
   1008        ctx.uniform1fv(ctx.getUniformLocation(program, 'u_maxGradient'), [gradientMax]);
   1009        ctx.uniform4fv(ctx.getUniformLocation(program, 'u_color'), color);
   1010    };
   1011 
   1012    /**
   1013     * @param {Array<rrVertexAttrib.VertexAttrib>} inputs
   1014     * @param {Array<rrVertexPacket.VertexPacket>} packets
   1015     * @param {number} numPackets
   1016     */
   1017    es3fFboTestUtil.DepthGradientShader.prototype.shadeVertices = function(inputs, packets, numPackets) {
   1018        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
   1019            /** @type {rrVertexPacket.VertexPacket} */ var packet = packets[packetNdx];
   1020 
   1021            packet.position = rrVertexAttrib.readVertexAttrib(inputs[0], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
   1022            packet.outputs[0] = rrVertexAttrib.readVertexAttrib(inputs[1], packet.instanceNdx, packet.vertexNdx, rrGenericVector.GenericVecType.FLOAT);
   1023        }
   1024    };
   1025 
   1026    /**
   1027     * @param {Array<rrFragmentOperations.Fragment>} packet
   1028     * @param {rrShadingContext.FragmentShadingContext} context
   1029     */
   1030    es3fFboTestUtil.DepthGradientShader.prototype.shadeFragments = function(packet, context) {
   1031        var numPackets = packet.length;
   1032        /** @const {number} */ var gradientMin = this.u_minGradient.value[0];
   1033        /** @const {number} */ var gradientMax = this.u_maxGradient.value[0];
   1034        /** @type {Array<number>} */ var color = this.u_color.value;
   1035        /** @type {Array<number>} */ var icolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deInt32);
   1036        /** @type {Array<number>} */ var uicolor = es3fFboTestUtil.castVectorSaturate(color, tcuTexture.deTypes.deUint32);
   1037 
   1038        for (var packetNdx = 0; packetNdx < numPackets; ++packetNdx) {
   1039            /** @type {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
   1040            /** @const {number} */ var x = coord[0];
   1041            /** @const {number} */ var y = coord[1];
   1042            /** @const {number} */ var f0 = (x + y) * 0.5;
   1043 
   1044            packet[packetNdx].sampleDepths[0] = gradientMin + (gradientMax - gradientMin) * f0;
   1045 
   1046            if (this.m_outputType == gluShaderUtil.DataType.FLOAT_VEC4)
   1047                packet[packetNdx].value = color;
   1048            else if (this.m_outputType == gluShaderUtil.DataType.INT_VEC4)
   1049                packet[packetNdx].value = icolor;
   1050            else if (this.m_outputType == gluShaderUtil.DataType.UINT_VEC4)
   1051                packet[packetNdx].value = uicolor;
   1052        }
   1053    };
   1054 
   1055    es3fFboTestUtil.getFormatName = function(format) {
   1056        switch (format) {
   1057            case gl.RGB565: return 'rgb565';
   1058            case gl.RGB5_A1: return 'rgb5_a1';
   1059            case gl.RGBA4: return 'rgba4';
   1060            case gl.DEPTH_COMPONENT16: return 'depth_component16';
   1061            case gl.STENCIL_INDEX8: return 'stencil_index8';
   1062            case gl.RGBA32F: return 'rgba32f';
   1063            case gl.RGBA32I: return 'rgba32i';
   1064            case gl.RGBA32UI: return 'rgba32ui';
   1065            case gl.RGBA16F: return 'rgba16f';
   1066            case gl.RGBA16I: return 'rgba16i';
   1067            case gl.RGBA16UI: return 'rgba16ui';
   1068            case gl.RGBA8: return 'rgba8';
   1069            case gl.RGBA8I: return 'rgba8i';
   1070            case gl.RGBA8UI: return 'rgba8ui';
   1071            case gl.SRGB8_ALPHA8: return 'srgb8_alpha8';
   1072            case gl.RGB10_A2: return 'rgb10_a2';
   1073            case gl.RGB10_A2UI: return 'rgb10_a2ui';
   1074            case gl.RGBA8_SNORM: return 'rgba8_snorm';
   1075            case gl.RGB8: return 'rgb8';
   1076            case gl.R11F_G11F_B10F: return 'r11f_g11f_b10f';
   1077            case gl.RGB32F: return 'rgb32f';
   1078            case gl.RGB32I: return 'rgb32i';
   1079            case gl.RGB32UI: return 'rgb32ui';
   1080            case gl.RGB16F: return 'rgb16f';
   1081            case gl.RGB16I: return 'rgb16i';
   1082            case gl.RGB16UI: return 'rgb16ui';
   1083            case gl.RGB8_SNORM: return 'rgb8_snorm';
   1084            case gl.RGB8I: return 'rgb8i';
   1085            case gl.RGB8UI: return 'rgb8ui';
   1086            case gl.SRGB8: return 'srgb8';
   1087            case gl.RGB9_E5: return 'rgb9_e5';
   1088            case gl.RG32F: return 'rg32f';
   1089            case gl.RG32I: return 'rg32i';
   1090            case gl.RG32UI: return 'rg32ui';
   1091            case gl.RG16F: return 'rg16f';
   1092            case gl.RG16I: return 'rg16i';
   1093            case gl.RG16UI: return 'rg16ui';
   1094            case gl.RG8: return 'rg8';
   1095            case gl.RG8I: return 'rg8i';
   1096            case gl.RG8UI: return 'rg8ui';
   1097            case gl.RG8_SNORM: return 'rg8_snorm';
   1098            case gl.R32F: return 'r32f';
   1099            case gl.R32I: return 'r32i';
   1100            case gl.R32UI: return 'r32ui';
   1101            case gl.R16F: return 'r16f';
   1102            case gl.R16I: return 'r16i';
   1103            case gl.R16UI: return 'r16ui';
   1104            case gl.R8: return 'r8';
   1105            case gl.R8I: return 'r8i';
   1106            case gl.R8UI: return 'r8ui';
   1107            case gl.R8_SNORM: return 'r8_snorm';
   1108            case gl.DEPTH_COMPONENT32F: return 'depth_component32f';
   1109            case gl.DEPTH_COMPONENT24: return 'depth_component24';
   1110            case gl.DEPTH32F_STENCIL8: return 'depth32f_stencil8';
   1111            case gl.DEPTH24_STENCIL8: return 'depth24_stencil8';
   1112 
   1113            default:
   1114                throw new Error('Unknown format in getFromatName()');
   1115        }
   1116    };
   1117 
   1118    /**
   1119     * @param {tcuTexture.TextureFormat} format
   1120     * @return {gluShaderUtil.DataType}
   1121     */
   1122    es3fFboTestUtil.getFragmentOutputType = function(format) {
   1123        switch (tcuTexture.getTextureChannelClass(format.type)) {
   1124            case tcuTexture.TextureChannelClass.FLOATING_POINT:
   1125            case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
   1126            case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
   1127                return gluShaderUtil.DataType.FLOAT_VEC4;
   1128 
   1129            case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
   1130                return gluShaderUtil.DataType.UINT_VEC4;
   1131 
   1132            case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
   1133                return gluShaderUtil.DataType.INT_VEC4;
   1134 
   1135            default:
   1136                throw new Error('Unknown format');
   1137        }
   1138    };
   1139 
   1140    /**
   1141     * @param {tcuTexture.TextureFormat} format
   1142     * @return {tcuTexture.TextureFormat}
   1143     */
   1144    es3fFboTestUtil.getFramebufferReadFormat = function(format) {
   1145        switch (tcuTexture.getTextureChannelClass(format.type)) {
   1146            case tcuTexture.TextureChannelClass.FLOATING_POINT:
   1147                return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.FLOAT);
   1148 
   1149            case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
   1150            case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
   1151                return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8);
   1152 
   1153            case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
   1154                return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT32);
   1155 
   1156            case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
   1157                return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT32);
   1158 
   1159            default:
   1160                throw new Error('Unknown format in es3fFboTestUtil.getFramebufferReadFormat()');
   1161        }
   1162    };
   1163 
   1164    /**
   1165     * @param {es3fFboTestUtil.Context} ctx GL-like context
   1166     * @param {tcuTexture.TextureFormat} format
   1167     * @param {Array<number>} value
   1168     */
   1169    es3fFboTestUtil.clearColorBuffer = function(ctx, format, value) {
   1170        /** @const @type {tcuTexture.TextureChannelClass} */
   1171        var fmtClass = tcuTexture.getTextureChannelClass(format.type);
   1172 
   1173        switch (fmtClass) {
   1174            case tcuTexture.TextureChannelClass.FLOATING_POINT:
   1175            case tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT:
   1176            case tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT:
   1177                ctx.clearBufferfv(gl.COLOR, 0, value);
   1178                break;
   1179 
   1180            case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
   1181                ctx.clearBufferuiv(gl.COLOR, 0, value);
   1182                break;
   1183 
   1184            case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
   1185                ctx.clearBufferiv(gl.COLOR, 0, value);
   1186                break;
   1187 
   1188            default:
   1189                throw new Error('Invalid channel class: ' + fmtClass);
   1190        }
   1191    };
   1192 
   1193    /**
   1194     * @param {tcuTexture.TextureFormat} format
   1195     * @return {tcuRGBA.RGBA}
   1196     */
   1197    es3fFboTestUtil.getThresholdFromTextureFormat = function(format) {
   1198        /** @const @type {Array<number>} */ var bits = tcuTextureUtil.getTextureFormatMantissaBitDepth(format);
   1199        return tcuRGBA.newRGBAComponents(
   1200            es3fFboTestUtil.calculateU8ConversionError(bits[0]),
   1201            es3fFboTestUtil.calculateU8ConversionError(bits[1]),
   1202            es3fFboTestUtil.calculateU8ConversionError(bits[2]),
   1203            es3fFboTestUtil.calculateU8ConversionError(bits[3])
   1204        );
   1205    };
   1206 
   1207    /**
   1208     * @param {number} glFormat
   1209     * @return {tcuRGBA.RGBA}
   1210     */
   1211    es3fFboTestUtil.getFormatThreshold = function(glFormat) {
   1212        /** @const @type {tcuTexture.TextureFormat} */ var format = gluTextureUtil.mapGLInternalFormat(glFormat);
   1213        return es3fFboTestUtil.getThresholdFromTextureFormat(format);
   1214    };
   1215 
   1216    /**
   1217     * @param {number} srcBits
   1218     * @return {number}
   1219     */
   1220    es3fFboTestUtil.getToSRGB8ConversionError = function(srcBits) {
   1221        // \note These are pre-computed based on simulation results.
   1222        /** @const @type {Array<number>} */ var errors = [
   1223            1, // 0 bits - rounding
   1224            255, // 1 bits
   1225            157, // 2 bits
   1226            106, // 3 bits
   1227            74, // 4 bits
   1228            51, // 5 bits
   1229            34, // 6 bits
   1230            22, // 7 bits
   1231            13, // 8 bits
   1232            7, // 9 bits
   1233            4, // 10 bits
   1234            3, // 11 bits
   1235            2 // 12 bits
   1236            // 1 from this on
   1237        ];
   1238 
   1239        DE_ASSERT(srcBits >= 0);
   1240        if (srcBits < errors.length)
   1241            return errors[srcBits];
   1242        else
   1243            return 1;
   1244    };
   1245 
   1246    /**
   1247     * @param {tcuTexture.TextureFormat} src
   1248     * @param {tcuTexture.TextureFormat} dst
   1249     * @return {tcuRGBA.RGBA}
   1250     */
   1251    es3fFboTestUtil.getToSRGBConversionThreshold = function(src, dst) {
   1252        // Only SRGB8 and SRGB8_ALPHA8 formats are supported.
   1253        DE_ASSERT(dst.type == tcuTexture.ChannelType.UNORM_INT8);
   1254        DE_ASSERT(dst.order == tcuTexture.ChannelOrder.sRGB || dst.order == tcuTexture.ChannelOrder.sRGBA);
   1255 
   1256        /** @const @type {Array<number>} */ var bits = tcuTextureUtil.getTextureFormatMantissaBitDepth(src);
   1257        /** @const @type {boolean} */ var dstHasAlpha = dst.order == tcuTexture.ChannelOrder.sRGBA;
   1258 
   1259        return tcuRGBA.newRGBAComponents(
   1260            es3fFboTestUtil.getToSRGB8ConversionError(bits[0]),
   1261            es3fFboTestUtil.getToSRGB8ConversionError(bits[1]),
   1262            es3fFboTestUtil.getToSRGB8ConversionError(bits[2]),
   1263            dstHasAlpha ? es3fFboTestUtil.calculateU8ConversionError(bits[3]) : 0);
   1264    };
   1265 
   1266    /**
   1267     * es3fFboTestUtil.readPixels()
   1268     * @param {(WebGL2RenderingContext|sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext)} ctx
   1269     * @param {tcuSurface.Surface} dst
   1270     * @param {number} x
   1271     * @param {number} y
   1272     * @param {number} width
   1273     * @param {number} height
   1274     * @param {tcuTexture.TextureFormat} format
   1275     * @param {Array<number>} scale
   1276     * @param {Array<number>} bias
   1277     */
   1278    es3fFboTestUtil.readPixels = function(ctx, dst, x, y, width, height, format, scale, bias) {
   1279        /** @type {tcuTexture.TextureFormat} */ var readFormat = es3fFboTestUtil.getFramebufferReadFormat(format);
   1280        /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(readFormat);
   1281        /** @type {number} */ var alignment = 4; // \note gl.PACK_ALIGNMENT = 4 is assumed.
   1282        /** @type {number} */ var rowSize = deMath.deAlign32(readFormat.getPixelSize() * width, alignment);
   1283        var typedArrayType = tcuTexture.getTypedArray(readFormat.type);
   1284        var data = new typedArrayType(rowSize * height);
   1285        ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, data);
   1286 
   1287        // Convert to surface.
   1288        var cpbaDescriptor = {
   1289            format: readFormat,
   1290            width: width,
   1291            height: height,
   1292            depth: 1,
   1293            rowPitch: rowSize,
   1294            slicePitch: 0,
   1295            data: data.buffer
   1296        };
   1297 
   1298        /** @type {tcuTexture.ConstPixelBufferAccess} */
   1299        var src = new tcuTexture.ConstPixelBufferAccess(cpbaDescriptor);
   1300 
   1301        dst.setSize(width, height);
   1302        /** @type {tcuTexture.PixelBufferAccess} */ var dstAccess = dst.getAccess();
   1303 
   1304        for (var yo = 0; yo < height; yo++)
   1305        for (var xo = 0; xo < width; xo++)
   1306            dstAccess.setPixel(deMath.add(deMath.multiply(src.getPixel(xo, yo), scale), bias), xo, yo);
   1307    };
   1308 
   1309    /**
   1310     * @param {number} srcBits
   1311     * @return {number}
   1312     */
   1313    es3fFboTestUtil.calculateU8ConversionError = function(srcBits) {
   1314        if (srcBits > 0) {
   1315            /** @const @type {number} */ var clampedBits = deMath.clamp(srcBits, 0, 8);
   1316            /** @const @type {number} */ var srcMaxValue = Math.max((1 << clampedBits) - 1, 1);
   1317            /** @const @type {number} */ var error = Math.floor(Math.ceil(255.0 * 2.0 / srcMaxValue));
   1318 
   1319            return deMath.clamp(error, 0, 255);
   1320        } else
   1321            return 1;
   1322    };
   1323 
   1324 });