am 114eb0ab: (-s ours) am 61cf23d7: Remove a few tests from M mustpass am: 3c4fdbd832
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fBlendTests.cpp
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
68 // \note src and dst can point to same memory as long as there is 1-to-1 correspondence between
69 //               pixels.
70 static void sRGBAToLinear (const tcu::PixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src)
71 {
72         const int       width   = src.getWidth();
73         const int       height  = src.getHeight();
74
75         for (int y = 0; y < height; y++)
76         for (int x = 0; x < width; x++)
77                 dst.setPixel(tcu::sRGBToLinear(src.getPixel(x, y)), x, y);
78 }
79
80 struct BlendParams
81 {
82         GLenum  equationRGB;
83         GLenum  srcFuncRGB;
84         GLenum  dstFuncRGB;
85         GLenum  equationAlpha;
86         GLenum  srcFuncAlpha;
87         GLenum  dstFuncAlpha;
88         Vec4    blendColor;
89
90         BlendParams (GLenum             equationRGB_,
91                                  GLenum         srcFuncRGB_,
92                                  GLenum         dstFuncRGB_,
93                                  GLenum         equationAlpha_,
94                                  GLenum         srcFuncAlpha_,
95                                  GLenum         dstFuncAlpha_,
96                                  Vec4           blendColor_)
97         : equationRGB   (equationRGB_)
98         , srcFuncRGB    (srcFuncRGB_)
99         , dstFuncRGB    (dstFuncRGB_)
100         , equationAlpha (equationAlpha_)
101         , srcFuncAlpha  (srcFuncAlpha_)
102         , dstFuncAlpha  (dstFuncAlpha_)
103         , blendColor    (blendColor_)
104         {
105         }
106 };
107
108 class BlendCase : public TestCase
109 {
110 public:
111                                                         BlendCase       (Context&                                               context,
112                                                                                  const char*                                    name,
113                                                                                  const char*                                    desc,
114                                                                                  const vector<BlendParams>&             paramSets,
115                                                                                  bool                                                   useSrgbFbo);
116
117                                                         ~BlendCase      (void);
118
119         void                                    init            (void);
120         void                                    deinit          (void);
121
122         IterateResult                   iterate         (void);
123
124 private:
125                                                         BlendCase       (const BlendCase& other);
126         BlendCase&                              operator=       (const BlendCase& other);
127
128         vector<BlendParams>             m_paramSets;
129         int                                             m_curParamSetNdx;
130
131         bool                                    m_useSrgbFbo;
132         deUint32                                m_colorRbo;
133         deUint32                                m_fbo;
134
135         QuadRenderer*                   m_renderer;
136         ReferenceQuadRenderer*  m_referenceRenderer;
137         TextureLevel*                   m_refColorBuffer;
138         Quad                                    m_firstQuad;
139         Quad                                    m_secondQuad;
140         IntegerQuad                             m_firstQuadInt;
141         IntegerQuad                             m_secondQuadInt;
142
143         int                                             m_renderWidth;
144         int                                             m_renderHeight;
145         int                                             m_viewportWidth;
146         int                                             m_viewportHeight;
147 };
148
149 BlendCase::BlendCase (Context&                                          context,
150                                           const char*                                   name,
151                                           const char*                                   desc,
152                                           const vector<BlendParams>&    paramSets,
153                                           bool                                                  useSrgbFbo)
154         : TestCase                              (context, name, desc)
155         , m_paramSets                   (paramSets)
156         , m_curParamSetNdx              (0)
157         , m_useSrgbFbo                  (useSrgbFbo)
158         , m_colorRbo                    (0)
159         , m_fbo                                 (0)
160         , m_renderer                    (DE_NULL)
161         , m_referenceRenderer   (DE_NULL)
162         , m_refColorBuffer              (DE_NULL)
163         , m_renderWidth                 (m_useSrgbFbo ? 2*MAX_VIEWPORT_WIDTH    : m_context.getRenderTarget().getWidth())
164         , m_renderHeight                (m_useSrgbFbo ? 2*MAX_VIEWPORT_HEIGHT   : m_context.getRenderTarget().getHeight())
165         , m_viewportWidth               (0)
166         , m_viewportHeight              (0)
167 {
168         DE_ASSERT(!m_paramSets.empty());
169 }
170
171 void BlendCase::init (void)
172 {
173         bool useRGB = !m_useSrgbFbo && m_context.getRenderTarget().getPixelFormat().alphaBits == 0;
174
175         static const Vec4 baseGradientColors[4] =
176         {
177                 Vec4(0.0f, 0.5f, 1.0f, 0.5f),
178                 Vec4(0.5f, 0.0f, 0.5f, 1.0f),
179                 Vec4(0.5f, 1.0f, 0.5f, 0.0f),
180                 Vec4(1.0f, 0.5f, 0.0f, 0.5f)
181         };
182
183         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_firstQuad.color) == DE_LENGTH_OF_ARRAY(m_firstQuadInt.color));
184         for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_firstQuad.color); i++)
185         {
186                 m_firstQuad.color[i]            = (baseGradientColors[i] - 0.5f) * 0.2f + 0.5f;
187                 m_firstQuadInt.color[i]         = m_firstQuad.color[i];
188
189                 m_secondQuad.color[i]           = (Vec4(1.0f) - baseGradientColors[i] - 0.5f) * 1.0f + 0.5f;
190                 m_secondQuadInt.color[i]        = m_secondQuad.color[i];
191         }
192
193         m_viewportWidth         = de::min<int>(m_renderWidth,   MAX_VIEWPORT_WIDTH);
194         m_viewportHeight        = de::min<int>(m_renderHeight,  MAX_VIEWPORT_HEIGHT);
195
196         m_firstQuadInt.posA             = tcu::IVec2(0,                                         0);
197         m_secondQuadInt.posA    = tcu::IVec2(0,                                         0);
198         m_firstQuadInt.posB             = tcu::IVec2(m_viewportWidth-1,         m_viewportHeight-1);
199         m_secondQuadInt.posB    = tcu::IVec2(m_viewportWidth-1,         m_viewportHeight-1);
200
201         DE_ASSERT(!m_renderer);
202         DE_ASSERT(!m_referenceRenderer);
203         DE_ASSERT(!m_refColorBuffer);
204
205         m_renderer                              = new QuadRenderer(m_context.getRenderContext(), glu::GLSL_VERSION_300_ES);
206         m_referenceRenderer             = new ReferenceQuadRenderer;
207         m_refColorBuffer                = new TextureLevel(TextureFormat(m_useSrgbFbo ? TextureFormat::sRGBA : useRGB ? TextureFormat::RGB : TextureFormat::RGBA, TextureFormat::UNORM_INT8),
208                                                                                            m_viewportWidth, m_viewportHeight);
209
210         m_curParamSetNdx = 0;
211
212         if (m_useSrgbFbo)
213         {
214                 m_testCtx.getLog() << TestLog::Message << "Using FBO of size (" << m_renderWidth << ", " << m_renderHeight << ") with format GL_SRGB8_ALPHA8" << TestLog::EndMessage;
215
216                 GLU_CHECK_CALL(glGenRenderbuffers(1, &m_colorRbo));
217                 GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo));
218                 GLU_CHECK_CALL(glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, m_renderWidth, m_renderHeight));
219
220                 GLU_CHECK_CALL(glGenFramebuffers(1, &m_fbo));
221                 GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo));
222                 GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo));
223         }
224 }
225
226 BlendCase::~BlendCase (void)
227 {
228         BlendCase::deinit();
229 }
230
231 void BlendCase::deinit (void)
232 {
233         delete m_renderer;
234         delete m_referenceRenderer;
235         delete m_refColorBuffer;
236
237         m_renderer                      = DE_NULL;
238         m_referenceRenderer     = DE_NULL;
239         m_refColorBuffer        = DE_NULL;
240
241         GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
242         GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
243
244         if (m_colorRbo != 0)
245         {
246                 GLU_CHECK_CALL(glDeleteRenderbuffers(1, &m_colorRbo));
247                 m_colorRbo = 0;
248         }
249         if (m_fbo != 0)
250         {
251                 GLU_CHECK_CALL(glDeleteFramebuffers(1, &m_fbo));
252                 m_fbo = 0;
253         }
254 }
255
256 BlendCase::IterateResult BlendCase::iterate (void)
257 {
258         de::Random                                              rnd                             (deStringHash(getName()) ^ deInt32Hash(m_curParamSetNdx));
259         int                                                             viewportX               = rnd.getInt(0, m_renderWidth - m_viewportWidth);
260         int                                                             viewportY               = rnd.getInt(0, m_renderHeight - m_viewportHeight);
261         TextureLevel                                    renderedImg             (TextureFormat(m_useSrgbFbo ? TextureFormat::sRGBA : TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight);
262         TextureLevel                                    referenceImg    (renderedImg.getFormat(), m_viewportWidth, m_viewportHeight);
263         TestLog&                                                log                             (m_testCtx.getLog());
264         const BlendParams&                              paramSet                = m_paramSets[m_curParamSetNdx];
265         rr::FragmentOperationState              referenceState;
266
267         // Log the blend parameters.
268
269         log << TestLog::Message << "RGB equation = " << getBlendEquationName(paramSet.equationRGB) << TestLog::EndMessage;
270         log << TestLog::Message << "RGB src func = " << getBlendFactorName(paramSet.srcFuncRGB) << TestLog::EndMessage;
271         log << TestLog::Message << "RGB dst func = " << getBlendFactorName(paramSet.dstFuncRGB) << TestLog::EndMessage;
272         log << TestLog::Message << "Alpha equation = " << getBlendEquationName(paramSet.equationAlpha) << TestLog::EndMessage;
273         log << TestLog::Message << "Alpha src func = " << getBlendFactorName(paramSet.srcFuncAlpha) << TestLog::EndMessage;
274         log << TestLog::Message << "Alpha dst func = " << getBlendFactorName(paramSet.dstFuncAlpha) << TestLog::EndMessage;
275         log << TestLog::Message << "Blend color = (" << paramSet.blendColor.x() << ", " << paramSet.blendColor.y() << ", " << paramSet.blendColor.z() << ", " << paramSet.blendColor.w() << ")" << TestLog::EndMessage;
276
277         // Set GL state.
278
279         GLU_CHECK_CALL(glBlendEquationSeparate(paramSet.equationRGB, paramSet.equationAlpha));
280         GLU_CHECK_CALL(glBlendFuncSeparate(paramSet.srcFuncRGB, paramSet.dstFuncRGB, paramSet.srcFuncAlpha, paramSet.dstFuncAlpha));
281         GLU_CHECK_CALL(glBlendColor(paramSet.blendColor.x(), paramSet.blendColor.y(), paramSet.blendColor.z(), paramSet.blendColor.w()));
282
283         // Set reference state.
284
285         referenceState.blendRGBState.equation   = sglr::rr_util::mapGLBlendEquation(paramSet.equationRGB);
286         referenceState.blendRGBState.srcFunc    = sglr::rr_util::mapGLBlendFunc(paramSet.srcFuncRGB);
287         referenceState.blendRGBState.dstFunc    = sglr::rr_util::mapGLBlendFunc(paramSet.dstFuncRGB);
288         referenceState.blendAState.equation             = sglr::rr_util::mapGLBlendEquation(paramSet.equationAlpha);
289         referenceState.blendAState.srcFunc              = sglr::rr_util::mapGLBlendFunc(paramSet.srcFuncAlpha);
290         referenceState.blendAState.dstFunc              = sglr::rr_util::mapGLBlendFunc(paramSet.dstFuncAlpha);
291         referenceState.blendColor                               = paramSet.blendColor;
292
293         // Render with GL.
294
295         glDisable(GL_BLEND);
296         glViewport(viewportX, viewportY, m_viewportWidth, m_viewportHeight);
297         m_renderer->render(m_firstQuad);
298         glEnable(GL_BLEND);
299         m_renderer->render(m_secondQuad);
300         glFlush();
301
302         // Render reference.
303
304         const tcu::PixelBufferAccess nullAccess = tcu::PixelBufferAccess();
305
306         referenceState.blendMode = rr::BLENDMODE_NONE;
307         m_referenceRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()), nullAccess /* no depth */, nullAccess /* no stencil */, m_firstQuadInt, referenceState);
308         referenceState.blendMode = rr::BLENDMODE_STANDARD;
309         m_referenceRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()), nullAccess /* no depth */, nullAccess /* no stencil */, m_secondQuadInt, referenceState);
310
311         // Copy to reference (expansion to RGBA happens here if necessary)
312         copy(referenceImg, m_refColorBuffer->getAccess());
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         if (m_useSrgbFbo)
322         {
323                 sRGBAToLinear(renderedImg, renderedImg);
324                 sRGBAToLinear(referenceImg, referenceImg);
325         }
326
327         UVec4 compareThreshold = (m_useSrgbFbo ? tcu::PixelFormat(8, 8, 8, 8) : m_context.getRenderTarget().getPixelFormat()).getColorThreshold().toIVec().asUint()
328                                                          * 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.
329
330         bool comparePass = tcu::intThresholdCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result",
331                                                                                                 referenceImg.getAccess(), renderedImg.getAccess(),
332                                                                                                 compareThreshold, tcu::COMPARE_LOG_RESULT);
333
334         // Fail now if images don't match.
335
336         if (!comparePass)
337         {
338                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Image compare failed");
339                 return STOP;
340         }
341
342         // Continue if param sets still remain in m_paramSets; otherwise stop.
343
344         m_curParamSetNdx++;
345
346         if (m_curParamSetNdx < (int)m_paramSets.size())
347                 return CONTINUE;
348         else
349         {
350                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
351                 return STOP;
352         }
353 }
354
355 BlendTests::BlendTests (Context& context)
356         : TestCaseGroup(context, "blend", "Blend tests")
357 {
358 }
359
360 BlendTests::~BlendTests (void)
361 {
362 }
363
364 void BlendTests::init (void)
365 {
366         struct EnumGL
367         {
368                 GLenum                  glValue;
369                 const char*             nameStr;
370         };
371
372         static const EnumGL blendEquations[] =
373         {
374                 { GL_FUNC_ADD,                                  "add"                                   },
375                 { GL_FUNC_SUBTRACT,                             "subtract"                              },
376                 { GL_FUNC_REVERSE_SUBTRACT,             "reverse_subtract"              },
377                 { GL_MIN,                                               "min"                                   },
378                 { GL_MAX,                                               "max"                                   }
379         };
380
381         static const EnumGL blendFunctions[] =
382         {
383                 { GL_ZERO,                                                      "zero"                                          },
384                 { GL_ONE,                                                       "one"                                           },
385                 { GL_SRC_COLOR,                                         "src_color"                                     },
386                 { GL_ONE_MINUS_SRC_COLOR,                       "one_minus_src_color"           },
387                 { GL_DST_COLOR,                                         "dst_color"                                     },
388                 { GL_ONE_MINUS_DST_COLOR,                       "one_minus_dst_color"           },
389                 { GL_SRC_ALPHA,                                         "src_alpha"                                     },
390                 { GL_ONE_MINUS_SRC_ALPHA,                       "one_minus_src_alpha"           },
391                 { GL_DST_ALPHA,                                         "dst_alpha"                                     },
392                 { GL_ONE_MINUS_DST_ALPHA,                       "one_minus_dst_alpha"           },
393                 { GL_CONSTANT_COLOR,                            "constant_color"                        },
394                 { GL_ONE_MINUS_CONSTANT_COLOR,          "one_minus_constant_color"      },
395                 { GL_CONSTANT_ALPHA,                            "constant_alpha"                        },
396                 { GL_ONE_MINUS_CONSTANT_ALPHA,          "one_minus_constant_alpha"      },
397                 { GL_SRC_ALPHA_SATURATE,                        "src_alpha_saturate"            }
398         };
399
400         const Vec4 defaultBlendColor(0.2f, 0.4f, 0.6f, 0.8f);
401
402         for (int useSrgbFboI = 0; useSrgbFboI <= 1; useSrgbFboI++)
403         {
404                 bool                    useSrgbFbo      = useSrgbFboI != 0;
405                 TestCaseGroup*  fbGroup         = new TestCaseGroup(m_context, useSrgbFbo ? "fbo_srgb" : "default_framebuffer", useSrgbFbo ? "Use a FBO with GL_SRGB8_ALPHA8" : "Use the default framebuffer");
406                 addChild(fbGroup);
407
408                 // Test all blend equation, src blend function, dst blend function combinations. RGB and alpha modes are the same.
409
410                 {
411                         TestCaseGroup* group = new TestCaseGroup(m_context, "equation_src_func_dst_func", "Combinations of Blend Equations and Functions");
412                         fbGroup->addChild(group);
413
414                         for (int equationNdx = 0;       equationNdx < DE_LENGTH_OF_ARRAY(blendEquations);       equationNdx++)
415                         for (int srcFuncNdx = 0;        srcFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);        srcFuncNdx++)
416                         for (int dstFuncNdx = 0;        dstFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);        dstFuncNdx++)
417                         {
418                                 const EnumGL& eq        = blendEquations[equationNdx];
419                                 const EnumGL& src       = blendFunctions[srcFuncNdx];
420                                 const EnumGL& dst       = blendFunctions[dstFuncNdx];
421
422                                 if ((eq.glValue == GL_MIN || eq.glValue == GL_MAX) && (srcFuncNdx > 0 || dstFuncNdx > 0)) // MIN and MAX don't depend on factors.
423                                         continue;
424
425                                 string name                     = eq.nameStr;
426                                 string description      = string("") +
427                                                                           "Equations "          + getBlendEquationName(eq.glValue) +
428                                                                           ", src funcs "        + getBlendFactorName(src.glValue) +
429                                                                           ", dst funcs "        + getBlendFactorName(dst.glValue);
430
431                                 if (eq.glValue != GL_MIN && eq.glValue != GL_MAX)
432                                         name += string("") + "_" + src.nameStr + "_" + dst.nameStr;
433
434                                 vector<BlendParams> paramSets;
435                                 paramSets.push_back(BlendParams(eq.glValue, src.glValue, dst.glValue, eq.glValue, src.glValue, dst.glValue, defaultBlendColor));
436
437                                 group->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets, useSrgbFbo));
438                         }
439                 }
440
441                 // Test all RGB src, alpha src and RGB dst, alpha dst combinations. Equations are ADD.
442                 // \note For all RGB src, alpha src combinations, also test a couple of different RGBA dst functions, and vice versa.
443
444                 {
445                         TestCaseGroup* mainGroup = new TestCaseGroup(m_context, "rgb_func_alpha_func", "Combinations of RGB and Alpha Functions");
446                         fbGroup->addChild(mainGroup);
447                         TestCaseGroup* srcGroup = new TestCaseGroup(m_context, "src", "Source functions");
448                         TestCaseGroup* dstGroup = new TestCaseGroup(m_context, "dst", "Destination functions");
449                         mainGroup->addChild(srcGroup);
450                         mainGroup->addChild(dstGroup);
451
452                         for (int isDstI = 0;            isDstI <= 1;                                                                            isDstI++)
453                         for (int rgbFuncNdx = 0;        rgbFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);        rgbFuncNdx++)
454                         for (int alphaFuncNdx = 0;      alphaFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);      alphaFuncNdx++)
455                         {
456                                 bool                    isSrc                   = isDstI == 0;
457                                 TestCaseGroup*  curGroup                = isSrc ? srcGroup : dstGroup;
458                                 const EnumGL&   funcRGB                 = blendFunctions[rgbFuncNdx];
459                                 const EnumGL&   funcAlpha               = blendFunctions[alphaFuncNdx];
460                                 const char*             dstOrSrcStr             = isSrc ? "src" : "dst";
461
462                                 string name                     = string("") + funcRGB.nameStr + "_" + funcAlpha.nameStr;
463                                 string description      = string("") +
464                                                                           "RGB "                + dstOrSrcStr + " func " + getBlendFactorName(funcRGB.glValue) +
465                                                                           ", alpha "    + dstOrSrcStr + " func " + getBlendFactorName(funcAlpha.glValue);
466
467                                 // First, make param sets as if this was a src case.
468
469                                 vector<BlendParams> paramSets;
470                                 paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_ONE,                   GL_FUNC_ADD, funcAlpha.glValue, GL_ONE,                 defaultBlendColor));
471                                 paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_ZERO,                  GL_FUNC_ADD, funcAlpha.glValue, GL_ZERO,                defaultBlendColor));
472                                 paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_SRC_COLOR,             GL_FUNC_ADD, funcAlpha.glValue, GL_SRC_COLOR,   defaultBlendColor));
473                                 paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_DST_COLOR,             GL_FUNC_ADD, funcAlpha.glValue, GL_DST_COLOR,   defaultBlendColor));
474
475                                 // Swap src and dst params if this is a dst case.
476
477                                 if (!isSrc)
478                                 {
479                                         for (int i = 0; i < (int)paramSets.size(); i++)
480                                         {
481                                                 std::swap(paramSets[i].srcFuncRGB,              paramSets[i].dstFuncRGB);
482                                                 std::swap(paramSets[i].srcFuncAlpha,    paramSets[i].dstFuncAlpha);
483                                         }
484                                 }
485
486                                 curGroup->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets, useSrgbFbo));
487                         }
488                 }
489
490                 // Test all RGB and alpha equation combinations. Src and dst funcs are ONE for both.
491
492                 {
493                         TestCaseGroup* group = new TestCaseGroup(m_context, "rgb_equation_alpha_equation", "Combinations of RGB and Alpha Equation Combinations");
494                         fbGroup->addChild(group);
495
496                         for (int equationRGBNdx = 0;    equationRGBNdx < DE_LENGTH_OF_ARRAY(blendEquations);    equationRGBNdx++)
497                         for (int equationAlphaNdx = 0;  equationAlphaNdx < DE_LENGTH_OF_ARRAY(blendEquations);  equationAlphaNdx++)
498                         {
499                                 const EnumGL& eqRGB                     = blendEquations[equationRGBNdx];
500                                 const EnumGL& eqAlpha           = blendEquations[equationAlphaNdx];
501
502                                 string name                     = string("") + eqRGB.nameStr + "_" + eqAlpha.nameStr;
503                                 string description      = string("") +
504                                                                           "RGB equation "               + getBlendEquationName(eqRGB.glValue) +
505                                                                           ", alpha equation "   + getBlendEquationName(eqAlpha.glValue);
506
507                                 vector<BlendParams> paramSets;
508                                 paramSets.push_back(BlendParams(eqRGB.glValue, GL_ONE, GL_ONE, eqAlpha.glValue, GL_ONE, GL_ONE, defaultBlendColor));
509
510                                 group->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets, useSrgbFbo));
511                         }
512                 }
513         }
514 }
515
516 } // Functional
517 } // gles3
518 } // deqp