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