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