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