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