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