diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js new file mode 100644 index 0000000000..a9c2a1f464 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/referencerenderer/rrFragmentOperations.js @@ -0,0 +1,583 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program OpenGL ES Utilities + * ------------------------------------------------ + * + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +'use strict'; +goog.provide('framework.referencerenderer.rrFragmentOperations'); +goog.require('framework.common.tcuTexture'); +goog.require('framework.common.tcuTextureUtil'); +goog.require('framework.delibs.debase.deMath'); +goog.require('framework.referencerenderer.rrRenderState'); + +goog.scope(function() { + +var rrFragmentOperations = framework.referencerenderer.rrFragmentOperations; +var deMath = framework.delibs.debase.deMath; +var rrRenderState = framework.referencerenderer.rrRenderState; +var tcuTexture = framework.common.tcuTexture; +var tcuTextureUtil = framework.common.tcuTextureUtil; + +/** Return oldValue with the bits indicated by mask replaced by corresponding bits of newValue. + * @param {number} oldValue + * @param {number} newValue + * @param {number} mask + * @return {number} + */ +rrFragmentOperations.maskedBitReplace = function(oldValue, newValue, mask) { + return (oldValue & ~mask) | (newValue & mask); +}; + +/** + * @param {Array<number>} point + * @param {?} rect + * @return {boolean} + */ +rrFragmentOperations.isInsideRect = function(point, rect) { + return deMath.deInBounds32(point[0], rect.left, rect.left + rect.width) && + deMath.deInBounds32(point[1], rect.bottom, rect.bottom + rect.height); +}; + +/** + * @constructor + * @param {Array<number>} coefficents + * @param {Array<number>} coords + * @param {number} depth + */ +rrFragmentOperations.Fragment = function(coefficents, coords, depth) { + /** @type {Array<number>} */ this.barycentric = coefficents; + /** @type {Array<number>} */ this.pixelCoord = coords; + /** @type {boolean} */ this.isAlive = true; + /** @type {boolean} */ this.stencilPassed = true; + /** @type {boolean} */ this.depthPassed = true; + /** @type {Array<number>} */ this.sampleDepths = [depth]; + /** @type {Array<number>} */ this.clampedBlendSrcColor = []; + /** @type {Array<number>} */ this.clampedBlendSrc1Color = []; + /** @type {Array<number>} */ this.clampedBlendDstColor = []; + /** @type {Array<number>} */ this.blendSrcFactorRGB = []; + /** @type {number} */ this.blendSrcFactorA = NaN; + /** @type {Array<number>} */ this.blendDstFactorRGB = []; + /** @type {number} */ this.blendDstFactorA = NaN; + /** @type {Array<number>} */ this.blendedRGB = []; + /** @type {number} */ this.blendedA = NaN; + /** @type {Array<number>} */ this.signedValue = []; //!< integer targets + /** @type {Array<number>} */ this.unsignedValue = []; //!< unsigned integer targets + /** @type {Array<number>} */ this.value = []; /*TODO: what type should it be? */ + /** @type {Array<number>} */ this.value1 = []; /*TODO: what type should it be? */ +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {rrRenderState.WindowRectangle} scissorRect + */ +rrFragmentOperations.executeScissorTest = function(inputFragments, scissorRect) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + if (!rrFragmentOperations.isInsideRect(frag.pixelCoord, scissorRect)) + frag.isAlive = false; + } + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {rrRenderState.StencilState} stencilState + * @param {number} numStencilBits + * @param {tcuTexture.PixelBufferAccess} stencilBuffer + */ +rrFragmentOperations.executeStencilCompare = function(inputFragments, stencilState, numStencilBits, stencilBuffer) { + var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1); + + /** + * @param {function(number=,number=):boolean} expression + */ + var sample_register_stencil_compare = function(expression) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var fragSampleNdx = 0; + var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + var maskedRef = stencilState.compMask & clampedStencilRef; + var maskedBuf = stencilState.compMask & stencilBufferValue; + frag.stencilPassed = expression(maskedRef, maskedBuf); + } + } + }; + + switch (stencilState.func) { + case rrRenderState.TestFunc.NEVER: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return false;}); break; + case rrRenderState.TestFunc.ALWAYS: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return true;}); break; + case rrRenderState.TestFunc.LESS: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef < maskedBuf;}); break; + case rrRenderState.TestFunc.LEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef <= maskedBuf;}); break; + case rrRenderState.TestFunc.GREATER: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef > maskedBuf;}); break; + case rrRenderState.TestFunc.GEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef >= maskedBuf;}); break; + case rrRenderState.TestFunc.EQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef == maskedBuf;}); break; + case rrRenderState.TestFunc.NOTEQUAL: sample_register_stencil_compare(function(maskedRef, maskedBuf) { return maskedRef != maskedBuf;}); break; + default: + throw new Error('Unrecognized stencil test function:' + stencilState.func); + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {rrRenderState.StencilState} stencilState + * @param {number} numStencilBits + * @param {tcuTexture.PixelBufferAccess} stencilBuffer + */ +rrFragmentOperations.executeStencilSFail = function(inputFragments, stencilState, numStencilBits, stencilBuffer) { + var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1); + /** + * @param {function(number,number):number} expression + */ + var sample_register_sfail = function(expression) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive && !frag.stencilPassed) { + var fragSampleNdx = 0; + var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + stencilBuffer.setPixStencil(rrFragmentOperations.maskedBitReplace(stencilBufferValue, expression(stencilBufferValue, numStencilBits), stencilState.writeMask), fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + frag.isAlive = false; + } + } + }; + + switch (stencilState.sFail) { + case rrRenderState.StencilOp.KEEP: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return stencilBufferValue;}); break; + case rrRenderState.StencilOp.ZERO: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return 0;}); break; + case rrRenderState.StencilOp.REPLACE: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return clampedStencilRef;}); break; + case rrRenderState.StencilOp.INCR: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.DECR: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.INCR_WRAP: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (stencilBufferValue + 1) & ((1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.DECR_WRAP: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (stencilBufferValue - 1) & ((1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.INVERT: + sample_register_sfail(function(stencilBufferValue, numStencilBits) { return (~stencilBufferValue) & ((1 << numStencilBits) - 1);}); break; + default: + throw new Error('Unrecognized stencil op:' + stencilState.sFail); + } + +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {rrRenderState.TestFunc} depthFunc + * @param {tcuTexture.PixelBufferAccess} depthBuffer + */ +rrFragmentOperations.executeDepthCompare = function(inputFragments, depthFunc, depthBuffer) { + /** + * @param {function(number=,number=):boolean} expression + */ + var convertToDepthBuffer = false; + + var access; + if (depthBuffer.getFormat().type != tcuTexture.ChannelType.FLOAT && + depthBuffer.getFormat().type != tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV) { + access = new tcuTexture.PixelBufferAccess({ + format: depthBuffer.getFormat(), + width: 1, + height: 1, + depth: 1, + data: new ArrayBuffer(8) + }); + convertToDepthBuffer = true; + } + + var sample_register_depth_compare = function(expression) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var fragSampleNdx = 0; + var depthBufferValue = depthBuffer.getPixDepth(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + var sampleDepthFloat = frag.sampleDepths[fragSampleNdx]; + + var sampleDepth; + if (convertToDepthBuffer) { + /* convert input float to target buffer format for comparison */ + access.setPixDepth(sampleDepthFloat, 0, 0, 0); + sampleDepth = access.getPixDepth(0, 0, 0); + } else { + sampleDepth = deMath.clamp(sampleDepthFloat, 0.0, 1.0); + } + + frag.depthPassed = expression(sampleDepth, depthBufferValue); + } + } + }; + + switch (depthFunc) { + case rrRenderState.TestFunc.NEVER: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return false;}); break; + case rrRenderState.TestFunc.ALWAYS: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return true;}); break; + case rrRenderState.TestFunc.LESS: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth < depthBufferValue;}); break; + case rrRenderState.TestFunc.LEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth <= depthBufferValue;}); break; + case rrRenderState.TestFunc.GREATER: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth > depthBufferValue;}); break; + case rrRenderState.TestFunc.GEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth >= depthBufferValue;}); break; + case rrRenderState.TestFunc.EQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth == depthBufferValue;}); break; + case rrRenderState.TestFunc.NOTEQUAL: sample_register_depth_compare(function(sampleDepth, depthBufferValue) { return sampleDepth != depthBufferValue;}); break; + default: + throw new Error('Unrecognized depth function:' + depthFunc); + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {tcuTexture.PixelBufferAccess} depthBuffer + */ +rrFragmentOperations.executeDepthWrite = function(inputFragments, depthBuffer) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive && frag.depthPassed) { + var fragSampleNdx = 0; + var clampedDepth = deMath.clamp(frag.sampleDepths[fragSampleNdx], 0.0, 1.0); + depthBuffer.setPixDepth(clampedDepth, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + } + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {rrRenderState.StencilState} stencilState + * @param {number} numStencilBits + * @param {tcuTexture.PixelBufferAccess} stencilBuffer + */ +rrFragmentOperations.executeStencilDpFailAndPass = function(inputFragments, stencilState, numStencilBits, stencilBuffer) { + var clampedStencilRef = deMath.clamp(stencilState.ref, 0, (1 << numStencilBits) - 1); + + /** + * @param {function(boolean):boolean} condition + * @param {function(number,number):number} expression + */ + var sample_register_dpfail_or_dppass = function(condition, expression) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive && condition(frag.depthPassed)) { + var fragSampleNdx = 0; + var stencilBufferValue = stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + stencilBuffer.setPixStencil(rrFragmentOperations.maskedBitReplace(stencilBufferValue, expression(stencilBufferValue, numStencilBits), stencilState.writeMask), fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + } + } + }; + + var switch_dpfail_or_dppass = function(op_name, condition) { + switch (stencilState[op_name]) { + case rrRenderState.StencilOp.KEEP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return stencilBufferValue;}); break; + case rrRenderState.StencilOp.ZERO: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return 0;}); break; + case rrRenderState.StencilOp.REPLACE: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return clampedStencilRef;}); break; + case rrRenderState.StencilOp.INCR: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.DECR: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return deMath.clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.INCR_WRAP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (stencilBufferValue + 1) & ((1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.DECR_WRAP: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (stencilBufferValue - 1) & ((1 << numStencilBits) - 1);}); break; + case rrRenderState.StencilOp.INVERT: sample_register_dpfail_or_dppass(condition, function(stencilBufferValue, numStencilBits) { return (~stencilBufferValue) & ((1 << numStencilBits) - 1);}); break; + default: + throw new Error('Unrecognized stencil operation:' + op_name); + } + }; + + var passed = function(depthPassed) { return depthPassed;}; + var failed = function(depthPassed) { return !depthPassed;}; + + switch_dpfail_or_dppass('dpFail', failed); + switch_dpfail_or_dppass('dpPass', passed); +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {Array<number>} blendColor + * @param {rrRenderState.BlendState} blendRGBState + */ +rrFragmentOperations.executeBlendFactorComputeRGB = function(inputFragments, blendColor, blendRGBState) { + /** + * @param {string} factor_name + * @param {function(Array<number>, Array<number>, Array<number>):Array<number>} expression + */ + var sample_register_blend_factor = function(factor_name, expression) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var src = frag.clampedBlendSrcColor; + var src1 = frag.clampedBlendSrc1Color; + var dst = frag.clampedBlendDstColor; + frag[factor_name] = deMath.clampVector(expression(src, src1, dst), 0, 1); + } + } + }; + + var switch_src_or_dst_factor_rgb = function(func_name, factor_name) { + switch (blendRGBState[func_name]) { + case rrRenderState.BlendFunc.ZERO: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [0, 0, 0];}); break; + case rrRenderState.BlendFunc.ONE: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1, 1, 1];}); break; + case rrRenderState.BlendFunc.SRC_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(src, [0, 1, 2]);}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(src, [0, 1, 2]));}); break; + case rrRenderState.BlendFunc.DST_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(dst, [0, 1, 2]);}); break; + case rrRenderState.BlendFunc.ONE_MINUS_DST_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(dst, [0, 1, 2]));}); break; + case rrRenderState.BlendFunc.SRC_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [src[3], src[3], src[3]];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - src[3], 1.0 - src[3], 1.0 - src[3]];}); break; + case rrRenderState.BlendFunc.DST_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [dst[3], dst[3], dst[3]];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_DST_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - dst[3], 1.0 - dst[3], 1.0 - dst[3]];}); break; + case rrRenderState.BlendFunc.CONSTANT_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(blendColor, [0, 1, 2]);}); break; + case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(blendColor, [0, 1, 2]));}); break; + case rrRenderState.BlendFunc.CONSTANT_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [blendColor[3], blendColor[3], blendColor[3]];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - blendColor[3], 1.0 - blendColor[3], 1.0 - blendColor[3]];}); break; + case rrRenderState.BlendFunc.SRC_ALPHA_SATURATE: + 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; + case rrRenderState.BlendFunc.SRC1_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.swizzle(src1, [0, 1, 2]);}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC1_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return deMath.subtract([1, 1, 1], deMath.swizzle(src1, [0, 1, 2]));}); break; + case rrRenderState.BlendFunc.SRC1_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [src1[3], src1[3], src1[3]];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC1_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return [1.0 - src1[3], 1.0 - src1[3], 1.0 - src1[3]];}); break; + default: + throw new Error('Unrecognized blend function:' + func_name); + } + }; + + switch_src_or_dst_factor_rgb('srcFunc', 'blendSrcFactorRGB'); + switch_src_or_dst_factor_rgb('dstFunc', 'blendDstFactorRGB'); + +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {Array<number>} blendColor + * @param {rrRenderState.BlendState} blendAState + */ +rrFragmentOperations.executeBlendFactorComputeA = function(inputFragments, blendColor, blendAState) { + /** + * @param {string} factor_name + * @param {function(Array<number>, Array<number>, Array<number>):number} expression + */ + var sample_register_blend_factor = function(factor_name, expression) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var src = frag.clampedBlendSrcColor; + var src1 = frag.clampedBlendSrc1Color; + var dst = frag.clampedBlendDstColor; + frag[factor_name] = deMath.clamp(expression(src, src1, dst), 0, 1); + } + } + }; + + var swictch_src_or_dst_factor_a = function(func_name, factor_name) { + switch (blendAState[func_name]) { + case rrRenderState.BlendFunc.ZERO: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 0.0;}); break; + case rrRenderState.BlendFunc.ONE: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0;}); break; + case rrRenderState.BlendFunc.SRC_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return src[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src[3];}); break; + case rrRenderState.BlendFunc.DST_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return dst[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_DST_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - dst[3];}); break; + case rrRenderState.BlendFunc.SRC_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return src[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src[3];}); break; + case rrRenderState.BlendFunc.DST_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return dst[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_DST_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - dst[3];}); break; + case rrRenderState.BlendFunc.CONSTANT_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return blendColor[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - blendColor[3];}); break; + case rrRenderState.BlendFunc.CONSTANT_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return blendColor[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_CONSTANT_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - blendColor[3];}); break; + case rrRenderState.BlendFunc.SRC_ALPHA_SATURATE: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0;}); break; + case rrRenderState.BlendFunc.SRC1_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return src1[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC1_COLOR: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src1[3];}); break; + case rrRenderState.BlendFunc.SRC1_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return src1[3];}); break; + case rrRenderState.BlendFunc.ONE_MINUS_SRC1_ALPHA: + sample_register_blend_factor(factor_name, function(src, src1, dst) { return 1.0 - src1[3];}); break; + default: + throw new Error('Unrecognized blend function:' + func_name); + } + }; + + swictch_src_or_dst_factor_a('srcFunc', 'blendSrcFactorA'); + swictch_src_or_dst_factor_a('dstFunc', 'blendDstFactorA'); +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write + * @param {rrRenderState.BlendState} blendRGBState + * @param {rrRenderState.BlendState} blendAState + */ +rrFragmentOperations.executeBlend = function(inputFragments, blendRGBState, blendAState) { + var sample_register_blended_color = function(color_name, expression) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var src = frag.clampedBlendSrcColor; + var dst = frag.clampedBlendDstColor; + frag[color_name] = expression(src, dst, frag); + } + } + }; + + switch (blendRGBState.equation) { + case rrRenderState.BlendEquation.ADD: + 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; + case rrRenderState.BlendEquation.SUBTRACT: + 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; + case rrRenderState.BlendEquation.REVERSE_SUBTRACT: + 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; + case rrRenderState.BlendEquation.MIN: + 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; + case rrRenderState.BlendEquation.MAX: + 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; + default: + throw new Error('Unrecognized blend equation:' + blendRGBState.equation); + } + + switch (blendAState.equation) { + case rrRenderState.BlendEquation.ADD: + sample_register_blended_color('blendedA', function(src, dst, frag) { return src[3] * frag.blendSrcFactorA + dst[3] * frag.blendDstFactorA;}); break; + case rrRenderState.BlendEquation.SUBTRACT: + sample_register_blended_color('blendedA', function(src, dst, frag) { return src[3] * frag.blendSrcFactorA - dst[3] * frag.blendDstFactorA;}); break; + case rrRenderState.BlendEquation.REVERSE_SUBTRACT: + sample_register_blended_color('blendedA', function(src, dst, frag) { return dst[3] * frag.blendDstFactorA - src[3] * frag.blendSrcFactorA;}); break; + case rrRenderState.BlendEquation.MIN: + sample_register_blended_color('blendedA', function(src, dst, frag) { return Math.min(src[3], dst[3]);}); break; + case rrRenderState.BlendEquation.MAX: + sample_register_blended_color('blendedA', function(src, dst, frag) { return Math.max(src[3], dst[3]);}); break; + default: + throw new Error('Unrecognized blend equation:' + blendAState.equation); + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments + * @param {boolean} isSRGB + * @param {tcuTexture.PixelBufferAccess} colorBuffer + */ +rrFragmentOperations.executeColorWrite = function(inputFragments, isSRGB, colorBuffer) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var combinedColor = frag.blendedRGB.slice(); + combinedColor[3] = frag.blendedA; + if (isSRGB) + combinedColor = tcuTextureUtil.linearToSRGB(combinedColor); + + colorBuffer.setPixel(combinedColor, 0, frag.pixelCoord[0], frag.pixelCoord[1]); + } + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments + * @param {Array<boolean>} colorMaskFactor + * @param {Array<boolean>} colorMaskNegationFactor + * @param {boolean} isSRGB + * @param {tcuTexture.PixelBufferAccess} colorBuffer + */ +rrFragmentOperations.executeMaskedColorWrite = function(inputFragments, colorMaskFactor, colorMaskNegationFactor, isSRGB, colorBuffer) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var fragSampleNdx = 0; + var originalColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + var newColor = frag.blendedRGB.slice(); + newColor[3] = frag.blendedA; + + if (isSRGB) + newColor = tcuTextureUtil.linearToSRGB(newColor); + + newColor = deMath.add(deMath.multiply(colorMaskFactor, newColor), deMath.multiply(colorMaskNegationFactor, originalColor)); + + colorBuffer.setPixel(newColor, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + } + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments + * @param {Array<boolean>} colorMask + * @param {tcuTexture.PixelBufferAccess} colorBuffer + */ +rrFragmentOperations.executeSignedValueWrite = function(inputFragments, colorMask, colorBuffer) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var fragSampleNdx = 0; + var originalValue = colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + var newValue = tcuTextureUtil.select(frag.signedValue, originalValue, colorMask); + + colorBuffer.setPixelInt(newValue, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + } + } +}; + +/** + * @param {Array<rrFragmentOperations.Fragment>} inputFragments + * @param {Array<boolean>} colorMask + * @param {tcuTexture.PixelBufferAccess} colorBuffer + */ +rrFragmentOperations.executeUnsignedValueWrite = function(inputFragments, colorMask, colorBuffer) { + for (var i = 0; i < inputFragments.length; i++) { + var frag = inputFragments[i]; + if (frag.isAlive) { + var fragSampleNdx = 0; + var originalValue = colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + var newValue = tcuTextureUtil.select(frag.unsignedValue, originalValue, colorMask); + + colorBuffer.setPixelInt(newValue, fragSampleNdx, frag.pixelCoord[0], frag.pixelCoord[1]); + } + } +}; + +/** + * @constructor + */ +rrFragmentOperations.FragmentProcessor = function() { + /* TODO: implement */ +}; + +}); |