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