rrFragmentOperations.js (32843B)
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('framework.referencerenderer.rrFragmentOperations'); 23 goog.require('framework.common.tcuTexture'); 24 goog.require('framework.common.tcuTextureUtil'); 25 goog.require('framework.delibs.debase.deMath'); 26 goog.require('framework.referencerenderer.rrRenderState'); 27 28 goog.scope(function() { 29 30 var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations; 31 var deMath = framework.delibs.debase.deMath; 32 var rrRenderState = framework.referencerenderer.rrRenderState; 33 var tcuTexture = framework.common.tcuTexture; 34 var tcuTextureUtil = framework.common.tcuTextureUtil; 35 36 /** Return oldValue with the bits indicated by mask replaced by corresponding bits of newValue. 37 * @param {number} oldValue 38 * @param {number} newValue 39 * @param {number} mask 40 * @return {number} 41 */ 42 rrFragmentOperations.maskedBitReplace = function(oldValue, newValue, mask) { 43 return (oldValue & ~mask) | (newValue & mask); 44 }; 45 46 /** 47 * @param {Array<number>} point 48 * @param {?} rect 49 * @return {boolean} 50 */ 51 rrFragmentOperations.isInsideRect = function(point, rect) { 52 return deMath.deInBounds32(point[0], rect.left, rect.left + rect.width) && 53 deMath.deInBounds32(point[1], rect.bottom, rect.bottom + rect.height); 54 }; 55 56 /** 57 * @constructor 58 * @param {Array<number>} coefficents 59 * @param {Array<number>} coords 60 * @param {number} depth 61 */ 62 rrFragmentOperations.Fragment = function(coefficents, coords, depth) { 63 /** @type {Array<number>} */ this.barycentric = coefficents; 64 /** @type {Array<number>} */ this.pixelCoord = coords; 65 /** @type {boolean} */ this.isAlive = true; 66 /** @type {boolean} */ this.stencilPassed = true; 67 /** @type {boolean} */ this.depthPassed = true; 68 /** @type {Array<number>} */ this.sampleDepths = [depth]; 69 /** @type {Array<number>} */ this.clampedBlendSrcColor = []; 70 /** @type {Array<number>} */ this.clampedBlendSrc1Color = []; 71 /** @type {Array<number>} */ this.clampedBlendDstColor = []; 72 /** @type {Array<number>} */ this.blendSrcFactorRGB = []; 73 /** @type {number} */ this.blendSrcFactorA = NaN; 74 /** @type {Array<number>} */ this.blendDstFactorRGB = []; 75 /** @type {number} */ this.blendDstFactorA = NaN; 76 /** @type {Array<number>} */ this.blendedRGB = []; 77 /** @type {number} */ this.blendedA = NaN; 78 /** @type {Array<number>} */ this.signedValue = []; //!< integer targets 79 /** @type {Array<number>} */ this.unsignedValue = []; //!< unsigned integer targets 80 /** @type {Array<number>} */ this.value = []; /*TODO: what type should it be? */ 81 /** @type {Array<number>} */ this.value1 = []; /*TODO: what type should it be? */ 82 }; 83 84 /** 85 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 86 * @param {rrRenderState.WindowRectangle} scissorRect 87 */ 88 rrFragmentOperations.executeScissorTest = function(inputFragments, scissorRect) { 89 for (var i = 0; i < inputFragments.length; i++) { 90 var frag = inputFragments[i]; 91 if (frag.isAlive) { 92 if (!rrFragmentOperations.isInsideRect(frag.pixelCoord, scissorRect)) 93 frag.isAlive = false; 94 } 95 } 96 }; 97 98 /** 99 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 100 * @param {rrRenderState.StencilState} stencilState 101 * @param {number} numStencilBits 102 * @param {tcuTexture.PixelBufferAccess} stencilBuffer 103 */ 104 rrFragmentOperations.executeStencilCompare = function(inputFragments, stencilState, numStencilBits, stencilBuffer) { 105 var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1); 106 107 /** 108 * @param {function(number=,number=):boolean} expression 109 */ 110 var sample_register_stencil_compare = function(expression) { 111 for (var i = 0; i < inputFragments.length; i++) { 112 var frag = inputFragments[i]; 113 if (frag.isAlive) { 114 var fragSampleNdx = 0; 115 var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 116 var maskedRef = stencilState.compMask & clampedStencilRef; 117 var maskedBuf = stencilState.compMask & stencilBufferValue; 118 frag.stencilPassed = expression(maskedRef, maskedBuf); 119 } 120 } 121 }; 122 123 switch (stencilState.func) { 124 case rrRenderState.TestFunc.NEVER: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return false;}); break; 125 case rrRenderState.TestFunc.ALWAYS: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return true;}); break; 126 case rrRenderState.TestFunc.LESS: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef < maskedBuf;}); break; 127 case rrRenderState.TestFunc.LEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef <= maskedBuf;}); break; 128 case rrRenderState.TestFunc.GREATER: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef > maskedBuf;}); break; 129 case rrRenderState.TestFunc.GEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef >= maskedBuf;}); break; 130 case rrRenderState.TestFunc.EQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef == maskedBuf;}); break; 131 case rrRenderState.TestFunc.NOTEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef != maskedBuf;}); break; 132 default: 133 throw new Error('Unrecognized stencil test function:' + stencilState.func); 134 } 135 }; 136 137 /** 138 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 139 * @param {rrRenderState.StencilState} stencilState 140 * @param {number} numStencilBits 141 * @param {tcuTexture.PixelBufferAccess} stencilBuffer 142 */ 143 rrFragmentOperations.executeStencilSFail = function(inputFragments, stencilState, numStencilBits, stencilBuffer) { 144 var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1); 145 /** 146 * @param {function(number,number):number} expression 147 */ 148 var sample_register_sfail = function(expression) { 149 for (var i = 0; i < inputFragments.length; i++) { 150 var frag = inputFragments[i]; 151 if (frag.isAlive && !frag.stencilPassed) { 152 var fragSampleNdx = 0; 153 var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 154 stencilBuffer.setPixStencil(rrFragmentOperations.maskedBitReplace(stencilBufferValue, expression(stencilBufferValue, numStencilBits), stencilState.writeMask), fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 155 frag.isAlive = false; 156 } 157 } 158 }; 159 160 switch (stencilState.sFail) { 161 case rrRenderState.StencilOp.KEEP: 162 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return stencilBufferValue;}); break; 163 case rrRenderState.StencilOp.ZERO: 164 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return 0;}); break; 165 case rrRenderState.StencilOp.REPLACE: 166 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return clampedStencilRef;}); break; 167 case rrRenderState.StencilOp.INCR: 168 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1);}); break; 169 case rrRenderState.StencilOp.DECR: 170 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1);}); break; 171 case rrRenderState.StencilOp.INCR_WRAP: 172 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (stencilBufferValue + 1) & ((1 << numStencilBits) - 1);}); break; 173 case rrRenderState.StencilOp.DECR_WRAP: 174 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (stencilBufferValue - 1) & ((1 << numStencilBits) - 1);}); break; 175 case rrRenderState.StencilOp.INVERT: 176 sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (~stencilBufferValue) & ((1 << numStencilBits) - 1);}); break; 177 default: 178 throw new Error('Unrecognized stencil op:' + stencilState.sFail); 179 } 180 181 }; 182 183 /** 184 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 185 * @param {rrRenderState.TestFunc} depthFunc 186 * @param {tcuTexture.PixelBufferAccess} depthBuffer 187 */ 188 rrFragmentOperations.executeDepthCompare = function(inputFragments, depthFunc, depthBuffer) { 189 /** 190 * @param {function(number=,number=):boolean} expression 191 */ 192 var convertToDepthBuffer = false; 193 194 var access; 195 if (depthBuffer.getFormat().type != tcuTexture.ChannelType.FLOAT && 196 depthBuffer.getFormat().type != tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV) { 197 access = new tcuTexture.PixelBufferAccess({ 198 format: depthBuffer.getFormat(), 199 width: 1, 200 height: 1, 201 depth: 1, 202 data: new ArrayBuffer(8) 203 }); 204 convertToDepthBuffer = true; 205 } 206 207 var sample_register_depth_compare = function(expression) { 208 for (var i = 0; i < inputFragments.length; i++) { 209 var frag = inputFragments[i]; 210 if (frag.isAlive) { 211 var fragSampleNdx = 0; 212 var depthBufferValue = depthBuffer.getPixDepth(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 213 var sampleDepthFloat = frag.sampleDepths[fragSampleNdx]; 214 215 var sampleDepth; 216 if (convertToDepthBuffer) { 217 /* convert input float to target buffer format for comparison */ 218 access.setPixDepth(sampleDepthFloat, 0, 0, 0); 219 sampleDepth = access.getPixDepth(0, 0, 0); 220 } else { 221 sampleDepth = deMath.clamp(sampleDepthFloat, 0.0, 1.0); 222 } 223 224 frag.depthPassed = expression(sampleDepth, depthBufferValue); 225 } 226 } 227 }; 228 229 switch (depthFunc) { 230 case rrRenderState.TestFunc.NEVER: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return false;}); break; 231 case rrRenderState.TestFunc.ALWAYS: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return true;}); break; 232 case rrRenderState.TestFunc.LESS: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth < depthBufferValue;}); break; 233 case rrRenderState.TestFunc.LEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth <= depthBufferValue;}); break; 234 case rrRenderState.TestFunc.GREATER: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth > depthBufferValue;}); break; 235 case rrRenderState.TestFunc.GEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth >= depthBufferValue;}); break; 236 case rrRenderState.TestFunc.EQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth == depthBufferValue;}); break; 237 case rrRenderState.TestFunc.NOTEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth != depthBufferValue;}); break; 238 default: 239 throw new Error('Unrecognized depth function:' + depthFunc); 240 } 241 }; 242 243 /** 244 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 245 * @param {tcuTexture.PixelBufferAccess} depthBuffer 246 */ 247 rrFragmentOperations.executeDepthWrite = function(inputFragments, depthBuffer) { 248 for (var i = 0; i < inputFragments.length; i++) { 249 var frag = inputFragments[i]; 250 if (frag.isAlive && frag.depthPassed) { 251 var fragSampleNdx = 0; 252 var clampedDepth = deMath.clamp(frag.sampleDepths[fragSampleNdx], 0.0, 1.0); 253 depthBuffer.setPixDepth(clampedDepth, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 254 } 255 } 256 }; 257 258 /** 259 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 260 * @param {rrRenderState.StencilState} stencilState 261 * @param {number} numStencilBits 262 * @param {tcuTexture.PixelBufferAccess} stencilBuffer 263 */ 264 rrFragmentOperations.executeStencilDpFailAndPass = function(inputFragments, stencilState, numStencilBits, stencilBuffer) { 265 var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1); 266 267 /** 268 * @param {function(boolean):boolean} condition 269 * @param {function(number,number):number} expression 270 */ 271 var sample_register_dpfail_or_dppass = function(condition, expression) { 272 for (var i = 0; i < inputFragments.length; i++) { 273 var frag = inputFragments[i]; 274 if (frag.isAlive && condition(frag.depthPassed)) { 275 var fragSampleNdx = 0; 276 var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 277 stencilBuffer.setPixStencil(rrFragmentOperations.maskedBitReplace(stencilBufferValue, expression(stencilBufferValue, numStencilBits), stencilState.writeMask), fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 278 } 279 } 280 }; 281 282 var switch_dpfail_or_dppass = function(op_name, condition) { 283 switch (stencilState[op_name]) { 284 case rrRenderState.StencilOp.KEEP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return stencilBufferValue;}); break; 285 case rrRenderState.StencilOp.ZERO: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return 0;}); break; 286 case rrRenderState.StencilOp.REPLACE: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return clampedStencilRef;}); break; 287 case rrRenderState.StencilOp.INCR: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1);}); break; 288 case rrRenderState.StencilOp.DECR: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1);}); break; 289 case rrRenderState.StencilOp.INCR_WRAP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (stencilBufferValue + 1) & ((1 << numStencilBits) - 1);}); break; 290 case rrRenderState.StencilOp.DECR_WRAP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (stencilBufferValue - 1) & ((1 << numStencilBits) - 1);}); break; 291 case rrRenderState.StencilOp.INVERT: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (~stencilBufferValue) & ((1 << numStencilBits) - 1);}); break; 292 default: 293 throw new Error('Unrecognized stencil operation:' + op_name); 294 } 295 }; 296 297 var passed = function(depthPassed) { return depthPassed;}; 298 var failed = function(depthPassed) { return !depthPassed;}; 299 300 switch_dpfail_or_dppass('dpFail', failed); 301 switch_dpfail_or_dppass('dpPass', passed); 302 }; 303 304 /** 305 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 306 * @param {Array<number>} blendColor 307 * @param {rrRenderState.BlendState} blendRGBState 308 */ 309 rrFragmentOperations.executeBlendFactorComputeRGB = function(inputFragments, blendColor, blendRGBState) { 310 /** 311 * @param {string} factor_name 312 * @param {function(Array<number>, Array<number>, Array<number>):Array<number>} expression 313 */ 314 var sample_register_blend_factor = function(factor_name, expression) { 315 for (var i = 0; i < inputFragments.length; i++) { 316 var frag = inputFragments[i]; 317 if (frag.isAlive) { 318 var src = frag.clampedBlendSrcColor; 319 var src1 = frag.clampedBlendSrc1Color; 320 var dst = frag.clampedBlendDstColor; 321 frag[factor_name] = deMath.clampVector(expression(src, src1, dst), 0, 1); 322 } 323 } 324 }; 325 326 var switch_src_or_dst_factor_rgb = function(func_name, factor_name) { 327 switch (blendRGBState[func_name]) { 328 case rrRenderState.BlendFunc.ZERO: 329 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [0, 0, 0];}); break; 330 case rrRenderState.BlendFunc.ONE: 331 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1, 1, 1];}); break; 332 case rrRenderState.BlendFunc.SRC_COLOR: 333 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(src, [0, 1, 2]);}); break; 334 case rrRenderState.BlendFunc.ONE_MINUS_SRC_COLOR: 335 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(src, [0, 1, 2]));}); break; 336 case rrRenderState.BlendFunc.DST_COLOR: 337 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(dst, [0, 1, 2]);}); break; 338 case rrRenderState.BlendFunc.ONE_MINUS_DST_COLOR: 339 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(dst, [0, 1, 2]));}); break; 340 case rrRenderState.BlendFunc.SRC_ALPHA: 341 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [src[3], src[3], src[3]];}); break; 342 case rrRenderState.BlendFunc.ONE_MINUS_SRC_ALPHA: 343 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - src[3], 1.0 - src[3], 1.0 - src[3]];}); break; 344 case rrRenderState.BlendFunc.DST_ALPHA: 345 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [dst[3], dst[3], dst[3]];}); break; 346 case rrRenderState.BlendFunc.ONE_MINUS_DST_ALPHA: 347 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - dst[3], 1.0 - dst[3], 1.0 - dst[3]];}); break; 348 case rrRenderState.BlendFunc.CONSTANT_COLOR: 349 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(blendColor, [0, 1, 2]);}); break; 350 case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_COLOR: 351 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(blendColor, [0, 1, 2]));}); break; 352 case rrRenderState.BlendFunc.CONSTANT_ALPHA: 353 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [blendColor[3], blendColor[3], blendColor[3]];}); break; 354 case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_ALPHA: 355 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - blendColor[3], 1.0 - blendColor[3], 1.0 - blendColor[3]];}); break; 356 case rrRenderState.BlendFunc.SRC_ALPHA_SATURATE: 357 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [Math.min(src[3], 1.0 - dst[3]), Math.min(src[3], 1.0 - dst[3]), Math.min(src[3], 1.0 - dst[3])];}); break; 358 case rrRenderState.BlendFunc.SRC1_COLOR: 359 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(src1, [0, 1, 2]);}); break; 360 case rrRenderState.BlendFunc.ONE_MINUS_SRC1_COLOR: 361 sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(src1, [0, 1, 2]));}); break; 362 case rrRenderState.BlendFunc.SRC1_ALPHA: 363 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [src1[3], src1[3], src1[3]];}); break; 364 case rrRenderState.BlendFunc.ONE_MINUS_SRC1_ALPHA: 365 sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - src1[3], 1.0 - src1[3], 1.0 - src1[3]];}); break; 366 default: 367 throw new Error('Unrecognized blend function:' + func_name); 368 } 369 }; 370 371 switch_src_or_dst_factor_rgb('srcFunc', 'blendSrcFactorRGB'); 372 switch_src_or_dst_factor_rgb('dstFunc', 'blendDstFactorRGB'); 373 374 }; 375 376 /** 377 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 378 * @param {Array<number>} blendColor 379 * @param {rrRenderState.BlendState} blendAState 380 */ 381 rrFragmentOperations.executeBlendFactorComputeA = function(inputFragments, blendColor, blendAState) { 382 /** 383 * @param {string} factor_name 384 * @param {function(Array<number>, Array<number>, Array<number>):number} expression 385 */ 386 var sample_register_blend_factor = function(factor_name, expression) { 387 for (var i = 0; i < inputFragments.length; i++) { 388 var frag = inputFragments[i]; 389 if (frag.isAlive) { 390 var src = frag.clampedBlendSrcColor; 391 var src1 = frag.clampedBlendSrc1Color; 392 var dst = frag.clampedBlendDstColor; 393 frag[factor_name] = deMath.clamp(expression(src, src1, dst), 0, 1); 394 } 395 } 396 }; 397 398 var swictch_src_or_dst_factor_a = function(func_name, factor_name) { 399 switch (blendAState[func_name]) { 400 case rrRenderState.BlendFunc.ZERO: 401 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 0.0;}); break; 402 case rrRenderState.BlendFunc.ONE: 403 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0;}); break; 404 case rrRenderState.BlendFunc.SRC_COLOR: 405 sample_register_blend_factor(factor_name, function(src, src1, dst) { return src[3];}); break; 406 case rrRenderState.BlendFunc.ONE_MINUS_SRC_COLOR: 407 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src[3];}); break; 408 case rrRenderState.BlendFunc.DST_COLOR: 409 sample_register_blend_factor(factor_name, function(src, src1, dst) { return dst[3];}); break; 410 case rrRenderState.BlendFunc.ONE_MINUS_DST_COLOR: 411 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - dst[3];}); break; 412 case rrRenderState.BlendFunc.SRC_ALPHA: 413 sample_register_blend_factor(factor_name, function(src, src1, dst) { return src[3];}); break; 414 case rrRenderState.BlendFunc.ONE_MINUS_SRC_ALPHA: 415 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src[3];}); break; 416 case rrRenderState.BlendFunc.DST_ALPHA: 417 sample_register_blend_factor(factor_name, function(src, src1, dst) { return dst[3];}); break; 418 case rrRenderState.BlendFunc.ONE_MINUS_DST_ALPHA: 419 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - dst[3];}); break; 420 case rrRenderState.BlendFunc.CONSTANT_COLOR: 421 sample_register_blend_factor(factor_name, function(src, src1, dst) { return blendColor[3];}); break; 422 case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_COLOR: 423 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - blendColor[3];}); break; 424 case rrRenderState.BlendFunc.CONSTANT_ALPHA: 425 sample_register_blend_factor(factor_name, function(src, src1, dst) { return blendColor[3];}); break; 426 case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_ALPHA: 427 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - blendColor[3];}); break; 428 case rrRenderState.BlendFunc.SRC_ALPHA_SATURATE: 429 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0;}); break; 430 case rrRenderState.BlendFunc.SRC1_COLOR: 431 sample_register_blend_factor(factor_name, function(src, src1, dst) { return src1[3];}); break; 432 case rrRenderState.BlendFunc.ONE_MINUS_SRC1_COLOR: 433 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src1[3];}); break; 434 case rrRenderState.BlendFunc.SRC1_ALPHA: 435 sample_register_blend_factor(factor_name, function(src, src1, dst) { return src1[3];}); break; 436 case rrRenderState.BlendFunc.ONE_MINUS_SRC1_ALPHA: 437 sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src1[3];}); break; 438 default: 439 throw new Error('Unrecognized blend function:' + func_name); 440 } 441 }; 442 443 swictch_src_or_dst_factor_a('srcFunc', 'blendSrcFactorA'); 444 swictch_src_or_dst_factor_a('dstFunc', 'blendDstFactorA'); 445 }; 446 447 /** 448 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write 449 * @param {rrRenderState.BlendState} blendRGBState 450 * @param {rrRenderState.BlendState} blendAState 451 */ 452 rrFragmentOperations.executeBlend = function(inputFragments, blendRGBState, blendAState) { 453 var sample_register_blended_color = function(color_name, expression) { 454 for (var i = 0; i < inputFragments.length; i++) { 455 var frag = inputFragments[i]; 456 if (frag.isAlive) { 457 var src = frag.clampedBlendSrcColor; 458 var dst = frag.clampedBlendDstColor; 459 frag[color_name] = expression(src, dst, frag); 460 } 461 } 462 }; 463 464 switch (blendRGBState.equation) { 465 case rrRenderState.BlendEquation.ADD: 466 sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.add(deMath.multiply(deMath.swizzle(src, [0, 1, 2]), frag.blendSrcFactorRGB), deMath.multiply(deMath.swizzle(dst, [0, 1, 2]), frag.blendDstFactorRGB));}); break; 467 case rrRenderState.BlendEquation.SUBTRACT: 468 sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.subtract(deMath.multiply(deMath.swizzle(src, [0, 1, 2]), frag.blendSrcFactorRGB), deMath.multiply(deMath.swizzle(dst, [0, 1, 2]), frag.blendDstFactorRGB));}); break; 469 case rrRenderState.BlendEquation.REVERSE_SUBTRACT: 470 sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.subtract(deMath.multiply(deMath.swizzle(dst, [0, 1, 2]), frag.blendDstFactorRGB), deMath.multiply(deMath.swizzle(src, [0, 1, 2]), frag.blendSrcFactorRGB));}); break; 471 case rrRenderState.BlendEquation.MIN: 472 sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.min(deMath.swizzle(src, [0, 1, 2]), deMath.swizzle(dst, [0, 1, 2]));}); break; 473 case rrRenderState.BlendEquation.MAX: 474 sample_register_blended_color('blendedRGB', function(src, dst, frag) { return deMath.max(deMath.swizzle(src, [0, 1, 2]), deMath.swizzle(dst, [0, 1, 2]));}); break; 475 default: 476 throw new Error('Unrecognized blend equation:' + blendRGBState.equation); 477 } 478 479 switch (blendAState.equation) { 480 case rrRenderState.BlendEquation.ADD: 481 sample_register_blended_color('blendedA', function(src, dst, frag) { return src[3] * frag.blendSrcFactorA + dst[3] * frag.blendDstFactorA;}); break; 482 case rrRenderState.BlendEquation.SUBTRACT: 483 sample_register_blended_color('blendedA', function(src, dst, frag) { return src[3] * frag.blendSrcFactorA - dst[3] * frag.blendDstFactorA;}); break; 484 case rrRenderState.BlendEquation.REVERSE_SUBTRACT: 485 sample_register_blended_color('blendedA', function(src, dst, frag) { return dst[3] * frag.blendDstFactorA - src[3] * frag.blendSrcFactorA;}); break; 486 case rrRenderState.BlendEquation.MIN: 487 sample_register_blended_color('blendedA', function(src, dst, frag) { return Math.min(src[3], dst[3]);}); break; 488 case rrRenderState.BlendEquation.MAX: 489 sample_register_blended_color('blendedA', function(src, dst, frag) { return Math.max(src[3], dst[3]);}); break; 490 default: 491 throw new Error('Unrecognized blend equation:' + blendAState.equation); 492 } 493 }; 494 495 /** 496 * @param {Array<rrFragmentOperations.Fragment>} inputFragments 497 * @param {boolean} isSRGB 498 * @param {tcuTexture.PixelBufferAccess} colorBuffer 499 */ 500 rrFragmentOperations.executeColorWrite = function(inputFragments, isSRGB, colorBuffer) { 501 for (var i = 0; i < inputFragments.length; i++) { 502 var frag = inputFragments[i]; 503 if (frag.isAlive) { 504 var combinedColor = frag.blendedRGB.slice(); 505 combinedColor[3] = frag.blendedA; 506 if (isSRGB) 507 combinedColor = tcuTextureUtil.linearToSRGB(combinedColor); 508 509 colorBuffer.setPixel(combinedColor, 0, frag.pixelCoord[0], frag.pixelCoord[1]); 510 } 511 } 512 }; 513 514 /** 515 * @param {Array<rrFragmentOperations.Fragment>} inputFragments 516 * @param {Array<boolean>} colorMaskFactor 517 * @param {Array<boolean>} colorMaskNegationFactor 518 * @param {boolean} isSRGB 519 * @param {tcuTexture.PixelBufferAccess} colorBuffer 520 */ 521 rrFragmentOperations.executeMaskedColorWrite = function(inputFragments, colorMaskFactor, colorMaskNegationFactor, isSRGB, colorBuffer) { 522 for (var i = 0; i < inputFragments.length; i++) { 523 var frag = inputFragments[i]; 524 if (frag.isAlive) { 525 var fragSampleNdx = 0; 526 var originalColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 527 var newColor = frag.blendedRGB.slice(); 528 newColor[3] = frag.blendedA; 529 530 if (isSRGB) 531 newColor = tcuTextureUtil.linearToSRGB(newColor); 532 533 newColor = deMath.add(deMath.multiply(colorMaskFactor, newColor), deMath.multiply(colorMaskNegationFactor, originalColor)); 534 535 colorBuffer.setPixel(newColor, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 536 } 537 } 538 }; 539 540 /** 541 * @param {Array<rrFragmentOperations.Fragment>} inputFragments 542 * @param {Array<boolean>} colorMask 543 * @param {tcuTexture.PixelBufferAccess} colorBuffer 544 */ 545 rrFragmentOperations.executeSignedValueWrite = function(inputFragments, colorMask, colorBuffer) { 546 for (var i = 0; i < inputFragments.length; i++) { 547 var frag = inputFragments[i]; 548 if (frag.isAlive) { 549 var fragSampleNdx = 0; 550 var originalValue = colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 551 var newValue = tcuTextureUtil.select(frag.signedValue, originalValue, colorMask); 552 553 colorBuffer.setPixelInt(newValue, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 554 } 555 } 556 }; 557 558 /** 559 * @param {Array<rrFragmentOperations.Fragment>} inputFragments 560 * @param {Array<boolean>} colorMask 561 * @param {tcuTexture.PixelBufferAccess} colorBuffer 562 */ 563 rrFragmentOperations.executeUnsignedValueWrite = function(inputFragments, colorMask, colorBuffer) { 564 for (var i = 0; i < inputFragments.length; i++) { 565 var frag = inputFragments[i]; 566 if (frag.isAlive) { 567 var fragSampleNdx = 0; 568 var originalValue = colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 569 var newValue = tcuTextureUtil.select(frag.unsignedValue, originalValue, colorMask); 570 571 colorBuffer.setPixelInt(newValue, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); 572 } 573 } 574 }; 575 576 /** 577 * @constructor 578 */ 579 rrFragmentOperations.FragmentProcessor = function() { 580 /* TODO: implement */ 581 }; 582 583 });