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 });