1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2015 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 Indexed blend operation tests (GL_EXT_draw_buffers_indexed) 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fDrawBuffersIndexedTests.hpp" 25 26 #include "gluContextInfo.hpp" 27 #include "gluDrawUtil.hpp" 28 #include "gluObjectWrapper.hpp" 29 #include "gluPixelTransfer.hpp" 30 #include "gluShaderProgram.hpp" 31 #include "gluStrUtil.hpp" 32 #include "gluTextureUtil.hpp" 33 34 #include "sglrReferenceUtils.hpp" 35 36 #include "rrMultisamplePixelBufferAccess.hpp" 37 #include "rrRenderer.hpp" 38 39 #include "glwEnums.hpp" 40 #include "glwFunctions.hpp" 41 42 #include "tcuEither.hpp" 43 #include "tcuImageCompare.hpp" 44 #include "tcuMaybe.hpp" 45 #include "tcuResultCollector.hpp" 46 #include "tcuStringTemplate.hpp" 47 #include "tcuTestLog.hpp" 48 #include "tcuTexture.hpp" 49 #include "tcuTextureUtil.hpp" 50 #include "tcuVector.hpp" 51 #include "tcuVectorUtil.hpp" 52 #include "tcuFloat.hpp" 53 54 #include "deRandom.hpp" 55 #include "deArrayUtil.hpp" 56 #include "deStringUtil.hpp" 57 #include "deUniquePtr.hpp" 58 59 #include "deInt32.h" 60 61 #include <string> 62 #include <vector> 63 #include <map> 64 65 using tcu::BVec4; 66 using tcu::Either; 67 using tcu::IVec2; 68 using tcu::IVec4; 69 using tcu::Maybe; 70 using tcu::TestLog; 71 using tcu::TextureFormat; 72 using tcu::TextureLevel; 73 using tcu::UVec4; 74 using tcu::Vec2; 75 using tcu::Vec4; 76 using tcu::just; 77 78 using std::string; 79 using std::vector; 80 using std::map; 81 82 using sglr::rr_util::mapGLBlendEquation; 83 using sglr::rr_util::mapGLBlendFunc; 84 using sglr::rr_util::mapGLBlendEquationAdvanced; 85 86 namespace deqp 87 { 88 namespace gles31 89 { 90 namespace Functional 91 { 92 namespace 93 { 94 95 typedef deUint32 BlendEq; 96 97 bool isAdvancedBlendEq (BlendEq eq) 98 { 99 switch (eq) 100 { 101 case GL_MULTIPLY: return true; 102 case GL_SCREEN: return true; 103 case GL_OVERLAY: return true; 104 case GL_DARKEN: return true; 105 case GL_LIGHTEN: return true; 106 case GL_COLORDODGE: return true; 107 case GL_COLORBURN: return true; 108 case GL_HARDLIGHT: return true; 109 case GL_SOFTLIGHT: return true; 110 case GL_DIFFERENCE: return true; 111 case GL_EXCLUSION: return true; 112 case GL_HSL_HUE: return true; 113 case GL_HSL_SATURATION: return true; 114 case GL_HSL_COLOR: return true; 115 case GL_HSL_LUMINOSITY: return true; 116 default: 117 return false; 118 } 119 } 120 121 struct SeparateBlendEq 122 { 123 SeparateBlendEq (BlendEq rgb_, BlendEq alpha_) 124 : rgb (rgb_) 125 , alpha (alpha_) 126 { 127 } 128 129 BlendEq rgb; 130 BlendEq alpha; 131 }; 132 133 struct BlendFunc 134 { 135 BlendFunc (deUint32 src_, deUint32 dst_) 136 : src (src_) 137 , dst (dst_) 138 { 139 } 140 141 deUint32 src; 142 deUint32 dst; 143 }; 144 145 struct SeparateBlendFunc 146 { 147 SeparateBlendFunc (BlendFunc rgb_, BlendFunc alpha_) 148 : rgb (rgb_) 149 , alpha (alpha_) 150 { 151 } 152 153 BlendFunc rgb; 154 BlendFunc alpha; 155 }; 156 157 typedef deUint32 DrawBuffer; 158 159 struct BlendState 160 { 161 BlendState (void) {} 162 163 BlendState (const Maybe<bool>& enableBlend_, 164 const Maybe<Either<BlendEq, SeparateBlendEq> >& blendEq_, 165 const Maybe<Either<BlendFunc, SeparateBlendFunc> >& blendFunc_, 166 const Maybe<BVec4>& colorMask_) 167 : enableBlend (enableBlend_) 168 , blendEq (blendEq_) 169 , blendFunc (blendFunc_) 170 , colorMask (colorMask_) 171 { 172 } 173 174 bool isEmpty (void) const 175 { 176 return (!enableBlend) && (!blendEq) && (!blendFunc) && (!colorMask); 177 } 178 179 Maybe<bool> enableBlend; 180 Maybe<Either<BlendEq, SeparateBlendEq> > blendEq; 181 Maybe<Either<BlendFunc, SeparateBlendFunc> > blendFunc; 182 Maybe<BVec4> colorMask; 183 }; 184 185 void setCommonBlendState (const glw::Functions& gl, const BlendState& blend) 186 { 187 if (blend.enableBlend) 188 { 189 if (*blend.enableBlend) 190 gl.enable(GL_BLEND); 191 else 192 gl.disable(GL_BLEND); 193 } 194 195 if (blend.colorMask) 196 { 197 const BVec4& mask = *blend.colorMask; 198 199 gl.colorMask(mask.x(), mask.y(), mask.z(), mask.w()); 200 } 201 202 if (blend.blendEq) 203 { 204 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq; 205 206 if (blendEq.is<BlendEq>()) 207 gl.blendEquation(blendEq.get<BlendEq>()); 208 else if (blendEq.is<SeparateBlendEq>()) 209 gl.blendEquationSeparate(blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha); 210 else 211 DE_ASSERT(false); 212 } 213 214 if (blend.blendFunc) 215 { 216 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc; 217 218 if (blendFunc.is<BlendFunc>()) 219 gl.blendFunc(blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst); 220 else if (blendFunc.is<SeparateBlendFunc>()) 221 gl.blendFuncSeparate(blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst); 222 else 223 DE_ASSERT(false); 224 } 225 226 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set common blend state."); 227 } 228 229 void setIndexedBlendState (const glw::Functions& gl, const BlendState& blend, deUint32 index) 230 { 231 if (blend.enableBlend) 232 { 233 if (*blend.enableBlend) 234 gl.enablei(GL_BLEND, index); 235 else 236 gl.disablei(GL_BLEND, index); 237 } 238 239 if (blend.colorMask) 240 { 241 const BVec4 mask = *blend.colorMask; 242 243 gl.colorMaski(index, mask.x(), mask.y(), mask.z(), mask.w()); 244 } 245 246 if (blend.blendEq) 247 { 248 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq; 249 250 if (blendEq.is<BlendEq>()) 251 gl.blendEquationi(index, blendEq.get<BlendEq>()); 252 else if (blendEq.is<SeparateBlendEq>()) 253 gl.blendEquationSeparatei(index, blendEq.get<SeparateBlendEq>().rgb, blendEq.get<SeparateBlendEq>().alpha); 254 else 255 DE_ASSERT(false); 256 } 257 258 if (blend.blendFunc) 259 { 260 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc; 261 262 if (blendFunc.is<BlendFunc>()) 263 gl.blendFunci(index, blendFunc.get<BlendFunc>().src, blendFunc.get<BlendFunc>().dst); 264 else if (blendFunc.is<SeparateBlendFunc>()) 265 gl.blendFuncSeparatei(index, blendFunc.get<SeparateBlendFunc>().rgb.src, blendFunc.get<SeparateBlendFunc>().rgb.dst, blendFunc.get<SeparateBlendFunc>().alpha.src, blendFunc.get<SeparateBlendFunc>().alpha.dst); 266 else 267 DE_ASSERT(false); 268 } 269 270 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set draw buffer specifig blend state."); 271 } 272 273 class DrawBufferInfo 274 { 275 public: 276 DrawBufferInfo (bool render, 277 const IVec2& size, 278 const BlendState& blendState, 279 const TextureFormat& format); 280 281 const TextureFormat& getFormat (void) const { return m_format; } 282 const IVec2& getSize (void) const { return m_size; } 283 const BlendState& getBlendState (void) const { return m_blendState; } 284 bool getRender (void) const { return m_render; } 285 286 private: 287 bool m_render; 288 IVec2 m_size; 289 TextureFormat m_format; 290 BlendState m_blendState; 291 }; 292 293 DrawBufferInfo::DrawBufferInfo (bool render, const IVec2& size, const BlendState& blendState, const TextureFormat& format) 294 : m_render (render) 295 , m_size (size) 296 , m_format (format) 297 , m_blendState (blendState) 298 { 299 } 300 301 void clearRenderbuffer (const glw::Functions& gl, 302 const tcu::TextureFormat& format, 303 int renderbufferNdx, 304 int renderbufferCount, 305 tcu::TextureLevel& refRenderbuffer) 306 { 307 const tcu::TextureFormatInfo info = tcu::getTextureFormatInfo(format); 308 309 // Clear each buffer to different color 310 const float redScale = float(renderbufferNdx + 1) / float(renderbufferCount); 311 const float blueScale = float(renderbufferCount - renderbufferNdx) / float(renderbufferCount); 312 const float greenScale = float(((renderbufferCount/2) + renderbufferNdx) % renderbufferCount) / float(renderbufferCount); 313 // Alpha should never be zero as advanced blend equations assume premultiplied alpha. 314 const float alphaScale = float(1 + (((renderbufferCount/2) + renderbufferCount - renderbufferNdx) % renderbufferCount)) / float(renderbufferCount); 315 316 switch (tcu::getTextureChannelClass(format.type)) 317 { 318 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 319 { 320 const float red = -1000.0f + 2000.0f * redScale; 321 const float green = -1000.0f + 2000.0f * greenScale; 322 const float blue = -1000.0f + 2000.0f * blueScale; 323 const float alpha = -1000.0f + 2000.0f * alphaScale; 324 const Vec4 color (red, green, blue, alpha); 325 326 tcu::clear(refRenderbuffer, color); 327 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr()); 328 break; 329 } 330 331 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 332 { 333 const deInt32 red = deInt32(info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale); 334 const deInt32 green = deInt32(info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale); 335 const deInt32 blue = deInt32(info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale); 336 const deInt32 alpha = deInt32(info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale); 337 const IVec4 color (red, green, blue, alpha); 338 339 tcu::clear(refRenderbuffer, color); 340 gl.clearBufferiv(GL_COLOR, renderbufferNdx, color.getPtr()); 341 break; 342 } 343 344 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 345 { 346 const deUint32 red = deUint32(info.valueMax.x() * redScale); 347 const deUint32 green = deUint32(info.valueMax.y() * greenScale); 348 const deUint32 blue = deUint32(info.valueMax.z() * blueScale); 349 const deUint32 alpha = deUint32(info.valueMax.w() * alphaScale); 350 const UVec4 color (red, green, blue, alpha); 351 352 tcu::clear(refRenderbuffer, color); 353 gl.clearBufferuiv(GL_COLOR, renderbufferNdx, color.getPtr()); 354 break; 355 } 356 357 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 358 { 359 const float red = info.valueMin.x() + (info.valueMax.x() - info.valueMin.x()) * redScale; 360 const float green = info.valueMin.y() + (info.valueMax.y() - info.valueMin.y()) * greenScale; 361 const float blue = info.valueMin.z() + (info.valueMax.z() - info.valueMin.z()) * blueScale; 362 const float alpha = info.valueMin.w() + (info.valueMax.w() - info.valueMin.w()) * alphaScale; 363 const Vec4 color (red, green, blue, alpha); 364 365 tcu::clear(refRenderbuffer, color); 366 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr()); 367 break; 368 } 369 370 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 371 { 372 const float red = info.valueMax.x() * redScale; 373 const float green = info.valueMax.y() * greenScale; 374 const float blue = info.valueMax.z() * blueScale; 375 const float alpha = info.valueMax.w() * alphaScale; 376 const Vec4 color (red, green, blue, alpha); 377 378 tcu::clear(refRenderbuffer, color); 379 gl.clearBufferfv(GL_COLOR, renderbufferNdx, color.getPtr()); 380 break; 381 } 382 383 default: 384 DE_ASSERT(DE_FALSE); 385 } 386 387 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear renderbuffer."); 388 } 389 390 void genRenderbuffers (const glw::Functions& gl, 391 const vector<DrawBufferInfo>& drawBuffers, 392 const glu::Framebuffer& framebuffer, 393 const glu::RenderbufferVector& renderbuffers, 394 vector<TextureLevel>& refRenderbuffers) 395 { 396 vector<deUint32> bufs; 397 398 bufs.resize(drawBuffers.size()); 399 400 DE_ASSERT(drawBuffers.size() == renderbuffers.size()); 401 DE_ASSERT(drawBuffers.size() == refRenderbuffers.size()); 402 403 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer); 404 405 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++) 406 { 407 const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx]; 408 const TextureFormat& format = drawBuffer.getFormat(); 409 const IVec2& size = drawBuffer.getSize(); 410 const deUint32 glFormat = glu::getInternalFormat(format); 411 412 bufs[renderbufferNdx] = GL_COLOR_ATTACHMENT0 + renderbufferNdx; 413 refRenderbuffers[renderbufferNdx] = TextureLevel(drawBuffer.getFormat(), size.x(), size.y()); 414 415 gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffers[renderbufferNdx]); 416 gl.renderbufferStorage(GL_RENDERBUFFER, glFormat, size.x(), size.y()); 417 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + renderbufferNdx, GL_RENDERBUFFER, renderbuffers[renderbufferNdx]); 418 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create renderbuffer."); 419 } 420 421 gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0])); 422 423 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++) 424 { 425 const DrawBufferInfo& drawBuffer = drawBuffers[renderbufferNdx]; 426 const TextureFormat& format = drawBuffer.getFormat(); 427 428 clearRenderbuffer(gl, format, renderbufferNdx, (int)refRenderbuffers.size(), refRenderbuffers[renderbufferNdx]); 429 } 430 431 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 432 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 433 } 434 435 Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat) 436 { 437 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT); 438 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT); 439 440 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER); 441 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER); 442 443 DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER); 444 DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER); 445 446 const tcu::IVec4 srcBits = tcu::getTextureFormatBitDepth(sourceFormat); 447 const tcu::IVec4 readBits = tcu::getTextureFormatBitDepth(readPixelsFormat); 448 449 return Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>(); 450 } 451 452 UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat) 453 { 454 const tcu::IVec4 srcMantissaBits = tcu::getTextureFormatMantissaBitDepth(sourceFormat); 455 const tcu::IVec4 readMantissaBits = tcu::getTextureFormatMantissaBitDepth(readPixelsFormat); 456 tcu::IVec4 ULPDiff(0); 457 458 for (int i = 0; i < 4; i++) 459 if (readMantissaBits[i] >= srcMantissaBits[i]) 460 ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i]; 461 462 return UVec4(4) * (UVec4(1) << (ULPDiff.cast<deUint32>())); 463 } 464 465 void verifyRenderbuffer (TestLog& log, 466 tcu::ResultCollector& results, 467 const tcu::TextureFormat& format, 468 int renderbufferNdx, 469 const tcu::TextureLevel& refRenderbuffer, 470 const tcu::TextureLevel& result) 471 { 472 switch (tcu::getTextureChannelClass(format.type)) 473 { 474 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 475 { 476 const string name = "Renderbuffer" + de::toString(renderbufferNdx); 477 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx); 478 const UVec4 threshold = getFloatULPThreshold(format, result.getFormat()); 479 480 if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT)) 481 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed."); 482 483 break; 484 } 485 486 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 487 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 488 { 489 const string name = "Renderbuffer" + de::toString(renderbufferNdx); 490 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx); 491 const UVec4 threshold (1, 1, 1, 1); 492 493 if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT)) 494 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed."); 495 496 break; 497 } 498 499 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 500 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 501 { 502 const string name = "Renderbuffer" + de::toString(renderbufferNdx); 503 const string desc = "Compare renderbuffer " + de::toString(renderbufferNdx); 504 const Vec4 threshold = getFixedPointFormatThreshold(format, result.getFormat()); 505 506 if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), refRenderbuffer, result, threshold, tcu::COMPARE_LOG_RESULT)) 507 results.fail("Verification of renderbuffer " + de::toString(renderbufferNdx) + " failed."); 508 509 break; 510 } 511 512 default: 513 DE_ASSERT(DE_FALSE); 514 } 515 } 516 517 TextureFormat getReadPixelFormat (const TextureFormat& format) 518 { 519 switch (tcu::getTextureChannelClass(format.type)) 520 { 521 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 522 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT32); 523 524 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 525 return TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT32); 526 527 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 528 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 529 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8); 530 531 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 532 return TextureFormat(TextureFormat::RGBA, TextureFormat::FLOAT); 533 534 default: 535 DE_ASSERT(false); 536 return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8); 537 } 538 } 539 540 void verifyRenderbuffers (TestLog& log, 541 tcu::ResultCollector& results, 542 glu::RenderContext& renderContext, 543 const glu::RenderbufferVector& renderbuffers, 544 const glu::Framebuffer& framebuffer, 545 const vector<TextureLevel>& refRenderbuffers) 546 { 547 const glw::Functions& gl = renderContext.getFunctions(); 548 549 DE_ASSERT(renderbuffers.size() == refRenderbuffers.size()); 550 551 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer); 552 553 for (int renderbufferNdx = 0; renderbufferNdx < (int)renderbuffers.size(); renderbufferNdx++) 554 { 555 const TextureLevel& refRenderbuffer = refRenderbuffers[renderbufferNdx]; 556 const int width = refRenderbuffer.getWidth(); 557 const int height = refRenderbuffer.getHeight(); 558 const TextureFormat format = refRenderbuffer.getFormat(); 559 560 tcu::TextureLevel result (getReadPixelFormat(format), width, height); 561 562 gl.readBuffer(GL_COLOR_ATTACHMENT0 + renderbufferNdx); 563 glu::readPixels(renderContext, 0, 0, result.getAccess()); 564 GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels from renderbuffer failed."); 565 566 verifyRenderbuffer(log, results, format, renderbufferNdx, refRenderbuffer, result); 567 } 568 569 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 570 } 571 572 static const float s_quadCoords[] = 573 { 574 -0.5f, -0.5f, 575 0.5f, -0.5f, 576 0.5f, 0.5f, 577 578 0.5f, 0.5f, 579 -0.5f, 0.5f, 580 -0.5f, -0.5f 581 }; 582 583 void setBlendState (rr::FragmentOperationState& fragOps, const BlendState& state) 584 { 585 if (state.blendEq) 586 { 587 if (state.blendEq->is<BlendEq>()) 588 { 589 if (isAdvancedBlendEq(state.blendEq->get<BlendEq>())) 590 { 591 const rr::BlendEquationAdvanced equation = mapGLBlendEquationAdvanced(state.blendEq->get<BlendEq>()); 592 593 fragOps.blendMode = rr::BLENDMODE_ADVANCED; 594 fragOps.blendEquationAdvaced = equation; 595 } 596 else 597 { 598 const rr::BlendEquation equation = mapGLBlendEquation(state.blendEq->get<BlendEq>()); 599 600 fragOps.blendMode = rr::BLENDMODE_STANDARD; 601 fragOps.blendRGBState.equation = equation; 602 fragOps.blendAState.equation = equation; 603 } 604 } 605 else 606 { 607 DE_ASSERT(state.blendEq->is<SeparateBlendEq>()); 608 609 fragOps.blendMode = rr::BLENDMODE_STANDARD; 610 fragOps.blendRGBState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().rgb); 611 fragOps.blendAState.equation = mapGLBlendEquation(state.blendEq->get<SeparateBlendEq>().alpha); 612 } 613 } 614 615 if (state.blendFunc) 616 { 617 if (state.blendFunc->is<BlendFunc>()) 618 { 619 const rr::BlendFunc srcFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().src); 620 const rr::BlendFunc dstFunction = mapGLBlendFunc(state.blendFunc->get<BlendFunc>().dst); 621 622 fragOps.blendRGBState.srcFunc = srcFunction; 623 fragOps.blendRGBState.dstFunc = dstFunction; 624 625 fragOps.blendAState.srcFunc = srcFunction; 626 fragOps.blendAState.dstFunc = dstFunction; 627 } 628 else 629 { 630 DE_ASSERT(state.blendFunc->is<SeparateBlendFunc>()); 631 632 fragOps.blendRGBState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.src); 633 fragOps.blendRGBState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().rgb.dst); 634 635 fragOps.blendAState.srcFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.src); 636 fragOps.blendAState.dstFunc = mapGLBlendFunc(state.blendFunc->get<SeparateBlendFunc>().alpha.dst); 637 } 638 } 639 640 if (state.colorMask) 641 fragOps.colorMask = *state.colorMask; 642 } 643 644 rr::RenderState createRenderState (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const DrawBufferInfo& info) 645 { 646 const IVec2 size = info.getSize(); 647 rr::RenderState state (rr::ViewportState(rr::WindowRectangle(0, 0, size.x(), size.y()))); 648 649 state.fragOps.blendMode = rr::BLENDMODE_STANDARD; 650 651 setBlendState(state.fragOps, preCommonBlendState); 652 setBlendState(state.fragOps, info.getBlendState()); 653 setBlendState(state.fragOps, postCommonBlendState); 654 655 if (postCommonBlendState.enableBlend) 656 state.fragOps.blendMode = (*(postCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE); 657 else if (info.getBlendState().enableBlend) 658 state.fragOps.blendMode = (*(info.getBlendState().enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE); 659 else if (preCommonBlendState.enableBlend) 660 state.fragOps.blendMode = (*(preCommonBlendState.enableBlend) ? state.fragOps.blendMode : rr::BLENDMODE_NONE); 661 else 662 state.fragOps.blendMode = rr::BLENDMODE_NONE; 663 664 if (tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT 665 && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT 666 && tcu::getTextureChannelClass(info.getFormat().type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT) 667 state.fragOps.blendMode = rr::BLENDMODE_NONE; 668 669 return state; 670 } 671 672 class VertexShader : public rr::VertexShader 673 { 674 public: 675 VertexShader (void); 676 virtual void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 677 }; 678 679 VertexShader::VertexShader (void) 680 : rr::VertexShader (1, 1) 681 { 682 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; 683 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; 684 } 685 686 void VertexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 687 { 688 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 689 { 690 rr::VertexPacket& packet = *packets[packetNdx]; 691 692 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx); 693 packet.outputs[0] = 0.5f * (Vec4(1.0f) + rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx)); 694 } 695 } 696 697 class FragmentShader : public rr::FragmentShader 698 { 699 public: 700 FragmentShader (int drawBufferNdx, const DrawBufferInfo& info); 701 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 702 703 private: 704 const int m_drawBufferNdx; 705 const DrawBufferInfo m_info; 706 }; 707 708 FragmentShader::FragmentShader (int drawBufferNdx, const DrawBufferInfo& info) 709 : rr::FragmentShader (1, 1) 710 , m_drawBufferNdx (drawBufferNdx) 711 , m_info (info) 712 { 713 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; 714 715 switch (tcu::getTextureChannelClass(m_info.getFormat().type)) 716 { 717 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 718 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 719 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 720 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; 721 break; 722 723 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 724 m_outputs[0].type = rr::GENERICVECTYPE_UINT32; 725 break; 726 727 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 728 m_outputs[0].type = rr::GENERICVECTYPE_INT32; 729 break; 730 731 default: 732 DE_ASSERT(false); 733 }; 734 } 735 736 void FragmentShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 737 { 738 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 739 { 740 rr::FragmentPacket& packet = packets[packetNdx]; 741 742 DE_ASSERT(m_drawBufferNdx >= 0); 743 DE_UNREF(m_info); 744 745 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 746 { 747 const Vec2 vColor = rr::readVarying<float>(packet, context, 0, fragNdx).xy(); 748 const float values[] = 749 { 750 vColor.x(), 751 vColor.y(), 752 (1.0f - vColor.x()), 753 (1.0f - vColor.y()) 754 }; 755 756 switch (tcu::getTextureChannelClass(m_info.getFormat().type)) 757 { 758 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 759 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 760 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 761 { 762 const Vec4 color (values[(m_drawBufferNdx + 0) % 4], 763 values[(m_drawBufferNdx + 1) % 4], 764 values[(m_drawBufferNdx + 2) % 4], 765 values[(m_drawBufferNdx + 3) % 4]); 766 767 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color); 768 break; 769 } 770 771 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 772 { 773 const UVec4 color ((deUint32)(values[(m_drawBufferNdx + 0) % 4]), 774 (deUint32)(values[(m_drawBufferNdx + 1) % 4]), 775 (deUint32)(values[(m_drawBufferNdx + 2) % 4]), 776 (deUint32)(values[(m_drawBufferNdx + 3) % 4])); 777 778 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color); 779 break; 780 } 781 782 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 783 { 784 const IVec4 color ((deInt32)(values[(m_drawBufferNdx + 0) % 4]), 785 (deInt32)(values[(m_drawBufferNdx + 1) % 4]), 786 (deInt32)(values[(m_drawBufferNdx + 2) % 4]), 787 (deInt32)(values[(m_drawBufferNdx + 3) % 4])); 788 789 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color); 790 break; 791 } 792 793 default: 794 DE_ASSERT(DE_FALSE); 795 }; 796 } 797 } 798 } 799 800 rr::VertexAttrib createVertexAttrib (const float* coords) 801 { 802 rr::VertexAttrib attrib; 803 804 attrib.type = rr::VERTEXATTRIBTYPE_FLOAT; 805 attrib.size = 2; 806 attrib.pointer = coords; 807 808 return attrib; 809 } 810 811 void renderRefQuad (const BlendState& preCommonBlendState, 812 const BlendState& postCommonBlendState, 813 const vector<DrawBufferInfo>& drawBuffers, 814 vector<TextureLevel>& refRenderbuffers) 815 { 816 const rr::Renderer renderer; 817 const rr::PrimitiveList primitives (rr::PRIMITIVETYPE_TRIANGLES, 6, 0); 818 const rr::VertexAttrib vertexAttribs[] = 819 { 820 createVertexAttrib(s_quadCoords) 821 }; 822 823 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++) 824 { 825 if (drawBuffers[drawBufferNdx].getRender()) 826 { 827 const rr::RenderState renderState (createRenderState(preCommonBlendState, postCommonBlendState, drawBuffers[drawBufferNdx])); 828 const rr::RenderTarget renderTarget (rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refRenderbuffers[drawBufferNdx].getAccess())); 829 const VertexShader vertexShader; 830 const FragmentShader fragmentShader (drawBufferNdx, drawBuffers[drawBufferNdx]); 831 const rr::Program program (&vertexShader, &fragmentShader); 832 const rr::DrawCommand command (renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), vertexAttribs, primitives); 833 834 renderer.draw(command); 835 } 836 } 837 } 838 839 bool requiresAdvancedBlendEq (const BlendState& pre, const BlendState post, const vector<DrawBufferInfo>& drawBuffers) 840 { 841 bool requiresAdvancedBlendEq = false; 842 843 if (pre.blendEq && pre.blendEq->is<BlendEq>()) 844 requiresAdvancedBlendEq |= isAdvancedBlendEq(pre.blendEq->get<BlendEq>()); 845 846 if (post.blendEq && post.blendEq->is<BlendEq>()) 847 requiresAdvancedBlendEq |= isAdvancedBlendEq(post.blendEq->get<BlendEq>()); 848 849 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++) 850 { 851 const BlendState& drawBufferBlendState = drawBuffers[drawBufferNdx].getBlendState(); 852 853 if (drawBufferBlendState.blendEq && drawBufferBlendState.blendEq->is<BlendEq>()) 854 requiresAdvancedBlendEq |= isAdvancedBlendEq(drawBufferBlendState.blendEq->get<BlendEq>()); 855 } 856 857 return requiresAdvancedBlendEq; 858 } 859 860 glu::VertexSource genVertexSource (glu::RenderContext& renderContext) 861 { 862 const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); 863 864 const char* const vertexSource = 865 "${GLSL_VERSION_DECL}\n" 866 "layout(location=0) in highp vec2 i_coord;\n" 867 "out highp vec2 v_color;\n" 868 "void main (void)\n" 869 "{\n" 870 "\tv_color = 0.5 * (vec2(1.0) + i_coord);\n" 871 "\tgl_Position = vec4(i_coord, 0.0, 1.0);\n" 872 "}"; 873 874 map<string, string> args; 875 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 876 877 return glu::VertexSource(tcu::StringTemplate(vertexSource).specialize(args)); 878 } 879 880 glu::FragmentSource genFragmentSource (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext) 881 { 882 std::ostringstream stream; 883 const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); 884 885 stream << "${GLSL_VERSION_DECL}\n"; 886 887 if (requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers)) 888 { 889 stream << "${GLSL_EXTENSION}" 890 << "layout(blend_support_all_equations) out;\n"; 891 } 892 893 stream << "in highp vec2 v_color;\n"; 894 895 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++) 896 { 897 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx]; 898 const TextureFormat& format = drawBuffer.getFormat(); 899 900 stream << "layout(location=" << drawBufferNdx << ") out highp "; 901 902 switch (tcu::getTextureChannelClass(format.type)) 903 { 904 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 905 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 906 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 907 stream << "vec4"; 908 break; 909 910 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 911 stream << "uvec4"; 912 break; 913 914 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 915 stream << "ivec4"; 916 break; 917 918 default: 919 DE_ASSERT(DE_FALSE); 920 }; 921 922 stream << " o_drawBuffer" << drawBufferNdx << ";\n"; 923 } 924 925 stream << "void main (void)\n" 926 << "{\n"; 927 928 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++) 929 { 930 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx]; 931 const TextureFormat& format = drawBuffer.getFormat(); 932 const char* const values[] = 933 { 934 "v_color.x", 935 "v_color.y", 936 "(1.0 - v_color.x)", 937 "(1.0 - v_color.y)" 938 }; 939 940 stream << "\to_drawBuffer" << drawBufferNdx; 941 942 switch (tcu::getTextureChannelClass(format.type)) 943 { 944 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 945 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 946 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 947 stream << " = vec4(" << values[(drawBufferNdx + 0) % 4] 948 << ", " << values[(drawBufferNdx + 1) % 4] 949 << ", " << values[(drawBufferNdx + 2) % 4] 950 << ", " << values[(drawBufferNdx + 3) % 4] << ");\n"; 951 break; 952 953 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 954 stream << " = uvec4(uint(" << values[(drawBufferNdx + 0) % 4] 955 << "), uint(" << values[(drawBufferNdx + 1) % 4] 956 << "), uint(" << values[(drawBufferNdx + 2) % 4] 957 << "), uint(" << values[(drawBufferNdx + 3) % 4] << "));\n"; 958 break; 959 960 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 961 stream << " = ivec4(int(" << values[(drawBufferNdx + 0) % 4] 962 << "), int(" << values[(drawBufferNdx + 1) % 4] 963 << "), int(" << values[(drawBufferNdx + 2) % 4] 964 << "), int(" << values[(drawBufferNdx + 3) % 4] << "));\n"; 965 break; 966 967 default: 968 DE_ASSERT(DE_FALSE); 969 }; 970 } 971 972 stream << "}"; 973 974 map<string, string> args; 975 args["GLSL_VERSION_DECL"] = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 976 args["GLSL_EXTENSION"] = isES32 ? "\n" : "#extension GL_KHR_blend_equation_advanced : require\n"; 977 978 return glu::FragmentSource(tcu::StringTemplate(stream.str()).specialize(args)); 979 } 980 981 glu::ProgramSources genShaderSources (const BlendState& preCommonBlendState, const BlendState& postCommonBlendState, const vector<DrawBufferInfo>& drawBuffers, glu::RenderContext& renderContext) 982 { 983 return glu::ProgramSources() << genVertexSource(renderContext) << genFragmentSource(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext); 984 } 985 986 void renderGLQuad (glu::RenderContext& renderContext, 987 const glu::ShaderProgram& program) 988 { 989 const glu::VertexArrayBinding vertexArrays[] = 990 { 991 glu::VertexArrayBinding(glu::BindingPoint(0), glu::VertexArrayPointer(glu::VTX_COMP_FLOAT, glu::VTX_COMP_CONVERT_NONE, 2, 6, 0, s_quadCoords)) 992 }; 993 994 glu::draw(renderContext, program.getProgram(), 1, vertexArrays, glu::pr::Triangles(6)); 995 } 996 997 void renderQuad (TestLog& log, 998 glu::RenderContext& renderContext, 999 const BlendState& preCommonBlendState, 1000 const BlendState& postCommonBlendState, 1001 const vector<DrawBufferInfo>& drawBuffers, 1002 const glu::Framebuffer& framebuffer, 1003 vector<TextureLevel>& refRenderbuffers) 1004 { 1005 const glw::Functions& gl = renderContext.getFunctions(); 1006 const glu::ShaderProgram program (gl, genShaderSources(preCommonBlendState, postCommonBlendState, drawBuffers, renderContext)); 1007 const IVec2 size = drawBuffers[0].getSize(); 1008 const bool requiresBlendBarriers = requiresAdvancedBlendEq(preCommonBlendState, postCommonBlendState, drawBuffers); 1009 1010 vector<deUint32> bufs; 1011 1012 bufs.resize(drawBuffers.size()); 1013 1014 for (int bufNdx = 0; bufNdx < (int)bufs.size(); bufNdx++) 1015 bufs[bufNdx] = (drawBuffers[bufNdx].getRender() ? GL_COLOR_ATTACHMENT0 + bufNdx : GL_NONE); 1016 1017 log << program; 1018 1019 gl.viewport(0, 0, size.x(), size.y()); 1020 gl.useProgram(program.getProgram()); 1021 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer); 1022 1023 setCommonBlendState(gl, preCommonBlendState); 1024 1025 for (int renderbufferNdx = 0; renderbufferNdx < (int)drawBuffers.size(); renderbufferNdx++) 1026 setIndexedBlendState(gl, drawBuffers[renderbufferNdx].getBlendState(), renderbufferNdx); 1027 1028 setCommonBlendState(gl, postCommonBlendState); 1029 1030 gl.drawBuffers((glw::GLsizei)bufs.size(), &(bufs[0])); 1031 1032 if (requiresBlendBarriers) 1033 gl.blendBarrier(); 1034 1035 renderGLQuad(renderContext, program); 1036 1037 if (requiresBlendBarriers) 1038 gl.blendBarrier(); 1039 1040 gl.drawBuffers(0, 0); 1041 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 1042 gl.useProgram(0); 1043 1044 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render"); 1045 1046 renderRefQuad(preCommonBlendState, postCommonBlendState, drawBuffers, refRenderbuffers); 1047 } 1048 1049 void logBlendState (TestLog& log, 1050 const BlendState& blend) 1051 { 1052 if (blend.enableBlend) 1053 { 1054 if (*blend.enableBlend) 1055 log << TestLog::Message << "Enable blending." << TestLog::EndMessage; 1056 else 1057 log << TestLog::Message << "Disable blending." << TestLog::EndMessage; 1058 } 1059 1060 if (blend.colorMask) 1061 { 1062 const BVec4 mask = *blend.colorMask; 1063 1064 log << TestLog::Message << "Set color mask: " << mask << "." << TestLog::EndMessage; 1065 } 1066 1067 if (blend.blendEq) 1068 { 1069 const Either<BlendEq, SeparateBlendEq>& blendEq = *blend.blendEq; 1070 1071 if (blendEq.is<BlendEq>()) 1072 log << TestLog::Message << "Set blend equation: " << glu::getBlendEquationStr(blendEq.get<BlendEq>()) << "." << TestLog::EndMessage; 1073 else if (blendEq.is<SeparateBlendEq>()) 1074 log << TestLog::Message << "Set blend equation rgb: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().rgb) << ", alpha: " << glu::getBlendEquationStr(blendEq.get<SeparateBlendEq>().alpha) << "." << TestLog::EndMessage; 1075 else 1076 DE_ASSERT(false); 1077 } 1078 1079 if (blend.blendFunc) 1080 { 1081 const Either<BlendFunc, SeparateBlendFunc>& blendFunc = *blend.blendFunc; 1082 1083 if (blendFunc.is<BlendFunc>()) 1084 log << TestLog::Message << "Set blend function source: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<BlendFunc>().dst) << "." << TestLog::EndMessage; 1085 else if (blendFunc.is<SeparateBlendFunc>()) 1086 { 1087 log << TestLog::Message << "Set blend function rgb source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().rgb.dst) << "." << TestLog::EndMessage; 1088 log << TestLog::Message << "Set blend function alpha source: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.src) << ", destination: " << glu::getBlendFactorStr(blendFunc.get<SeparateBlendFunc>().alpha.dst) << "." << TestLog::EndMessage; 1089 } 1090 else 1091 DE_ASSERT(false); 1092 } 1093 } 1094 1095 void logTestCaseInfo (TestLog& log, 1096 const BlendState& preCommonBlendState, 1097 const BlendState& postCommonBlendState, 1098 const vector<DrawBufferInfo>& drawBuffers) 1099 { 1100 { 1101 tcu::ScopedLogSection drawBuffersSection(log, "DrawBuffers", "Draw buffers"); 1102 1103 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++) 1104 { 1105 const tcu::ScopedLogSection drawBufferSection (log, "DrawBuffer" + de::toString(drawBufferNdx), "Draw Buffer " + de::toString(drawBufferNdx)); 1106 const DrawBufferInfo& drawBuffer = drawBuffers[drawBufferNdx]; 1107 1108 log << TestLog::Message << "Format: " << drawBuffer.getFormat() << TestLog::EndMessage; 1109 log << TestLog::Message << "Size: " << drawBuffer.getSize() << TestLog::EndMessage; 1110 log << TestLog::Message << "Render: " << (drawBuffer.getRender() ? "true" : "false") << TestLog::EndMessage; 1111 } 1112 } 1113 1114 if (!preCommonBlendState.isEmpty()) 1115 { 1116 tcu::ScopedLogSection s(log, "PreCommonState", "First set common blend state"); 1117 logBlendState(log, preCommonBlendState); 1118 } 1119 1120 for (int drawBufferNdx = 0; drawBufferNdx < (int)drawBuffers.size(); drawBufferNdx++) 1121 { 1122 if (!drawBuffers[drawBufferNdx].getBlendState().isEmpty()) 1123 { 1124 const tcu::ScopedLogSection s(log, "DrawBufferState" + de::toString(drawBufferNdx), "Set DrawBuffer " + de::toString(drawBufferNdx) + " state to"); 1125 1126 logBlendState(log, drawBuffers[drawBufferNdx].getBlendState()); 1127 } 1128 } 1129 1130 if (!postCommonBlendState.isEmpty()) 1131 { 1132 tcu::ScopedLogSection s(log, "PostCommonState", "After set common blend state"); 1133 logBlendState(log, postCommonBlendState); 1134 } 1135 } 1136 1137 void runTest (TestLog& log, 1138 tcu::ResultCollector& results, 1139 glu::RenderContext& renderContext, 1140 1141 const BlendState& preCommonBlendState, 1142 const BlendState& postCommonBlendState, 1143 const vector<DrawBufferInfo>& drawBuffers) 1144 { 1145 const glw::Functions& gl = renderContext.getFunctions(); 1146 glu::RenderbufferVector renderbuffers (gl, drawBuffers.size()); 1147 glu::Framebuffer framebuffer (gl); 1148 vector<TextureLevel> refRenderbuffers (drawBuffers.size()); 1149 1150 logTestCaseInfo(log, preCommonBlendState, postCommonBlendState, drawBuffers); 1151 1152 genRenderbuffers(gl, drawBuffers, framebuffer, renderbuffers, refRenderbuffers); 1153 1154 renderQuad(log, renderContext, preCommonBlendState, postCommonBlendState, drawBuffers, framebuffer, refRenderbuffers); 1155 1156 verifyRenderbuffers(log, results, renderContext, renderbuffers, framebuffer, refRenderbuffers); 1157 } 1158 1159 class DrawBuffersIndexedTest : public TestCase 1160 { 1161 public: 1162 DrawBuffersIndexedTest (Context& context, 1163 const BlendState& preCommonBlendState, 1164 const BlendState& postCommonBlendState, 1165 const vector<DrawBufferInfo>& drawBuffers, 1166 const string& name, 1167 const string& description); 1168 1169 void init (void); 1170 IterateResult iterate (void); 1171 1172 private: 1173 const BlendState m_preCommonBlendState; 1174 const BlendState m_postCommonBlendState; 1175 const vector<DrawBufferInfo> m_drawBuffers; 1176 }; 1177 1178 DrawBuffersIndexedTest::DrawBuffersIndexedTest (Context& context, 1179 const BlendState& preCommonBlendState, 1180 const BlendState& postCommonBlendState, 1181 const vector<DrawBufferInfo>& drawBuffers, 1182 const string& name, 1183 const string& description) 1184 : TestCase (context, name.c_str(), description.c_str()) 1185 , m_preCommonBlendState (preCommonBlendState) 1186 , m_postCommonBlendState (postCommonBlendState) 1187 , m_drawBuffers (drawBuffers) 1188 { 1189 } 1190 1191 void DrawBuffersIndexedTest::init (void) 1192 { 1193 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1194 1195 if (!isES32) 1196 { 1197 if (requiresAdvancedBlendEq(m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers) && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced")) 1198 TCU_THROW(NotSupportedError, "Extension GL_KHR_blend_equation_advanced not supported"); 1199 1200 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed")) 1201 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported"); 1202 } 1203 } 1204 1205 TestCase::IterateResult DrawBuffersIndexedTest::iterate (void) 1206 { 1207 TestLog& log = m_testCtx.getLog(); 1208 tcu::ResultCollector results (log); 1209 1210 runTest(log, results, m_context.getRenderContext(), m_preCommonBlendState, m_postCommonBlendState, m_drawBuffers); 1211 1212 results.setTestContextResult(m_testCtx); 1213 1214 return STOP; 1215 } 1216 1217 BlendEq getRandomBlendEq (de::Random& rng) 1218 { 1219 const BlendEq eqs[] = 1220 { 1221 GL_FUNC_ADD, 1222 GL_FUNC_SUBTRACT, 1223 GL_FUNC_REVERSE_SUBTRACT, 1224 GL_MIN, 1225 GL_MAX 1226 }; 1227 1228 return de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(eqs)>(eqs, rng.getUint32() % DE_LENGTH_OF_ARRAY(eqs)); 1229 } 1230 1231 BlendFunc getRandomBlendFunc (de::Random& rng) 1232 { 1233 const deUint32 funcs[] = 1234 { 1235 GL_ZERO, 1236 GL_ONE, 1237 GL_SRC_COLOR, 1238 GL_ONE_MINUS_SRC_COLOR, 1239 GL_DST_COLOR, 1240 GL_ONE_MINUS_DST_COLOR, 1241 GL_SRC_ALPHA, 1242 GL_ONE_MINUS_SRC_ALPHA, 1243 GL_DST_ALPHA, 1244 GL_ONE_MINUS_DST_ALPHA, 1245 GL_CONSTANT_COLOR, 1246 GL_ONE_MINUS_CONSTANT_COLOR, 1247 GL_CONSTANT_ALPHA, 1248 GL_ONE_MINUS_CONSTANT_ALPHA, 1249 GL_SRC_ALPHA_SATURATE 1250 }; 1251 1252 const deUint32 src = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs)); 1253 const deUint32 dst = de::getSizedArrayElement<DE_LENGTH_OF_ARRAY(funcs)>(funcs, rng.getUint32() % DE_LENGTH_OF_ARRAY(funcs)); 1254 1255 return BlendFunc(src, dst); 1256 } 1257 1258 void genRandomBlendState (de::Random& rng, BlendState& blendState) 1259 { 1260 if (rng.getBool()) 1261 blendState.enableBlend = rng.getBool(); 1262 1263 if (rng.getBool()) 1264 { 1265 if (rng.getBool()) 1266 blendState.blendEq = getRandomBlendEq(rng); 1267 else 1268 { 1269 const BlendEq rgb = getRandomBlendEq(rng); 1270 const BlendEq alpha = getRandomBlendEq(rng); 1271 1272 blendState.blendEq = SeparateBlendEq(rgb, alpha); 1273 } 1274 } 1275 1276 if (rng.getBool()) 1277 { 1278 if (rng.getBool()) 1279 blendState.blendFunc = getRandomBlendFunc(rng); 1280 else 1281 { 1282 const BlendFunc rgb = getRandomBlendFunc(rng); 1283 const BlendFunc alpha = getRandomBlendFunc(rng); 1284 1285 blendState.blendFunc = SeparateBlendFunc(rgb, alpha); 1286 } 1287 } 1288 1289 if (rng.getBool()) 1290 { 1291 const bool red = rng.getBool(); 1292 const bool green = rng.getBool(); 1293 const bool blue = rng.getBool(); 1294 const bool alpha = rng.getBool(); 1295 1296 blendState.colorMask = BVec4(red, blue, green, alpha); 1297 } 1298 } 1299 1300 TextureFormat getRandomFormat (de::Random& rng, Context& context) 1301 { 1302 const bool isES32 = glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1303 1304 const deUint32 glFormats[] = 1305 { 1306 GL_R8, 1307 GL_RG8, 1308 GL_RGB8, 1309 GL_RGB565, 1310 GL_RGBA4, 1311 GL_RGB5_A1, 1312 GL_RGBA8, 1313 GL_RGB10_A2, 1314 GL_RGB10_A2UI, 1315 GL_R8I, 1316 GL_R8UI, 1317 GL_R16I, 1318 GL_R16UI, 1319 GL_R32I, 1320 GL_R32UI, 1321 GL_RG8I, 1322 GL_RG8UI, 1323 GL_RG16I, 1324 GL_RG16UI, 1325 GL_RG32I, 1326 GL_RG32UI, 1327 GL_RGBA8I, 1328 GL_RGBA8UI, 1329 GL_RGBA16I, 1330 GL_RGBA16UI, 1331 GL_RGBA32I, 1332 GL_RGBA32UI, 1333 GL_RGBA16F, 1334 GL_R32F, 1335 GL_RG32F, 1336 GL_RGBA32F, 1337 GL_R11F_G11F_B10F 1338 }; 1339 1340 if (isES32) 1341 return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % DE_LENGTH_OF_ARRAY(glFormats))); 1342 else 1343 { 1344 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(glFormats) == 32); 1345 return glu::mapGLInternalFormat(de::getArrayElement(glFormats, rng.getUint32() % (DE_LENGTH_OF_ARRAY(glFormats) - 5))); 1346 } 1347 } 1348 1349 void genRandomTest (de::Random& rng, BlendState& preCommon, BlendState& postCommon, vector<DrawBufferInfo>& drawBuffers, int maxDrawBufferCount, Context& context) 1350 { 1351 genRandomBlendState(rng, preCommon); 1352 genRandomBlendState(rng, postCommon); 1353 1354 for (int drawBufferNdx = 0; drawBufferNdx < maxDrawBufferCount; drawBufferNdx++) 1355 { 1356 const bool render = rng.getFloat() > 0.1f; 1357 const IVec2 size (64, 64); 1358 const TextureFormat format (getRandomFormat(rng, context)); 1359 BlendState blendState; 1360 1361 genRandomBlendState(rng, blendState); 1362 1363 // 32bit float formats don't support blending in GLES32 1364 if (format.type == tcu::TextureFormat::FLOAT) 1365 { 1366 // If format is 32bit float post common can't enable blending 1367 if (postCommon.enableBlend && *postCommon.enableBlend) 1368 { 1369 // Either don't set enable blend or disable blending 1370 if (rng.getBool()) 1371 postCommon.enableBlend = tcu::nothing<bool>(); 1372 else 1373 postCommon.enableBlend = tcu::just(false); 1374 } 1375 1376 // If post common doesn't disable blending, per attachment state or 1377 // pre common must. 1378 if (!postCommon.enableBlend) 1379 { 1380 // If pre common enables blend per attachment must disable it 1381 // If per attachment state changes blend state it must disable it 1382 if ((preCommon.enableBlend && *preCommon.enableBlend) 1383 || blendState.enableBlend) 1384 blendState.enableBlend = tcu::just(false); 1385 } 1386 } 1387 1388 drawBuffers.push_back(DrawBufferInfo(render, size, blendState, format)); 1389 } 1390 } 1391 1392 class MaxDrawBuffersIndexedTest : public TestCase 1393 { 1394 public: 1395 MaxDrawBuffersIndexedTest (Context& contet, int seed); 1396 1397 void init (void); 1398 IterateResult iterate (void); 1399 1400 private: 1401 const int m_seed; 1402 }; 1403 1404 MaxDrawBuffersIndexedTest::MaxDrawBuffersIndexedTest (Context& context, int seed) 1405 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str()) 1406 , m_seed (deInt32Hash(seed) ^ 1558001307u) 1407 { 1408 } 1409 1410 void MaxDrawBuffersIndexedTest::init (void) 1411 { 1412 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1413 1414 if (!isES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed")) 1415 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported"); 1416 } 1417 1418 TestCase::IterateResult MaxDrawBuffersIndexedTest::iterate (void) 1419 { 1420 TestLog& log = m_testCtx.getLog(); 1421 tcu::ResultCollector results (log); 1422 de::Random rng (m_seed); 1423 BlendState preCommonBlendState; 1424 BlendState postCommonBlendState; 1425 vector<DrawBufferInfo> drawBuffers; 1426 1427 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, 4, m_context); 1428 1429 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers); 1430 1431 results.setTestContextResult(m_testCtx); 1432 1433 return STOP; 1434 } 1435 1436 class ImplMaxDrawBuffersIndexedTest : public TestCase 1437 { 1438 public: 1439 ImplMaxDrawBuffersIndexedTest (Context& contet, int seed); 1440 1441 void init (void); 1442 IterateResult iterate (void); 1443 1444 private: 1445 const int m_seed; 1446 }; 1447 1448 ImplMaxDrawBuffersIndexedTest::ImplMaxDrawBuffersIndexedTest (Context& context, int seed) 1449 : TestCase (context, de::toString(seed).c_str(), de::toString(seed).c_str()) 1450 , m_seed (deInt32Hash(seed) ^ 2686315738u) 1451 { 1452 } 1453 1454 void ImplMaxDrawBuffersIndexedTest::init (void) 1455 { 1456 const bool isES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1457 1458 if (!isES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_draw_buffers_indexed")) 1459 TCU_THROW(NotSupportedError, "Extension GL_EXT_draw_buffers_indexed not supported"); 1460 } 1461 1462 TestCase::IterateResult ImplMaxDrawBuffersIndexedTest::iterate (void) 1463 { 1464 TestLog& log = m_testCtx.getLog(); 1465 tcu::ResultCollector results (log); 1466 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1467 de::Random rng (m_seed); 1468 deInt32 maxDrawBuffers = 0; 1469 BlendState preCommonBlendState; 1470 BlendState postCommonBlendState; 1471 vector<DrawBufferInfo> drawBuffers; 1472 1473 gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); 1474 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_DRAW_BUFFERS) failed"); 1475 1476 TCU_CHECK(maxDrawBuffers > 0); 1477 1478 genRandomTest(rng, preCommonBlendState, postCommonBlendState, drawBuffers, maxDrawBuffers, m_context); 1479 1480 runTest(log, results, m_context.getRenderContext(), preCommonBlendState, postCommonBlendState, drawBuffers); 1481 1482 results.setTestContextResult(m_testCtx); 1483 1484 return STOP; 1485 } 1486 1487 enum PrePost 1488 { 1489 PRE, 1490 POST 1491 }; 1492 1493 TestCase* createDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState) 1494 { 1495 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>()); 1496 1497 if (prepost == PRE) 1498 { 1499 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)), 1500 commonState.blendEq, 1501 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))), 1502 tcu::nothing<BVec4>()); 1503 vector<DrawBufferInfo> drawBuffers; 1504 1505 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))); 1506 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))); 1507 1508 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name); 1509 } 1510 else if (prepost == POST) 1511 { 1512 const BlendState preState = BlendState(just(true), 1513 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), 1514 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)), 1515 tcu::nothing<BVec4>()); 1516 vector<DrawBufferInfo> drawBuffers; 1517 1518 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), emptyState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))); 1519 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))); 1520 1521 return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name); 1522 } 1523 else 1524 { 1525 DE_ASSERT(false); 1526 return DE_NULL; 1527 } 1528 } 1529 1530 TestCase* createAdvancedEqDiffTest (Context& context, PrePost prepost, const char* name, const BlendState& commonState, const BlendState& drawBufferState) 1531 { 1532 const BlendState emptyState = BlendState(tcu::nothing<bool>(), tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), tcu::nothing<Either<BlendFunc, SeparateBlendFunc> >(), tcu::nothing<BVec4>()); 1533 1534 if (prepost == PRE) 1535 { 1536 const BlendState preState = BlendState((commonState.enableBlend ? commonState.enableBlend : just(true)), 1537 commonState.blendEq, 1538 (commonState.blendFunc ? commonState.blendFunc : just(Either<BlendFunc, SeparateBlendFunc>(BlendFunc(GL_ONE, GL_ONE)))), 1539 tcu::nothing<BVec4>()); 1540 vector<DrawBufferInfo> drawBuffers; 1541 1542 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))); 1543 1544 return new DrawBuffersIndexedTest(context, preState, emptyState, drawBuffers, name, name); 1545 } 1546 else if (prepost == POST) 1547 { 1548 const BlendState preState = BlendState(just(true), 1549 tcu::nothing<Either<BlendEq, SeparateBlendEq> >(), 1550 Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_ONE, GL_ONE)), 1551 tcu::nothing<BVec4>()); 1552 vector<DrawBufferInfo> drawBuffers; 1553 1554 drawBuffers.push_back(DrawBufferInfo(true, IVec2(64, 64), drawBufferState, TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))); 1555 1556 return new DrawBuffersIndexedTest(context, preState, commonState, drawBuffers, name, name); 1557 } 1558 else 1559 { 1560 DE_ASSERT(false); 1561 return DE_NULL; 1562 } 1563 } 1564 1565 void addDrawBufferCommonTests (TestCaseGroup* root, PrePost prepost) 1566 { 1567 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1568 1569 { 1570 const BlendState disableState = BlendState(just(false), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1571 const BlendState enableState = BlendState(just(true), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1572 1573 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_enable", enableState, enableState)); 1574 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_disable", disableState, disableState)); 1575 root->addChild(createDiffTest(root->getContext(), prepost, "common_disable_buffer_enable", disableState, enableState)); 1576 root->addChild(createDiffTest(root->getContext(), prepost, "common_enable_buffer_disable", enableState, disableState)); 1577 } 1578 1579 { 1580 const BlendState eqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_ADD), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1581 const BlendState eqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_FUNC_SUBTRACT), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1582 1583 const BlendState separateEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_ADD, GL_FUNC_SUBTRACT)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1584 const BlendState separateEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(SeparateBlendEq(GL_FUNC_SUBTRACT, GL_FUNC_ADD)), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1585 1586 const BlendState advancedEqStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_DIFFERENCE), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1587 const BlendState advancedEqStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(GL_SCREEN), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1588 1589 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_blend_eq", eqStateA, eqStateB)); 1590 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_separate_blend_eq", eqStateA, separateEqStateB)); 1591 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_blend_eq_buffer_advanced_blend_eq", eqStateA, advancedEqStateB)); 1592 1593 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_blend_eq", separateEqStateA, eqStateB)); 1594 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_separate_blend_eq", separateEqStateA, separateEqStateB)); 1595 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_separate_blend_eq_buffer_advanced_blend_eq", separateEqStateA, advancedEqStateB)); 1596 1597 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_blend_eq", advancedEqStateA, eqStateB)); 1598 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_separate_blend_eq", advancedEqStateA, separateEqStateB)); 1599 root->addChild(createAdvancedEqDiffTest(root->getContext(), prepost, "common_advanced_blend_eq_buffer_advanced_blend_eq", advancedEqStateA, advancedEqStateB)); 1600 } 1601 1602 { 1603 const BlendState funcStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA)), Maybe<BVec4>()); 1604 const BlendState funcStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA)), Maybe<BVec4>()); 1605 const BlendState separateFuncStateA = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA), BlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA))), Maybe<BVec4>()); 1606 const BlendState separateFuncStateB = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(SeparateBlendFunc(BlendFunc(GL_DST_ALPHA, GL_SRC_ALPHA), BlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA))), Maybe<BVec4>()); 1607 1608 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_blend_func", funcStateA, funcStateB)); 1609 root->addChild(createDiffTest(root->getContext(), prepost, "common_blend_func_buffer_separate_blend_func", funcStateA, separateFuncStateB)); 1610 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_blend_func", separateFuncStateA, funcStateB)); 1611 root->addChild(createDiffTest(root->getContext(), prepost, "common_separate_blend_func_buffer_separate_blend_func", separateFuncStateA, separateFuncStateB)); 1612 } 1613 1614 { 1615 const BlendState commonColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(true, false, true, false))); 1616 const BlendState bufferColorMaskState = BlendState(tcu::nothing<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>(BVec4(false, true, false, true))); 1617 1618 root->addChild(createDiffTest(root->getContext(), prepost, "common_color_mask_buffer_color_mask", commonColorMaskState, bufferColorMaskState)); 1619 } 1620 } 1621 1622 void addRandomMaxTest (TestCaseGroup* root) 1623 { 1624 for (int i = 0; i < 20; i++) 1625 root->addChild(new MaxDrawBuffersIndexedTest(root->getContext(), i)); 1626 } 1627 1628 void addRandomImplMaxTest (TestCaseGroup* root) 1629 { 1630 for (int i = 0; i < 20; i++) 1631 root->addChild(new ImplMaxDrawBuffersIndexedTest(root->getContext(), i)); 1632 } 1633 1634 } // anonymous 1635 1636 TestCaseGroup* createDrawBuffersIndexedTests (Context& context) 1637 { 1638 const BlendState emptyState = BlendState(Maybe<bool>(), Maybe<Either<BlendEq, SeparateBlendEq> >(), Maybe<Either<BlendFunc, SeparateBlendFunc> >(), Maybe<BVec4>()); 1639 TestCaseGroup* const group = new TestCaseGroup(context, "draw_buffers_indexed", "Test for indexed draw buffers. GL_EXT_draw_buffers_indexed."); 1640 1641 TestCaseGroup* const preGroup = new TestCaseGroup(context, "overwrite_common", "Set common state and overwrite it with draw buffer blend state."); 1642 TestCaseGroup* const postGroup = new TestCaseGroup(context, "overwrite_indexed", "Set indexed blend state and overwrite it with common state."); 1643 TestCaseGroup* const randomGroup = new TestCaseGroup(context, "random", "Random indexed blend state tests."); 1644 TestCaseGroup* const maxGroup = new TestCaseGroup(context, "max_required_draw_buffers", "Random tests using minimum maximum number of draw buffers."); 1645 TestCaseGroup* const maxImplGroup = new TestCaseGroup(context, "max_implementation_draw_buffers", "Random tests using maximum number of draw buffers reported by implementation."); 1646 1647 group->addChild(preGroup); 1648 group->addChild(postGroup); 1649 group->addChild(randomGroup); 1650 1651 randomGroup->addChild(maxGroup); 1652 randomGroup->addChild(maxImplGroup); 1653 1654 addDrawBufferCommonTests(preGroup, PRE); 1655 addDrawBufferCommonTests(postGroup, POST); 1656 addRandomMaxTest(maxGroup); 1657 addRandomImplMaxTest(maxImplGroup); 1658 1659 return group; 1660 } 1661 1662 } // Functional 1663 } // gles31 1664 } // deqp 1665