Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / functional / gles3 / es3fFboTestUtil.js
blobed152a43e4f438c2af1a32df708a9759e5a9154f
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  */
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');
40 goog.scope(function() {
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;
60 var DE_ASSERT = function(x) {
61     if (!x)
62         throw new Error('Assert failed');
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';
75 /** @typedef { (WebGL2RenderingContext|sglrReferenceContext.ReferenceContext)} */
76 es3fFboTestUtil.Context;
78 es3fFboTestUtil.FboIncompleteException.prototype.getReason = function() {return this.reason; };
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     };
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     };
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;
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     };
145     es3fFboTestUtil.FlatColorShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
146     es3fFboTestUtil.FlatColorShader.prototype.constructor = es3fFboTestUtil.FlatColorShader;
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');
156         context.useProgram(program);
157         context.uniform4fv(location, color);
158     };
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     };
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);
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     };
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     };
240     es3fFboTestUtil.GradientShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
241     es3fFboTestUtil.GradientShader.prototype.constructor = es3fFboTestUtil.GradientShader;
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     };
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];
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     };
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;
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];
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);
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     };
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 = '';
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';
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         }
320         // Output scale & bias
321         src += 'uniform ' + precision + ' vec4 u_outScale0;\n' +
322                'uniform ' + precision + ' vec4 u_outBias0;\n';
324         src += '\n' +
325                'void main (void)\n' +
326                '{\n' +
327                ' ' + precision + ' vec4 out0 = vec4(0.0);\n';
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';
334         // Write output.
335         src += ' o_color0 = ' + gluShaderUtil.getDataTypeName(outputType) + '(out0 * u_outScale0 + u_outBias0);\n' +
336                '}\n';
338         return src;
339     };
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();
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)));
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'));
366         decl.pushFragmentSource(new sglrShaderProgram.FragmentSource(es3fFboTestUtil.genTexFragmentShader(samplerTypes, outputType)));
368         decl.pushUniform(new sglrShaderProgram.Uniform('u_outScale0', gluShaderUtil.DataType.FLOAT_VEC4));
369         decl.pushUniform(new sglrShaderProgram.Uniform('u_outBias0', gluShaderUtil.DataType.FLOAT_VEC4));
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         }
377         return decl;
378     };
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     };
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     };
416     es3fFboTestUtil.Texture2DShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
417     es3fFboTestUtil.Texture2DShader.prototype.constructor = es3fFboTestUtil.Texture2DShader;
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     };
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     };
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     };
446     /**
447      * @param context GL-like context
448      * @param program
449      */
450     es3fFboTestUtil.Texture2DShader.prototype.setUniforms = function(context, program) {
451         context.useProgram(program);
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;
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         }
463         context.uniform4fv(context.getUniformLocation(program, 'u_outScale0'), this.m_outScale);
464         context.uniform4fv(context.getUniformLocation(program, 'u_outBias0'), this.m_outBias);
465     };
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     };
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 = [];
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]];
497             // clear result
498             colors = [0.0, 0.0, 0.0, 0.0];
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)));
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;
510                 var tmpColors = tex.sample(texCoords, lod);
512                 colors = deMath.add(colors, deMath.add(deMath.multiply(tmpColors, scale), bias));
513             }
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);
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     };
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     };
576     es3fFboTestUtil.TextureCubeShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
577     es3fFboTestUtil.TextureCubeShader.prototype.constructor = es3fFboTestUtil.TextureCubeShader;
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     };
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     };
620     /**
621      * @param ctx GL-like context
622      * @param program
623      */
624     es3fFboTestUtil.TextureCubeShader.prototype.setUniforms = function(ctx, program) {
625         ctx.useProgram(program);
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     };
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);
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]);
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     };
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;
662         var texCoords = [];
663         var colors = [];
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)));
671             var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
672             texCoords = [coord[0], coord[1], coord[2]];
674             colors = tex.sample(texCoords, lod);
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);
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     };
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     };
736     es3fFboTestUtil.Texture2DArrayShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
737     es3fFboTestUtil.Texture2DArrayShader.prototype.constructor = es3fFboTestUtil.Texture2DArrayShader;
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);
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     };
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];
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     };
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];
790         var texCoords = [];
791         var colors = [];
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)));
799             /** @const {Array<number>} */ var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
800             texCoords = [coord[0], coord[1], layer];
802             colors = tex.sample(texCoords, lod);
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);
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     };
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     };
864     es3fFboTestUtil.Texture3DShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
865     es3fFboTestUtil.Texture3DShader.prototype.constructor = es3fFboTestUtil.Texture3DShader;
867     /**
868      * @param {number} depth
869      */
870     es3fFboTestUtil.Texture3DShader.prototype.setDepth = function(depth) {
871         this.m_depth = depth;
872     };
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     };
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     };
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];
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     };
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];
919         var texCoords = [];
920         var colors = [];
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)));
929             var coord = rrShadingContext.readTriangleVarying(packet[packetNdx], context, 0);
930             texCoords = [coord[0], coord[1], depth];
932             colors = tex.sample(texCoords, lod);
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);
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     };
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     };
995     es3fFboTestUtil.DepthGradientShader.prototype = Object.create(sglrShaderProgram.ShaderProgram.prototype);
996     es3fFboTestUtil.DepthGradientShader.prototype.constructor = es3fFboTestUtil.DepthGradientShader;
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     };
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];
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     };
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);
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;
1044             packet[packetNdx].sampleDepths[0] = gradientMin + (gradientMax - gradientMin) * f0;
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     };
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';
1113             default:
1114                 throw new Error('Unknown format in getFromatName()');
1115         }
1116     };
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;
1129             case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
1130                 return gluShaderUtil.DataType.UINT_VEC4;
1132             case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
1133                 return gluShaderUtil.DataType.INT_VEC4;
1135             default:
1136                 throw new Error('Unknown format');
1137         }
1138     };
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);
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);
1153             case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
1154                 return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT32);
1156             case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
1157                 return new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.SIGNED_INT32);
1159             default:
1160                 throw new Error('Unknown format in es3fFboTestUtil.getFramebufferReadFormat()');
1161         }
1162     };
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);
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;
1180             case tcuTexture.TextureChannelClass.UNSIGNED_INTEGER:
1181                 ctx.clearBufferuiv(gl.COLOR, 0, value);
1182                 break;
1184             case tcuTexture.TextureChannelClass.SIGNED_INTEGER:
1185                 ctx.clearBufferiv(gl.COLOR, 0, value);
1186                 break;
1188             default:
1189                 throw new Error('Invalid channel class: ' + fmtClass);
1190         }
1191     };
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     };
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     };
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         ];
1239         DE_ASSERT(srcBits >= 0);
1240         if (srcBits < errors.length)
1241             return errors[srcBits];
1242         else
1243             return 1;
1244     };
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);
1256         /** @const @type {Array<number>} */ var bits = tcuTextureUtil.getTextureFormatMantissaBitDepth(src);
1257         /** @const @type {boolean} */ var dstHasAlpha = dst.order == tcuTexture.ChannelOrder.sRGBA;
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     };
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);
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         };
1298         /** @type {tcuTexture.ConstPixelBufferAccess} */
1299         var src = new tcuTexture.ConstPixelBufferAccess(cpbaDescriptor);
1301         dst.setSize(width, height);
1302         /** @type {tcuTexture.PixelBufferAccess} */ var dstAccess = dst.getAccess();
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     };
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));
1319             return deMath.clamp(error, 0, 255);
1320         } else
1321             return 1;
1322     };