es2fBlendTests.cpp revision 83d2cade65513f21ff9e1871d4b71ae1040d6cce
117c83b1a74c906c9a36257a3a99cd1e3730b002eJeremy Sharpe/*-------------------------------------------------------------------------
2417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * drawElements Quality Program OpenGL ES 2.0 Module
3417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * -------------------------------------------------
4417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes *
5417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * Copyright 2014 The Android Open Source Project
6417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes *
7417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
8417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * you may not use this file except in compliance with the License.
9417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * You may obtain a copy of the License at
107a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes *
117a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
127a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes *
137a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes * Unless required by applicable law or agreed to in writing, software
147a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
15417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
167a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes * See the License for the specific language governing permissions and
177a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes * limitations under the License.
187a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes *
197a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes *//*!
207a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes * \file
217a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes * \brief Blend tests.
227a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes *//*--------------------------------------------------------------------*/
23417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
24417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes#include "es2fBlendTests.hpp"
25417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes#include "glsFragmentOpUtil.hpp"
267a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "gluPixelTransfer.hpp"
277a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "gluStrUtil.hpp"
287a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "tcuSurface.hpp"
297a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "tcuImageCompare.hpp"
307a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "tcuRenderTarget.hpp"
317a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "tcuTestLog.hpp"
327a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "deRandom.hpp"
337a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "rrFragmentOperations.hpp"
347a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "sglrReferenceUtils.hpp"
357a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes
367a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include "glw.h"
377a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes
387a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include <string>
397a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes#include <vector>
407a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes
41417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughesnamespace deqp
42417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes{
43417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
447a647e8547e57ca573541be55b3728ef7ce376feElliott Hughesusing gls::FragmentOpUtil::Quad;
45417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughesusing gls::FragmentOpUtil::IntegerQuad;
46417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughesusing gls::FragmentOpUtil::QuadRenderer;
47using gls::FragmentOpUtil::ReferenceQuadRenderer;
48using glu::getBlendEquationName;
49using glu::getBlendFactorName;
50using tcu::Vec4;
51using tcu::UVec4;
52using tcu::TestLog;
53using tcu::Surface;
54using tcu::TextureFormat;
55using tcu::TextureLevel;
56using std::string;
57using std::vector;
58
59namespace gles2
60{
61namespace Functional
62{
63
64static const int MAX_VIEWPORT_WIDTH		= 64;
65static const int MAX_VIEWPORT_HEIGHT	= 64;
66
67struct BlendParams
68{
69	GLenum	equationRGB;
70	GLenum	srcFuncRGB;
71	GLenum	dstFuncRGB;
72	GLenum	equationAlpha;
73	GLenum	srcFuncAlpha;
74	GLenum	dstFuncAlpha;
75	Vec4	blendColor;
76
77	BlendParams (GLenum		equationRGB_,
78				 GLenum		srcFuncRGB_,
79				 GLenum		dstFuncRGB_,
80				 GLenum		equationAlpha_,
81				 GLenum		srcFuncAlpha_,
82				 GLenum		dstFuncAlpha_,
83				 Vec4		blendColor_)
84	: equationRGB	(equationRGB_)
85	, srcFuncRGB	(srcFuncRGB_)
86	, dstFuncRGB	(dstFuncRGB_)
87	, equationAlpha	(equationAlpha_)
88	, srcFuncAlpha	(srcFuncAlpha_)
89	, dstFuncAlpha	(dstFuncAlpha_)
90	, blendColor	(blendColor_)
91	{
92	}
93};
94
95class BlendCase : public TestCase
96{
97public:
98							BlendCase	(Context&						context,
99										 const char*					name,
100										 const char*					desc,
101										 const vector<BlendParams>&		paramSets);
102
103							~BlendCase	(void);
104
105	void					init		(void);
106	void					deinit		(void);
107
108	IterateResult			iterate		(void);
109
110private:
111							BlendCase	(const BlendCase& other);
112	BlendCase&				operator=	(const BlendCase& other);
113
114	vector<BlendParams>		m_paramSets;
115	int						m_curParamSetNdx;
116
117	QuadRenderer*			m_renderer;
118	ReferenceQuadRenderer*	m_referenceRenderer;
119	TextureLevel*			m_refColorBuffer;
120	Quad					m_firstQuad;
121	Quad					m_secondQuad;
122	IntegerQuad				m_firstQuadInt;
123	IntegerQuad				m_secondQuadInt;
124
125	int						m_viewportW;
126	int						m_viewportH;
127};
128
129BlendCase::BlendCase (Context&						context,
130					  const char*					name,
131					  const char*					desc,
132					  const vector<BlendParams>&	paramSets)
133	: TestCase				(context, name, desc)
134	, m_paramSets			(paramSets)
135	, m_curParamSetNdx		(0)
136	, m_renderer			(DE_NULL)
137	, m_referenceRenderer	(DE_NULL)
138	, m_refColorBuffer		(DE_NULL)
139	, m_viewportW			(0)
140	, m_viewportH			(0)
141{
142	DE_ASSERT(!m_paramSets.empty());
143	for (int i = 0; i < (int)m_paramSets.size(); i++)
144		DE_ASSERT(m_paramSets[i].dstFuncRGB != GL_SRC_ALPHA_SATURATE && m_paramSets[i].dstFuncAlpha != GL_SRC_ALPHA_SATURATE);
145}
146
147void BlendCase::init (void)
148{
149	bool useRGB = m_context.getRenderTarget().getPixelFormat().alphaBits == 0;
150
151	static const Vec4 baseGradientColors[4] =
152	{
153		Vec4(0.0f, 0.5f, 1.0f, 0.5f),
154		Vec4(0.5f, 0.0f, 0.5f, 1.0f),
155		Vec4(0.5f, 1.0f, 0.5f, 0.0f),
156		Vec4(1.0f, 0.5f, 0.0f, 0.5f)
157	};
158
159	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_firstQuad.color) == DE_LENGTH_OF_ARRAY(m_firstQuadInt.color));
160	for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_firstQuad.color); i++)
161	{
162		m_firstQuad.color[i]		= (baseGradientColors[i] - 0.5f) * 0.2f + 0.5f;
163		m_firstQuadInt.color[i]		= m_firstQuad.color[i];
164
165		m_secondQuad.color[i]		= (Vec4(1.0f) - baseGradientColors[i] - 0.5f) * 1.0f + 0.5f;
166		m_secondQuadInt.color[i]	= m_secondQuad.color[i];
167	}
168
169	m_viewportW = de::min<int>(m_context.getRenderTarget().getWidth(),	MAX_VIEWPORT_WIDTH);
170	m_viewportH = de::min<int>(m_context.getRenderTarget().getHeight(),	MAX_VIEWPORT_HEIGHT);
171
172	m_firstQuadInt.posA		= tcu::IVec2(0,					0);
173	m_secondQuadInt.posA	= tcu::IVec2(0,					0);
174	m_firstQuadInt.posB		= tcu::IVec2(m_viewportW-1,		m_viewportH-1);
175	m_secondQuadInt.posB	= tcu::IVec2(m_viewportW-1,		m_viewportH-1);
176
177	DE_ASSERT(!m_renderer);
178	DE_ASSERT(!m_referenceRenderer);
179	DE_ASSERT(!m_refColorBuffer);
180
181	m_renderer				= new QuadRenderer(m_context.getRenderContext(), glu::GLSL_VERSION_100_ES);
182	m_referenceRenderer		= new ReferenceQuadRenderer;
183	m_refColorBuffer		= new TextureLevel(TextureFormat(useRGB ? TextureFormat::RGB : TextureFormat::RGBA, TextureFormat::UNORM_INT8),
184											   m_viewportW, m_viewportH);
185
186	m_curParamSetNdx = 0;
187}
188
189BlendCase::~BlendCase (void)
190{
191	delete m_renderer;
192	delete m_referenceRenderer;
193	delete m_refColorBuffer;
194}
195
196void BlendCase::deinit (void)
197{
198	delete m_renderer;
199	delete m_referenceRenderer;
200	delete m_refColorBuffer;
201
202	m_renderer			= DE_NULL;
203	m_referenceRenderer	= DE_NULL;
204	m_refColorBuffer	= DE_NULL;
205}
206
207BlendCase::IterateResult BlendCase::iterate (void)
208{
209	de::Random						rnd				(deStringHash(getName()) ^ deInt32Hash(m_curParamSetNdx));
210	int								viewportX		= rnd.getInt(0, m_context.getRenderTarget().getWidth() - m_viewportW);
211	int								viewportY		= rnd.getInt(0, m_context.getRenderTarget().getHeight() - m_viewportH);
212	tcu::Surface					renderedImg		(m_viewportW, m_viewportH);
213	TestLog&						log				(m_testCtx.getLog());
214	const BlendParams&				paramSet		= m_paramSets[m_curParamSetNdx];
215	rr::FragmentOperationState		referenceState;
216
217	// Log the blend parameters.
218
219	log << TestLog::Message << "RGB equation = " << getBlendEquationName(paramSet.equationRGB) << TestLog::EndMessage;
220	log << TestLog::Message << "RGB src func = " << getBlendFactorName(paramSet.srcFuncRGB) << TestLog::EndMessage;
221	log << TestLog::Message << "RGB dst func = " << getBlendFactorName(paramSet.dstFuncRGB) << TestLog::EndMessage;
222	log << TestLog::Message << "Alpha equation = " << getBlendEquationName(paramSet.equationAlpha) << TestLog::EndMessage;
223	log << TestLog::Message << "Alpha src func = " << getBlendFactorName(paramSet.srcFuncAlpha) << TestLog::EndMessage;
224	log << TestLog::Message << "Alpha dst func = " << getBlendFactorName(paramSet.dstFuncAlpha) << TestLog::EndMessage;
225	log << TestLog::Message << "Blend color = (" << paramSet.blendColor.x() << ", " << paramSet.blendColor.y() << ", " << paramSet.blendColor.z() << ", " << paramSet.blendColor.w() << ")" << TestLog::EndMessage;
226
227	// Set GL state.
228
229	GLU_CHECK_CALL(glBlendEquationSeparate(paramSet.equationRGB, paramSet.equationAlpha));
230	GLU_CHECK_CALL(glBlendFuncSeparate(paramSet.srcFuncRGB, paramSet.dstFuncRGB, paramSet.srcFuncAlpha, paramSet.dstFuncAlpha));
231	GLU_CHECK_CALL(glBlendColor(paramSet.blendColor.x(), paramSet.blendColor.y(), paramSet.blendColor.z(), paramSet.blendColor.w()));
232
233	// Set reference state.
234
235	referenceState.blendRGBState.equation	= sglr::rr_util::mapGLBlendEquation(paramSet.equationRGB);
236	referenceState.blendRGBState.srcFunc	= sglr::rr_util::mapGLBlendFunc(paramSet.srcFuncRGB);
237	referenceState.blendRGBState.dstFunc	= sglr::rr_util::mapGLBlendFunc(paramSet.dstFuncRGB);
238	referenceState.blendAState.equation		= sglr::rr_util::mapGLBlendEquation(paramSet.equationAlpha);
239	referenceState.blendAState.srcFunc		= sglr::rr_util::mapGLBlendFunc(paramSet.srcFuncAlpha);
240	referenceState.blendAState.dstFunc		= sglr::rr_util::mapGLBlendFunc(paramSet.dstFuncAlpha);
241	referenceState.blendColor				= paramSet.blendColor;
242
243	// Render with GL.
244
245	glDisable(GL_BLEND);
246	glViewport(viewportX, viewportY, m_viewportW, m_viewportH);
247	m_renderer->render(m_firstQuad);
248	glEnable(GL_BLEND);
249	m_renderer->render(m_secondQuad);
250	glFlush();
251
252	// Render reference.
253
254	const tcu::PixelBufferAccess nullAccess(TextureFormat(), 0, 0, 0, DE_NULL);
255
256	referenceState.blendMode = rr::BLENDMODE_NONE;
257	m_referenceRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()), nullAccess /* no depth */, nullAccess /* no stencil */, m_firstQuadInt, referenceState);
258	referenceState.blendMode = rr::BLENDMODE_STANDARD;
259	m_referenceRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()), nullAccess /* no depth */, nullAccess /* no stencil */, m_secondQuadInt, referenceState);
260
261	// Read GL image.
262
263	glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());
264
265	// Compare images.
266
267	UVec4 compareThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold().toIVec().asUint()
268							 * UVec4(5) / UVec4(2) + UVec4(3); // \note Non-scientific ad hoc formula. Need big threshold when few color bits; blending brings extra inaccuracy.
269
270	bool comparePass = tcu::intThresholdCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", m_refColorBuffer->getAccess(), renderedImg.getAccess(), compareThreshold, tcu::COMPARE_LOG_RESULT);
271
272	// Fail now if images don't match.
273
274	if (!comparePass)
275	{
276		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Image compare failed");
277		return STOP;
278	}
279
280	// Continue if param sets still remain in m_paramSets; otherwise stop.
281
282	m_curParamSetNdx++;
283
284	if (m_curParamSetNdx < (int)m_paramSets.size())
285		return CONTINUE;
286	else
287	{
288		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
289		return STOP;
290	}
291}
292
293BlendTests::BlendTests (Context& context)
294	: TestCaseGroup(context, "blend", "Blend tests")
295{
296}
297
298BlendTests::~BlendTests (void)
299{
300}
301
302void BlendTests::init (void)
303{
304	struct EnumGL
305	{
306		GLenum			glValue;
307		const char*		nameStr;
308	};
309
310	static const EnumGL blendEquations[] =
311	{
312		{ GL_FUNC_ADD,					"add"					},
313		{ GL_FUNC_SUBTRACT,				"subtract"				},
314		{ GL_FUNC_REVERSE_SUBTRACT,		"reverse_subtract"		}
315	};
316
317	static const EnumGL blendFunctions[] =
318	{
319		{ GL_ZERO,							"zero"						},
320		{ GL_ONE,							"one"						},
321		{ GL_SRC_COLOR,						"src_color"					},
322		{ GL_ONE_MINUS_SRC_COLOR,			"one_minus_src_color"		},
323		{ GL_DST_COLOR,						"dst_color"					},
324		{ GL_ONE_MINUS_DST_COLOR,			"one_minus_dst_color"		},
325		{ GL_SRC_ALPHA,						"src_alpha"					},
326		{ GL_ONE_MINUS_SRC_ALPHA,			"one_minus_src_alpha"		},
327		{ GL_DST_ALPHA,						"dst_alpha"					},
328		{ GL_ONE_MINUS_DST_ALPHA,			"one_minus_dst_alpha"		},
329		{ GL_CONSTANT_COLOR,				"constant_color"			},
330		{ GL_ONE_MINUS_CONSTANT_COLOR,		"one_minus_constant_color"	},
331		{ GL_CONSTANT_ALPHA,				"constant_alpha"			},
332		{ GL_ONE_MINUS_CONSTANT_ALPHA,		"one_minus_constant_alpha"	},
333		{ GL_SRC_ALPHA_SATURATE,			"src_alpha_saturate"		}
334	};
335
336	const Vec4 defaultBlendColor(0.2f, 0.4f, 0.6f, 0.8f);
337
338	// Test all blend equation, src blend function, dst blend function combinations. RGB and alpha modes are the same.
339
340	{
341		TestCaseGroup* group = new TestCaseGroup(m_context, "equation_src_func_dst_func", "Combinations of Blend Equations and Functions");
342		addChild(group);
343
344		for (int equationNdx = 0;	equationNdx < DE_LENGTH_OF_ARRAY(blendEquations);	equationNdx++)
345		for (int srcFuncNdx = 0;	srcFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);	srcFuncNdx++)
346		for (int dstFuncNdx = 0;	dstFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);	dstFuncNdx++)
347		{
348			const EnumGL& eq	= blendEquations[equationNdx];
349			const EnumGL& src	= blendFunctions[srcFuncNdx];
350			const EnumGL& dst	= blendFunctions[dstFuncNdx];
351
352			if (dst.glValue == GL_SRC_ALPHA_SATURATE) // SRC_ALPHA_SATURATE is only valid for src func.
353				continue;
354
355			string name			= string("") + eq.nameStr + "_" + src.nameStr + "_" + dst.nameStr;
356			string description	= string("") +
357								  "Equations "		+ getBlendEquationName(eq.glValue) +
358								  ", src funcs "	+ getBlendFactorName(src.glValue) +
359								  ", dst funcs "	+ getBlendFactorName(dst.glValue);
360
361			vector<BlendParams> paramSets;
362			paramSets.push_back(BlendParams(eq.glValue, src.glValue, dst.glValue, eq.glValue, src.glValue, dst.glValue, defaultBlendColor));
363
364			group->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets));
365		}
366	}
367
368	// Test all RGB src, alpha src and RGB dst, alpha dst combinations. Equations are ADD.
369	// \note For all RGB src, alpha src combinations, also test a couple of different RGBA dst functions, and vice versa.
370
371	{
372		TestCaseGroup* mainGroup = new TestCaseGroup(m_context, "rgb_func_alpha_func", "Combinations of RGB and Alpha Functions");
373		addChild(mainGroup);
374		TestCaseGroup* srcGroup = new TestCaseGroup(m_context, "src", "Source functions");
375		TestCaseGroup* dstGroup = new TestCaseGroup(m_context, "dst", "Destination functions");
376		mainGroup->addChild(srcGroup);
377		mainGroup->addChild(dstGroup);
378
379		for (int isDstI = 0;		isDstI <= 1;										isDstI++)
380		for (int rgbFuncNdx = 0;	rgbFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);	rgbFuncNdx++)
381		for (int alphaFuncNdx = 0;	alphaFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);	alphaFuncNdx++)
382		{
383			bool			isSrc			= isDstI == 0;
384			TestCaseGroup*	curGroup		= isSrc ? srcGroup : dstGroup;
385			const EnumGL&	funcRGB			= blendFunctions[rgbFuncNdx];
386			const EnumGL&	funcAlpha		= blendFunctions[alphaFuncNdx];
387			const char*		dstOrSrcStr		= isSrc ? "src" : "dst";
388
389			if (!isSrc && (funcRGB.glValue == GL_SRC_ALPHA_SATURATE || funcAlpha.glValue == GL_SRC_ALPHA_SATURATE)) // SRC_ALPHA_SATURATE is only valid for src func.
390				continue;
391
392			string name			= string("") + funcRGB.nameStr + "_" + funcAlpha.nameStr;
393			string description	= string("") +
394								  "RGB "		+ dstOrSrcStr + " func " + getBlendFactorName(funcRGB.glValue) +
395								  ", alpha "	+ dstOrSrcStr + " func " + getBlendFactorName(funcAlpha.glValue);
396
397			// First, make param sets as if this was a src case.
398
399			vector<BlendParams> paramSets;
400			paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_ONE,			GL_FUNC_ADD, funcAlpha.glValue, GL_ONE,			defaultBlendColor));
401			paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_ZERO,			GL_FUNC_ADD, funcAlpha.glValue, GL_ZERO,		defaultBlendColor));
402			paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_SRC_COLOR,		GL_FUNC_ADD, funcAlpha.glValue, GL_SRC_COLOR,	defaultBlendColor));
403			paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_DST_COLOR,		GL_FUNC_ADD, funcAlpha.glValue, GL_DST_COLOR,	defaultBlendColor));
404
405			// Swap src and dst params if this is a dst case.
406
407			if (!isSrc)
408			{
409				for (int i = 0; i < (int)paramSets.size(); i++)
410				{
411					std::swap(paramSets[i].srcFuncRGB,		paramSets[i].dstFuncRGB);
412					std::swap(paramSets[i].srcFuncAlpha,	paramSets[i].dstFuncAlpha);
413				}
414			}
415
416			curGroup->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets));
417		}
418	}
419
420	// Test all RGB and alpha equation combinations. Src and dst funcs are ONE for both.
421
422	{
423		TestCaseGroup* group = new TestCaseGroup(m_context, "rgb_equation_alpha_equation", "Combinations of RGB and Alpha Equation Combinations");
424		addChild(group);
425
426		for (int equationRGBNdx = 0;	equationRGBNdx < DE_LENGTH_OF_ARRAY(blendEquations);	equationRGBNdx++)
427		for (int equationAlphaNdx = 0;	equationAlphaNdx < DE_LENGTH_OF_ARRAY(blendEquations);	equationAlphaNdx++)
428		{
429			const EnumGL& eqRGB			= blendEquations[equationRGBNdx];
430			const EnumGL& eqAlpha		= blendEquations[equationAlphaNdx];
431
432			string name			= string("") + eqRGB.nameStr + "_" + eqAlpha.nameStr;
433			string description	= string("") +
434								  "RGB equation "		+ getBlendEquationName(eqRGB.glValue) +
435								  ", alpha equation "	+ getBlendEquationName(eqAlpha.glValue);
436
437			vector<BlendParams> paramSets;
438			paramSets.push_back(BlendParams(eqRGB.glValue, GL_ONE, GL_ONE, eqAlpha.glValue, GL_ONE, GL_ONE, defaultBlendColor));
439
440			group->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets));
441		}
442	}
443}
444
445} // Functional
446} // gles2
447} // deqp
448