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 43namespace deqp 44{ 45 46using gls::FragmentOpUtil::Quad; 47using gls::FragmentOpUtil::IntegerQuad; 48using gls::FragmentOpUtil::QuadRenderer; 49using gls::FragmentOpUtil::ReferenceQuadRenderer; 50using glu::getBlendEquationName; 51using glu::getBlendFactorName; 52using tcu::Vec4; 53using tcu::UVec4; 54using tcu::TestLog; 55using tcu::TextureLevel; 56using tcu::TextureFormat; 57using std::string; 58using std::vector; 59 60namespace gles3 61{ 62namespace Functional 63{ 64 65static const int MAX_VIEWPORT_WIDTH = 64; 66static const int MAX_VIEWPORT_HEIGHT = 64; 67 68static 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 84struct BlendParams 85{ 86 GLenum equationRGB; 87 GLenum srcFuncRGB; 88 GLenum dstFuncRGB; 89 GLenum equationAlpha; 90 GLenum srcFuncAlpha; 91 GLenum dstFuncAlpha; 92 Vec4 blendColor; 93 94 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 112class BlendCase : public TestCase 113{ 114public: 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 128private: 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 153BlendCase::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 175void 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 230BlendCase::~BlendCase (void) 231{ 232 BlendCase::deinit(); 233} 234 235void 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 260BlendCase::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 350BlendTests::BlendTests (Context& context) 351 : TestCaseGroup(context, "blend", "Blend tests") 352{ 353} 354 355BlendTests::~BlendTests (void) 356{ 357} 358 359void 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