xref: /aosp_15_r20/external/deqp/framework/referencerenderer/rrFragmentOperations.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Reference Renderer
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Reference implementation for per-fragment operations.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "rrFragmentOperations.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker #include <limits>
28*35238bceSAndroid Build Coastguard Worker 
29*35238bceSAndroid Build Coastguard Worker using de::clamp;
30*35238bceSAndroid Build Coastguard Worker using de::max;
31*35238bceSAndroid Build Coastguard Worker using de::min;
32*35238bceSAndroid Build Coastguard Worker using tcu::clamp;
33*35238bceSAndroid Build Coastguard Worker using tcu::IVec2;
34*35238bceSAndroid Build Coastguard Worker using tcu::IVec4;
35*35238bceSAndroid Build Coastguard Worker using tcu::max;
36*35238bceSAndroid Build Coastguard Worker using tcu::min;
37*35238bceSAndroid Build Coastguard Worker using tcu::UVec4;
38*35238bceSAndroid Build Coastguard Worker using tcu::Vec3;
39*35238bceSAndroid Build Coastguard Worker using tcu::Vec4;
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker namespace rr
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker 
44*35238bceSAndroid Build Coastguard Worker // Return oldValue with the bits indicated by mask replaced by corresponding bits of newValue.
maskedBitReplace(int oldValue,int newValue,uint32_t mask)45*35238bceSAndroid Build Coastguard Worker static inline int maskedBitReplace(int oldValue, int newValue, uint32_t mask)
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker     return (oldValue & ~mask) | (newValue & mask);
48*35238bceSAndroid Build Coastguard Worker }
49*35238bceSAndroid Build Coastguard Worker 
isInsideRect(const IVec2 & point,const WindowRectangle & rect)50*35238bceSAndroid Build Coastguard Worker static inline bool isInsideRect(const IVec2 &point, const WindowRectangle &rect)
51*35238bceSAndroid Build Coastguard Worker {
52*35238bceSAndroid Build Coastguard Worker     return de::inBounds(point.x(), rect.left, rect.left + rect.width) &&
53*35238bceSAndroid Build Coastguard Worker            de::inBounds(point.y(), rect.bottom, rect.bottom + rect.height);
54*35238bceSAndroid Build Coastguard Worker }
55*35238bceSAndroid Build Coastguard Worker 
unpremultiply(const Vec4 & v)56*35238bceSAndroid Build Coastguard Worker static inline Vec4 unpremultiply(const Vec4 &v)
57*35238bceSAndroid Build Coastguard Worker {
58*35238bceSAndroid Build Coastguard Worker     if (v.w() > 0.0f)
59*35238bceSAndroid Build Coastguard Worker         return Vec4(v.x() / v.w(), v.y() / v.w(), v.z() / v.w(), v.w());
60*35238bceSAndroid Build Coastguard Worker     else
61*35238bceSAndroid Build Coastguard Worker     {
62*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(v.x() == 0.0f && v.y() == 0.0f && v.z() == 0.0f);
63*35238bceSAndroid Build Coastguard Worker         return Vec4(0.0f, 0.0f, 0.0f, 0.0f);
64*35238bceSAndroid Build Coastguard Worker     }
65*35238bceSAndroid Build Coastguard Worker }
66*35238bceSAndroid Build Coastguard Worker 
clearMultisampleColorBuffer(const tcu::PixelBufferAccess & dst,const Vec4 & v,const WindowRectangle & r)67*35238bceSAndroid Build Coastguard Worker void clearMultisampleColorBuffer(const tcu::PixelBufferAccess &dst, const Vec4 &v, const WindowRectangle &r)
68*35238bceSAndroid Build Coastguard Worker {
69*35238bceSAndroid Build Coastguard Worker     tcu::clear(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v);
70*35238bceSAndroid Build Coastguard Worker }
clearMultisampleColorBuffer(const tcu::PixelBufferAccess & dst,const IVec4 & v,const WindowRectangle & r)71*35238bceSAndroid Build Coastguard Worker void clearMultisampleColorBuffer(const tcu::PixelBufferAccess &dst, const IVec4 &v, const WindowRectangle &r)
72*35238bceSAndroid Build Coastguard Worker {
73*35238bceSAndroid Build Coastguard Worker     tcu::clear(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v);
74*35238bceSAndroid Build Coastguard Worker }
clearMultisampleColorBuffer(const tcu::PixelBufferAccess & dst,const UVec4 & v,const WindowRectangle & r)75*35238bceSAndroid Build Coastguard Worker void clearMultisampleColorBuffer(const tcu::PixelBufferAccess &dst, const UVec4 &v, const WindowRectangle &r)
76*35238bceSAndroid Build Coastguard Worker {
77*35238bceSAndroid Build Coastguard Worker     tcu::clear(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v.cast<int>());
78*35238bceSAndroid Build Coastguard Worker }
clearMultisampleDepthBuffer(const tcu::PixelBufferAccess & dst,float v,const WindowRectangle & r)79*35238bceSAndroid Build Coastguard Worker void clearMultisampleDepthBuffer(const tcu::PixelBufferAccess &dst, float v, const WindowRectangle &r)
80*35238bceSAndroid Build Coastguard Worker {
81*35238bceSAndroid Build Coastguard Worker     tcu::clearDepth(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v);
82*35238bceSAndroid Build Coastguard Worker }
clearMultisampleStencilBuffer(const tcu::PixelBufferAccess & dst,int v,const WindowRectangle & r)83*35238bceSAndroid Build Coastguard Worker void clearMultisampleStencilBuffer(const tcu::PixelBufferAccess &dst, int v, const WindowRectangle &r)
84*35238bceSAndroid Build Coastguard Worker {
85*35238bceSAndroid Build Coastguard Worker     tcu::clearStencil(tcu::getSubregion(dst, 0, r.left, r.bottom, dst.getWidth(), r.width, r.height), v);
86*35238bceSAndroid Build Coastguard Worker }
87*35238bceSAndroid Build Coastguard Worker 
FragmentProcessor(void)88*35238bceSAndroid Build Coastguard Worker FragmentProcessor::FragmentProcessor(void) : m_sampleRegister()
89*35238bceSAndroid Build Coastguard Worker {
90*35238bceSAndroid Build Coastguard Worker }
91*35238bceSAndroid Build Coastguard Worker 
executeScissorTest(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const WindowRectangle & scissorRect)92*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeScissorTest(int fragNdxOffset, int numSamplesPerFragment, const Fragment *inputFragments,
93*35238bceSAndroid Build Coastguard Worker                                            const WindowRectangle &scissorRect)
94*35238bceSAndroid Build Coastguard Worker {
95*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
96*35238bceSAndroid Build Coastguard Worker     {
97*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)
98*35238bceSAndroid Build Coastguard Worker         {
99*35238bceSAndroid Build Coastguard Worker             int fragNdx = fragNdxOffset + regSampleNdx / numSamplesPerFragment;
100*35238bceSAndroid Build Coastguard Worker 
101*35238bceSAndroid Build Coastguard Worker             if (!isInsideRect(inputFragments[fragNdx].pixelCoord, scissorRect))
102*35238bceSAndroid Build Coastguard Worker                 m_sampleRegister[regSampleNdx].isAlive = false;
103*35238bceSAndroid Build Coastguard Worker         }
104*35238bceSAndroid Build Coastguard Worker     }
105*35238bceSAndroid Build Coastguard Worker }
106*35238bceSAndroid Build Coastguard Worker 
executeStencilCompare(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const StencilState & stencilState,int numStencilBits,const tcu::ConstPixelBufferAccess & stencilBuffer)107*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeStencilCompare(int fragNdxOffset, int numSamplesPerFragment,
108*35238bceSAndroid Build Coastguard Worker                                               const Fragment *inputFragments, const StencilState &stencilState,
109*35238bceSAndroid Build Coastguard Worker                                               int numStencilBits, const tcu::ConstPixelBufferAccess &stencilBuffer)
110*35238bceSAndroid Build Coastguard Worker {
111*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_STENCIL_COMPARE(COMPARE_EXPRESSION)                                              \
112*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)                      \
113*35238bceSAndroid Build Coastguard Worker     {                                                                                                    \
114*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)                                                      \
115*35238bceSAndroid Build Coastguard Worker         {                                                                                                \
116*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;                                 \
117*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment]; \
118*35238bceSAndroid Build Coastguard Worker             int stencilBufferValue =                                                                     \
119*35238bceSAndroid Build Coastguard Worker                 stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());    \
120*35238bceSAndroid Build Coastguard Worker             int maskedRef = stencilState.compMask & clampedStencilRef;                                   \
121*35238bceSAndroid Build Coastguard Worker             int maskedBuf = stencilState.compMask & stencilBufferValue;                                  \
122*35238bceSAndroid Build Coastguard Worker             DE_UNREF(maskedRef);                                                                         \
123*35238bceSAndroid Build Coastguard Worker             DE_UNREF(maskedBuf);                                                                         \
124*35238bceSAndroid Build Coastguard Worker                                                                                                          \
125*35238bceSAndroid Build Coastguard Worker             m_sampleRegister[regSampleNdx].stencilPassed = (COMPARE_EXPRESSION);                         \
126*35238bceSAndroid Build Coastguard Worker         }                                                                                                \
127*35238bceSAndroid Build Coastguard Worker     }
128*35238bceSAndroid Build Coastguard Worker 
129*35238bceSAndroid Build Coastguard Worker     int clampedStencilRef = de::clamp(stencilState.ref, 0, (1 << numStencilBits) - 1);
130*35238bceSAndroid Build Coastguard Worker 
131*35238bceSAndroid Build Coastguard Worker     switch (stencilState.func)
132*35238bceSAndroid Build Coastguard Worker     {
133*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_NEVER:
134*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(false) break;
135*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_ALWAYS:
136*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(true) break;
137*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_LESS:
138*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef < maskedBuf) break;
139*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_LEQUAL:
140*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef <= maskedBuf) break;
141*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_GREATER:
142*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef > maskedBuf) break;
143*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_GEQUAL:
144*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef >= maskedBuf) break;
145*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_EQUAL:
146*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef == maskedBuf) break;
147*35238bceSAndroid Build Coastguard Worker     case TESTFUNC_NOTEQUAL:
148*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_STENCIL_COMPARE(maskedRef != maskedBuf) break;
149*35238bceSAndroid Build Coastguard Worker     default:
150*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
151*35238bceSAndroid Build Coastguard Worker     }
152*35238bceSAndroid Build Coastguard Worker 
153*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_STENCIL_COMPARE
154*35238bceSAndroid Build Coastguard Worker }
155*35238bceSAndroid Build Coastguard Worker 
executeStencilSFail(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const StencilState & stencilState,int numStencilBits,const tcu::PixelBufferAccess & stencilBuffer)156*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeStencilSFail(int fragNdxOffset, int numSamplesPerFragment,
157*35238bceSAndroid Build Coastguard Worker                                             const Fragment *inputFragments, const StencilState &stencilState,
158*35238bceSAndroid Build Coastguard Worker                                             int numStencilBits, const tcu::PixelBufferAccess &stencilBuffer)
159*35238bceSAndroid Build Coastguard Worker {
160*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_SFAIL(SFAIL_EXPRESSION)                                                                  \
161*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)                              \
162*35238bceSAndroid Build Coastguard Worker     {                                                                                                            \
163*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive && !m_sampleRegister[regSampleNdx].stencilPassed)             \
164*35238bceSAndroid Build Coastguard Worker         {                                                                                                        \
165*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;                                         \
166*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];         \
167*35238bceSAndroid Build Coastguard Worker             int stencilBufferValue =                                                                             \
168*35238bceSAndroid Build Coastguard Worker                 stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());            \
169*35238bceSAndroid Build Coastguard Worker                                                                                                                  \
170*35238bceSAndroid Build Coastguard Worker             stencilBuffer.setPixStencil(                                                                         \
171*35238bceSAndroid Build Coastguard Worker                 maskedBitReplace(stencilBufferValue, (SFAIL_EXPRESSION), stencilState.writeMask), fragSampleNdx, \
172*35238bceSAndroid Build Coastguard Worker                 frag.pixelCoord.x(), frag.pixelCoord.y());                                                       \
173*35238bceSAndroid Build Coastguard Worker             m_sampleRegister[regSampleNdx].isAlive = false;                                                      \
174*35238bceSAndroid Build Coastguard Worker         }                                                                                                        \
175*35238bceSAndroid Build Coastguard Worker     }
176*35238bceSAndroid Build Coastguard Worker 
177*35238bceSAndroid Build Coastguard Worker     int clampedStencilRef = de::clamp(stencilState.ref, 0, (1 << numStencilBits) - 1);
178*35238bceSAndroid Build Coastguard Worker 
179*35238bceSAndroid Build Coastguard Worker     switch (stencilState.sFail)
180*35238bceSAndroid Build Coastguard Worker     {
181*35238bceSAndroid Build Coastguard Worker     case STENCILOP_KEEP:
182*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL(stencilBufferValue) break;
183*35238bceSAndroid Build Coastguard Worker     case STENCILOP_ZERO:
184*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL(0) break;
185*35238bceSAndroid Build Coastguard Worker     case STENCILOP_REPLACE:
186*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL(clampedStencilRef) break;
187*35238bceSAndroid Build Coastguard Worker     case STENCILOP_INCR:
188*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL(de::clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1)) break;
189*35238bceSAndroid Build Coastguard Worker     case STENCILOP_DECR:
190*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL(de::clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1)) break;
191*35238bceSAndroid Build Coastguard Worker     case STENCILOP_INCR_WRAP:
192*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL((stencilBufferValue + 1) & ((1 << numStencilBits) - 1)) break;
193*35238bceSAndroid Build Coastguard Worker     case STENCILOP_DECR_WRAP:
194*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL((stencilBufferValue - 1) & ((1 << numStencilBits) - 1)) break;
195*35238bceSAndroid Build Coastguard Worker     case STENCILOP_INVERT:
196*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_SFAIL((~stencilBufferValue) & ((1 << numStencilBits) - 1)) break;
197*35238bceSAndroid Build Coastguard Worker     default:
198*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
199*35238bceSAndroid Build Coastguard Worker     }
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_SFAIL
202*35238bceSAndroid Build Coastguard Worker }
203*35238bceSAndroid Build Coastguard Worker 
executeDepthBoundsTest(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const float minDepthBound,const float maxDepthBound,const tcu::ConstPixelBufferAccess & depthBuffer)204*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeDepthBoundsTest(int fragNdxOffset, int numSamplesPerFragment,
205*35238bceSAndroid Build Coastguard Worker                                                const Fragment *inputFragments, const float minDepthBound,
206*35238bceSAndroid Build Coastguard Worker                                                const float maxDepthBound,
207*35238bceSAndroid Build Coastguard Worker                                                const tcu::ConstPixelBufferAccess &depthBuffer)
208*35238bceSAndroid Build Coastguard Worker {
209*35238bceSAndroid Build Coastguard Worker     if (depthBuffer.getFormat().type == tcu::TextureFormat::FLOAT ||
210*35238bceSAndroid Build Coastguard Worker         depthBuffer.getFormat().type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
211*35238bceSAndroid Build Coastguard Worker     {
212*35238bceSAndroid Build Coastguard Worker         for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; ++regSampleNdx)
213*35238bceSAndroid Build Coastguard Worker         {
214*35238bceSAndroid Build Coastguard Worker             if (m_sampleRegister[regSampleNdx].isAlive)
215*35238bceSAndroid Build Coastguard Worker             {
216*35238bceSAndroid Build Coastguard Worker                 const int fragSampleNdx = regSampleNdx % numSamplesPerFragment;
217*35238bceSAndroid Build Coastguard Worker                 const Fragment &frag    = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
218*35238bceSAndroid Build Coastguard Worker                 const float depthBufferValue =
219*35238bceSAndroid Build Coastguard Worker                     depthBuffer.getPixDepth(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker                 if (!de::inRange(depthBufferValue, minDepthBound, maxDepthBound))
222*35238bceSAndroid Build Coastguard Worker                     m_sampleRegister[regSampleNdx].isAlive = false;
223*35238bceSAndroid Build Coastguard Worker             }
224*35238bceSAndroid Build Coastguard Worker         }
225*35238bceSAndroid Build Coastguard Worker     }
226*35238bceSAndroid Build Coastguard Worker     else
227*35238bceSAndroid Build Coastguard Worker     {
228*35238bceSAndroid Build Coastguard Worker         /* Convert float bounds to target buffer format for comparison */
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker         uint32_t minDepthBoundUint, maxDepthBoundUint;
231*35238bceSAndroid Build Coastguard Worker         {
232*35238bceSAndroid Build Coastguard Worker             uint32_t buffer[2];
233*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(sizeof(buffer) >= (size_t)depthBuffer.getFormat().getPixelSize());
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker             tcu::PixelBufferAccess access(depthBuffer.getFormat(), 1, 1, 1, &buffer);
236*35238bceSAndroid Build Coastguard Worker             access.setPixDepth(minDepthBound, 0, 0, 0);
237*35238bceSAndroid Build Coastguard Worker             minDepthBoundUint = access.getPixelUint(0, 0, 0).x();
238*35238bceSAndroid Build Coastguard Worker         }
239*35238bceSAndroid Build Coastguard Worker         {
240*35238bceSAndroid Build Coastguard Worker             uint32_t buffer[2];
241*35238bceSAndroid Build Coastguard Worker 
242*35238bceSAndroid Build Coastguard Worker             tcu::PixelBufferAccess access(depthBuffer.getFormat(), 1, 1, 1, &buffer);
243*35238bceSAndroid Build Coastguard Worker             access.setPixDepth(maxDepthBound, 0, 0, 0);
244*35238bceSAndroid Build Coastguard Worker             maxDepthBoundUint = access.getPixelUint(0, 0, 0).x();
245*35238bceSAndroid Build Coastguard Worker         }
246*35238bceSAndroid Build Coastguard Worker 
247*35238bceSAndroid Build Coastguard Worker         for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; ++regSampleNdx)
248*35238bceSAndroid Build Coastguard Worker         {
249*35238bceSAndroid Build Coastguard Worker             if (m_sampleRegister[regSampleNdx].isAlive)
250*35238bceSAndroid Build Coastguard Worker             {
251*35238bceSAndroid Build Coastguard Worker                 const int fragSampleNdx = regSampleNdx % numSamplesPerFragment;
252*35238bceSAndroid Build Coastguard Worker                 const Fragment &frag    = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
253*35238bceSAndroid Build Coastguard Worker                 const uint32_t depthBufferValue =
254*35238bceSAndroid Build Coastguard Worker                     depthBuffer.getPixelUint(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()).x();
255*35238bceSAndroid Build Coastguard Worker 
256*35238bceSAndroid Build Coastguard Worker                 if (!de::inRange(depthBufferValue, minDepthBoundUint, maxDepthBoundUint))
257*35238bceSAndroid Build Coastguard Worker                     m_sampleRegister[regSampleNdx].isAlive = false;
258*35238bceSAndroid Build Coastguard Worker             }
259*35238bceSAndroid Build Coastguard Worker         }
260*35238bceSAndroid Build Coastguard Worker     }
261*35238bceSAndroid Build Coastguard Worker }
262*35238bceSAndroid Build Coastguard Worker 
executeDepthCompare(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,TestFunc depthFunc,const tcu::ConstPixelBufferAccess & depthBuffer)263*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeDepthCompare(int fragNdxOffset, int numSamplesPerFragment,
264*35238bceSAndroid Build Coastguard Worker                                             const Fragment *inputFragments, TestFunc depthFunc,
265*35238bceSAndroid Build Coastguard Worker                                             const tcu::ConstPixelBufferAccess &depthBuffer)
266*35238bceSAndroid Build Coastguard Worker {
267*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_DEPTH_COMPARE_F(COMPARE_EXPRESSION)                                                            \
268*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)                                    \
269*35238bceSAndroid Build Coastguard Worker     {                                                                                                                  \
270*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)                                                                    \
271*35238bceSAndroid Build Coastguard Worker         {                                                                                                              \
272*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx      = regSampleNdx % numSamplesPerFragment;                                             \
273*35238bceSAndroid Build Coastguard Worker             const Fragment &frag   = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];             \
274*35238bceSAndroid Build Coastguard Worker             float depthBufferValue = depthBuffer.getPixDepth(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()); \
275*35238bceSAndroid Build Coastguard Worker             float sampleDepthFloat = frag.sampleDepths[fragSampleNdx];                                                 \
276*35238bceSAndroid Build Coastguard Worker             float sampleDepth      = de::clamp(sampleDepthFloat, 0.0f, 1.0f);                                          \
277*35238bceSAndroid Build Coastguard Worker                                                                                                                        \
278*35238bceSAndroid Build Coastguard Worker             m_sampleRegister[regSampleNdx].depthPassed = (COMPARE_EXPRESSION);                                         \
279*35238bceSAndroid Build Coastguard Worker                                                                                                                        \
280*35238bceSAndroid Build Coastguard Worker             DE_UNREF(depthBufferValue);                                                                                \
281*35238bceSAndroid Build Coastguard Worker             DE_UNREF(sampleDepth);                                                                                     \
282*35238bceSAndroid Build Coastguard Worker         }                                                                                                              \
283*35238bceSAndroid Build Coastguard Worker     }
284*35238bceSAndroid Build Coastguard Worker 
285*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_DEPTH_COMPARE_UI(COMPARE_EXPRESSION)                                             \
286*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)                      \
287*35238bceSAndroid Build Coastguard Worker     {                                                                                                    \
288*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)                                                      \
289*35238bceSAndroid Build Coastguard Worker         {                                                                                                \
290*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;                                 \
291*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment]; \
292*35238bceSAndroid Build Coastguard Worker             uint32_t depthBufferValue =                                                                  \
293*35238bceSAndroid Build Coastguard Worker                 depthBuffer.getPixelUint(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y()).x();   \
294*35238bceSAndroid Build Coastguard Worker             float sampleDepthFloat = frag.sampleDepths[fragSampleNdx];                                   \
295*35238bceSAndroid Build Coastguard Worker                                                                                                          \
296*35238bceSAndroid Build Coastguard Worker             /* Convert input float to target buffer format for comparison */                             \
297*35238bceSAndroid Build Coastguard Worker                                                                                                          \
298*35238bceSAndroid Build Coastguard Worker             uint32_t buffer[2];                                                                          \
299*35238bceSAndroid Build Coastguard Worker                                                                                                          \
300*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(sizeof(buffer) >= (size_t)depthBuffer.getFormat().getPixelSize());                 \
301*35238bceSAndroid Build Coastguard Worker                                                                                                          \
302*35238bceSAndroid Build Coastguard Worker             tcu::PixelBufferAccess access(depthBuffer.getFormat(), 1, 1, 1, &buffer);                    \
303*35238bceSAndroid Build Coastguard Worker             access.setPixDepth(sampleDepthFloat, 0, 0, 0);                                               \
304*35238bceSAndroid Build Coastguard Worker             uint32_t sampleDepth = access.getPixelUint(0, 0, 0).x();                                     \
305*35238bceSAndroid Build Coastguard Worker                                                                                                          \
306*35238bceSAndroid Build Coastguard Worker             m_sampleRegister[regSampleNdx].depthPassed = (COMPARE_EXPRESSION);                           \
307*35238bceSAndroid Build Coastguard Worker                                                                                                          \
308*35238bceSAndroid Build Coastguard Worker             DE_UNREF(depthBufferValue);                                                                  \
309*35238bceSAndroid Build Coastguard Worker             DE_UNREF(sampleDepth);                                                                       \
310*35238bceSAndroid Build Coastguard Worker         }                                                                                                \
311*35238bceSAndroid Build Coastguard Worker     }
312*35238bceSAndroid Build Coastguard Worker 
313*35238bceSAndroid Build Coastguard Worker     if (depthBuffer.getFormat().type == tcu::TextureFormat::FLOAT ||
314*35238bceSAndroid Build Coastguard Worker         depthBuffer.getFormat().type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
315*35238bceSAndroid Build Coastguard Worker     {
316*35238bceSAndroid Build Coastguard Worker 
317*35238bceSAndroid Build Coastguard Worker         switch (depthFunc)
318*35238bceSAndroid Build Coastguard Worker         {
319*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_NEVER:
320*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(false) break;
321*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_ALWAYS:
322*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(true) break;
323*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_LESS:
324*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth < depthBufferValue) break;
325*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_LEQUAL:
326*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth <= depthBufferValue) break;
327*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_GREATER:
328*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth > depthBufferValue) break;
329*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_GEQUAL:
330*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth >= depthBufferValue) break;
331*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_EQUAL:
332*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth == depthBufferValue) break;
333*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_NOTEQUAL:
334*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_F(sampleDepth != depthBufferValue) break;
335*35238bceSAndroid Build Coastguard Worker         default:
336*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
337*35238bceSAndroid Build Coastguard Worker         }
338*35238bceSAndroid Build Coastguard Worker     }
339*35238bceSAndroid Build Coastguard Worker     else
340*35238bceSAndroid Build Coastguard Worker     {
341*35238bceSAndroid Build Coastguard Worker         switch (depthFunc)
342*35238bceSAndroid Build Coastguard Worker         {
343*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_NEVER:
344*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(false) break;
345*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_ALWAYS:
346*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(true) break;
347*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_LESS:
348*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth < depthBufferValue) break;
349*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_LEQUAL:
350*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth <= depthBufferValue) break;
351*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_GREATER:
352*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth > depthBufferValue) break;
353*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_GEQUAL:
354*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth >= depthBufferValue) break;
355*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_EQUAL:
356*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth == depthBufferValue) break;
357*35238bceSAndroid Build Coastguard Worker         case TESTFUNC_NOTEQUAL:
358*35238bceSAndroid Build Coastguard Worker             SAMPLE_REGISTER_DEPTH_COMPARE_UI(sampleDepth != depthBufferValue) break;
359*35238bceSAndroid Build Coastguard Worker         default:
360*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
361*35238bceSAndroid Build Coastguard Worker         }
362*35238bceSAndroid Build Coastguard Worker     }
363*35238bceSAndroid Build Coastguard Worker 
364*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_DEPTH_COMPARE_F
365*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_DEPTH_COMPARE_UI
366*35238bceSAndroid Build Coastguard Worker }
367*35238bceSAndroid Build Coastguard Worker 
executeDepthWrite(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const tcu::PixelBufferAccess & depthBuffer)368*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeDepthWrite(int fragNdxOffset, int numSamplesPerFragment, const Fragment *inputFragments,
369*35238bceSAndroid Build Coastguard Worker                                           const tcu::PixelBufferAccess &depthBuffer)
370*35238bceSAndroid Build Coastguard Worker {
371*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
372*35238bceSAndroid Build Coastguard Worker     {
373*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive && m_sampleRegister[regSampleNdx].depthPassed)
374*35238bceSAndroid Build Coastguard Worker         {
375*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx        = regSampleNdx % numSamplesPerFragment;
376*35238bceSAndroid Build Coastguard Worker             const Fragment &frag     = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
377*35238bceSAndroid Build Coastguard Worker             const float clampedDepth = de::clamp(frag.sampleDepths[fragSampleNdx], 0.0f, 1.0f);
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker             depthBuffer.setPixDepth(clampedDepth, fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
380*35238bceSAndroid Build Coastguard Worker         }
381*35238bceSAndroid Build Coastguard Worker     }
382*35238bceSAndroid Build Coastguard Worker }
383*35238bceSAndroid Build Coastguard Worker 
executeStencilDpFailAndPass(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const StencilState & stencilState,int numStencilBits,const tcu::PixelBufferAccess & stencilBuffer)384*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeStencilDpFailAndPass(int fragNdxOffset, int numSamplesPerFragment,
385*35238bceSAndroid Build Coastguard Worker                                                     const Fragment *inputFragments, const StencilState &stencilState,
386*35238bceSAndroid Build Coastguard Worker                                                     int numStencilBits, const tcu::PixelBufferAccess &stencilBuffer)
387*35238bceSAndroid Build Coastguard Worker {
388*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, EXPRESSION)                                                     \
389*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)                                 \
390*35238bceSAndroid Build Coastguard Worker     {                                                                                                               \
391*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive && (CONDITION))                                                  \
392*35238bceSAndroid Build Coastguard Worker         {                                                                                                           \
393*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;                                            \
394*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];            \
395*35238bceSAndroid Build Coastguard Worker             int stencilBufferValue =                                                                                \
396*35238bceSAndroid Build Coastguard Worker                 stencilBuffer.getPixStencil(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());               \
397*35238bceSAndroid Build Coastguard Worker                                                                                                                     \
398*35238bceSAndroid Build Coastguard Worker             stencilBuffer.setPixStencil(maskedBitReplace(stencilBufferValue, (EXPRESSION), stencilState.writeMask), \
399*35238bceSAndroid Build Coastguard Worker                                         fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());                   \
400*35238bceSAndroid Build Coastguard Worker         }                                                                                                           \
401*35238bceSAndroid Build Coastguard Worker     }
402*35238bceSAndroid Build Coastguard Worker 
403*35238bceSAndroid Build Coastguard Worker #define SWITCH_DPFAIL_OR_DPPASS(OP_NAME, CONDITION)                                                                  \
404*35238bceSAndroid Build Coastguard Worker     switch (stencilState.OP_NAME)                                                                                    \
405*35238bceSAndroid Build Coastguard Worker     {                                                                                                                \
406*35238bceSAndroid Build Coastguard Worker     case STENCILOP_KEEP:                                                                                             \
407*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, stencilBufferValue) break;                                       \
408*35238bceSAndroid Build Coastguard Worker     case STENCILOP_ZERO:                                                                                             \
409*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, 0) break;                                                        \
410*35238bceSAndroid Build Coastguard Worker     case STENCILOP_REPLACE:                                                                                          \
411*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, clampedStencilRef) break;                                        \
412*35238bceSAndroid Build Coastguard Worker     case STENCILOP_INCR:                                                                                             \
413*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, de::clamp(stencilBufferValue + 1, 0, (1 << numStencilBits) - 1)) \
414*35238bceSAndroid Build Coastguard Worker         break;                                                                                                       \
415*35238bceSAndroid Build Coastguard Worker     case STENCILOP_DECR:                                                                                             \
416*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, de::clamp(stencilBufferValue - 1, 0, (1 << numStencilBits) - 1)) \
417*35238bceSAndroid Build Coastguard Worker         break;                                                                                                       \
418*35238bceSAndroid Build Coastguard Worker     case STENCILOP_INCR_WRAP:                                                                                        \
419*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, (stencilBufferValue + 1) & ((1 << numStencilBits) - 1)) break;   \
420*35238bceSAndroid Build Coastguard Worker     case STENCILOP_DECR_WRAP:                                                                                        \
421*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, (stencilBufferValue - 1) & ((1 << numStencilBits) - 1)) break;   \
422*35238bceSAndroid Build Coastguard Worker     case STENCILOP_INVERT:                                                                                           \
423*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_DPFAIL_OR_DPPASS(CONDITION, (~stencilBufferValue) & ((1 << numStencilBits) - 1)) break;      \
424*35238bceSAndroid Build Coastguard Worker     default:                                                                                                         \
425*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);                                                                                            \
426*35238bceSAndroid Build Coastguard Worker     }
427*35238bceSAndroid Build Coastguard Worker 
428*35238bceSAndroid Build Coastguard Worker     int clampedStencilRef = de::clamp(stencilState.ref, 0, (1 << numStencilBits) - 1);
429*35238bceSAndroid Build Coastguard Worker 
430*35238bceSAndroid Build Coastguard Worker     SWITCH_DPFAIL_OR_DPPASS(dpFail, !m_sampleRegister[regSampleNdx].depthPassed)
431*35238bceSAndroid Build Coastguard Worker     SWITCH_DPFAIL_OR_DPPASS(dpPass, m_sampleRegister[regSampleNdx].depthPassed)
432*35238bceSAndroid Build Coastguard Worker 
433*35238bceSAndroid Build Coastguard Worker #undef SWITCH_DPFAIL_OR_DPPASS
434*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_DPFAIL_OR_DPPASS
435*35238bceSAndroid Build Coastguard Worker }
436*35238bceSAndroid Build Coastguard Worker 
executeBlendFactorComputeRGB(const Vec4 & blendColor,const BlendState & blendRGBState)437*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeBlendFactorComputeRGB(const Vec4 &blendColor, const BlendState &blendRGBState)
438*35238bceSAndroid Build Coastguard Worker {
439*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION)                 \
440*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)  \
441*35238bceSAndroid Build Coastguard Worker     {                                                                                \
442*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)                                  \
443*35238bceSAndroid Build Coastguard Worker         {                                                                            \
444*35238bceSAndroid Build Coastguard Worker             const Vec4 &src  = m_sampleRegister[regSampleNdx].clampedBlendSrcColor;  \
445*35238bceSAndroid Build Coastguard Worker             const Vec4 &src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \
446*35238bceSAndroid Build Coastguard Worker             const Vec4 &dst  = m_sampleRegister[regSampleNdx].clampedBlendDstColor;  \
447*35238bceSAndroid Build Coastguard Worker             DE_UNREF(src);                                                           \
448*35238bceSAndroid Build Coastguard Worker             DE_UNREF(src1);                                                          \
449*35238bceSAndroid Build Coastguard Worker             DE_UNREF(dst);                                                           \
450*35238bceSAndroid Build Coastguard Worker                                                                                      \
451*35238bceSAndroid Build Coastguard Worker             m_sampleRegister[regSampleNdx].FACTOR_NAME = (FACTOR_EXPRESSION);        \
452*35238bceSAndroid Build Coastguard Worker         }                                                                            \
453*35238bceSAndroid Build Coastguard Worker     }
454*35238bceSAndroid Build Coastguard Worker 
455*35238bceSAndroid Build Coastguard Worker #define SWITCH_SRC_OR_DST_FACTOR_RGB(FUNC_NAME, FACTOR_NAME)                                       \
456*35238bceSAndroid Build Coastguard Worker     switch (blendRGBState.FUNC_NAME)                                                               \
457*35238bceSAndroid Build Coastguard Worker     {                                                                                              \
458*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ZERO:                                                                           \
459*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(0.0f)) break;                               \
460*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE:                                                                            \
461*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f)) break;                               \
462*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC_COLOR:                                                                      \
463*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src.swizzle(0, 1, 2)) break;                     \
464*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC_COLOR:                                                            \
465*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - src.swizzle(0, 1, 2)) break;        \
466*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_DST_COLOR:                                                                      \
467*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, dst.swizzle(0, 1, 2)) break;                     \
468*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_DST_COLOR:                                                            \
469*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - dst.swizzle(0, 1, 2)) break;        \
470*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC_ALPHA:                                                                      \
471*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(src.w())) break;                            \
472*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC_ALPHA:                                                            \
473*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - src.w())) break;                     \
474*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_DST_ALPHA:                                                                      \
475*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(dst.w())) break;                            \
476*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_DST_ALPHA:                                                            \
477*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - dst.w())) break;                     \
478*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_CONSTANT_COLOR:                                                                 \
479*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, blendColor.swizzle(0, 1, 2)) break;              \
480*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_CONSTANT_COLOR:                                                       \
481*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - blendColor.swizzle(0, 1, 2)) break; \
482*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_CONSTANT_ALPHA:                                                                 \
483*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(blendColor.w())) break;                     \
484*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_CONSTANT_ALPHA:                                                       \
485*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - blendColor.w())) break;              \
486*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC_ALPHA_SATURATE:                                                             \
487*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(de::min(src.w(), 1.0f - dst.w()))) break;   \
488*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC1_COLOR:                                                                     \
489*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src1.swizzle(0, 1, 2)) break;                    \
490*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC1_COLOR:                                                           \
491*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f) - src1.swizzle(0, 1, 2)) break;       \
492*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC1_ALPHA:                                                                     \
493*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(src1.w())) break;                           \
494*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC1_ALPHA:                                                           \
495*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, Vec3(1.0f - src1.w())) break;                    \
496*35238bceSAndroid Build Coastguard Worker     default:                                                                                       \
497*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);                                                                          \
498*35238bceSAndroid Build Coastguard Worker     }
499*35238bceSAndroid Build Coastguard Worker 
500*35238bceSAndroid Build Coastguard Worker     SWITCH_SRC_OR_DST_FACTOR_RGB(srcFunc, blendSrcFactorRGB)
501*35238bceSAndroid Build Coastguard Worker     SWITCH_SRC_OR_DST_FACTOR_RGB(dstFunc, blendDstFactorRGB)
502*35238bceSAndroid Build Coastguard Worker 
503*35238bceSAndroid Build Coastguard Worker #undef SWITCH_SRC_OR_DST_FACTOR_RGB
504*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_BLEND_FACTOR
505*35238bceSAndroid Build Coastguard Worker }
506*35238bceSAndroid Build Coastguard Worker 
executeBlendFactorComputeA(const Vec4 & blendColor,const BlendState & blendAState)507*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeBlendFactorComputeA(const Vec4 &blendColor, const BlendState &blendAState)
508*35238bceSAndroid Build Coastguard Worker {
509*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, FACTOR_EXPRESSION)                 \
510*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)  \
511*35238bceSAndroid Build Coastguard Worker     {                                                                                \
512*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)                                  \
513*35238bceSAndroid Build Coastguard Worker         {                                                                            \
514*35238bceSAndroid Build Coastguard Worker             const Vec4 &src  = m_sampleRegister[regSampleNdx].clampedBlendSrcColor;  \
515*35238bceSAndroid Build Coastguard Worker             const Vec4 &src1 = m_sampleRegister[regSampleNdx].clampedBlendSrc1Color; \
516*35238bceSAndroid Build Coastguard Worker             const Vec4 &dst  = m_sampleRegister[regSampleNdx].clampedBlendDstColor;  \
517*35238bceSAndroid Build Coastguard Worker             DE_UNREF(src);                                                           \
518*35238bceSAndroid Build Coastguard Worker             DE_UNREF(src1);                                                          \
519*35238bceSAndroid Build Coastguard Worker             DE_UNREF(dst);                                                           \
520*35238bceSAndroid Build Coastguard Worker                                                                                      \
521*35238bceSAndroid Build Coastguard Worker             m_sampleRegister[regSampleNdx].FACTOR_NAME = (FACTOR_EXPRESSION);        \
522*35238bceSAndroid Build Coastguard Worker         }                                                                            \
523*35238bceSAndroid Build Coastguard Worker     }
524*35238bceSAndroid Build Coastguard Worker 
525*35238bceSAndroid Build Coastguard Worker #define SWITCH_SRC_OR_DST_FACTOR_A(FUNC_NAME, FACTOR_NAME)                      \
526*35238bceSAndroid Build Coastguard Worker     switch (blendAState.FUNC_NAME)                                              \
527*35238bceSAndroid Build Coastguard Worker     {                                                                           \
528*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ZERO:                                                        \
529*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 0.0f) break;                  \
530*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE:                                                         \
531*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f) break;                  \
532*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC_COLOR:                                                   \
533*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src.w()) break;               \
534*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC_COLOR:                                         \
535*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src.w()) break;        \
536*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_DST_COLOR:                                                   \
537*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, dst.w()) break;               \
538*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_DST_COLOR:                                         \
539*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - dst.w()) break;        \
540*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC_ALPHA:                                                   \
541*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src.w()) break;               \
542*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC_ALPHA:                                         \
543*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src.w()) break;        \
544*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_DST_ALPHA:                                                   \
545*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, dst.w()) break;               \
546*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_DST_ALPHA:                                         \
547*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - dst.w()) break;        \
548*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_CONSTANT_COLOR:                                              \
549*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, blendColor.w()) break;        \
550*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_CONSTANT_COLOR:                                    \
551*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - blendColor.w()) break; \
552*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_CONSTANT_ALPHA:                                              \
553*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, blendColor.w()) break;        \
554*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_CONSTANT_ALPHA:                                    \
555*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - blendColor.w()) break; \
556*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC_ALPHA_SATURATE:                                          \
557*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f) break;                  \
558*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC1_COLOR:                                                  \
559*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src1.w()) break;              \
560*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC1_COLOR:                                        \
561*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src1.w()) break;       \
562*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_SRC1_ALPHA:                                                  \
563*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, src1.w()) break;              \
564*35238bceSAndroid Build Coastguard Worker     case BLENDFUNC_ONE_MINUS_SRC1_ALPHA:                                        \
565*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLEND_FACTOR(FACTOR_NAME, 1.0f - src1.w()) break;       \
566*35238bceSAndroid Build Coastguard Worker     default:                                                                    \
567*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);                                                       \
568*35238bceSAndroid Build Coastguard Worker     }
569*35238bceSAndroid Build Coastguard Worker 
570*35238bceSAndroid Build Coastguard Worker     SWITCH_SRC_OR_DST_FACTOR_A(srcFunc, blendSrcFactorA)
571*35238bceSAndroid Build Coastguard Worker     SWITCH_SRC_OR_DST_FACTOR_A(dstFunc, blendDstFactorA)
572*35238bceSAndroid Build Coastguard Worker 
573*35238bceSAndroid Build Coastguard Worker #undef SWITCH_SRC_OR_DST_FACTOR_A
574*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_BLEND_FACTOR
575*35238bceSAndroid Build Coastguard Worker }
576*35238bceSAndroid Build Coastguard Worker 
executeBlend(const BlendState & blendRGBState,const BlendState & blendAState)577*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeBlend(const BlendState &blendRGBState, const BlendState &blendAState)
578*35238bceSAndroid Build Coastguard Worker {
579*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_BLENDED_COLOR(COLOR_NAME, COLOR_EXPRESSION)                 \
580*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \
581*35238bceSAndroid Build Coastguard Worker     {                                                                               \
582*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)                                 \
583*35238bceSAndroid Build Coastguard Worker         {                                                                           \
584*35238bceSAndroid Build Coastguard Worker             SampleData &sample   = m_sampleRegister[regSampleNdx];                  \
585*35238bceSAndroid Build Coastguard Worker             const Vec4 &srcColor = sample.clampedBlendSrcColor;                     \
586*35238bceSAndroid Build Coastguard Worker             const Vec4 &dstColor = sample.clampedBlendDstColor;                     \
587*35238bceSAndroid Build Coastguard Worker                                                                                     \
588*35238bceSAndroid Build Coastguard Worker             sample.COLOR_NAME = (COLOR_EXPRESSION);                                 \
589*35238bceSAndroid Build Coastguard Worker         }                                                                           \
590*35238bceSAndroid Build Coastguard Worker     }
591*35238bceSAndroid Build Coastguard Worker 
592*35238bceSAndroid Build Coastguard Worker     switch (blendRGBState.equation)
593*35238bceSAndroid Build Coastguard Worker     {
594*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADD:
595*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, srcColor.swizzle(0, 1, 2) * sample.blendSrcFactorRGB +
596*35238bceSAndroid Build Coastguard Worker                                                       dstColor.swizzle(0, 1, 2) * sample.blendDstFactorRGB)
597*35238bceSAndroid Build Coastguard Worker         break;
598*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_SUBTRACT:
599*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, srcColor.swizzle(0, 1, 2) * sample.blendSrcFactorRGB -
600*35238bceSAndroid Build Coastguard Worker                                                       dstColor.swizzle(0, 1, 2) * sample.blendDstFactorRGB)
601*35238bceSAndroid Build Coastguard Worker         break;
602*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_REVERSE_SUBTRACT:
603*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, dstColor.swizzle(0, 1, 2) * sample.blendDstFactorRGB -
604*35238bceSAndroid Build Coastguard Worker                                                       srcColor.swizzle(0, 1, 2) * sample.blendSrcFactorRGB)
605*35238bceSAndroid Build Coastguard Worker         break;
606*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_MIN:
607*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, min(srcColor.swizzle(0, 1, 2), dstColor.swizzle(0, 1, 2))) break;
608*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_MAX:
609*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedRGB, max(srcColor.swizzle(0, 1, 2), dstColor.swizzle(0, 1, 2))) break;
610*35238bceSAndroid Build Coastguard Worker     default:
611*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
612*35238bceSAndroid Build Coastguard Worker     }
613*35238bceSAndroid Build Coastguard Worker 
614*35238bceSAndroid Build Coastguard Worker     switch (blendAState.equation)
615*35238bceSAndroid Build Coastguard Worker     {
616*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADD:
617*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedA,
618*35238bceSAndroid Build Coastguard Worker                                       srcColor.w() * sample.blendSrcFactorA + dstColor.w() * sample.blendDstFactorA)
619*35238bceSAndroid Build Coastguard Worker         break;
620*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_SUBTRACT:
621*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedA,
622*35238bceSAndroid Build Coastguard Worker                                       srcColor.w() * sample.blendSrcFactorA - dstColor.w() * sample.blendDstFactorA)
623*35238bceSAndroid Build Coastguard Worker         break;
624*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_REVERSE_SUBTRACT:
625*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedA,
626*35238bceSAndroid Build Coastguard Worker                                       dstColor.w() * sample.blendDstFactorA - srcColor.w() * sample.blendSrcFactorA)
627*35238bceSAndroid Build Coastguard Worker         break;
628*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_MIN:
629*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedA, min(srcColor.w(), dstColor.w())) break;
630*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_MAX:
631*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_BLENDED_COLOR(blendedA, max(srcColor.w(), dstColor.w())) break;
632*35238bceSAndroid Build Coastguard Worker     default:
633*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
634*35238bceSAndroid Build Coastguard Worker     }
635*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_BLENDED_COLOR
636*35238bceSAndroid Build Coastguard Worker }
637*35238bceSAndroid Build Coastguard Worker 
638*35238bceSAndroid Build Coastguard Worker namespace advblend
639*35238bceSAndroid Build Coastguard Worker {
640*35238bceSAndroid Build Coastguard Worker 
multiply(float src,float dst)641*35238bceSAndroid Build Coastguard Worker inline float multiply(float src, float dst)
642*35238bceSAndroid Build Coastguard Worker {
643*35238bceSAndroid Build Coastguard Worker     return src * dst;
644*35238bceSAndroid Build Coastguard Worker }
screen(float src,float dst)645*35238bceSAndroid Build Coastguard Worker inline float screen(float src, float dst)
646*35238bceSAndroid Build Coastguard Worker {
647*35238bceSAndroid Build Coastguard Worker     return src + dst - src * dst;
648*35238bceSAndroid Build Coastguard Worker }
darken(float src,float dst)649*35238bceSAndroid Build Coastguard Worker inline float darken(float src, float dst)
650*35238bceSAndroid Build Coastguard Worker {
651*35238bceSAndroid Build Coastguard Worker     return de::min(src, dst);
652*35238bceSAndroid Build Coastguard Worker }
lighten(float src,float dst)653*35238bceSAndroid Build Coastguard Worker inline float lighten(float src, float dst)
654*35238bceSAndroid Build Coastguard Worker {
655*35238bceSAndroid Build Coastguard Worker     return de::max(src, dst);
656*35238bceSAndroid Build Coastguard Worker }
difference(float src,float dst)657*35238bceSAndroid Build Coastguard Worker inline float difference(float src, float dst)
658*35238bceSAndroid Build Coastguard Worker {
659*35238bceSAndroid Build Coastguard Worker     return de::abs(dst - src);
660*35238bceSAndroid Build Coastguard Worker }
exclusion(float src,float dst)661*35238bceSAndroid Build Coastguard Worker inline float exclusion(float src, float dst)
662*35238bceSAndroid Build Coastguard Worker {
663*35238bceSAndroid Build Coastguard Worker     return src + dst - 2.0f * src * dst;
664*35238bceSAndroid Build Coastguard Worker }
665*35238bceSAndroid Build Coastguard Worker 
overlay(float src,float dst)666*35238bceSAndroid Build Coastguard Worker inline float overlay(float src, float dst)
667*35238bceSAndroid Build Coastguard Worker {
668*35238bceSAndroid Build Coastguard Worker     if (dst <= 0.5f)
669*35238bceSAndroid Build Coastguard Worker         return 2.0f * src * dst;
670*35238bceSAndroid Build Coastguard Worker     else
671*35238bceSAndroid Build Coastguard Worker         return 1.0f - 2.0f * (1.0f - src) * (1.0f - dst);
672*35238bceSAndroid Build Coastguard Worker }
673*35238bceSAndroid Build Coastguard Worker 
colordodge(float src,float dst)674*35238bceSAndroid Build Coastguard Worker inline float colordodge(float src, float dst)
675*35238bceSAndroid Build Coastguard Worker {
676*35238bceSAndroid Build Coastguard Worker     if (dst <= 0.0f)
677*35238bceSAndroid Build Coastguard Worker         return 0.0f;
678*35238bceSAndroid Build Coastguard Worker     else if (src < 1.0f)
679*35238bceSAndroid Build Coastguard Worker         return de::min(1.0f, dst / (1.0f - src));
680*35238bceSAndroid Build Coastguard Worker     else
681*35238bceSAndroid Build Coastguard Worker         return 1.0f;
682*35238bceSAndroid Build Coastguard Worker }
683*35238bceSAndroid Build Coastguard Worker 
colorburn(float src,float dst)684*35238bceSAndroid Build Coastguard Worker inline float colorburn(float src, float dst)
685*35238bceSAndroid Build Coastguard Worker {
686*35238bceSAndroid Build Coastguard Worker     if (dst >= 1.0f)
687*35238bceSAndroid Build Coastguard Worker         return 1.0f;
688*35238bceSAndroid Build Coastguard Worker     else if (src > 0.0f)
689*35238bceSAndroid Build Coastguard Worker         return 1.0f - de::min(1.0f, (1.0f - dst) / src);
690*35238bceSAndroid Build Coastguard Worker     else
691*35238bceSAndroid Build Coastguard Worker         return 0.0f;
692*35238bceSAndroid Build Coastguard Worker }
693*35238bceSAndroid Build Coastguard Worker 
hardlight(float src,float dst)694*35238bceSAndroid Build Coastguard Worker inline float hardlight(float src, float dst)
695*35238bceSAndroid Build Coastguard Worker {
696*35238bceSAndroid Build Coastguard Worker     if (src <= 0.5f)
697*35238bceSAndroid Build Coastguard Worker         return 2.0f * src * dst;
698*35238bceSAndroid Build Coastguard Worker     else
699*35238bceSAndroid Build Coastguard Worker         return 1.0f - 2.0f * (1.0f - src) * (1.0f - dst);
700*35238bceSAndroid Build Coastguard Worker }
701*35238bceSAndroid Build Coastguard Worker 
softlight(float src,float dst)702*35238bceSAndroid Build Coastguard Worker inline float softlight(float src, float dst)
703*35238bceSAndroid Build Coastguard Worker {
704*35238bceSAndroid Build Coastguard Worker     if (src <= 0.5f)
705*35238bceSAndroid Build Coastguard Worker         return dst - (1.0f - 2.0f * src) * dst * (1.0f - dst);
706*35238bceSAndroid Build Coastguard Worker     else if (dst <= 0.25f)
707*35238bceSAndroid Build Coastguard Worker         return dst + (2.0f * src - 1.0f) * dst * ((16.0f * dst - 12.0f) * dst + 3.0f);
708*35238bceSAndroid Build Coastguard Worker     else
709*35238bceSAndroid Build Coastguard Worker         return dst + (2.0f * src - 1.0f) * (deFloatSqrt(dst) - dst);
710*35238bceSAndroid Build Coastguard Worker }
711*35238bceSAndroid Build Coastguard Worker 
minComp(const Vec3 & v)712*35238bceSAndroid Build Coastguard Worker inline float minComp(const Vec3 &v)
713*35238bceSAndroid Build Coastguard Worker {
714*35238bceSAndroid Build Coastguard Worker     return de::min(de::min(v.x(), v.y()), v.z());
715*35238bceSAndroid Build Coastguard Worker }
716*35238bceSAndroid Build Coastguard Worker 
maxComp(const Vec3 & v)717*35238bceSAndroid Build Coastguard Worker inline float maxComp(const Vec3 &v)
718*35238bceSAndroid Build Coastguard Worker {
719*35238bceSAndroid Build Coastguard Worker     return de::max(de::max(v.x(), v.y()), v.z());
720*35238bceSAndroid Build Coastguard Worker }
721*35238bceSAndroid Build Coastguard Worker 
luminosity(const Vec3 & rgb)722*35238bceSAndroid Build Coastguard Worker inline float luminosity(const Vec3 &rgb)
723*35238bceSAndroid Build Coastguard Worker {
724*35238bceSAndroid Build Coastguard Worker     return dot(rgb, Vec3(0.3f, 0.59f, 0.11f));
725*35238bceSAndroid Build Coastguard Worker }
726*35238bceSAndroid Build Coastguard Worker 
saturation(const Vec3 & rgb)727*35238bceSAndroid Build Coastguard Worker inline float saturation(const Vec3 &rgb)
728*35238bceSAndroid Build Coastguard Worker {
729*35238bceSAndroid Build Coastguard Worker     return maxComp(rgb) - minComp(rgb);
730*35238bceSAndroid Build Coastguard Worker }
731*35238bceSAndroid Build Coastguard Worker 
setLum(const Vec3 & cbase,const Vec3 & clum)732*35238bceSAndroid Build Coastguard Worker Vec3 setLum(const Vec3 &cbase, const Vec3 &clum)
733*35238bceSAndroid Build Coastguard Worker {
734*35238bceSAndroid Build Coastguard Worker     const float lbase = luminosity(cbase);
735*35238bceSAndroid Build Coastguard Worker     const float llum  = luminosity(clum);
736*35238bceSAndroid Build Coastguard Worker     const float ldiff = llum - lbase;
737*35238bceSAndroid Build Coastguard Worker     const Vec3 color  = cbase + Vec3(ldiff);
738*35238bceSAndroid Build Coastguard Worker     const float minC  = minComp(color);
739*35238bceSAndroid Build Coastguard Worker     const float maxC  = maxComp(color);
740*35238bceSAndroid Build Coastguard Worker 
741*35238bceSAndroid Build Coastguard Worker     if (minC < 0.0f)
742*35238bceSAndroid Build Coastguard Worker         return llum + ((color - llum) * llum / (llum != minC ? (llum - minC) : 1.0f));
743*35238bceSAndroid Build Coastguard Worker     else if (maxC > 1.0f)
744*35238bceSAndroid Build Coastguard Worker         return llum + ((color - llum) * (1.0f - llum) / (llum != maxC ? (maxC - llum) : 1.0f));
745*35238bceSAndroid Build Coastguard Worker     else
746*35238bceSAndroid Build Coastguard Worker         return color;
747*35238bceSAndroid Build Coastguard Worker }
748*35238bceSAndroid Build Coastguard Worker 
setLumSat(const Vec3 & cbase,const Vec3 & csat,const Vec3 & clum)749*35238bceSAndroid Build Coastguard Worker Vec3 setLumSat(const Vec3 &cbase, const Vec3 &csat, const Vec3 &clum)
750*35238bceSAndroid Build Coastguard Worker {
751*35238bceSAndroid Build Coastguard Worker     const float minbase = minComp(cbase);
752*35238bceSAndroid Build Coastguard Worker     const float sbase   = saturation(cbase);
753*35238bceSAndroid Build Coastguard Worker     const float ssat    = saturation(csat);
754*35238bceSAndroid Build Coastguard Worker     Vec3 color          = Vec3(0.0f);
755*35238bceSAndroid Build Coastguard Worker 
756*35238bceSAndroid Build Coastguard Worker     if (sbase > 0.0f)
757*35238bceSAndroid Build Coastguard Worker         color = (cbase - minbase) * ssat / sbase;
758*35238bceSAndroid Build Coastguard Worker 
759*35238bceSAndroid Build Coastguard Worker     return setLum(color, clum);
760*35238bceSAndroid Build Coastguard Worker }
761*35238bceSAndroid Build Coastguard Worker 
762*35238bceSAndroid Build Coastguard Worker } // namespace advblend
763*35238bceSAndroid Build Coastguard Worker 
executeAdvancedBlend(BlendEquationAdvanced equation)764*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeAdvancedBlend(BlendEquationAdvanced equation)
765*35238bceSAndroid Build Coastguard Worker {
766*35238bceSAndroid Build Coastguard Worker     using namespace advblend;
767*35238bceSAndroid Build Coastguard Worker 
768*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_ADV_BLEND(FUNCTION_NAME)                                               \
769*35238bceSAndroid Build Coastguard Worker     do                                                                                         \
770*35238bceSAndroid Build Coastguard Worker     {                                                                                          \
771*35238bceSAndroid Build Coastguard Worker         for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)        \
772*35238bceSAndroid Build Coastguard Worker         {                                                                                      \
773*35238bceSAndroid Build Coastguard Worker             if (m_sampleRegister[regSampleNdx].isAlive)                                        \
774*35238bceSAndroid Build Coastguard Worker             {                                                                                  \
775*35238bceSAndroid Build Coastguard Worker                 SampleData &sample   = m_sampleRegister[regSampleNdx];                         \
776*35238bceSAndroid Build Coastguard Worker                 const Vec4 &srcColor = sample.clampedBlendSrcColor;                            \
777*35238bceSAndroid Build Coastguard Worker                 const Vec4 &dstColor = sample.clampedBlendDstColor;                            \
778*35238bceSAndroid Build Coastguard Worker                 const Vec3 &bias     = sample.blendSrcFactorRGB;                               \
779*35238bceSAndroid Build Coastguard Worker                 const float p0       = sample.blendSrcFactorA;                                 \
780*35238bceSAndroid Build Coastguard Worker                 const float r        = FUNCTION_NAME(srcColor[0], dstColor[0]) * p0 + bias[0]; \
781*35238bceSAndroid Build Coastguard Worker                 const float g        = FUNCTION_NAME(srcColor[1], dstColor[1]) * p0 + bias[1]; \
782*35238bceSAndroid Build Coastguard Worker                 const float b        = FUNCTION_NAME(srcColor[2], dstColor[2]) * p0 + bias[2]; \
783*35238bceSAndroid Build Coastguard Worker                                                                                                \
784*35238bceSAndroid Build Coastguard Worker                 sample.blendedRGB = Vec3(r, g, b);                                             \
785*35238bceSAndroid Build Coastguard Worker             }                                                                                  \
786*35238bceSAndroid Build Coastguard Worker         }                                                                                      \
787*35238bceSAndroid Build Coastguard Worker     } while (0)
788*35238bceSAndroid Build Coastguard Worker 
789*35238bceSAndroid Build Coastguard Worker #define SAMPLE_REGISTER_ADV_BLEND_HSL(COLOR_EXPRESSION)                                 \
790*35238bceSAndroid Build Coastguard Worker     do                                                                                  \
791*35238bceSAndroid Build Coastguard Worker     {                                                                                   \
792*35238bceSAndroid Build Coastguard Worker         for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++) \
793*35238bceSAndroid Build Coastguard Worker         {                                                                               \
794*35238bceSAndroid Build Coastguard Worker             if (m_sampleRegister[regSampleNdx].isAlive)                                 \
795*35238bceSAndroid Build Coastguard Worker             {                                                                           \
796*35238bceSAndroid Build Coastguard Worker                 SampleData &sample  = m_sampleRegister[regSampleNdx];                   \
797*35238bceSAndroid Build Coastguard Worker                 const Vec3 srcColor = sample.clampedBlendSrcColor.swizzle(0, 1, 2);     \
798*35238bceSAndroid Build Coastguard Worker                 const Vec3 dstColor = sample.clampedBlendDstColor.swizzle(0, 1, 2);     \
799*35238bceSAndroid Build Coastguard Worker                 const Vec3 &bias    = sample.blendSrcFactorRGB;                         \
800*35238bceSAndroid Build Coastguard Worker                 const float p0      = sample.blendSrcFactorA;                           \
801*35238bceSAndroid Build Coastguard Worker                                                                                         \
802*35238bceSAndroid Build Coastguard Worker                 sample.blendedRGB = (COLOR_EXPRESSION)*p0 + bias;                       \
803*35238bceSAndroid Build Coastguard Worker             }                                                                           \
804*35238bceSAndroid Build Coastguard Worker         }                                                                               \
805*35238bceSAndroid Build Coastguard Worker     } while (0)
806*35238bceSAndroid Build Coastguard Worker 
807*35238bceSAndroid Build Coastguard Worker     // Pre-compute factors & compute alpha \todo [2014-03-18 pyry] Re-using variable names.
808*35238bceSAndroid Build Coastguard Worker     // \note clampedBlend*Color contains clamped & unpremultiplied colors
809*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
810*35238bceSAndroid Build Coastguard Worker     {
811*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)
812*35238bceSAndroid Build Coastguard Worker         {
813*35238bceSAndroid Build Coastguard Worker             SampleData &sample   = m_sampleRegister[regSampleNdx];
814*35238bceSAndroid Build Coastguard Worker             const Vec4 &srcColor = sample.clampedBlendSrcColor;
815*35238bceSAndroid Build Coastguard Worker             const Vec4 &dstColor = sample.clampedBlendDstColor;
816*35238bceSAndroid Build Coastguard Worker             const float srcA     = srcColor.w();
817*35238bceSAndroid Build Coastguard Worker             const float dstA     = dstColor.w();
818*35238bceSAndroid Build Coastguard Worker             const float p0       = srcA * dstA;
819*35238bceSAndroid Build Coastguard Worker             const float p1       = srcA * (1.0f - dstA);
820*35238bceSAndroid Build Coastguard Worker             const float p2       = dstA * (1.0f - srcA);
821*35238bceSAndroid Build Coastguard Worker             const Vec3 bias(srcColor[0] * p1 + dstColor[0] * p2, srcColor[1] * p1 + dstColor[1] * p2,
822*35238bceSAndroid Build Coastguard Worker                             srcColor[2] * p1 + dstColor[2] * p2);
823*35238bceSAndroid Build Coastguard Worker 
824*35238bceSAndroid Build Coastguard Worker             sample.blendSrcFactorRGB = bias;
825*35238bceSAndroid Build Coastguard Worker             sample.blendSrcFactorA   = p0;
826*35238bceSAndroid Build Coastguard Worker             sample.blendedA          = p0 + p1 + p2;
827*35238bceSAndroid Build Coastguard Worker         }
828*35238bceSAndroid Build Coastguard Worker     }
829*35238bceSAndroid Build Coastguard Worker 
830*35238bceSAndroid Build Coastguard Worker     switch (equation)
831*35238bceSAndroid Build Coastguard Worker     {
832*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_MULTIPLY:
833*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(multiply);
834*35238bceSAndroid Build Coastguard Worker         break;
835*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_SCREEN:
836*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(screen);
837*35238bceSAndroid Build Coastguard Worker         break;
838*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_OVERLAY:
839*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(overlay);
840*35238bceSAndroid Build Coastguard Worker         break;
841*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_DARKEN:
842*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(darken);
843*35238bceSAndroid Build Coastguard Worker         break;
844*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_LIGHTEN:
845*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(lighten);
846*35238bceSAndroid Build Coastguard Worker         break;
847*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_COLORDODGE:
848*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(colordodge);
849*35238bceSAndroid Build Coastguard Worker         break;
850*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_COLORBURN:
851*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(colorburn);
852*35238bceSAndroid Build Coastguard Worker         break;
853*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_HARDLIGHT:
854*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(hardlight);
855*35238bceSAndroid Build Coastguard Worker         break;
856*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_SOFTLIGHT:
857*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(softlight);
858*35238bceSAndroid Build Coastguard Worker         break;
859*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_DIFFERENCE:
860*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(difference);
861*35238bceSAndroid Build Coastguard Worker         break;
862*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_EXCLUSION:
863*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND(exclusion);
864*35238bceSAndroid Build Coastguard Worker         break;
865*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_HSL_HUE:
866*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND_HSL(setLumSat(srcColor, dstColor, dstColor));
867*35238bceSAndroid Build Coastguard Worker         break;
868*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_HSL_SATURATION:
869*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND_HSL(setLumSat(dstColor, srcColor, dstColor));
870*35238bceSAndroid Build Coastguard Worker         break;
871*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_HSL_COLOR:
872*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND_HSL(setLum(srcColor, dstColor));
873*35238bceSAndroid Build Coastguard Worker         break;
874*35238bceSAndroid Build Coastguard Worker     case BLENDEQUATION_ADVANCED_HSL_LUMINOSITY:
875*35238bceSAndroid Build Coastguard Worker         SAMPLE_REGISTER_ADV_BLEND_HSL(setLum(dstColor, srcColor));
876*35238bceSAndroid Build Coastguard Worker         break;
877*35238bceSAndroid Build Coastguard Worker     default:
878*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
879*35238bceSAndroid Build Coastguard Worker     }
880*35238bceSAndroid Build Coastguard Worker 
881*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_ADV_BLEND
882*35238bceSAndroid Build Coastguard Worker #undef SAMPLE_REGISTER_ADV_BLEND_HSL
883*35238bceSAndroid Build Coastguard Worker }
884*35238bceSAndroid Build Coastguard Worker 
executeColorWrite(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,bool isSRGB,const tcu::PixelBufferAccess & colorBuffer)885*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeColorWrite(int fragNdxOffset, int numSamplesPerFragment, const Fragment *inputFragments,
886*35238bceSAndroid Build Coastguard Worker                                           bool isSRGB, const tcu::PixelBufferAccess &colorBuffer)
887*35238bceSAndroid Build Coastguard Worker {
888*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
889*35238bceSAndroid Build Coastguard Worker     {
890*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)
891*35238bceSAndroid Build Coastguard Worker         {
892*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;
893*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
894*35238bceSAndroid Build Coastguard Worker             Vec4 combinedColor;
895*35238bceSAndroid Build Coastguard Worker 
896*35238bceSAndroid Build Coastguard Worker             combinedColor.xyz() = m_sampleRegister[regSampleNdx].blendedRGB;
897*35238bceSAndroid Build Coastguard Worker             combinedColor.w()   = m_sampleRegister[regSampleNdx].blendedA;
898*35238bceSAndroid Build Coastguard Worker 
899*35238bceSAndroid Build Coastguard Worker             if (isSRGB)
900*35238bceSAndroid Build Coastguard Worker                 combinedColor = tcu::linearToSRGB(combinedColor);
901*35238bceSAndroid Build Coastguard Worker 
902*35238bceSAndroid Build Coastguard Worker             colorBuffer.setPixel(combinedColor, fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
903*35238bceSAndroid Build Coastguard Worker         }
904*35238bceSAndroid Build Coastguard Worker     }
905*35238bceSAndroid Build Coastguard Worker }
906*35238bceSAndroid Build Coastguard Worker 
executeRGBA8ColorWrite(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const tcu::PixelBufferAccess & colorBuffer)907*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeRGBA8ColorWrite(int fragNdxOffset, int numSamplesPerFragment,
908*35238bceSAndroid Build Coastguard Worker                                                const Fragment *inputFragments,
909*35238bceSAndroid Build Coastguard Worker                                                const tcu::PixelBufferAccess &colorBuffer)
910*35238bceSAndroid Build Coastguard Worker {
911*35238bceSAndroid Build Coastguard Worker     const int fragStride   = 4;
912*35238bceSAndroid Build Coastguard Worker     const int xStride      = colorBuffer.getRowPitch();
913*35238bceSAndroid Build Coastguard Worker     const int yStride      = colorBuffer.getSlicePitch();
914*35238bceSAndroid Build Coastguard Worker     uint8_t *const basePtr = (uint8_t *)colorBuffer.getDataPtr();
915*35238bceSAndroid Build Coastguard Worker 
916*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
917*35238bceSAndroid Build Coastguard Worker     {
918*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)
919*35238bceSAndroid Build Coastguard Worker         {
920*35238bceSAndroid Build Coastguard Worker             const int fragSampleNdx = regSampleNdx % numSamplesPerFragment;
921*35238bceSAndroid Build Coastguard Worker             const Fragment &frag    = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
922*35238bceSAndroid Build Coastguard Worker             uint8_t *dstPtr =
923*35238bceSAndroid Build Coastguard Worker                 basePtr + fragSampleNdx * fragStride + frag.pixelCoord.x() * xStride + frag.pixelCoord.y() * yStride;
924*35238bceSAndroid Build Coastguard Worker 
925*35238bceSAndroid Build Coastguard Worker             dstPtr[0] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedRGB.x());
926*35238bceSAndroid Build Coastguard Worker             dstPtr[1] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedRGB.y());
927*35238bceSAndroid Build Coastguard Worker             dstPtr[2] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedRGB.z());
928*35238bceSAndroid Build Coastguard Worker             dstPtr[3] = tcu::floatToU8(m_sampleRegister[regSampleNdx].blendedA);
929*35238bceSAndroid Build Coastguard Worker         }
930*35238bceSAndroid Build Coastguard Worker     }
931*35238bceSAndroid Build Coastguard Worker }
932*35238bceSAndroid Build Coastguard Worker 
executeMaskedColorWrite(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const Vec4 & colorMaskFactor,const Vec4 & colorMaskNegationFactor,bool isSRGB,const tcu::PixelBufferAccess & colorBuffer)933*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeMaskedColorWrite(int fragNdxOffset, int numSamplesPerFragment,
934*35238bceSAndroid Build Coastguard Worker                                                 const Fragment *inputFragments, const Vec4 &colorMaskFactor,
935*35238bceSAndroid Build Coastguard Worker                                                 const Vec4 &colorMaskNegationFactor, bool isSRGB,
936*35238bceSAndroid Build Coastguard Worker                                                 const tcu::PixelBufferAccess &colorBuffer)
937*35238bceSAndroid Build Coastguard Worker {
938*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
939*35238bceSAndroid Build Coastguard Worker     {
940*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)
941*35238bceSAndroid Build Coastguard Worker         {
942*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;
943*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
944*35238bceSAndroid Build Coastguard Worker             Vec4 originalColor   = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
945*35238bceSAndroid Build Coastguard Worker             Vec4 newColor;
946*35238bceSAndroid Build Coastguard Worker 
947*35238bceSAndroid Build Coastguard Worker             newColor.xyz() = m_sampleRegister[regSampleNdx].blendedRGB;
948*35238bceSAndroid Build Coastguard Worker             newColor.w()   = m_sampleRegister[regSampleNdx].blendedA;
949*35238bceSAndroid Build Coastguard Worker 
950*35238bceSAndroid Build Coastguard Worker             if (isSRGB)
951*35238bceSAndroid Build Coastguard Worker                 newColor = tcu::linearToSRGB(newColor);
952*35238bceSAndroid Build Coastguard Worker 
953*35238bceSAndroid Build Coastguard Worker             newColor = colorMaskFactor * newColor + colorMaskNegationFactor * originalColor;
954*35238bceSAndroid Build Coastguard Worker 
955*35238bceSAndroid Build Coastguard Worker             colorBuffer.setPixel(newColor, fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
956*35238bceSAndroid Build Coastguard Worker         }
957*35238bceSAndroid Build Coastguard Worker     }
958*35238bceSAndroid Build Coastguard Worker }
959*35238bceSAndroid Build Coastguard Worker 
executeSignedValueWrite(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const tcu::BVec4 & colorMask,const tcu::PixelBufferAccess & colorBuffer)960*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeSignedValueWrite(int fragNdxOffset, int numSamplesPerFragment,
961*35238bceSAndroid Build Coastguard Worker                                                 const Fragment *inputFragments, const tcu::BVec4 &colorMask,
962*35238bceSAndroid Build Coastguard Worker                                                 const tcu::PixelBufferAccess &colorBuffer)
963*35238bceSAndroid Build Coastguard Worker {
964*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
965*35238bceSAndroid Build Coastguard Worker     {
966*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)
967*35238bceSAndroid Build Coastguard Worker         {
968*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;
969*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
970*35238bceSAndroid Build Coastguard Worker             const IVec4 originalValue =
971*35238bceSAndroid Build Coastguard Worker                 colorBuffer.getPixelInt(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
972*35238bceSAndroid Build Coastguard Worker 
973*35238bceSAndroid Build Coastguard Worker             colorBuffer.setPixel(tcu::select(m_sampleRegister[regSampleNdx].signedValue, originalValue, colorMask),
974*35238bceSAndroid Build Coastguard Worker                                  fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
975*35238bceSAndroid Build Coastguard Worker         }
976*35238bceSAndroid Build Coastguard Worker     }
977*35238bceSAndroid Build Coastguard Worker }
978*35238bceSAndroid Build Coastguard Worker 
executeUnsignedValueWrite(int fragNdxOffset,int numSamplesPerFragment,const Fragment * inputFragments,const tcu::BVec4 & colorMask,const tcu::PixelBufferAccess & colorBuffer)979*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::executeUnsignedValueWrite(int fragNdxOffset, int numSamplesPerFragment,
980*35238bceSAndroid Build Coastguard Worker                                                   const Fragment *inputFragments, const tcu::BVec4 &colorMask,
981*35238bceSAndroid Build Coastguard Worker                                                   const tcu::PixelBufferAccess &colorBuffer)
982*35238bceSAndroid Build Coastguard Worker {
983*35238bceSAndroid Build Coastguard Worker     for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
984*35238bceSAndroid Build Coastguard Worker     {
985*35238bceSAndroid Build Coastguard Worker         if (m_sampleRegister[regSampleNdx].isAlive)
986*35238bceSAndroid Build Coastguard Worker         {
987*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;
988*35238bceSAndroid Build Coastguard Worker             const Fragment &frag = inputFragments[fragNdxOffset + regSampleNdx / numSamplesPerFragment];
989*35238bceSAndroid Build Coastguard Worker             const UVec4 originalValue =
990*35238bceSAndroid Build Coastguard Worker                 colorBuffer.getPixelUint(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
991*35238bceSAndroid Build Coastguard Worker 
992*35238bceSAndroid Build Coastguard Worker             colorBuffer.setPixel(tcu::select(m_sampleRegister[regSampleNdx].unsignedValue, originalValue, colorMask),
993*35238bceSAndroid Build Coastguard Worker                                  fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
994*35238bceSAndroid Build Coastguard Worker         }
995*35238bceSAndroid Build Coastguard Worker     }
996*35238bceSAndroid Build Coastguard Worker }
997*35238bceSAndroid Build Coastguard Worker 
render(const rr::MultisamplePixelBufferAccess & msColorBuffer,const rr::MultisamplePixelBufferAccess & msDepthBuffer,const rr::MultisamplePixelBufferAccess & msStencilBuffer,const Fragment * inputFragments,int numFragments,FaceType fragmentFacing,const FragmentOperationState & state)998*35238bceSAndroid Build Coastguard Worker void FragmentProcessor::render(const rr::MultisamplePixelBufferAccess &msColorBuffer,
999*35238bceSAndroid Build Coastguard Worker                                const rr::MultisamplePixelBufferAccess &msDepthBuffer,
1000*35238bceSAndroid Build Coastguard Worker                                const rr::MultisamplePixelBufferAccess &msStencilBuffer, const Fragment *inputFragments,
1001*35238bceSAndroid Build Coastguard Worker                                int numFragments, FaceType fragmentFacing, const FragmentOperationState &state)
1002*35238bceSAndroid Build Coastguard Worker {
1003*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(fragmentFacing < FACETYPE_LAST);
1004*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(state.numStencilBits < 32); // code bitshifts numStencilBits, avoid undefined behavior
1005*35238bceSAndroid Build Coastguard Worker 
1006*35238bceSAndroid Build Coastguard Worker     const tcu::PixelBufferAccess &colorBuffer   = msColorBuffer.raw();
1007*35238bceSAndroid Build Coastguard Worker     const tcu::PixelBufferAccess &depthBuffer   = msDepthBuffer.raw();
1008*35238bceSAndroid Build Coastguard Worker     const tcu::PixelBufferAccess &stencilBuffer = msStencilBuffer.raw();
1009*35238bceSAndroid Build Coastguard Worker 
1010*35238bceSAndroid Build Coastguard Worker     bool hasDepth   = depthBuffer.getWidth() > 0 && depthBuffer.getHeight() > 0 && depthBuffer.getDepth() > 0;
1011*35238bceSAndroid Build Coastguard Worker     bool hasStencil = stencilBuffer.getWidth() > 0 && stencilBuffer.getHeight() > 0 && stencilBuffer.getDepth() > 0;
1012*35238bceSAndroid Build Coastguard Worker     bool doDepthBoundsTest = hasDepth && state.depthBoundsTestEnabled;
1013*35238bceSAndroid Build Coastguard Worker     bool doDepthTest       = hasDepth && state.depthTestEnabled;
1014*35238bceSAndroid Build Coastguard Worker     bool doStencilTest     = hasStencil && state.stencilTestEnabled;
1015*35238bceSAndroid Build Coastguard Worker 
1016*35238bceSAndroid Build Coastguard Worker     tcu::TextureChannelClass colorbufferClass = tcu::getTextureChannelClass(msColorBuffer.raw().getFormat().type);
1017*35238bceSAndroid Build Coastguard Worker     rr::GenericVecType fragmentDataType =
1018*35238bceSAndroid Build Coastguard Worker         (colorbufferClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ?
1019*35238bceSAndroid Build Coastguard Worker             (rr::GENERICVECTYPE_INT32) :
1020*35238bceSAndroid Build Coastguard Worker             ((colorbufferClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (rr::GENERICVECTYPE_UINT32) :
1021*35238bceSAndroid Build Coastguard Worker                                                                                (rr::GENERICVECTYPE_FLOAT));
1022*35238bceSAndroid Build Coastguard Worker 
1023*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((!hasDepth || colorBuffer.getWidth() == depthBuffer.getWidth()) &&
1024*35238bceSAndroid Build Coastguard Worker               (!hasStencil || colorBuffer.getWidth() == stencilBuffer.getWidth()));
1025*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((!hasDepth || colorBuffer.getHeight() == depthBuffer.getHeight()) &&
1026*35238bceSAndroid Build Coastguard Worker               (!hasStencil || colorBuffer.getHeight() == stencilBuffer.getHeight()));
1027*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((!hasDepth || colorBuffer.getDepth() == depthBuffer.getDepth()) &&
1028*35238bceSAndroid Build Coastguard Worker               (!hasStencil || colorBuffer.getDepth() == stencilBuffer.getDepth()));
1029*35238bceSAndroid Build Coastguard Worker 
1030*35238bceSAndroid Build Coastguard Worker     // Combined formats must be separated beforehand
1031*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!hasDepth || (!tcu::isCombinedDepthStencilType(depthBuffer.getFormat().type) &&
1032*35238bceSAndroid Build Coastguard Worker                             depthBuffer.getFormat().order == tcu::TextureFormat::D));
1033*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!hasStencil || (!tcu::isCombinedDepthStencilType(stencilBuffer.getFormat().type) &&
1034*35238bceSAndroid Build Coastguard Worker                               stencilBuffer.getFormat().order == tcu::TextureFormat::S));
1035*35238bceSAndroid Build Coastguard Worker 
1036*35238bceSAndroid Build Coastguard Worker     int numSamplesPerFragment = colorBuffer.getWidth();
1037*35238bceSAndroid Build Coastguard Worker     int totalNumSamples       = numFragments * numSamplesPerFragment;
1038*35238bceSAndroid Build Coastguard Worker     int numSampleGroups =
1039*35238bceSAndroid Build Coastguard Worker         (totalNumSamples - 1) / SAMPLE_REGISTER_SIZE + 1; // \note totalNumSamples/SAMPLE_REGISTER_SIZE rounded up.
1040*35238bceSAndroid Build Coastguard Worker     const StencilState &stencilState = state.stencilStates[fragmentFacing];
1041*35238bceSAndroid Build Coastguard Worker     Vec4 colorMaskFactor(state.colorMask[0] ? 1.0f : 0.0f, state.colorMask[1] ? 1.0f : 0.0f,
1042*35238bceSAndroid Build Coastguard Worker                          state.colorMask[2] ? 1.0f : 0.0f, state.colorMask[3] ? 1.0f : 0.0f);
1043*35238bceSAndroid Build Coastguard Worker     Vec4 colorMaskNegationFactor(state.colorMask[0] ? 0.0f : 1.0f, state.colorMask[1] ? 0.0f : 1.0f,
1044*35238bceSAndroid Build Coastguard Worker                                  state.colorMask[2] ? 0.0f : 1.0f, state.colorMask[3] ? 0.0f : 1.0f);
1045*35238bceSAndroid Build Coastguard Worker     bool sRGBTarget = state.sRGBEnabled && tcu::isSRGB(colorBuffer.getFormat());
1046*35238bceSAndroid Build Coastguard Worker 
1047*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(SAMPLE_REGISTER_SIZE % numSamplesPerFragment == 0);
1048*35238bceSAndroid Build Coastguard Worker 
1049*35238bceSAndroid Build Coastguard Worker     // Divide the fragments' samples into groups of size SAMPLE_REGISTER_SIZE, and perform
1050*35238bceSAndroid Build Coastguard Worker     // the per-sample operations for one group at a time.
1051*35238bceSAndroid Build Coastguard Worker 
1052*35238bceSAndroid Build Coastguard Worker     for (int sampleGroupNdx = 0; sampleGroupNdx < numSampleGroups; sampleGroupNdx++)
1053*35238bceSAndroid Build Coastguard Worker     {
1054*35238bceSAndroid Build Coastguard Worker         // The index of the fragment of the sample at the beginning of m_sampleRegisters.
1055*35238bceSAndroid Build Coastguard Worker         int groupFirstFragNdx = (sampleGroupNdx * SAMPLE_REGISTER_SIZE) / numSamplesPerFragment;
1056*35238bceSAndroid Build Coastguard Worker 
1057*35238bceSAndroid Build Coastguard Worker         // Initialize sample data in the sample register.
1058*35238bceSAndroid Build Coastguard Worker 
1059*35238bceSAndroid Build Coastguard Worker         for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1060*35238bceSAndroid Build Coastguard Worker         {
1061*35238bceSAndroid Build Coastguard Worker             int fragNdx       = groupFirstFragNdx + regSampleNdx / numSamplesPerFragment;
1062*35238bceSAndroid Build Coastguard Worker             int fragSampleNdx = regSampleNdx % numSamplesPerFragment;
1063*35238bceSAndroid Build Coastguard Worker 
1064*35238bceSAndroid Build Coastguard Worker             if (fragNdx < numFragments)
1065*35238bceSAndroid Build Coastguard Worker             {
1066*35238bceSAndroid Build Coastguard Worker                 m_sampleRegister[regSampleNdx].isAlive =
1067*35238bceSAndroid Build Coastguard Worker                     (inputFragments[fragNdx].coverage & (1u << fragSampleNdx)) != 0;
1068*35238bceSAndroid Build Coastguard Worker                 m_sampleRegister[regSampleNdx].depthPassed =
1069*35238bceSAndroid Build Coastguard Worker                     true; // \note This will stay true if depth test is disabled.
1070*35238bceSAndroid Build Coastguard Worker             }
1071*35238bceSAndroid Build Coastguard Worker             else
1072*35238bceSAndroid Build Coastguard Worker                 m_sampleRegister[regSampleNdx].isAlive = false;
1073*35238bceSAndroid Build Coastguard Worker         }
1074*35238bceSAndroid Build Coastguard Worker 
1075*35238bceSAndroid Build Coastguard Worker         // Scissor test.
1076*35238bceSAndroid Build Coastguard Worker 
1077*35238bceSAndroid Build Coastguard Worker         if (state.scissorTestEnabled)
1078*35238bceSAndroid Build Coastguard Worker             executeScissorTest(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.scissorRectangle);
1079*35238bceSAndroid Build Coastguard Worker 
1080*35238bceSAndroid Build Coastguard Worker         // Depth bounds test.
1081*35238bceSAndroid Build Coastguard Worker 
1082*35238bceSAndroid Build Coastguard Worker         if (doDepthBoundsTest)
1083*35238bceSAndroid Build Coastguard Worker             executeDepthBoundsTest(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.minDepthBound,
1084*35238bceSAndroid Build Coastguard Worker                                    state.maxDepthBound, depthBuffer);
1085*35238bceSAndroid Build Coastguard Worker 
1086*35238bceSAndroid Build Coastguard Worker         // Stencil test.
1087*35238bceSAndroid Build Coastguard Worker 
1088*35238bceSAndroid Build Coastguard Worker         if (doStencilTest)
1089*35238bceSAndroid Build Coastguard Worker         {
1090*35238bceSAndroid Build Coastguard Worker             executeStencilCompare(groupFirstFragNdx, numSamplesPerFragment, inputFragments, stencilState,
1091*35238bceSAndroid Build Coastguard Worker                                   state.numStencilBits, stencilBuffer);
1092*35238bceSAndroid Build Coastguard Worker             executeStencilSFail(groupFirstFragNdx, numSamplesPerFragment, inputFragments, stencilState,
1093*35238bceSAndroid Build Coastguard Worker                                 state.numStencilBits, stencilBuffer);
1094*35238bceSAndroid Build Coastguard Worker         }
1095*35238bceSAndroid Build Coastguard Worker 
1096*35238bceSAndroid Build Coastguard Worker         // Depth test.
1097*35238bceSAndroid Build Coastguard Worker         // \note Current value of isAlive is needed for dpPass and dpFail, so it's only updated after them and not right after depth test.
1098*35238bceSAndroid Build Coastguard Worker 
1099*35238bceSAndroid Build Coastguard Worker         if (doDepthTest)
1100*35238bceSAndroid Build Coastguard Worker         {
1101*35238bceSAndroid Build Coastguard Worker             executeDepthCompare(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.depthFunc, depthBuffer);
1102*35238bceSAndroid Build Coastguard Worker 
1103*35238bceSAndroid Build Coastguard Worker             if (state.depthMask)
1104*35238bceSAndroid Build Coastguard Worker                 executeDepthWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, depthBuffer);
1105*35238bceSAndroid Build Coastguard Worker         }
1106*35238bceSAndroid Build Coastguard Worker 
1107*35238bceSAndroid Build Coastguard Worker         // Do dpFail and dpPass stencil writes.
1108*35238bceSAndroid Build Coastguard Worker 
1109*35238bceSAndroid Build Coastguard Worker         if (doStencilTest)
1110*35238bceSAndroid Build Coastguard Worker             executeStencilDpFailAndPass(groupFirstFragNdx, numSamplesPerFragment, inputFragments, stencilState,
1111*35238bceSAndroid Build Coastguard Worker                                         state.numStencilBits, stencilBuffer);
1112*35238bceSAndroid Build Coastguard Worker 
1113*35238bceSAndroid Build Coastguard Worker         // Kill the samples that failed depth test.
1114*35238bceSAndroid Build Coastguard Worker 
1115*35238bceSAndroid Build Coastguard Worker         if (doDepthTest)
1116*35238bceSAndroid Build Coastguard Worker         {
1117*35238bceSAndroid Build Coastguard Worker             for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1118*35238bceSAndroid Build Coastguard Worker                 m_sampleRegister[regSampleNdx].isAlive =
1119*35238bceSAndroid Build Coastguard Worker                     m_sampleRegister[regSampleNdx].isAlive && m_sampleRegister[regSampleNdx].depthPassed;
1120*35238bceSAndroid Build Coastguard Worker         }
1121*35238bceSAndroid Build Coastguard Worker 
1122*35238bceSAndroid Build Coastguard Worker         // Paint fragments to target
1123*35238bceSAndroid Build Coastguard Worker 
1124*35238bceSAndroid Build Coastguard Worker         switch (fragmentDataType)
1125*35238bceSAndroid Build Coastguard Worker         {
1126*35238bceSAndroid Build Coastguard Worker         case rr::GENERICVECTYPE_FLOAT:
1127*35238bceSAndroid Build Coastguard Worker         {
1128*35238bceSAndroid Build Coastguard Worker             // Select min/max clamping values for blending factors and operands
1129*35238bceSAndroid Build Coastguard Worker             Vec4 minClampValue;
1130*35238bceSAndroid Build Coastguard Worker             Vec4 maxClampValue;
1131*35238bceSAndroid Build Coastguard Worker 
1132*35238bceSAndroid Build Coastguard Worker             if (colorbufferClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
1133*35238bceSAndroid Build Coastguard Worker             {
1134*35238bceSAndroid Build Coastguard Worker                 minClampValue = Vec4(0.0f);
1135*35238bceSAndroid Build Coastguard Worker                 maxClampValue = Vec4(1.0f);
1136*35238bceSAndroid Build Coastguard Worker             }
1137*35238bceSAndroid Build Coastguard Worker             else if (colorbufferClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
1138*35238bceSAndroid Build Coastguard Worker             {
1139*35238bceSAndroid Build Coastguard Worker                 minClampValue = Vec4(-1.0f);
1140*35238bceSAndroid Build Coastguard Worker                 maxClampValue = Vec4(1.0f);
1141*35238bceSAndroid Build Coastguard Worker             }
1142*35238bceSAndroid Build Coastguard Worker             else
1143*35238bceSAndroid Build Coastguard Worker             {
1144*35238bceSAndroid Build Coastguard Worker                 // No clamping
1145*35238bceSAndroid Build Coastguard Worker                 minClampValue = Vec4(-std::numeric_limits<float>::infinity());
1146*35238bceSAndroid Build Coastguard Worker                 maxClampValue = Vec4(std::numeric_limits<float>::infinity());
1147*35238bceSAndroid Build Coastguard Worker             }
1148*35238bceSAndroid Build Coastguard Worker 
1149*35238bceSAndroid Build Coastguard Worker             // Blend calculation - only if using blend.
1150*35238bceSAndroid Build Coastguard Worker             if (state.blendMode == BLENDMODE_STANDARD)
1151*35238bceSAndroid Build Coastguard Worker             {
1152*35238bceSAndroid Build Coastguard Worker                 // Put dst color to register, doing srgb-to-linear conversion if needed.
1153*35238bceSAndroid Build Coastguard Worker                 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1154*35238bceSAndroid Build Coastguard Worker                 {
1155*35238bceSAndroid Build Coastguard Worker                     if (m_sampleRegister[regSampleNdx].isAlive)
1156*35238bceSAndroid Build Coastguard Worker                     {
1157*35238bceSAndroid Build Coastguard Worker                         int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;
1158*35238bceSAndroid Build Coastguard Worker                         const Fragment &frag = inputFragments[groupFirstFragNdx + regSampleNdx / numSamplesPerFragment];
1159*35238bceSAndroid Build Coastguard Worker                         Vec4 dstColor = colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
1160*35238bceSAndroid Build Coastguard Worker 
1161*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].clampedBlendSrcColor =
1162*35238bceSAndroid Build Coastguard Worker                             clamp(frag.value.get<float>(), minClampValue, maxClampValue);
1163*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].clampedBlendSrc1Color =
1164*35238bceSAndroid Build Coastguard Worker                             clamp(frag.value1.get<float>(), minClampValue, maxClampValue);
1165*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].clampedBlendDstColor =
1166*35238bceSAndroid Build Coastguard Worker                             clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, minClampValue, maxClampValue);
1167*35238bceSAndroid Build Coastguard Worker                     }
1168*35238bceSAndroid Build Coastguard Worker                 }
1169*35238bceSAndroid Build Coastguard Worker 
1170*35238bceSAndroid Build Coastguard Worker                 // Calculate blend factors to register.
1171*35238bceSAndroid Build Coastguard Worker                 executeBlendFactorComputeRGB(state.blendColor, state.blendRGBState);
1172*35238bceSAndroid Build Coastguard Worker                 executeBlendFactorComputeA(state.blendColor, state.blendAState);
1173*35238bceSAndroid Build Coastguard Worker 
1174*35238bceSAndroid Build Coastguard Worker                 // Compute blended color.
1175*35238bceSAndroid Build Coastguard Worker                 executeBlend(state.blendRGBState, state.blendAState);
1176*35238bceSAndroid Build Coastguard Worker             }
1177*35238bceSAndroid Build Coastguard Worker             else if (state.blendMode == BLENDMODE_ADVANCED)
1178*35238bceSAndroid Build Coastguard Worker             {
1179*35238bceSAndroid Build Coastguard Worker                 // Unpremultiply colors for blending, and do sRGB->linear if necessary
1180*35238bceSAndroid Build Coastguard Worker                 // \todo [2014-03-17 pyry] Re-consider clampedBlend*Color var names
1181*35238bceSAndroid Build Coastguard Worker                 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1182*35238bceSAndroid Build Coastguard Worker                 {
1183*35238bceSAndroid Build Coastguard Worker                     if (m_sampleRegister[regSampleNdx].isAlive)
1184*35238bceSAndroid Build Coastguard Worker                     {
1185*35238bceSAndroid Build Coastguard Worker                         int fragSampleNdx    = regSampleNdx % numSamplesPerFragment;
1186*35238bceSAndroid Build Coastguard Worker                         const Fragment &frag = inputFragments[groupFirstFragNdx + regSampleNdx / numSamplesPerFragment];
1187*35238bceSAndroid Build Coastguard Worker                         const Vec4 srcColor  = frag.value.get<float>();
1188*35238bceSAndroid Build Coastguard Worker                         const Vec4 dstColor =
1189*35238bceSAndroid Build Coastguard Worker                             colorBuffer.getPixel(fragSampleNdx, frag.pixelCoord.x(), frag.pixelCoord.y());
1190*35238bceSAndroid Build Coastguard Worker 
1191*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].clampedBlendSrcColor =
1192*35238bceSAndroid Build Coastguard Worker                             unpremultiply(clamp(srcColor, minClampValue, maxClampValue));
1193*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].clampedBlendDstColor = unpremultiply(
1194*35238bceSAndroid Build Coastguard Worker                             clamp(sRGBTarget ? tcu::sRGBToLinear(dstColor) : dstColor, minClampValue, maxClampValue));
1195*35238bceSAndroid Build Coastguard Worker                     }
1196*35238bceSAndroid Build Coastguard Worker                 }
1197*35238bceSAndroid Build Coastguard Worker 
1198*35238bceSAndroid Build Coastguard Worker                 executeAdvancedBlend(state.blendEquationAdvaced);
1199*35238bceSAndroid Build Coastguard Worker             }
1200*35238bceSAndroid Build Coastguard Worker             else
1201*35238bceSAndroid Build Coastguard Worker             {
1202*35238bceSAndroid Build Coastguard Worker                 // Not using blend - just put values to register as-is.
1203*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(state.blendMode == BLENDMODE_NONE);
1204*35238bceSAndroid Build Coastguard Worker 
1205*35238bceSAndroid Build Coastguard Worker                 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1206*35238bceSAndroid Build Coastguard Worker                 {
1207*35238bceSAndroid Build Coastguard Worker                     if (m_sampleRegister[regSampleNdx].isAlive)
1208*35238bceSAndroid Build Coastguard Worker                     {
1209*35238bceSAndroid Build Coastguard Worker                         const Fragment &frag = inputFragments[groupFirstFragNdx + regSampleNdx / numSamplesPerFragment];
1210*35238bceSAndroid Build Coastguard Worker 
1211*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].blendedRGB = frag.value.get<float>().xyz();
1212*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].blendedA   = frag.value.get<float>().w();
1213*35238bceSAndroid Build Coastguard Worker                     }
1214*35238bceSAndroid Build Coastguard Worker                 }
1215*35238bceSAndroid Build Coastguard Worker             }
1216*35238bceSAndroid Build Coastguard Worker 
1217*35238bceSAndroid Build Coastguard Worker             // Clamp result values in sample register
1218*35238bceSAndroid Build Coastguard Worker             if (colorbufferClass != tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1219*35238bceSAndroid Build Coastguard Worker             {
1220*35238bceSAndroid Build Coastguard Worker                 for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1221*35238bceSAndroid Build Coastguard Worker                 {
1222*35238bceSAndroid Build Coastguard Worker                     if (m_sampleRegister[regSampleNdx].isAlive)
1223*35238bceSAndroid Build Coastguard Worker                     {
1224*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].blendedRGB =
1225*35238bceSAndroid Build Coastguard Worker                             clamp(m_sampleRegister[regSampleNdx].blendedRGB, minClampValue.swizzle(0, 1, 2),
1226*35238bceSAndroid Build Coastguard Worker                                   maxClampValue.swizzle(0, 1, 2));
1227*35238bceSAndroid Build Coastguard Worker                         m_sampleRegister[regSampleNdx].blendedA =
1228*35238bceSAndroid Build Coastguard Worker                             clamp(m_sampleRegister[regSampleNdx].blendedA, minClampValue.w(), maxClampValue.w());
1229*35238bceSAndroid Build Coastguard Worker                     }
1230*35238bceSAndroid Build Coastguard Worker                 }
1231*35238bceSAndroid Build Coastguard Worker             }
1232*35238bceSAndroid Build Coastguard Worker 
1233*35238bceSAndroid Build Coastguard Worker             // Finally, write the colors to the color buffer.
1234*35238bceSAndroid Build Coastguard Worker 
1235*35238bceSAndroid Build Coastguard Worker             if (state.colorMask[0] && state.colorMask[1] && state.colorMask[2] && state.colorMask[3])
1236*35238bceSAndroid Build Coastguard Worker             {
1237*35238bceSAndroid Build Coastguard Worker                 if (colorBuffer.getFormat() ==
1238*35238bceSAndroid Build Coastguard Worker                     tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))
1239*35238bceSAndroid Build Coastguard Worker                     executeRGBA8ColorWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, colorBuffer);
1240*35238bceSAndroid Build Coastguard Worker                 else
1241*35238bceSAndroid Build Coastguard Worker                     executeColorWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, sRGBTarget,
1242*35238bceSAndroid Build Coastguard Worker                                       colorBuffer);
1243*35238bceSAndroid Build Coastguard Worker             }
1244*35238bceSAndroid Build Coastguard Worker             else if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
1245*35238bceSAndroid Build Coastguard Worker                 executeMaskedColorWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, colorMaskFactor,
1246*35238bceSAndroid Build Coastguard Worker                                         colorMaskNegationFactor, sRGBTarget, colorBuffer);
1247*35238bceSAndroid Build Coastguard Worker             break;
1248*35238bceSAndroid Build Coastguard Worker         }
1249*35238bceSAndroid Build Coastguard Worker         case rr::GENERICVECTYPE_INT32:
1250*35238bceSAndroid Build Coastguard Worker             // Write fragments
1251*35238bceSAndroid Build Coastguard Worker             for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1252*35238bceSAndroid Build Coastguard Worker             {
1253*35238bceSAndroid Build Coastguard Worker                 if (m_sampleRegister[regSampleNdx].isAlive)
1254*35238bceSAndroid Build Coastguard Worker                 {
1255*35238bceSAndroid Build Coastguard Worker                     const Fragment &frag = inputFragments[groupFirstFragNdx + regSampleNdx / numSamplesPerFragment];
1256*35238bceSAndroid Build Coastguard Worker 
1257*35238bceSAndroid Build Coastguard Worker                     m_sampleRegister[regSampleNdx].signedValue = frag.value.get<int32_t>();
1258*35238bceSAndroid Build Coastguard Worker                 }
1259*35238bceSAndroid Build Coastguard Worker             }
1260*35238bceSAndroid Build Coastguard Worker 
1261*35238bceSAndroid Build Coastguard Worker             if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
1262*35238bceSAndroid Build Coastguard Worker                 executeSignedValueWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.colorMask,
1263*35238bceSAndroid Build Coastguard Worker                                         colorBuffer);
1264*35238bceSAndroid Build Coastguard Worker             break;
1265*35238bceSAndroid Build Coastguard Worker 
1266*35238bceSAndroid Build Coastguard Worker         case rr::GENERICVECTYPE_UINT32:
1267*35238bceSAndroid Build Coastguard Worker             // Write fragments
1268*35238bceSAndroid Build Coastguard Worker             for (int regSampleNdx = 0; regSampleNdx < SAMPLE_REGISTER_SIZE; regSampleNdx++)
1269*35238bceSAndroid Build Coastguard Worker             {
1270*35238bceSAndroid Build Coastguard Worker                 if (m_sampleRegister[regSampleNdx].isAlive)
1271*35238bceSAndroid Build Coastguard Worker                 {
1272*35238bceSAndroid Build Coastguard Worker                     const Fragment &frag = inputFragments[groupFirstFragNdx + regSampleNdx / numSamplesPerFragment];
1273*35238bceSAndroid Build Coastguard Worker 
1274*35238bceSAndroid Build Coastguard Worker                     m_sampleRegister[regSampleNdx].unsignedValue = frag.value.get<uint32_t>();
1275*35238bceSAndroid Build Coastguard Worker                 }
1276*35238bceSAndroid Build Coastguard Worker             }
1277*35238bceSAndroid Build Coastguard Worker 
1278*35238bceSAndroid Build Coastguard Worker             if (state.colorMask[0] || state.colorMask[1] || state.colorMask[2] || state.colorMask[3])
1279*35238bceSAndroid Build Coastguard Worker                 executeUnsignedValueWrite(groupFirstFragNdx, numSamplesPerFragment, inputFragments, state.colorMask,
1280*35238bceSAndroid Build Coastguard Worker                                           colorBuffer);
1281*35238bceSAndroid Build Coastguard Worker             break;
1282*35238bceSAndroid Build Coastguard Worker 
1283*35238bceSAndroid Build Coastguard Worker         default:
1284*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
1285*35238bceSAndroid Build Coastguard Worker         }
1286*35238bceSAndroid Build Coastguard Worker     }
1287*35238bceSAndroid Build Coastguard Worker }
1288*35238bceSAndroid Build Coastguard Worker 
1289*35238bceSAndroid Build Coastguard Worker } // namespace rr
1290