1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL (ES) Module 3 * ----------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Framebuffer completeness tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "glsFboCompletenessTests.hpp" 25 26 #include "gluStrUtil.hpp" 27 #include "gluObjectWrapper.hpp" 28 #include "deStringUtil.hpp" 29 30 #include <cctype> 31 #include <iterator> 32 #include <algorithm> 33 34 using namespace glw; 35 using glu::RenderContext; 36 using glu::getFramebufferStatusName; 37 using glu::getPixelFormatName; 38 using glu::getTypeName; 39 using glu::getErrorName; 40 using glu::Framebuffer; 41 using tcu::TestCase; 42 using tcu::TestCaseGroup; 43 using tcu::TestLog; 44 using tcu::MessageBuilder; 45 using tcu::TestNode; 46 using std::string; 47 using de::toString; 48 using namespace deqp::gls::FboUtil; 49 using namespace deqp::gls::FboUtil::config; 50 typedef TestCase::IterateResult IterateResult; 51 52 namespace deqp 53 { 54 namespace gls 55 { 56 namespace fboc 57 { 58 59 namespace details 60 { 61 // \todo [2013-12-04 lauri] Place in deStrUtil.hpp? 62 63 string toLower (const string& str) 64 { 65 string ret; 66 std::transform(str.begin(), str.end(), std::inserter(ret, ret.begin()), ::tolower); 67 return ret; 68 } 69 70 // The following extensions are applicable both to ES2 and ES3. 71 72 // GL_OES_depth_texture 73 static const FormatKey s_oesDepthTextureFormats[] = 74 { 75 GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT), 76 GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT), 77 }; 78 79 // GL_OES_packed_depth_stencil 80 static const FormatKey s_oesPackedDepthStencilSizedFormats[] = 81 { 82 GL_DEPTH24_STENCIL8, 83 }; 84 85 static const FormatKey s_oesPackedDepthStencilTexFormats[] = 86 { 87 GLS_UNSIZED_FORMATKEY(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8), 88 }; 89 90 // GL_OES_required_internalformat 91 static const FormatKey s_oesRequiredInternalFormatColorFormats[] = 92 { 93 // Same as ES2 RBO formats, plus RGBA8 (even without OES_rgb8_rgba8) 94 GL_RGB5_A1, GL_RGBA8, GL_RGBA4, GL_RGB565 95 }; 96 97 static const FormatKey s_oesRequiredInternalFormatDepthFormats[] = 98 { 99 GL_DEPTH_COMPONENT16, 100 }; 101 102 // GL_EXT_color_buffer_half_float 103 static const FormatKey s_extColorBufferHalfFloatFormats[] = 104 { 105 GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F, 106 }; 107 108 static const FormatKey s_oesDepth24SizedFormats[] = 109 { 110 GL_DEPTH_COMPONENT24 111 }; 112 113 static const FormatKey s_oesDepth32SizedFormats[] = 114 { 115 GL_DEPTH_COMPONENT32 116 }; 117 118 static const FormatKey s_oesRgb8Rgba8RboFormats[] = 119 { 120 GL_RGB8, 121 GL_RGBA8, 122 }; 123 124 static const FormatKey s_oesRequiredInternalFormatRgb8ColorFormat[] = 125 { 126 GL_RGB8, 127 }; 128 129 static const FormatKey s_extTextureType2101010RevFormats[] = 130 { 131 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV), 132 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV), 133 }; 134 135 static const FormatKey s_oesRequiredInternalFormat10bitColorFormats[] = 136 { 137 GL_RGB10_A2, GL_RGB10, 138 }; 139 140 static const FormatKey s_extTextureRgRboFormats[] = 141 { 142 GL_R8, GL_RG8, 143 }; 144 145 static const FormatKey s_extTextureRgTexFormats[] = 146 { 147 GLS_UNSIZED_FORMATKEY(GL_RED, GL_UNSIGNED_BYTE), 148 GLS_UNSIZED_FORMATKEY(GL_RG, GL_UNSIGNED_BYTE), 149 }; 150 151 static const FormatKey s_extTextureRgFloatTexFormats[] = 152 { 153 GLS_UNSIZED_FORMATKEY(GL_RED, GL_FLOAT), 154 GLS_UNSIZED_FORMATKEY(GL_RG, GL_FLOAT), 155 }; 156 157 static const FormatKey s_extTextureRgHalfFloatTexFormats[] = 158 { 159 GLS_UNSIZED_FORMATKEY(GL_RED, GL_HALF_FLOAT_OES), 160 GLS_UNSIZED_FORMATKEY(GL_RG, GL_HALF_FLOAT_OES), 161 }; 162 163 static const FormatKey s_nvPackedFloatRboFormats[] = 164 { 165 GL_R11F_G11F_B10F, 166 }; 167 168 static const FormatKey s_nvPackedFloatTexFormats[] = 169 { 170 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV), 171 }; 172 173 static const FormatKey s_extSrgbRboFormats[] = 174 { 175 GL_SRGB8_ALPHA8, 176 }; 177 178 static const FormatKey s_extSrgbRenderableTexFormats[] = 179 { 180 GLS_UNSIZED_FORMATKEY(GL_SRGB_ALPHA, GL_UNSIGNED_BYTE), 181 }; 182 183 static const FormatKey s_extSrgbNonRenderableTexFormats[] = 184 { 185 GLS_UNSIZED_FORMATKEY(GL_SRGB, GL_UNSIGNED_BYTE), 186 GL_SRGB8, 187 }; 188 189 static const FormatKey s_nvSrgbFormatsRboFormats[] = 190 { 191 GL_SRGB8, 192 }; 193 194 static const FormatKey s_nvSrgbFormatsTextureFormats[] = 195 { 196 GL_SRGB8, 197 198 // The extension does not actually require any unsized format 199 // to be renderable. However, the renderablility of unsized 200 // SRGB,UBYTE internalformat-type pair is implied. 201 GLS_UNSIZED_FORMATKEY(GL_SRGB, GL_UNSIGNED_BYTE), 202 }; 203 204 static const FormatKey s_oesRgb8Rgba8TexFormats[] = 205 { 206 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_BYTE), 207 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_BYTE), 208 }; 209 210 static const FormatExtEntry s_esExtFormats[] = 211 { 212 { 213 "GL_OES_depth_texture", 214 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID, 215 GLS_ARRAY_RANGE(s_oesDepthTextureFormats), 216 }, 217 { 218 "GL_OES_packed_depth_stencil", 219 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID, 220 GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats) 221 }, 222 { 223 "GL_OES_packed_depth_stencil GL_OES_required_internalformat", 224 TEXTURE_VALID, 225 GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats) 226 }, 227 { 228 "GL_OES_packed_depth_stencil", 229 DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID, 230 GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats) 231 }, 232 // \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a 233 // requirement on ES3 also. Or is color_buffer_half_float applicatble at 234 // all on ES3, since there's also EXT_color_buffer_float? 235 { 236 "GL_OES_texture_half_float GL_EXT_color_buffer_half_float", 237 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 238 GLS_ARRAY_RANGE(s_extColorBufferHalfFloatFormats) 239 }, 240 241 // OES_required_internalformat doesn't actually specify that these are renderable, 242 // since it was written against ES 1.1. 243 { 244 "GL_OES_required_internalformat", 245 // Allow but don't require RGBA8 to be color-renderable if 246 // OES_rgb8_rgba8 is not present. 247 COLOR_RENDERABLE | TEXTURE_VALID, 248 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatColorFormats) 249 }, 250 { 251 "GL_OES_required_internalformat", 252 DEPTH_RENDERABLE | TEXTURE_VALID, 253 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatDepthFormats) 254 }, 255 { 256 "GL_EXT_texture_rg", 257 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 258 GLS_ARRAY_RANGE(s_extTextureRgRboFormats) 259 }, 260 // These are not specified to be color-renderable, but the wording is 261 // exactly as ambiguous as the wording in the ES2 spec. 262 { 263 "GL_EXT_texture_rg", 264 COLOR_RENDERABLE | TEXTURE_VALID, 265 GLS_ARRAY_RANGE(s_extTextureRgTexFormats) 266 }, 267 { 268 "GL_EXT_texture_rg GL_OES_texture_float", 269 COLOR_RENDERABLE | TEXTURE_VALID, 270 GLS_ARRAY_RANGE(s_extTextureRgFloatTexFormats) 271 }, 272 { 273 "GL_EXT_texture_rg GL_OES_texture_half_float", 274 COLOR_RENDERABLE | TEXTURE_VALID, 275 GLS_ARRAY_RANGE(s_extTextureRgHalfFloatTexFormats) 276 }, 277 278 { 279 "GL_NV_packed_float", 280 COLOR_RENDERABLE | TEXTURE_VALID, 281 GLS_ARRAY_RANGE(s_nvPackedFloatTexFormats) 282 }, 283 { 284 "GL_NV_packed_float GL_EXT_color_buffer_half_float", 285 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 286 GLS_ARRAY_RANGE(s_nvPackedFloatRboFormats) 287 }, 288 289 // Some Tegra drivers report GL_EXT_packed_float even for ES. Treat it as 290 // a synonym for the NV_ version. 291 { 292 "GL_EXT_packed_float", 293 COLOR_RENDERABLE | TEXTURE_VALID, 294 GLS_ARRAY_RANGE(s_nvPackedFloatTexFormats) 295 }, 296 { 297 "GL_EXT_packed_float GL_EXT_color_buffer_half_float", 298 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 299 GLS_ARRAY_RANGE(s_nvPackedFloatRboFormats) 300 }, 301 302 { 303 "GL_EXT_sRGB", 304 COLOR_RENDERABLE | TEXTURE_VALID, 305 GLS_ARRAY_RANGE(s_extSrgbRenderableTexFormats) 306 }, 307 { 308 "GL_EXT_sRGB", 309 TEXTURE_VALID, 310 GLS_ARRAY_RANGE(s_extSrgbNonRenderableTexFormats) 311 }, 312 { 313 "GL_EXT_sRGB", 314 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 315 GLS_ARRAY_RANGE(s_extSrgbRboFormats) 316 }, 317 { 318 "GL_NV_sRGB_formats", 319 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 320 GLS_ARRAY_RANGE(s_nvSrgbFormatsRboFormats) 321 }, 322 { 323 "GL_NV_sRGB_formats", 324 REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID, 325 GLS_ARRAY_RANGE(s_nvSrgbFormatsTextureFormats) 326 }, 327 328 // In Khronos bug 7333 discussion, the consensus is that these texture 329 // formats, at least, should be color-renderable. Still, that cannot be 330 // found in any extension specs, so only allow it, not require it. 331 { 332 "GL_OES_rgb8_rgba8", 333 COLOR_RENDERABLE | TEXTURE_VALID, 334 GLS_ARRAY_RANGE(s_oesRgb8Rgba8TexFormats) 335 }, 336 { 337 "GL_OES_rgb8_rgba8", 338 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 339 GLS_ARRAY_RANGE(s_oesRgb8Rgba8RboFormats) 340 }, 341 { 342 "GL_OES_rgb8_rgba8 GL_OES_required_internalformat", 343 TEXTURE_VALID, 344 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatRgb8ColorFormat) 345 }, 346 347 // The depth-renderability of the depth RBO formats is not explicitly 348 // spelled out, but all renderbuffer formats are meant to be renderable. 349 { 350 "GL_OES_depth24", 351 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, 352 GLS_ARRAY_RANGE(s_oesDepth24SizedFormats) 353 }, 354 { 355 "GL_OES_depth24 GL_OES_required_internalformat GL_OES_depth_texture", 356 TEXTURE_VALID, 357 GLS_ARRAY_RANGE(s_oesDepth24SizedFormats) 358 }, 359 360 { 361 "GL_OES_depth32", 362 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, 363 GLS_ARRAY_RANGE(s_oesDepth32SizedFormats) 364 }, 365 { 366 "GL_OES_depth32 GL_OES_required_internalformat GL_OES_depth_texture", 367 TEXTURE_VALID, 368 GLS_ARRAY_RANGE(s_oesDepth32SizedFormats) 369 }, 370 371 { 372 "GL_EXT_texture_type_2_10_10_10_REV", 373 TEXTURE_VALID, // explicitly unrenderable 374 GLS_ARRAY_RANGE(s_extTextureType2101010RevFormats) 375 }, 376 { 377 "GL_EXT_texture_type_2_10_10_10_REV GL_OES_required_internalformat", 378 TEXTURE_VALID, // explicitly unrenderable 379 GLS_ARRAY_RANGE(s_oesRequiredInternalFormat10bitColorFormats) 380 }, 381 }; 382 383 Context::Context (TestContext& testCtx, 384 RenderContext& renderCtx, 385 CheckerFactory& factory) 386 : m_testCtx (testCtx) 387 , m_renderCtx (renderCtx) 388 , m_verifier (m_ctxFormats, factory) 389 , m_haveMultiColorAtts (false) 390 { 391 FormatExtEntries extRange = GLS_ARRAY_RANGE(s_esExtFormats); 392 addExtFormats(extRange); 393 } 394 395 void Context::addFormats (FormatEntries fmtRange) 396 { 397 FboUtil::addFormats(m_minFormats, fmtRange); 398 FboUtil::addFormats(m_ctxFormats, fmtRange); 399 FboUtil::addFormats(m_maxFormats, fmtRange); 400 } 401 402 void Context::addExtFormats (FormatExtEntries extRange) 403 { 404 FboUtil::addExtFormats(m_ctxFormats, extRange, &m_renderCtx); 405 FboUtil::addExtFormats(m_maxFormats, extRange, DE_NULL); 406 } 407 408 void TestBase::pass (void) 409 { 410 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 411 } 412 413 void TestBase::qualityWarning (const char* msg) 414 { 415 m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, msg); 416 } 417 418 void TestBase::fail (const char* msg) 419 { 420 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, msg); 421 } 422 423 static string statusName (GLenum status) 424 { 425 const char* errorName = getErrorName(status); 426 if (status != GL_NO_ERROR && errorName != DE_NULL) 427 return string(errorName) + " (during FBO initialization)"; 428 429 const char* fbStatusName = getFramebufferStatusName(status); 430 if (fbStatusName != DE_NULL) 431 return fbStatusName; 432 433 return "unknown value (" + toString(status) + ")"; 434 } 435 436 const glw::Functions& gl (const TestBase& test) 437 { 438 return test.getContext().getRenderContext().getFunctions(); 439 } 440 441 IterateResult TestBase::iterate (void) 442 { 443 glu::Framebuffer fbo(m_ctx.getRenderContext()); 444 FboBuilder builder(*fbo, GL_FRAMEBUFFER, gl(*this)); 445 const IterateResult ret = build(builder); 446 const StatusCodes statuses = m_ctx.getVerifier().validStatusCodes(builder); 447 448 GLenum glStatus = builder.getError(); 449 if (glStatus == GL_NO_ERROR) 450 glStatus = gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER); 451 452 // \todo [2013-12-04 lauri] Check if drawing operations succeed. 453 454 StatusCodes::const_iterator it = statuses.begin(); 455 GLenum err = *it++; 456 logFramebufferConfig(builder, m_testCtx.getLog()); 457 458 MessageBuilder msg(&m_testCtx.getLog()); 459 460 msg << "Expected "; 461 if (it != statuses.end()) 462 { 463 msg << "one of "; 464 while (it != statuses.end()) 465 { 466 msg << statusName(err); 467 err = *it++; 468 msg << (it == statuses.end() ? " or " : ", "); 469 } 470 } 471 msg << statusName(err) << "." << TestLog::EndMessage; 472 m_testCtx.getLog() << TestLog::Message << "Received " << statusName(glStatus) 473 << "." << TestLog::EndMessage; 474 475 if (!contains(statuses, glStatus)) 476 { 477 // The returned status value was not acceptable. 478 if (glStatus == GL_FRAMEBUFFER_COMPLETE) 479 fail("Framebuffer checked as complete, expected incomplete"); 480 else if (statuses.size() == 1 && contains(statuses, GL_FRAMEBUFFER_COMPLETE)) 481 fail("Framebuffer checked is incomplete, expected complete"); 482 else 483 // An incomplete status is allowed, but not _this_ incomplete status. 484 fail("Framebuffer checked as incomplete, but with wrong status"); 485 } 486 else if (glStatus != GL_FRAMEBUFFER_COMPLETE && 487 contains(statuses, GL_FRAMEBUFFER_COMPLETE)) 488 { 489 qualityWarning("Framebuffer object could have checked as complete but did not."); 490 } 491 else 492 pass(); 493 494 return ret; 495 } 496 497 IterateResult TestBase::build (FboBuilder& builder) 498 { 499 DE_UNREF(builder); 500 return STOP; 501 } 502 503 ImageFormat TestBase::getDefaultFormat (GLenum attPoint, GLenum bufType) const 504 { 505 if (bufType == GL_NONE) 506 { 507 return ImageFormat::none(); 508 } 509 510 // Prefer a standard format, if there is one, but if not, use a format 511 // provided by an extension. 512 Formats formats = m_ctx.getMinFormats().getFormats(formatFlag(attPoint) | 513 formatFlag(bufType)); 514 Formats::const_iterator it = formats.begin(); 515 if (it == formats.end()) 516 { 517 formats = m_ctx.getCtxFormats().getFormats(formatFlag(attPoint) | 518 formatFlag(bufType)); 519 it = formats.begin(); 520 } 521 if (it == formats.end()) 522 throw tcu::NotSupportedError("Unsupported attachment kind for attachment point", 523 "", __FILE__, __LINE__); 524 return *it; 525 }; 526 527 Image* makeImage (GLenum bufType, ImageFormat format, 528 GLsizei width, GLsizei height, FboBuilder& builder) 529 { 530 Image* image = DE_NULL; 531 switch (bufType) 532 { 533 case GL_NONE: 534 return DE_NULL; 535 case GL_RENDERBUFFER: 536 image = &builder.makeConfig<Renderbuffer>(); 537 break; 538 case GL_TEXTURE: 539 image = &builder.makeConfig<Texture2D>(); 540 break; 541 default: 542 DE_ASSERT(!"Impossible case"); 543 } 544 image->internalFormat = format; 545 image->width = width; 546 image->height = height; 547 return image; 548 } 549 550 Attachment* makeAttachment (GLenum bufType, ImageFormat format, 551 GLsizei width, GLsizei height, FboBuilder& builder) 552 { 553 Image* const imgCfg = makeImage (bufType, format, width, height, builder); 554 Attachment* att = DE_NULL; 555 GLuint img = 0; 556 557 if (Renderbuffer* rboCfg = dynamic_cast<Renderbuffer*>(imgCfg)) 558 { 559 img = builder.glCreateRbo(*rboCfg); 560 att = &builder.makeConfig<RenderbufferAttachment>(); 561 } 562 else if (Texture2D* texCfg = dynamic_cast<Texture2D*>(imgCfg)) 563 { 564 img = builder.glCreateTexture(*texCfg); 565 TextureFlatAttachment& texAtt = builder.makeConfig<TextureFlatAttachment>(); 566 texAtt.texTarget = GL_TEXTURE_2D; 567 att = &texAtt; 568 } 569 else 570 { 571 DE_ASSERT(imgCfg == DE_NULL); 572 return DE_NULL; 573 } 574 att->imageName = img; 575 return att; 576 } 577 578 void TestBase::attachTargetToNew (GLenum target, GLenum bufType, ImageFormat format, 579 GLsizei width, GLsizei height, FboBuilder& builder) 580 { 581 ImageFormat imgFmt = format; 582 if (imgFmt.format == GL_NONE) 583 imgFmt = getDefaultFormat(target, bufType); 584 585 const Attachment* const att = makeAttachment(bufType, imgFmt, width, height, builder); 586 builder.glAttach(target, att); 587 } 588 589 static string formatName (ImageFormat format) 590 { 591 const string s = getPixelFormatName(format.format); 592 const string fmtStr = toLower(s.substr(3)); 593 594 if (format.unsizedType != GL_NONE) 595 { 596 const string typeStr = getTypeName(format.unsizedType); 597 return fmtStr + "_" + toLower(typeStr.substr(3)); 598 } 599 600 return fmtStr; 601 } 602 603 static string formatDesc (ImageFormat format) 604 { 605 const string fmtStr = getPixelFormatName(format.format); 606 607 if (format.unsizedType != GL_NONE) 608 { 609 const string typeStr = getTypeName(format.unsizedType); 610 return fmtStr + " with type " + typeStr; 611 } 612 613 return fmtStr; 614 } 615 616 struct RenderableParams 617 { 618 GLenum attPoint; 619 GLenum bufType; 620 ImageFormat format; 621 static string getName (const RenderableParams& params) 622 { 623 return formatName(params.format); 624 } 625 static string getDescription (const RenderableParams& params) 626 { 627 return formatDesc(params.format); 628 } 629 }; 630 631 class RenderableTest : public ParamTest<RenderableParams> 632 { 633 public: 634 RenderableTest (Context& group, const Params& params) 635 : ParamTest<RenderableParams> (group, params) {} 636 IterateResult build (FboBuilder& builder); 637 }; 638 639 IterateResult RenderableTest::build (FboBuilder& builder) 640 { 641 attachTargetToNew(m_params.attPoint, m_params.bufType, m_params.format, 64, 64, builder); 642 return STOP; 643 } 644 645 string attTypeName (GLenum bufType) 646 { 647 switch (bufType) 648 { 649 case GL_NONE: 650 return "none"; 651 case GL_RENDERBUFFER: 652 return "rbo"; 653 case GL_TEXTURE: 654 return "tex"; 655 default: 656 DE_ASSERT(!"Impossible case"); 657 } 658 return ""; // Shut up compiler 659 } 660 661 struct AttachmentParams 662 { 663 GLenum color0Kind; 664 GLenum colornKind; 665 GLenum depthKind; 666 GLenum stencilKind; 667 668 static string getName (const AttachmentParams& params); 669 static string getDescription (const AttachmentParams& params) 670 { 671 return getName(params); 672 } 673 }; 674 675 string AttachmentParams::getName (const AttachmentParams& params) 676 { 677 return (attTypeName(params.color0Kind) + "_" + 678 attTypeName(params.colornKind) + "_" + 679 attTypeName(params.depthKind) + "_" + 680 attTypeName(params.stencilKind)); 681 } 682 683 //! Test for combinations of different kinds of attachments 684 class AttachmentTest : public ParamTest<AttachmentParams> 685 { 686 public: 687 AttachmentTest (Context& group, Params& params) 688 : ParamTest<AttachmentParams> (group, params) {} 689 690 protected: 691 IterateResult build (FboBuilder& builder); 692 void makeDepthAndStencil (FboBuilder& builder); 693 }; 694 695 696 void AttachmentTest::makeDepthAndStencil (FboBuilder& builder) 697 { 698 if (m_params.stencilKind == m_params.depthKind) 699 { 700 // If there is a common stencil+depth -format, try to use a common 701 // image for both attachments. 702 const FormatFlags flags = 703 DEPTH_RENDERABLE | STENCIL_RENDERABLE | formatFlag(m_params.stencilKind); 704 const Formats& formats = m_ctx.getMinFormats().getFormats(flags); 705 Formats::const_iterator it = formats.begin(); 706 if (it != formats.end()) 707 { 708 const ImageFormat format = *it; 709 Attachment* att = makeAttachment(m_params.depthKind, format, 64, 64, builder); 710 builder.glAttach(GL_DEPTH_ATTACHMENT, att); 711 builder.glAttach(GL_STENCIL_ATTACHMENT, att); 712 return; 713 } 714 } 715 // Either the kinds were separate, or a suitable format was not found. 716 // Create separate images. 717 attachTargetToNew(GL_STENCIL_ATTACHMENT, m_params.stencilKind, ImageFormat::none(), 718 64, 64, builder); 719 attachTargetToNew(GL_DEPTH_ATTACHMENT, m_params.depthKind, ImageFormat::none(), 720 64, 64, builder); 721 } 722 723 IterateResult AttachmentTest::build (FboBuilder& builder) 724 { 725 attachTargetToNew(GL_COLOR_ATTACHMENT0, m_params.color0Kind, ImageFormat::none(), 726 64, 64, builder); 727 728 if (m_params.colornKind != GL_NONE) 729 { 730 TCU_CHECK_AND_THROW(NotSupportedError, m_ctx.haveMultiColorAtts(), 731 "Multiple attachments not supported"); 732 GLint maxAttachments = 1; 733 gl(*this).getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachments); 734 GLU_EXPECT_NO_ERROR( 735 gl(*this).getError(), "Couldn't read GL_MAX_COLOR_ATTACHMENTS"); 736 737 for (int i = 1; i < maxAttachments; i++) 738 { 739 attachTargetToNew(GL_COLOR_ATTACHMENT0 + i, m_params.colornKind, 740 ImageFormat::none(), 64, 64, builder); 741 } 742 } 743 744 makeDepthAndStencil(builder); 745 746 return STOP; 747 } 748 749 class EmptyImageTest : public TestBase 750 { 751 public: 752 EmptyImageTest (Context& group, 753 const char* name, const char* desc) 754 : TestBase (group, name, desc) {} 755 756 IterateResult build (FboBuilder& builder); 757 }; 758 759 IterateResult EmptyImageTest::build (FboBuilder& builder) 760 { 761 attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 762 0, 0, builder); 763 return STOP; 764 } 765 766 767 class DistinctSizeTest : public TestBase 768 { 769 public: 770 DistinctSizeTest (Context& group, 771 const char* name, const char* desc) 772 : TestBase (group, name, desc) {} 773 774 IterateResult build (FboBuilder& builder); 775 }; 776 777 IterateResult DistinctSizeTest::build (FboBuilder& builder) 778 { 779 attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 780 64, 64, builder); 781 attachTargetToNew(GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ImageFormat::none(), 782 128, 128, builder); 783 return STOP; 784 } 785 786 TestCaseGroup* Context::createRenderableTests (void) 787 { 788 TestCaseGroup* const renderableTests = new TestCaseGroup( 789 m_testCtx, "renderable", "Tests for support of renderable image formats"); 790 791 TestCaseGroup* const rbRenderableTests = new TestCaseGroup( 792 m_testCtx, "renderbuffer", "Tests for renderbuffer formats"); 793 794 TestCaseGroup* const texRenderableTests = new TestCaseGroup( 795 m_testCtx, "texture", "Tests for texture formats"); 796 797 static const struct AttPoint { 798 GLenum attPoint; 799 const char* name; 800 const char* desc; 801 } attPoints[] = 802 { 803 { GL_COLOR_ATTACHMENT0, "color0", "Tests for color attachments" }, 804 { GL_STENCIL_ATTACHMENT, "stencil", "Tests for stencil attachments" }, 805 { GL_DEPTH_ATTACHMENT, "depth", "Tests for depth attachments" }, 806 }; 807 808 // At each attachment point, iterate through all the possible formats to 809 // detect both false positives and false negatives. 810 const Formats rboFmts = m_maxFormats.getFormats(ANY_FORMAT); 811 const Formats texFmts = m_maxFormats.getFormats(ANY_FORMAT); 812 813 for (const AttPoint* it = DE_ARRAY_BEGIN(attPoints); it != DE_ARRAY_END(attPoints); it++) 814 { 815 TestCaseGroup* const rbAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc); 816 TestCaseGroup* const texAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc); 817 818 for (Formats::const_iterator it2 = rboFmts.begin(); it2 != rboFmts.end(); it2++) 819 { 820 const RenderableParams params = { it->attPoint, GL_RENDERBUFFER, *it2 }; 821 rbAttTests->addChild(new RenderableTest(*this, params)); 822 } 823 rbRenderableTests->addChild(rbAttTests); 824 825 for (Formats::const_iterator it2 = texFmts.begin(); it2 != texFmts.end(); it2++) 826 { 827 const RenderableParams params = { it->attPoint, GL_TEXTURE, *it2 }; 828 texAttTests->addChild(new RenderableTest(*this, params)); 829 } 830 texRenderableTests->addChild(texAttTests); 831 } 832 renderableTests->addChild(rbRenderableTests); 833 renderableTests->addChild(texRenderableTests); 834 835 return renderableTests; 836 } 837 838 TestCaseGroup* Context::createAttachmentTests (void) 839 { 840 TestCaseGroup* const attCombTests = new TestCaseGroup( 841 m_testCtx, "attachment_combinations", "Tests for attachment combinations"); 842 843 static const GLenum s_bufTypes[] = { GL_NONE, GL_RENDERBUFFER, GL_TEXTURE }; 844 static const Range<GLenum> s_kinds = GLS_ARRAY_RANGE(s_bufTypes); 845 846 for (const GLenum* col0 = s_kinds.begin(); col0 != s_kinds.end(); ++col0) 847 for (const GLenum* coln = s_kinds.begin(); coln != s_kinds.end(); ++coln) 848 for (const GLenum* dep = s_kinds.begin(); dep != s_kinds.end(); ++dep) 849 for (const GLenum* stc = s_kinds.begin(); stc != s_kinds.end(); ++stc) 850 { 851 AttachmentParams params = { *col0, *coln, *dep, *stc }; 852 attCombTests->addChild(new AttachmentTest(*this, params)); 853 } 854 855 return attCombTests; 856 } 857 858 TestCaseGroup* Context::createSizeTests (void) 859 { 860 TestCaseGroup* const sizeTests = new TestCaseGroup( 861 m_testCtx, "size", "Tests for attachment sizes"); 862 sizeTests->addChild(new EmptyImageTest( 863 *this, "zero", 864 "Test for zero-sized image attachment")); 865 sizeTests->addChild(new DistinctSizeTest( 866 *this, "distinct", 867 "Test for attachments with different sizes")); 868 869 return sizeTests; 870 } 871 872 } // details 873 874 } // fboc 875 } // gls 876 } // deqp 877