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 Advanced blending (GL_KHR_blend_equation_advanced) tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fAdvancedBlendTests.hpp" 25 #include "gluStrUtil.hpp" 26 #include "glsFragmentOpUtil.hpp" 27 #include "gluPixelTransfer.hpp" 28 #include "gluObjectWrapper.hpp" 29 #include "gluContextInfo.hpp" 30 #include "gluShaderProgram.hpp" 31 #include "tcuPixelFormat.hpp" 32 #include "tcuTexture.hpp" 33 #include "tcuTextureUtil.hpp" 34 #include "tcuImageCompare.hpp" 35 #include "tcuRenderTarget.hpp" 36 #include "tcuTestLog.hpp" 37 #include "tcuStringTemplate.hpp" 38 #include "deRandom.hpp" 39 #include "rrFragmentOperations.hpp" 40 #include "sglrReferenceUtils.hpp" 41 #include "glwEnums.hpp" 42 #include "glwFunctions.hpp" 43 44 #include <string> 45 #include <vector> 46 47 namespace deqp 48 { 49 50 using gls::FragmentOpUtil::IntegerQuad; 51 using gls::FragmentOpUtil::ReferenceQuadRenderer; 52 using tcu::TextureLevel; 53 using tcu::Vec2; 54 using tcu::Vec4; 55 using tcu::UVec4; 56 using tcu::TestLog; 57 using tcu::TextureFormat; 58 using std::string; 59 using std::vector; 60 using std::map; 61 62 namespace gles31 63 { 64 namespace Functional 65 { 66 67 namespace 68 { 69 70 enum 71 { 72 MAX_VIEWPORT_WIDTH = 128, 73 MAX_VIEWPORT_HEIGHT = 128 74 }; 75 76 enum RenderTargetType 77 { 78 RENDERTARGETTYPE_DEFAULT = 0, //!< Default framebuffer 79 RENDERTARGETTYPE_SRGB_FBO, 80 RENDERTARGETTYPE_MSAA_FBO, 81 82 RENDERTARGETTYPE_LAST 83 }; 84 85 class AdvancedBlendCase : public TestCase 86 { 87 public: 88 AdvancedBlendCase (Context& context, const char* name, const char* desc, deUint32 mode, int overdrawCount, bool coherent, RenderTargetType rtType); 89 90 ~AdvancedBlendCase (void); 91 92 void init (void); 93 void deinit (void); 94 95 IterateResult iterate (void); 96 97 private: 98 AdvancedBlendCase (const AdvancedBlendCase&); 99 AdvancedBlendCase& operator= (const AdvancedBlendCase&); 100 101 const deUint32 m_blendMode; 102 const int m_overdrawCount; 103 const bool m_coherentBlending; 104 const RenderTargetType m_rtType; 105 const int m_numIters; 106 107 deUint32 m_colorRbo; 108 deUint32 m_fbo; 109 110 deUint32 m_resolveColorRbo; 111 deUint32 m_resolveFbo; 112 113 glu::ShaderProgram* m_program; 114 115 ReferenceQuadRenderer* m_referenceRenderer; 116 TextureLevel* m_refColorBuffer; 117 118 const int m_renderWidth; 119 const int m_renderHeight; 120 const int m_viewportWidth; 121 const int m_viewportHeight; 122 123 int m_iterNdx; 124 }; 125 126 AdvancedBlendCase::AdvancedBlendCase (Context& context, 127 const char* name, 128 const char* desc, 129 deUint32 mode, 130 int overdrawCount, 131 bool coherent, 132 RenderTargetType rtType) 133 : TestCase (context, name, desc) 134 , m_blendMode (mode) 135 , m_overdrawCount (overdrawCount) 136 , m_coherentBlending (coherent) 137 , m_rtType (rtType) 138 , m_numIters (5) 139 , m_colorRbo (0) 140 , m_fbo (0) 141 , m_resolveColorRbo (0) 142 , m_resolveFbo (0) 143 , m_program (DE_NULL) 144 , m_referenceRenderer (DE_NULL) 145 , m_refColorBuffer (DE_NULL) 146 , m_renderWidth (rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_WIDTH : m_context.getRenderTarget().getWidth()) 147 , m_renderHeight (rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_HEIGHT : m_context.getRenderTarget().getHeight()) 148 , m_viewportWidth (de::min<int>(m_renderWidth, MAX_VIEWPORT_WIDTH)) 149 , m_viewportHeight (de::min<int>(m_renderHeight, MAX_VIEWPORT_HEIGHT)) 150 , m_iterNdx (0) 151 { 152 } 153 154 const char* getBlendLayoutQualifier (rr::BlendEquationAdvanced equation) 155 { 156 static const char* s_qualifiers[] = 157 { 158 "blend_support_multiply", 159 "blend_support_screen", 160 "blend_support_overlay", 161 "blend_support_darken", 162 "blend_support_lighten", 163 "blend_support_colordodge", 164 "blend_support_colorburn", 165 "blend_support_hardlight", 166 "blend_support_softlight", 167 "blend_support_difference", 168 "blend_support_exclusion", 169 "blend_support_hsl_hue", 170 "blend_support_hsl_saturation", 171 "blend_support_hsl_color", 172 "blend_support_hsl_luminosity", 173 }; 174 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qualifiers) == rr::BLENDEQUATION_ADVANCED_LAST); 175 DE_ASSERT(de::inBounds<int>(equation, 0, rr::BLENDEQUATION_ADVANCED_LAST)); 176 return s_qualifiers[equation]; 177 } 178 179 glu::ProgramSources getBlendProgramSrc (rr::BlendEquationAdvanced equation) 180 { 181 static const char* s_vertSrc = "#version 310 es\n" 182 "in highp vec4 a_position;\n" 183 "in mediump vec4 a_color;\n" 184 "out mediump vec4 v_color;\n" 185 "void main()\n" 186 "{\n" 187 " gl_Position = a_position;\n" 188 " v_color = a_color;\n" 189 "}\n"; 190 static const char* s_fragSrc = "#version 310 es\n" 191 "#extension GL_KHR_blend_equation_advanced : require\n" 192 "in mediump vec4 v_color;\n" 193 "layout(${SUPPORT_QUALIFIER}) out;\n" 194 "layout(location = 0) out mediump vec4 o_color;\n" 195 "void main()\n" 196 "{\n" 197 " o_color = v_color;\n" 198 "}\n"; 199 200 map<string, string> args; 201 202 args["SUPPORT_QUALIFIER"] = getBlendLayoutQualifier(equation); 203 204 return glu::ProgramSources() 205 << glu::VertexSource(s_vertSrc) 206 << glu::FragmentSource(tcu::StringTemplate(s_fragSrc).specialize(args)); 207 } 208 209 void AdvancedBlendCase::init (void) 210 { 211 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 212 const bool useFbo = m_rtType != RENDERTARGETTYPE_DEFAULT; 213 const bool useSRGB = m_rtType == RENDERTARGETTYPE_SRGB_FBO; 214 215 if (!m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced")) 216 throw tcu::NotSupportedError("GL_KHR_blend_equation_advanced is not supported", DE_NULL, __FILE__, __LINE__); 217 218 if (m_coherentBlending && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced_coherent")) 219 throw tcu::NotSupportedError("GL_KHR_blend_equation_advanced_coherent is not supported", DE_NULL, __FILE__, __LINE__); 220 221 TCU_CHECK(gl.blendBarrierKHR); 222 223 DE_ASSERT(!m_program); 224 DE_ASSERT(!m_referenceRenderer); 225 DE_ASSERT(!m_refColorBuffer); 226 227 m_program = new glu::ShaderProgram(m_context.getRenderContext(), getBlendProgramSrc(sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode))); 228 m_testCtx.getLog() << *m_program; 229 230 if (!m_program->isOk()) 231 { 232 delete m_program; 233 m_program = DE_NULL; 234 TCU_FAIL("Compile failed"); 235 } 236 237 m_referenceRenderer = new ReferenceQuadRenderer; 238 m_refColorBuffer = new TextureLevel(TextureFormat(useSRGB ? TextureFormat::sRGBA : TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight); 239 240 if (useFbo) 241 { 242 const deUint32 format = useSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA8; 243 const int numSamples = m_rtType == RENDERTARGETTYPE_MSAA_FBO ? 4 : 0; 244 245 m_testCtx.getLog() << TestLog::Message << "Using FBO of size (" << m_renderWidth << ", " << m_renderHeight << ") with format " 246 << glu::getPixelFormatStr(format) << " and " << numSamples << " samples" 247 << TestLog::EndMessage; 248 249 gl.genRenderbuffers(1, &m_colorRbo); 250 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorRbo); 251 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, format, m_renderWidth, m_renderHeight); 252 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create color RBO"); 253 254 gl.genFramebuffers(1, &m_fbo); 255 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 256 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo); 257 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO"); 258 259 TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 260 261 if (numSamples > 0) 262 { 263 // Create resolve FBO 264 gl.genRenderbuffers(1, &m_resolveColorRbo); 265 gl.bindRenderbuffer(GL_RENDERBUFFER, m_resolveColorRbo); 266 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, m_renderWidth, m_renderHeight); 267 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create resolve color RBO"); 268 269 gl.genFramebuffers(1, &m_resolveFbo); 270 gl.bindFramebuffer(GL_FRAMEBUFFER, m_resolveFbo); 271 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_resolveColorRbo); 272 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO"); 273 274 TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 275 276 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 277 } 278 } 279 else 280 DE_ASSERT(m_rtType == RENDERTARGETTYPE_DEFAULT); 281 282 m_iterNdx = 0; 283 } 284 285 AdvancedBlendCase::~AdvancedBlendCase (void) 286 { 287 AdvancedBlendCase::deinit(); 288 } 289 290 void AdvancedBlendCase::deinit (void) 291 { 292 delete m_program; 293 delete m_referenceRenderer; 294 delete m_refColorBuffer; 295 296 m_program = DE_NULL; 297 m_referenceRenderer = DE_NULL; 298 m_refColorBuffer = DE_NULL; 299 300 if (m_colorRbo || m_fbo) 301 { 302 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 303 304 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 305 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 306 307 if (m_colorRbo != 0) 308 { 309 gl.deleteRenderbuffers(1, &m_colorRbo); 310 m_colorRbo = 0; 311 } 312 313 if (m_fbo != 0) 314 { 315 gl.deleteFramebuffers(1, &m_fbo); 316 m_fbo = 0; 317 } 318 319 if (m_resolveColorRbo) 320 { 321 gl.deleteRenderbuffers(1, &m_resolveColorRbo); 322 m_resolveColorRbo = 0; 323 } 324 325 if (m_resolveFbo) 326 { 327 gl.deleteRenderbuffers(1, &m_resolveFbo); 328 m_resolveFbo = 0; 329 } 330 } 331 } 332 333 static tcu::Vec4 randomColor (de::Random* rnd) 334 { 335 const float rgbValues[] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f }; 336 const float alphaValues[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f }; 337 338 // \note Spec assumes premultiplied inputs. 339 const float a = rnd->choose<float>(DE_ARRAY_BEGIN(alphaValues), DE_ARRAY_END(alphaValues)); 340 const float r = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues)); 341 const float g = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues)); 342 const float b = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues)); 343 return tcu::Vec4(r, g, b, a); 344 } 345 346 static tcu::ConstPixelBufferAccess getLinearAccess (const tcu::ConstPixelBufferAccess& access) 347 { 348 if (access.getFormat().order == TextureFormat::sRGBA) 349 return tcu::ConstPixelBufferAccess(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), 350 access.getWidth(), access.getHeight(), access.getDepth(), 351 access.getRowPitch(), access.getSlicePitch(), access.getDataPtr()); 352 else 353 return access; 354 } 355 356 AdvancedBlendCase::IterateResult AdvancedBlendCase::iterate (void) 357 { 358 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 359 const glw::Functions& gl = renderCtx.getFunctions(); 360 de::Random rnd (deStringHash(getName()) ^ deInt32Hash(m_iterNdx)); 361 const int viewportX = rnd.getInt(0, m_renderWidth - m_viewportWidth); 362 const int viewportY = rnd.getInt(0, m_renderHeight - m_viewportHeight); 363 const bool useFbo = m_rtType != RENDERTARGETTYPE_DEFAULT; 364 const bool requiresResolve = m_rtType == RENDERTARGETTYPE_MSAA_FBO; 365 const int numQuads = m_overdrawCount+1; 366 TextureLevel renderedImg (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight); 367 vector<Vec4> colors (numQuads*4); 368 369 for (vector<Vec4>::iterator col = colors.begin(); col != colors.end(); ++col) 370 *col = randomColor(&rnd); 371 372 // Render with GL. 373 { 374 const deUint32 program = m_program->getProgram(); 375 const int posLoc = gl.getAttribLocation(program, "a_position"); 376 const int colorLoc = gl.getAttribLocation(program, "a_color"); 377 const glu::Buffer indexBuffer (renderCtx); 378 const glu::Buffer positionBuffer (renderCtx); 379 const glu::Buffer colorBuffer (renderCtx); 380 vector<Vec2> positions (numQuads*4); 381 vector<deUint16> indices (numQuads*6); 382 const deUint16 singleQuadIndices[] = { 0, 2, 1, 1, 2, 3 }; 383 const Vec2 singleQuadPos[] = 384 { 385 Vec2(-1.0f, -1.0f), 386 Vec2(-1.0f, +1.0f), 387 Vec2(+1.0f, -1.0f), 388 Vec2(+1.0f, +1.0f), 389 }; 390 391 TCU_CHECK(posLoc >= 0 && colorLoc >= 0); 392 393 for (int quadNdx = 0; quadNdx < numQuads; quadNdx++) 394 { 395 std::copy(DE_ARRAY_BEGIN(singleQuadPos), DE_ARRAY_END(singleQuadPos), &positions[quadNdx*4]); 396 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleQuadIndices); ndx++) 397 indices[quadNdx*6 + ndx] = (deUint16)(quadNdx*4 + singleQuadIndices[ndx]); 398 } 399 400 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *indexBuffer); 401 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size()*sizeof(indices[0])), &indices[0], GL_STATIC_DRAW); 402 403 gl.bindBuffer(GL_ARRAY_BUFFER, *positionBuffer); 404 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(positions.size()*sizeof(positions[0])), &positions[0], GL_STATIC_DRAW); 405 gl.enableVertexAttribArray(posLoc); 406 gl.vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL); 407 408 gl.bindBuffer(GL_ARRAY_BUFFER, *colorBuffer); 409 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(colors.size()*sizeof(colors[0])), &colors[0], GL_STATIC_DRAW); 410 gl.enableVertexAttribArray(colorLoc); 411 gl.vertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 412 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffers"); 413 414 gl.useProgram(program); 415 gl.viewport(viewportX, viewportY, m_viewportWidth, m_viewportHeight); 416 gl.blendEquation(m_blendMode); 417 if (m_coherentBlending) 418 gl.enable(GL_BLEND_ADVANCED_COHERENT_KHR); 419 420 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set render state"); 421 422 gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 423 424 gl.disable(GL_BLEND); 425 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL); 426 gl.enable(GL_BLEND); 427 428 if (!m_coherentBlending) 429 gl.blendBarrierKHR(); 430 431 if (m_coherentBlending) 432 { 433 gl.drawElements(GL_TRIANGLES, 6*(numQuads-1), GL_UNSIGNED_SHORT, (const void*)(deUintptr)(6*sizeof(deUint16))); 434 } 435 else 436 { 437 for (int quadNdx = 1; quadNdx < numQuads; quadNdx++) 438 { 439 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void*)(deUintptr)(quadNdx*6*sizeof(deUint16))); 440 gl.blendBarrierKHR(); 441 } 442 } 443 444 gl.flush(); 445 GLU_EXPECT_NO_ERROR(gl.getError(), "Render failed"); 446 } 447 448 // Render reference. 449 { 450 rr::FragmentOperationState referenceState; 451 const tcu::PixelBufferAccess colorAccess = gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()); 452 const tcu::PixelBufferAccess nullAccess (TextureFormat(), 0, 0, 0, DE_NULL); 453 IntegerQuad quad; 454 455 if (!useFbo && m_context.getRenderTarget().getPixelFormat().alphaBits == 0) 456 { 457 // Emulate lack of alpha by clearing to 1 and masking out alpha writes 458 tcu::clear(*m_refColorBuffer, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 459 referenceState.colorMask = tcu::BVec4(true, true, true, false); 460 } 461 462 referenceState.blendEquationAdvaced = sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode); 463 464 quad.posA = tcu::IVec2(0, 0); 465 quad.posB = tcu::IVec2(m_viewportWidth-1, m_viewportHeight-1); 466 467 for (int quadNdx = 0; quadNdx < numQuads; quadNdx++) 468 { 469 referenceState.blendMode = quadNdx == 0 ? rr::BLENDMODE_NONE : rr::BLENDMODE_ADVANCED; 470 std::copy(&colors[4*quadNdx], &colors[4*quadNdx] + 4, &quad.color[0]); 471 m_referenceRenderer->render(colorAccess, nullAccess /* no depth */, nullAccess /* no stencil */, quad, referenceState); 472 } 473 } 474 475 if (requiresResolve) 476 { 477 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolveFbo); 478 gl.blitFramebuffer(0, 0, m_renderWidth, m_renderHeight, 0, 0, m_renderWidth, m_renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); 479 GLU_EXPECT_NO_ERROR(gl.getError(), "Resolve blit failed"); 480 481 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_resolveFbo); 482 } 483 484 glu::readPixels(renderCtx, viewportX, viewportY, renderedImg.getAccess()); 485 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()"); 486 487 if (requiresResolve) 488 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 489 490 { 491 const bool isHSLMode = m_blendMode == GL_HSL_HUE_KHR || 492 m_blendMode == GL_HSL_SATURATION_KHR || 493 m_blendMode == GL_HSL_COLOR_KHR || 494 m_blendMode == GL_HSL_LUMINOSITY_KHR; 495 bool comparePass = false; 496 497 if (isHSLMode) 498 { 499 // Compensate for more demanding HSL code by using fuzzy comparison. 500 const float threshold = 0.002f; 501 comparePass = tcu::fuzzyCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", 502 getLinearAccess(m_refColorBuffer->getAccess()), 503 renderedImg.getAccess(), 504 threshold, tcu::COMPARE_LOG_RESULT); 505 } 506 else 507 { 508 const UVec4 compareThreshold = (useFbo ? tcu::PixelFormat(8, 8, 8, 8) : m_context.getRenderTarget().getPixelFormat()).getColorThreshold().toIVec().asUint() 509 * UVec4(5) / UVec4(2) + UVec4(3 * m_overdrawCount); 510 511 comparePass = tcu::bilinearCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", 512 getLinearAccess(m_refColorBuffer->getAccess()), 513 renderedImg.getAccess(), 514 tcu::RGBA(compareThreshold[0], compareThreshold[1], compareThreshold[2], compareThreshold[3]), 515 tcu::COMPARE_LOG_RESULT); 516 } 517 518 if (!comparePass) 519 { 520 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 521 return STOP; 522 } 523 } 524 525 m_iterNdx += 1; 526 527 if (m_iterNdx < m_numIters) 528 return CONTINUE; 529 else 530 { 531 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 532 return STOP; 533 } 534 } 535 536 } // anonymous 537 538 AdvancedBlendTests::AdvancedBlendTests (Context& context) 539 : TestCaseGroup(context, "blend_equation_advanced", "GL_KHR_blend_equation_advanced Tests") 540 { 541 } 542 543 AdvancedBlendTests::~AdvancedBlendTests (void) 544 { 545 } 546 547 void AdvancedBlendTests::init (void) 548 { 549 static const struct 550 { 551 deUint32 mode; 552 const char* name; 553 } s_blendModes[] = 554 { 555 { GL_MULTIPLY_KHR, "multiply" }, 556 { GL_SCREEN_KHR, "screen" }, 557 { GL_OVERLAY_KHR, "overlay" }, 558 { GL_DARKEN_KHR, "darken" }, 559 { GL_LIGHTEN_KHR, "lighten" }, 560 { GL_COLORDODGE_KHR, "colordodge" }, 561 { GL_COLORBURN_KHR, "colorburn" }, 562 { GL_HARDLIGHT_KHR, "hardlight" }, 563 { GL_SOFTLIGHT_KHR, "softlight" }, 564 { GL_DIFFERENCE_KHR, "difference" }, 565 { GL_EXCLUSION_KHR, "exclusion" }, 566 { GL_HSL_HUE_KHR, "hsl_hue" }, 567 { GL_HSL_SATURATION_KHR, "hsl_saturation" }, 568 { GL_HSL_COLOR_KHR, "hsl_color" }, 569 { GL_HSL_LUMINOSITY_KHR, "hsl_luminosity" } 570 }; 571 572 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Single quad only"); 573 tcu::TestCaseGroup* const srgbGroup = new tcu::TestCaseGroup(m_testCtx, "srgb", "Advanced blending with sRGB FBO"); 574 tcu::TestCaseGroup* const msaaGroup = new tcu::TestCaseGroup(m_testCtx, "msaa", "Advanced blending with MSAA FBO"); 575 tcu::TestCaseGroup* const barrierGroup = new tcu::TestCaseGroup(m_testCtx, "barrier", "Multiple overlapping quads with blend barriers"); 576 tcu::TestCaseGroup* const coherentGroup = new tcu::TestCaseGroup(m_testCtx, "coherent", "Overlapping quads with coherent blending"); 577 tcu::TestCaseGroup* const coherentMsaaGroup = new tcu::TestCaseGroup(m_testCtx, "coherent_msaa", "Overlapping quads with coherent blending with MSAA FBO"); 578 579 addChild(basicGroup); 580 addChild(srgbGroup); 581 addChild(msaaGroup); 582 addChild(barrierGroup); 583 addChild(coherentGroup); 584 addChild(coherentMsaaGroup); 585 586 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(s_blendModes); modeNdx++) 587 { 588 const char* const name = s_blendModes[modeNdx].name; 589 const char* const desc = ""; 590 const deUint32 mode = s_blendModes[modeNdx].mode; 591 592 basicGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_DEFAULT)); 593 srgbGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_SRGB_FBO)); 594 msaaGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_MSAA_FBO)); 595 barrierGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, false, RENDERTARGETTYPE_DEFAULT)); 596 coherentGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, true, RENDERTARGETTYPE_DEFAULT)); 597 coherentMsaaGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, true, RENDERTARGETTYPE_MSAA_FBO)); 598 } 599 } 600 601 } // Functional 602 } // gles31 603 } // deqp 604