1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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');
28 goog
.scope(function() {
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
;
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
42 rrFragmentOperations
.maskedBitReplace = function(oldValue
, newValue
, mask
) {
43 return (oldValue
& ~mask
) | (newValue
& mask
);
47 * @param {Array<number>} point
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
);
58 * @param {Array<number>} coefficents
59 * @param {Array<number>} coords
60 * @param {number} depth
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? */
85 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
86 * @param {rrRenderState.WindowRectangle} scissorRect
88 rrFragmentOperations
.executeScissorTest = function(inputFragments
, scissorRect
) {
89 for (var i
= 0; i
< inputFragments
.length
; i
++) {
90 var frag
= inputFragments
[i
];
92 if (!rrFragmentOperations
.isInsideRect(frag
.pixelCoord
, scissorRect
))
99 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
100 * @param {rrRenderState.StencilState} stencilState
101 * @param {number} numStencilBits
102 * @param {tcuTexture.PixelBufferAccess} stencilBuffer
104 rrFragmentOperations
.executeStencilCompare = function(inputFragments
, stencilState
, numStencilBits
, stencilBuffer
) {
105 var clampedStencilRef
= deMath
.clamp(stencilState
.ref
, 0, (1 << numStencilBits
) - 1);
108 * @param {function(number=,number=):boolean} expression
110 var sample_register_stencil_compare = function(expression
) {
111 for (var i
= 0; i
< inputFragments
.length
; i
++) {
112 var frag
= inputFragments
[i
];
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
);
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;
133 throw new Error('Unrecognized stencil test function:' + stencilState
.func
);
138 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
139 * @param {rrRenderState.StencilState} stencilState
140 * @param {number} numStencilBits
141 * @param {tcuTexture.PixelBufferAccess} stencilBuffer
143 rrFragmentOperations
.executeStencilSFail = function(inputFragments
, stencilState
, numStencilBits
, stencilBuffer
) {
144 var clampedStencilRef
= deMath
.clamp(stencilState
.ref
, 0, (1 << numStencilBits
) - 1);
146 * @param {function(number,number):number} expression
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;
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;
178 throw new Error('Unrecognized stencil op:' + stencilState
.sFail
);
184 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
185 * @param {rrRenderState.TestFunc} depthFunc
186 * @param {tcuTexture.PixelBufferAccess} depthBuffer
188 rrFragmentOperations
.executeDepthCompare = function(inputFragments
, depthFunc
, depthBuffer
) {
190 * @param {function(number=,number=):boolean} expression
192 var convertToDepthBuffer
= false;
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(),
202 data
: new ArrayBuffer(8)
204 convertToDepthBuffer
= true;
207 var sample_register_depth_compare = function(expression
) {
208 for (var i
= 0; i
< inputFragments
.length
; i
++) {
209 var frag
= inputFragments
[i
];
211 var fragSampleNdx
= 0;
212 var depthBufferValue
= depthBuffer
.getPixDepth(fragSampleNdx
, frag
.pixelCoord
[0], frag
.pixelCoord
[1]);
213 var sampleDepthFloat
= frag
.sampleDepths
[fragSampleNdx
];
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);
221 sampleDepth
= deMath
.clamp(sampleDepthFloat
, 0.0, 1.0);
224 frag
.depthPassed
= expression(sampleDepth
, depthBufferValue
);
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;
239 throw new Error('Unrecognized depth function:' + depthFunc
);
244 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
245 * @param {tcuTexture.PixelBufferAccess} depthBuffer
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]);
259 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
260 * @param {rrRenderState.StencilState} stencilState
261 * @param {number} numStencilBits
262 * @param {tcuTexture.PixelBufferAccess} stencilBuffer
264 rrFragmentOperations
.executeStencilDpFailAndPass = function(inputFragments
, stencilState
, numStencilBits
, stencilBuffer
) {
265 var clampedStencilRef
= deMath
.clamp(stencilState
.ref
, 0, (1 << numStencilBits
) - 1);
268 * @param {function(boolean):boolean} condition
269 * @param {function(number,number):number} expression
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]);
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;
293 throw new Error('Unrecognized stencil operation:' + op_name
);
297 var passed = function(depthPassed
) { return depthPassed
;};
298 var failed = function(depthPassed
) { return !depthPassed
;};
300 switch_dpfail_or_dppass('dpFail', failed
);
301 switch_dpfail_or_dppass('dpPass', passed
);
305 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
306 * @param {Array<number>} blendColor
307 * @param {rrRenderState.BlendState} blendRGBState
309 rrFragmentOperations
.executeBlendFactorComputeRGB = function(inputFragments
, blendColor
, blendRGBState
) {
311 * @param {string} factor_name
312 * @param {function(Array<number>, Array<number>, Array<number>):Array<number>} expression
314 var sample_register_blend_factor = function(factor_name
, expression
) {
315 for (var i
= 0; i
< inputFragments
.length
; i
++) {
316 var frag
= inputFragments
[i
];
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);
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;
367 throw new Error('Unrecognized blend function:' + func_name
);
371 switch_src_or_dst_factor_rgb('srcFunc', 'blendSrcFactorRGB');
372 switch_src_or_dst_factor_rgb('dstFunc', 'blendDstFactorRGB');
377 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
378 * @param {Array<number>} blendColor
379 * @param {rrRenderState.BlendState} blendAState
381 rrFragmentOperations
.executeBlendFactorComputeA = function(inputFragments
, blendColor
, blendAState
) {
383 * @param {string} factor_name
384 * @param {function(Array<number>, Array<number>, Array<number>):number} expression
386 var sample_register_blend_factor = function(factor_name
, expression
) {
387 for (var i
= 0; i
< inputFragments
.length
; i
++) {
388 var frag
= inputFragments
[i
];
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);
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;
439 throw new Error('Unrecognized blend function:' + func_name
);
443 swictch_src_or_dst_factor_a('srcFunc', 'blendSrcFactorA');
444 swictch_src_or_dst_factor_a('dstFunc', 'blendDstFactorA');
448 * @param {Array<rrFragmentOperations.Fragment>} inputFragments Fragments to write
449 * @param {rrRenderState.BlendState} blendRGBState
450 * @param {rrRenderState.BlendState} blendAState
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
];
457 var src
= frag
.clampedBlendSrcColor
;
458 var dst
= frag
.clampedBlendDstColor
;
459 frag
[color_name
] = expression(src
, dst
, frag
);
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;
476 throw new Error('Unrecognized blend equation:' + blendRGBState
.equation
);
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;
491 throw new Error('Unrecognized blend equation:' + blendAState
.equation
);
496 * @param {Array<rrFragmentOperations.Fragment>} inputFragments
497 * @param {boolean} isSRGB
498 * @param {tcuTexture.PixelBufferAccess} colorBuffer
500 rrFragmentOperations
.executeColorWrite = function(inputFragments
, isSRGB
, colorBuffer
) {
501 for (var i
= 0; i
< inputFragments
.length
; i
++) {
502 var frag
= inputFragments
[i
];
504 var combinedColor
= frag
.blendedRGB
.slice();
505 combinedColor
[3] = frag
.blendedA
;
507 combinedColor
= tcuTextureUtil
.linearToSRGB(combinedColor
);
509 colorBuffer
.setPixel(combinedColor
, 0, frag
.pixelCoord
[0], frag
.pixelCoord
[1]);
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
521 rrFragmentOperations
.executeMaskedColorWrite = function(inputFragments
, colorMaskFactor
, colorMaskNegationFactor
, isSRGB
, colorBuffer
) {
522 for (var i
= 0; i
< inputFragments
.length
; i
++) {
523 var frag
= inputFragments
[i
];
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
;
531 newColor
= tcuTextureUtil
.linearToSRGB(newColor
);
533 newColor
= deMath
.add(deMath
.multiply(colorMaskFactor
, newColor
), deMath
.multiply(colorMaskNegationFactor
, originalColor
));
535 colorBuffer
.setPixel(newColor
, fragSampleNdx
, frag
.pixelCoord
[0], frag
.pixelCoord
[1]);
541 * @param {Array<rrFragmentOperations.Fragment>} inputFragments
542 * @param {Array<boolean>} colorMask
543 * @param {tcuTexture.PixelBufferAccess} colorBuffer
545 rrFragmentOperations
.executeSignedValueWrite = function(inputFragments
, colorMask
, colorBuffer
) {
546 for (var i
= 0; i
< inputFragments
.length
; i
++) {
547 var frag
= inputFragments
[i
];
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
);
553 colorBuffer
.setPixelInt(newValue
, fragSampleNdx
, frag
.pixelCoord
[0], frag
.pixelCoord
[1]);
559 * @param {Array<rrFragmentOperations.Fragment>} inputFragments
560 * @param {Array<boolean>} colorMask
561 * @param {tcuTexture.PixelBufferAccess} colorBuffer
563 rrFragmentOperations
.executeUnsignedValueWrite = function(inputFragments
, colorMask
, colorBuffer
) {
564 for (var i
= 0; i
< inputFragments
.length
; i
++) {
565 var frag
= inputFragments
[i
];
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
);
571 colorBuffer
.setPixelInt(newValue
, fragSampleNdx
, frag
.pixelCoord
[0], frag
.pixelCoord
[1]);
579 rrFragmentOperations
.FragmentProcessor = function() {
580 /* TODO: implement */