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 "glsStateQueryUtil.hpp" 28#include "gluPixelTransfer.hpp" 29#include "gluObjectWrapper.hpp" 30#include "gluContextInfo.hpp" 31#include "gluShaderProgram.hpp" 32#include "gluCallLogWrapper.hpp" 33#include "gluStrUtil.hpp" 34#include "tcuPixelFormat.hpp" 35#include "tcuTexture.hpp" 36#include "tcuTextureUtil.hpp" 37#include "tcuImageCompare.hpp" 38#include "tcuRenderTarget.hpp" 39#include "tcuTestLog.hpp" 40#include "tcuStringTemplate.hpp" 41#include "deRandom.hpp" 42#include "deStringUtil.hpp" 43#include "rrFragmentOperations.hpp" 44#include "sglrReferenceUtils.hpp" 45#include "glwEnums.hpp" 46#include "glwFunctions.hpp" 47 48#include <string> 49#include <vector> 50 51namespace deqp 52{ 53 54using gls::FragmentOpUtil::IntegerQuad; 55using gls::FragmentOpUtil::ReferenceQuadRenderer; 56using tcu::TextureLevel; 57using tcu::Vec2; 58using tcu::Vec4; 59using tcu::UVec4; 60using tcu::TestLog; 61using tcu::TextureFormat; 62using std::string; 63using std::vector; 64using std::map; 65 66namespace gles31 67{ 68namespace Functional 69{ 70 71namespace 72{ 73 74enum 75{ 76 MAX_VIEWPORT_WIDTH = 128, 77 MAX_VIEWPORT_HEIGHT = 128 78}; 79 80enum RenderTargetType 81{ 82 RENDERTARGETTYPE_DEFAULT = 0, //!< Default framebuffer 83 RENDERTARGETTYPE_SRGB_FBO, 84 RENDERTARGETTYPE_MSAA_FBO, 85 86 RENDERTARGETTYPE_LAST 87}; 88 89static const char* getEquationName (glw::GLenum equation) 90{ 91 switch (equation) 92 { 93 case GL_MULTIPLY: return "multiply"; 94 case GL_SCREEN: return "screen"; 95 case GL_OVERLAY: return "overlay"; 96 case GL_DARKEN: return "darken"; 97 case GL_LIGHTEN: return "lighten"; 98 case GL_COLORDODGE: return "colordodge"; 99 case GL_COLORBURN: return "colorburn"; 100 case GL_HARDLIGHT: return "hardlight"; 101 case GL_SOFTLIGHT: return "softlight"; 102 case GL_DIFFERENCE: return "difference"; 103 case GL_EXCLUSION: return "exclusion"; 104 case GL_HSL_HUE: return "hsl_hue"; 105 case GL_HSL_SATURATION: return "hsl_saturation"; 106 case GL_HSL_COLOR: return "hsl_color"; 107 case GL_HSL_LUMINOSITY: return "hsl_luminosity"; 108 default: 109 DE_ASSERT(false); 110 return DE_NULL; 111 } 112} 113 114class AdvancedBlendCase : public TestCase 115{ 116public: 117 AdvancedBlendCase (Context& context, const char* name, const char* desc, deUint32 mode, int overdrawCount, bool coherent, RenderTargetType rtType); 118 119 ~AdvancedBlendCase (void); 120 121 void init (void); 122 void deinit (void); 123 124 IterateResult iterate (void); 125 126private: 127 AdvancedBlendCase (const AdvancedBlendCase&); 128 AdvancedBlendCase& operator= (const AdvancedBlendCase&); 129 130 const deUint32 m_blendMode; 131 const int m_overdrawCount; 132 const bool m_coherentBlending; 133 const RenderTargetType m_rtType; 134 const int m_numIters; 135 136 bool m_coherentExtensionSupported; 137 138 deUint32 m_colorRbo; 139 deUint32 m_fbo; 140 141 deUint32 m_resolveColorRbo; 142 deUint32 m_resolveFbo; 143 144 glu::ShaderProgram* m_program; 145 146 ReferenceQuadRenderer* m_referenceRenderer; 147 TextureLevel* m_refColorBuffer; 148 149 const int m_renderWidth; 150 const int m_renderHeight; 151 const int m_viewportWidth; 152 const int m_viewportHeight; 153 154 int m_iterNdx; 155}; 156 157AdvancedBlendCase::AdvancedBlendCase (Context& context, 158 const char* name, 159 const char* desc, 160 deUint32 mode, 161 int overdrawCount, 162 bool coherent, 163 RenderTargetType rtType) 164 : TestCase (context, name, desc) 165 , m_blendMode (mode) 166 , m_overdrawCount (overdrawCount) 167 , m_coherentBlending (coherent) 168 , m_rtType (rtType) 169 , m_numIters (5) 170 , m_coherentExtensionSupported (false) 171 , m_colorRbo (0) 172 , m_fbo (0) 173 , m_resolveColorRbo (0) 174 , m_resolveFbo (0) 175 , m_program (DE_NULL) 176 , m_referenceRenderer (DE_NULL) 177 , m_refColorBuffer (DE_NULL) 178 , m_renderWidth (rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_WIDTH : m_context.getRenderTarget().getWidth()) 179 , m_renderHeight (rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_HEIGHT : m_context.getRenderTarget().getHeight()) 180 , m_viewportWidth (de::min<int>(m_renderWidth, MAX_VIEWPORT_WIDTH)) 181 , m_viewportHeight (de::min<int>(m_renderHeight, MAX_VIEWPORT_HEIGHT)) 182 , m_iterNdx (0) 183{ 184} 185 186const char* getBlendLayoutQualifier (rr::BlendEquationAdvanced equation) 187{ 188 static const char* s_qualifiers[] = 189 { 190 "blend_support_multiply", 191 "blend_support_screen", 192 "blend_support_overlay", 193 "blend_support_darken", 194 "blend_support_lighten", 195 "blend_support_colordodge", 196 "blend_support_colorburn", 197 "blend_support_hardlight", 198 "blend_support_softlight", 199 "blend_support_difference", 200 "blend_support_exclusion", 201 "blend_support_hsl_hue", 202 "blend_support_hsl_saturation", 203 "blend_support_hsl_color", 204 "blend_support_hsl_luminosity", 205 }; 206 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qualifiers) == rr::BLENDEQUATION_ADVANCED_LAST); 207 DE_ASSERT(de::inBounds<int>(equation, 0, rr::BLENDEQUATION_ADVANCED_LAST)); 208 return s_qualifiers[equation]; 209} 210 211glu::ProgramSources getBlendProgramSrc (rr::BlendEquationAdvanced equation, glu::RenderContext& renderContext) 212{ 213 const bool supportsES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); 214 215 static const char* s_vertSrc = "${GLSL_VERSION_DECL}\n" 216 "in highp vec4 a_position;\n" 217 "in mediump vec4 a_color;\n" 218 "out mediump vec4 v_color;\n" 219 "void main()\n" 220 "{\n" 221 " gl_Position = a_position;\n" 222 " v_color = a_color;\n" 223 "}\n"; 224 static const char* s_fragSrc = "${GLSL_VERSION_DECL}\n" 225 "${EXTENSION}" 226 "in mediump vec4 v_color;\n" 227 "layout(${SUPPORT_QUALIFIER}) out;\n" 228 "layout(location = 0) out mediump vec4 o_color;\n" 229 "void main()\n" 230 "{\n" 231 " o_color = v_color;\n" 232 "}\n"; 233 234 map<string, string> args; 235 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 236 args["EXTENSION"] = supportsES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n"; 237 args["SUPPORT_QUALIFIER"] = getBlendLayoutQualifier(equation); 238 239 return glu::ProgramSources() 240 << glu::VertexSource(tcu::StringTemplate(s_vertSrc).specialize(args)) 241 << glu::FragmentSource(tcu::StringTemplate(s_fragSrc).specialize(args)); 242} 243 244void AdvancedBlendCase::init (void) 245{ 246 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 247 const bool useFbo = m_rtType != RENDERTARGETTYPE_DEFAULT; 248 const bool useSRGB = m_rtType == RENDERTARGETTYPE_SRGB_FBO; 249 250 m_coherentExtensionSupported = m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced_coherent"); 251 252 if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2))) 253 if (!m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced")) 254 TCU_THROW(NotSupportedError, "GL_KHR_blend_equation_advanced is not supported"); 255 256 if (m_coherentBlending && !m_coherentExtensionSupported) 257 TCU_THROW(NotSupportedError, "GL_KHR_blend_equation_advanced_coherent is not supported"); 258 259 TCU_CHECK(gl.blendBarrier); 260 261 DE_ASSERT(!m_program); 262 DE_ASSERT(!m_referenceRenderer); 263 DE_ASSERT(!m_refColorBuffer); 264 265 m_program = new glu::ShaderProgram(m_context.getRenderContext(), getBlendProgramSrc(sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode), m_context.getRenderContext())); 266 m_testCtx.getLog() << *m_program; 267 268 if (!m_program->isOk()) 269 { 270 delete m_program; 271 m_program = DE_NULL; 272 TCU_FAIL("Compile failed"); 273 } 274 275 m_referenceRenderer = new ReferenceQuadRenderer; 276 m_refColorBuffer = new TextureLevel(TextureFormat(useSRGB ? TextureFormat::sRGBA : TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight); 277 278 if (useFbo) 279 { 280 const deUint32 format = useSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA8; 281 const int numSamples = m_rtType == RENDERTARGETTYPE_MSAA_FBO ? 4 : 0; 282 283 m_testCtx.getLog() << TestLog::Message << "Using FBO of size (" << m_renderWidth << ", " << m_renderHeight << ") with format " 284 << glu::getTextureFormatStr(format) << " and " << numSamples << " samples" 285 << TestLog::EndMessage; 286 287 gl.genRenderbuffers(1, &m_colorRbo); 288 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorRbo); 289 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, format, m_renderWidth, m_renderHeight); 290 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create color RBO"); 291 292 gl.genFramebuffers(1, &m_fbo); 293 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 294 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo); 295 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO"); 296 297 TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 298 299 if (numSamples > 0) 300 { 301 // Create resolve FBO 302 gl.genRenderbuffers(1, &m_resolveColorRbo); 303 gl.bindRenderbuffer(GL_RENDERBUFFER, m_resolveColorRbo); 304 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, m_renderWidth, m_renderHeight); 305 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create resolve color RBO"); 306 307 gl.genFramebuffers(1, &m_resolveFbo); 308 gl.bindFramebuffer(GL_FRAMEBUFFER, m_resolveFbo); 309 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_resolveColorRbo); 310 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO"); 311 312 TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 313 314 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 315 } 316 317 if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()) && useSRGB) 318 gl.enable(GL_FRAMEBUFFER_SRGB); 319 } 320 else 321 DE_ASSERT(m_rtType == RENDERTARGETTYPE_DEFAULT); 322 323 m_iterNdx = 0; 324} 325 326AdvancedBlendCase::~AdvancedBlendCase (void) 327{ 328 AdvancedBlendCase::deinit(); 329} 330 331void AdvancedBlendCase::deinit (void) 332{ 333 delete m_program; 334 delete m_referenceRenderer; 335 delete m_refColorBuffer; 336 337 m_program = DE_NULL; 338 m_referenceRenderer = DE_NULL; 339 m_refColorBuffer = DE_NULL; 340 341 if (m_colorRbo || m_fbo) 342 { 343 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 344 345 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 346 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 347 348 if (m_colorRbo != 0) 349 { 350 gl.deleteRenderbuffers(1, &m_colorRbo); 351 m_colorRbo = 0; 352 } 353 354 if (m_fbo != 0) 355 { 356 gl.deleteFramebuffers(1, &m_fbo); 357 m_fbo = 0; 358 } 359 360 if (m_resolveColorRbo) 361 { 362 gl.deleteRenderbuffers(1, &m_resolveColorRbo); 363 m_resolveColorRbo = 0; 364 } 365 366 if (m_resolveFbo) 367 { 368 gl.deleteRenderbuffers(1, &m_resolveFbo); 369 m_resolveFbo = 0; 370 } 371 372 if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()) && RENDERTARGETTYPE_SRGB_FBO == m_rtType) 373 gl.disable(GL_FRAMEBUFFER_SRGB); 374 } 375} 376 377static tcu::Vec4 randomColor (de::Random* rnd) 378{ 379 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 }; 380 const float alphaValues[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f }; 381 382 // \note Spec assumes premultiplied inputs. 383 const float a = rnd->choose<float>(DE_ARRAY_BEGIN(alphaValues), DE_ARRAY_END(alphaValues)); 384 const float r = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues)); 385 const float g = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues)); 386 const float b = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues)); 387 return tcu::Vec4(r, g, b, a); 388} 389 390static tcu::ConstPixelBufferAccess getLinearAccess (const tcu::ConstPixelBufferAccess& access) 391{ 392 if (access.getFormat().order == TextureFormat::sRGBA) 393 return tcu::ConstPixelBufferAccess(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), 394 access.getWidth(), access.getHeight(), access.getDepth(), 395 access.getRowPitch(), access.getSlicePitch(), access.getDataPtr()); 396 else 397 return access; 398} 399 400AdvancedBlendCase::IterateResult AdvancedBlendCase::iterate (void) 401{ 402 const glu::RenderContext& renderCtx = m_context.getRenderContext(); 403 const glw::Functions& gl = renderCtx.getFunctions(); 404 de::Random rnd (deStringHash(getName()) ^ deInt32Hash(m_iterNdx)); 405 const int viewportX = rnd.getInt(0, m_renderWidth - m_viewportWidth); 406 const int viewportY = rnd.getInt(0, m_renderHeight - m_viewportHeight); 407 const bool useFbo = m_rtType != RENDERTARGETTYPE_DEFAULT; 408 const bool requiresResolve = m_rtType == RENDERTARGETTYPE_MSAA_FBO; 409 const int numQuads = m_overdrawCount+1; 410 TextureLevel renderedImg (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight); 411 vector<Vec4> colors (numQuads*4); 412 413 for (vector<Vec4>::iterator col = colors.begin(); col != colors.end(); ++col) 414 *col = randomColor(&rnd); 415 416 // Render with GL. 417 { 418 const deUint32 program = m_program->getProgram(); 419 const int posLoc = gl.getAttribLocation(program, "a_position"); 420 const int colorLoc = gl.getAttribLocation(program, "a_color"); 421 deUint32 vao = 0; 422 const glu::Buffer indexBuffer (renderCtx); 423 const glu::Buffer positionBuffer (renderCtx); 424 const glu::Buffer colorBuffer (renderCtx); 425 vector<Vec2> positions (numQuads*4); 426 vector<deUint16> indices (numQuads*6); 427 const deUint16 singleQuadIndices[] = { 0, 2, 1, 1, 2, 3 }; 428 const Vec2 singleQuadPos[] = 429 { 430 Vec2(-1.0f, -1.0f), 431 Vec2(-1.0f, +1.0f), 432 Vec2(+1.0f, -1.0f), 433 Vec2(+1.0f, +1.0f), 434 }; 435 436 TCU_CHECK(posLoc >= 0 && colorLoc >= 0); 437 438 for (int quadNdx = 0; quadNdx < numQuads; quadNdx++) 439 { 440 std::copy(DE_ARRAY_BEGIN(singleQuadPos), DE_ARRAY_END(singleQuadPos), &positions[quadNdx*4]); 441 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleQuadIndices); ndx++) 442 indices[quadNdx*6 + ndx] = (deUint16)(quadNdx*4 + singleQuadIndices[ndx]); 443 } 444 445 if (!glu::isContextTypeES(renderCtx.getType())) 446 { 447 gl.genVertexArrays(1, &vao); 448 gl.bindVertexArray(vao); 449 } 450 451 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *indexBuffer); 452 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size()*sizeof(indices[0])), &indices[0], GL_STATIC_DRAW); 453 454 gl.bindBuffer(GL_ARRAY_BUFFER, *positionBuffer); 455 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(positions.size()*sizeof(positions[0])), &positions[0], GL_STATIC_DRAW); 456 gl.enableVertexAttribArray(posLoc); 457 gl.vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL); 458 459 gl.bindBuffer(GL_ARRAY_BUFFER, *colorBuffer); 460 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(colors.size()*sizeof(colors[0])), &colors[0], GL_STATIC_DRAW); 461 gl.enableVertexAttribArray(colorLoc); 462 gl.vertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 463 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffers"); 464 465 gl.useProgram(program); 466 gl.viewport(viewportX, viewportY, m_viewportWidth, m_viewportHeight); 467 gl.blendEquation(m_blendMode); 468 469 // \note coherent extension enables GL_BLEND_ADVANCED_COHERENT_KHR by default 470 if (m_coherentBlending) 471 gl.enable(GL_BLEND_ADVANCED_COHERENT_KHR); 472 else if (m_coherentExtensionSupported) 473 gl.disable(GL_BLEND_ADVANCED_COHERENT_KHR); 474 475 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set render state"); 476 477 gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 478 479 gl.disable(GL_BLEND); 480 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL); 481 gl.enable(GL_BLEND); 482 483 if (!m_coherentBlending) 484 gl.blendBarrier(); 485 486 if (m_coherentBlending) 487 { 488 gl.drawElements(GL_TRIANGLES, 6*(numQuads-1), GL_UNSIGNED_SHORT, (const void*)(deUintptr)(6*sizeof(deUint16))); 489 } 490 else 491 { 492 for (int quadNdx = 1; quadNdx < numQuads; quadNdx++) 493 { 494 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void*)(deUintptr)(quadNdx*6*sizeof(deUint16))); 495 gl.blendBarrier(); 496 } 497 } 498 499 if (vao) 500 gl.deleteVertexArrays(1, &vao); 501 502 gl.flush(); 503 GLU_EXPECT_NO_ERROR(gl.getError(), "Render failed"); 504 } 505 506 // Render reference. 507 { 508 rr::FragmentOperationState referenceState; 509 const tcu::PixelBufferAccess colorAccess = gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()); 510 const tcu::PixelBufferAccess nullAccess = tcu::PixelBufferAccess(); 511 IntegerQuad quad; 512 513 if (!useFbo && m_context.getRenderTarget().getPixelFormat().alphaBits == 0) 514 { 515 // Emulate lack of alpha by clearing to 1 and masking out alpha writes 516 tcu::clear(*m_refColorBuffer, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 517 referenceState.colorMask = tcu::BVec4(true, true, true, false); 518 } 519 520 referenceState.blendEquationAdvaced = sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode); 521 522 quad.posA = tcu::IVec2(0, 0); 523 quad.posB = tcu::IVec2(m_viewportWidth-1, m_viewportHeight-1); 524 525 for (int quadNdx = 0; quadNdx < numQuads; quadNdx++) 526 { 527 referenceState.blendMode = quadNdx == 0 ? rr::BLENDMODE_NONE : rr::BLENDMODE_ADVANCED; 528 std::copy(&colors[4*quadNdx], &colors[4*quadNdx] + 4, &quad.color[0]); 529 m_referenceRenderer->render(colorAccess, nullAccess /* no depth */, nullAccess /* no stencil */, quad, referenceState); 530 } 531 } 532 533 if (requiresResolve) 534 { 535 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolveFbo); 536 gl.blitFramebuffer(0, 0, m_renderWidth, m_renderHeight, 0, 0, m_renderWidth, m_renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); 537 GLU_EXPECT_NO_ERROR(gl.getError(), "Resolve blit failed"); 538 539 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_resolveFbo); 540 } 541 542 glu::readPixels(renderCtx, viewportX, viewportY, renderedImg.getAccess()); 543 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()"); 544 545 if (requiresResolve) 546 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 547 548 { 549 const bool isHSLMode = m_blendMode == GL_HSL_HUE || 550 m_blendMode == GL_HSL_SATURATION || 551 m_blendMode == GL_HSL_COLOR || 552 m_blendMode == GL_HSL_LUMINOSITY; 553 bool comparePass = false; 554 555 if (isHSLMode) 556 { 557 // Compensate for more demanding HSL code by using fuzzy comparison. 558 const float threshold = 0.002f; 559 comparePass = tcu::fuzzyCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", 560 getLinearAccess(m_refColorBuffer->getAccess()), 561 renderedImg.getAccess(), 562 threshold, tcu::COMPARE_LOG_RESULT); 563 } 564 else 565 { 566 const UVec4 compareThreshold = (useFbo ? tcu::PixelFormat(8, 8, 8, 8) : m_context.getRenderTarget().getPixelFormat()).getColorThreshold().toIVec().asUint() 567 * UVec4(5) / UVec4(2) + UVec4(3 * m_overdrawCount); 568 569 comparePass = tcu::bilinearCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", 570 getLinearAccess(m_refColorBuffer->getAccess()), 571 renderedImg.getAccess(), 572 tcu::RGBA(compareThreshold[0], compareThreshold[1], compareThreshold[2], compareThreshold[3]), 573 tcu::COMPARE_LOG_RESULT); 574 } 575 576 if (!comparePass) 577 { 578 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 579 return STOP; 580 } 581 } 582 583 m_iterNdx += 1; 584 585 if (m_iterNdx < m_numIters) 586 return CONTINUE; 587 else 588 { 589 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 590 return STOP; 591 } 592} 593 594class BlendAdvancedCoherentStateCase : public TestCase 595{ 596public: 597 BlendAdvancedCoherentStateCase (Context& context, 598 const char* name, 599 const char* description, 600 gls::StateQueryUtil::QueryType type); 601private: 602 IterateResult iterate (void); 603 604 const gls::StateQueryUtil::QueryType m_type; 605}; 606 607BlendAdvancedCoherentStateCase::BlendAdvancedCoherentStateCase (Context& context, 608 const char* name, 609 const char* description, 610 gls::StateQueryUtil::QueryType type) 611 : TestCase (context, name, description) 612 , m_type (type) 613{ 614} 615 616BlendAdvancedCoherentStateCase::IterateResult BlendAdvancedCoherentStateCase::iterate (void) 617{ 618 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced_coherent"), "GL_KHR_blend_equation_advanced_coherent is not supported"); 619 620 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 621 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 622 623 gl.enableLogging(true); 624 625 // check inital value 626 { 627 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial"); 628 gls::StateQueryUtil::verifyStateBoolean(result, gl, GL_BLEND_ADVANCED_COHERENT_KHR, true, m_type); 629 } 630 631 // check toggle 632 { 633 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Toggle", "Toggle"); 634 gl.glDisable(GL_BLEND_ADVANCED_COHERENT_KHR); 635 GLU_EXPECT_NO_ERROR(gl.glGetError(), "glDisable"); 636 637 gls::StateQueryUtil::verifyStateBoolean(result, gl, GL_BLEND_ADVANCED_COHERENT_KHR, false, m_type); 638 639 gl.glEnable(GL_BLEND_ADVANCED_COHERENT_KHR); 640 GLU_EXPECT_NO_ERROR(gl.glGetError(), "glEnable"); 641 642 gls::StateQueryUtil::verifyStateBoolean(result, gl, GL_BLEND_ADVANCED_COHERENT_KHR, true, m_type); 643 } 644 645 result.setTestContextResult(m_testCtx); 646 return STOP; 647} 648 649class BlendEquationStateCase : public TestCase 650{ 651public: 652 BlendEquationStateCase (Context& context, 653 const char* name, 654 const char* description, 655 const glw::GLenum* equations, 656 int numEquations, 657 gls::StateQueryUtil::QueryType type); 658private: 659 IterateResult iterate (void); 660 661 const gls::StateQueryUtil::QueryType m_type; 662 const glw::GLenum* m_equations; 663 const int m_numEquations; 664}; 665 666BlendEquationStateCase::BlendEquationStateCase (Context& context, 667 const char* name, 668 const char* description, 669 const glw::GLenum* equations, 670 int numEquations, 671 gls::StateQueryUtil::QueryType type) 672 : TestCase (context, name, description) 673 , m_type (type) 674 , m_equations (equations) 675 , m_numEquations (numEquations) 676{ 677} 678 679BlendEquationStateCase::IterateResult BlendEquationStateCase::iterate (void) 680{ 681 if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2))) 682 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"), "GL_KHR_blend_equation_advanced is not supported"); 683 684 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 685 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 686 687 gl.enableLogging(true); 688 689 for (int ndx = 0; ndx < m_numEquations; ++ndx) 690 { 691 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Type", "Test " + de::toString(glu::getBlendEquationStr(m_equations[ndx]))); 692 693 gl.glBlendEquation(m_equations[ndx]); 694 GLU_EXPECT_NO_ERROR(gl.glGetError(), "glBlendEquation"); 695 696 gls::StateQueryUtil::verifyStateInteger(result, gl, GL_BLEND_EQUATION, m_equations[ndx], m_type); 697 } 698 699 result.setTestContextResult(m_testCtx); 700 return STOP; 701} 702 703class BlendEquationIndexedStateCase : public TestCase 704{ 705public: 706 BlendEquationIndexedStateCase (Context& context, 707 const char* name, 708 const char* description, 709 const glw::GLenum* equations, 710 int numEquations, 711 gls::StateQueryUtil::QueryType type); 712private: 713 IterateResult iterate (void); 714 715 const gls::StateQueryUtil::QueryType m_type; 716 const glw::GLenum* m_equations; 717 const int m_numEquations; 718}; 719 720BlendEquationIndexedStateCase::BlendEquationIndexedStateCase (Context& context, 721 const char* name, 722 const char* description, 723 const glw::GLenum* equations, 724 int numEquations, 725 gls::StateQueryUtil::QueryType type) 726 : TestCase (context, name, description) 727 , m_type (type) 728 , m_equations (equations) 729 , m_numEquations (numEquations) 730{ 731} 732 733BlendEquationIndexedStateCase::IterateResult BlendEquationIndexedStateCase::iterate (void) 734{ 735 const auto& renderContext = m_context.getRenderContext(); 736 if (!glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)) && 737 !glu::contextSupports(renderContext.getType(), glu::ApiType::core(4, 5))) 738 { 739 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"), "GL_KHR_blend_equation_advanced is not supported"); 740 TCU_CHECK_AND_THROW(NotSupportedError, m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed"), "GL_EXT_draw_buffers_indexed is not supported"); 741 } 742 743 glu::CallLogWrapper gl (renderContext.getFunctions(), m_testCtx.getLog()); 744 tcu::ResultCollector result (m_testCtx.getLog(), " // ERROR: "); 745 746 gl.enableLogging(true); 747 748 for (int ndx = 0; ndx < m_numEquations; ++ndx) 749 { 750 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Type", "Test " + de::toString(glu::getBlendEquationStr(m_equations[ndx]))); 751 752 gl.glBlendEquationi(2, m_equations[ndx]); 753 GLU_EXPECT_NO_ERROR(gl.glGetError(), "glBlendEquationi"); 754 755 gls::StateQueryUtil::verifyStateIndexedInteger(result, gl, GL_BLEND_EQUATION, 2, m_equations[ndx], m_type); 756 } 757 758 result.setTestContextResult(m_testCtx); 759 return STOP; 760} 761 762} // anonymous 763 764AdvancedBlendTests::AdvancedBlendTests (Context& context) 765 : TestCaseGroup(context, "blend_equation_advanced", "GL_blend_equation_advanced Tests") 766{ 767} 768 769AdvancedBlendTests::~AdvancedBlendTests (void) 770{ 771} 772 773void AdvancedBlendTests::init (void) 774{ 775 static const glw::GLenum s_blendEquations[] = 776 { 777 GL_MULTIPLY, 778 GL_SCREEN, 779 GL_OVERLAY, 780 GL_DARKEN, 781 GL_LIGHTEN, 782 GL_COLORDODGE, 783 GL_COLORBURN, 784 GL_HARDLIGHT, 785 GL_SOFTLIGHT, 786 GL_DIFFERENCE, 787 GL_EXCLUSION, 788 GL_HSL_HUE, 789 GL_HSL_SATURATION, 790 GL_HSL_COLOR, 791 GL_HSL_LUMINOSITY, 792 793 }; 794 795 tcu::TestCaseGroup* const stateQueryGroup = new tcu::TestCaseGroup(m_testCtx, "state_query", "State query tests"); 796 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Single quad only"); 797 tcu::TestCaseGroup* const srgbGroup = new tcu::TestCaseGroup(m_testCtx, "srgb", "Advanced blending with sRGB FBO"); 798 tcu::TestCaseGroup* const msaaGroup = new tcu::TestCaseGroup(m_testCtx, "msaa", "Advanced blending with MSAA FBO"); 799 tcu::TestCaseGroup* const barrierGroup = new tcu::TestCaseGroup(m_testCtx, "barrier", "Multiple overlapping quads with blend barriers"); 800 tcu::TestCaseGroup* const coherentGroup = new tcu::TestCaseGroup(m_testCtx, "coherent", "Overlapping quads with coherent blending"); 801 tcu::TestCaseGroup* const coherentMsaaGroup = new tcu::TestCaseGroup(m_testCtx, "coherent_msaa", "Overlapping quads with coherent blending with MSAA FBO"); 802 803 addChild(stateQueryGroup); 804 addChild(basicGroup); 805 addChild(srgbGroup); 806 addChild(msaaGroup); 807 addChild(barrierGroup); 808 addChild(coherentGroup); 809 addChild(coherentMsaaGroup); 810 811 // .state_query 812 { 813 using namespace gls::StateQueryUtil; 814 815 stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getboolean", "Test BLEND_ADVANCED_COHERENT_KHR", QUERY_BOOLEAN)); 816 stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_isenabled", "Test BLEND_ADVANCED_COHERENT_KHR", QUERY_ISENABLED)); 817 stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getinteger", "Test BLEND_ADVANCED_COHERENT_KHR", QUERY_INTEGER)); 818 stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getinteger64", "Test BLEND_ADVANCED_COHERENT_KHR", QUERY_INTEGER64)); 819 stateQueryGroup->addChild(new BlendAdvancedCoherentStateCase(m_context, "blend_advanced_coherent_getfloat", "Test BLEND_ADVANCED_COHERENT_KHR", QUERY_FLOAT)); 820 821 stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getboolean", "Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_BOOLEAN)); 822 stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getinteger", "Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INTEGER)); 823 stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getinteger64", "Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INTEGER64)); 824 stateQueryGroup->addChild(new BlendEquationStateCase(m_context, "blend_equation_getfloat", "Test BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_FLOAT)); 825 826 stateQueryGroup->addChild(new BlendEquationIndexedStateCase(m_context, "blend_equation_getbooleani_v", "Test per-attchment BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INDEXED_BOOLEAN)); 827 stateQueryGroup->addChild(new BlendEquationIndexedStateCase(m_context, "blend_equation_getintegeri_v", "Test per-attchment BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INDEXED_INTEGER)); 828 stateQueryGroup->addChild(new BlendEquationIndexedStateCase(m_context, "blend_equation_getinteger64i_v", "Test per-attchment BLEND_EQUATION", s_blendEquations, DE_LENGTH_OF_ARRAY(s_blendEquations), QUERY_INDEXED_INTEGER64)); 829 } 830 831 // others 832 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(s_blendEquations); modeNdx++) 833 { 834 const char* const name = getEquationName(s_blendEquations[modeNdx]); 835 const char* const desc = ""; 836 const deUint32 mode = s_blendEquations[modeNdx]; 837 838 basicGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_DEFAULT)); 839 srgbGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_SRGB_FBO)); 840 msaaGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_MSAA_FBO)); 841 barrierGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, false, RENDERTARGETTYPE_DEFAULT)); 842 coherentGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, true, RENDERTARGETTYPE_DEFAULT)); 843 coherentMsaaGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, true, RENDERTARGETTYPE_MSAA_FBO)); 844 } 845} 846 847} // Functional 848} // gles31 849} // deqp 850