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_extSrgbTexFormats[] = 179 { 180 GLS_UNSIZED_FORMATKEY(GL_SRGB, GL_UNSIGNED_BYTE), 181 GLS_UNSIZED_FORMATKEY(GL_SRGB_ALPHA, GL_UNSIGNED_BYTE), 182 }; 183 184 static const FormatKey s_oesRgb8Rgba8TexFormats[] = 185 { 186 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_BYTE), 187 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_BYTE), 188 }; 189 190 static const FormatExtEntry s_esExtFormats[] = 191 { 192 { 193 "GL_OES_depth_texture", 194 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID, 195 GLS_ARRAY_RANGE(s_oesDepthTextureFormats), 196 }, 197 { 198 "GL_OES_packed_depth_stencil", 199 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID, 200 GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats) 201 }, 202 { 203 "GL_OES_packed_depth_stencil GL_OES_required_internalformat", 204 TEXTURE_VALID, 205 GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats) 206 }, 207 { 208 "GL_OES_packed_depth_stencil", 209 DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID, 210 GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats) 211 }, 212 // \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a 213 // requirement on ES3 also. Or is color_buffer_half_float applicatble at 214 // all on ES3, since there's also EXT_color_buffer_float? 215 { 216 "GL_OES_texture_half_float GL_EXT_color_buffer_half_float", 217 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 218 GLS_ARRAY_RANGE(s_extColorBufferHalfFloatFormats) 219 }, 220 221 // OES_required_internalformat doesn't actually specify that these are renderable, 222 // since it was written against ES 1.1. 223 { 224 "GL_OES_required_internalformat", 225 // Allow but don't require RGBA8 to be color-renderable if 226 // OES_rgb8_rgba8 is not present. 227 COLOR_RENDERABLE | TEXTURE_VALID, 228 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatColorFormats) 229 }, 230 { 231 "GL_OES_required_internalformat", 232 DEPTH_RENDERABLE | TEXTURE_VALID, 233 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatDepthFormats) 234 }, 235 { 236 "GL_EXT_texture_rg", 237 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 238 GLS_ARRAY_RANGE(s_extTextureRgRboFormats) 239 }, 240 // These are not specified to be color-renderable, but the wording is 241 // exactly as ambiguous as the wording in the ES2 spec. 242 { 243 "GL_EXT_texture_rg", 244 COLOR_RENDERABLE | TEXTURE_VALID, 245 GLS_ARRAY_RANGE(s_extTextureRgTexFormats) 246 }, 247 { 248 "GL_EXT_texture_rg GL_OES_texture_float", 249 COLOR_RENDERABLE | TEXTURE_VALID, 250 GLS_ARRAY_RANGE(s_extTextureRgFloatTexFormats) 251 }, 252 { 253 "GL_EXT_texture_rg GL_OES_texture_half_float", 254 COLOR_RENDERABLE | TEXTURE_VALID, 255 GLS_ARRAY_RANGE(s_extTextureRgHalfFloatTexFormats) 256 }, 257 258 { 259 "GL_NV_packed_float", 260 COLOR_RENDERABLE | TEXTURE_VALID, 261 GLS_ARRAY_RANGE(s_nvPackedFloatTexFormats) 262 }, 263 { 264 "GL_NV_packed_float GL_EXT_color_buffer_half_float", 265 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 266 GLS_ARRAY_RANGE(s_nvPackedFloatRboFormats) 267 }, 268 269 // Some Tegra drivers report GL_EXT_packed_float even for ES. Treat it as 270 // a synonym for the NV_ version. 271 { 272 "GL_EXT_packed_float", 273 COLOR_RENDERABLE | TEXTURE_VALID, 274 GLS_ARRAY_RANGE(s_nvPackedFloatTexFormats) 275 }, 276 { 277 "GL_EXT_packed_float GL_EXT_color_buffer_half_float", 278 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 279 GLS_ARRAY_RANGE(s_nvPackedFloatRboFormats) 280 }, 281 282 { 283 "GL_EXT_sRGB", 284 COLOR_RENDERABLE | TEXTURE_VALID, 285 GLS_ARRAY_RANGE(s_extSrgbTexFormats) 286 }, 287 { 288 "GL_EXT_sRGB", 289 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 290 GLS_ARRAY_RANGE(s_extSrgbRboFormats) 291 }, 292 293 // In Khronos bug 7333 discussion, the consensus is that these texture 294 // formats, at least, should be color-renderable. Still, that cannot be 295 // found in any extension specs, so only allow it, not require it. 296 { 297 "GL_OES_rgb8_rgba8", 298 COLOR_RENDERABLE | TEXTURE_VALID, 299 GLS_ARRAY_RANGE(s_oesRgb8Rgba8TexFormats) 300 }, 301 { 302 "GL_OES_rgb8_rgba8", 303 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 304 GLS_ARRAY_RANGE(s_oesRgb8Rgba8RboFormats) 305 }, 306 { 307 "GL_OES_rgb8_rgba8 GL_OES_required_internalformat", 308 TEXTURE_VALID, 309 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatRgb8ColorFormat) 310 }, 311 312 // The depth-renderability of the depth RBO formats is not explicitly 313 // spelled out, but all renderbuffer formats are meant to be renderable. 314 { 315 "GL_OES_depth24", 316 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, 317 GLS_ARRAY_RANGE(s_oesDepth24SizedFormats) 318 }, 319 { 320 "GL_OES_depth24 GL_OES_required_internalformat GL_OES_depth_texture", 321 TEXTURE_VALID, 322 GLS_ARRAY_RANGE(s_oesDepth24SizedFormats) 323 }, 324 325 { 326 "GL_OES_depth32", 327 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, 328 GLS_ARRAY_RANGE(s_oesDepth32SizedFormats) 329 }, 330 { 331 "GL_OES_depth32 GL_OES_required_internalformat GL_OES_depth_texture", 332 TEXTURE_VALID, 333 GLS_ARRAY_RANGE(s_oesDepth32SizedFormats) 334 }, 335 336 { 337 "GL_EXT_texture_type_2_10_10_10_REV", 338 TEXTURE_VALID, // explicitly unrenderable 339 GLS_ARRAY_RANGE(s_extTextureType2101010RevFormats) 340 }, 341 { 342 "GL_EXT_texture_type_2_10_10_10_REV GL_OES_required_internalformat", 343 TEXTURE_VALID, // explicitly unrenderable 344 GLS_ARRAY_RANGE(s_oesRequiredInternalFormat10bitColorFormats) 345 }, 346 }; 347 348 Context::Context (TestContext& testCtx, 349 RenderContext& renderCtx, 350 CheckerFactory& factory) 351 : m_testCtx (testCtx) 352 , m_renderCtx (renderCtx) 353 , m_verifier (m_ctxFormats, factory) 354 , m_haveMultiColorAtts (false) 355 { 356 FormatExtEntries extRange = GLS_ARRAY_RANGE(s_esExtFormats); 357 addExtFormats(extRange); 358 } 359 360 void Context::addFormats (FormatEntries fmtRange) 361 { 362 FboUtil::addFormats(m_minFormats, fmtRange); 363 FboUtil::addFormats(m_ctxFormats, fmtRange); 364 FboUtil::addFormats(m_maxFormats, fmtRange); 365 } 366 367 void Context::addExtFormats (FormatExtEntries extRange) 368 { 369 FboUtil::addExtFormats(m_ctxFormats, extRange, &m_renderCtx); 370 FboUtil::addExtFormats(m_maxFormats, extRange, DE_NULL); 371 } 372 373 void TestBase::pass (void) 374 { 375 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 376 } 377 378 void TestBase::qualityWarning (const char* msg) 379 { 380 m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, msg); 381 } 382 383 void TestBase::fail (const char* msg) 384 { 385 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, msg); 386 } 387 388 static string statusName (GLenum status) 389 { 390 const char* errorName = getErrorName(status); 391 if (status != GL_NO_ERROR && errorName != DE_NULL) 392 return string(errorName) + " (during FBO initialization)"; 393 394 const char* fbStatusName = getFramebufferStatusName(status); 395 if (fbStatusName != DE_NULL) 396 return fbStatusName; 397 398 return "unknown value (" + toString(status) + ")"; 399 } 400 401 const glw::Functions& gl (const TestBase& test) 402 { 403 return test.getContext().getRenderContext().getFunctions(); 404 } 405 406 IterateResult TestBase::iterate (void) 407 { 408 glu::Framebuffer fbo(m_ctx.getRenderContext()); 409 FboBuilder builder(*fbo, GL_FRAMEBUFFER, gl(*this)); 410 const IterateResult ret = build(builder); 411 const StatusCodes statuses = m_ctx.getVerifier().validStatusCodes(builder); 412 413 GLenum glStatus = builder.getError(); 414 if (glStatus == GL_NO_ERROR) 415 glStatus = gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER); 416 417 // \todo [2013-12-04 lauri] Check if drawing operations succeed. 418 419 StatusCodes::const_iterator it = statuses.begin(); 420 GLenum err = *it++; 421 logFramebufferConfig(builder, m_testCtx.getLog()); 422 423 MessageBuilder msg(&m_testCtx.getLog()); 424 425 msg << "Expected "; 426 if (it != statuses.end()) 427 { 428 msg << "one of "; 429 while (it != statuses.end()) 430 { 431 msg << statusName(err); 432 err = *it++; 433 msg << (it == statuses.end() ? " or " : ", "); 434 } 435 } 436 msg << statusName(err) << "." << TestLog::EndMessage; 437 m_testCtx.getLog() << TestLog::Message << "Received " << statusName(glStatus) 438 << "." << TestLog::EndMessage; 439 440 if (!contains(statuses, glStatus)) 441 { 442 // The returned status value was not acceptable. 443 if (glStatus == GL_FRAMEBUFFER_COMPLETE) 444 fail("Framebuffer checked as complete, expected incomplete"); 445 else if (statuses.size() == 1 && contains(statuses, GL_FRAMEBUFFER_COMPLETE)) 446 fail("Framebuffer checked is incomplete, expected complete"); 447 else 448 // An incomplete status is allowed, but not _this_ incomplete status. 449 fail("Framebuffer checked as incomplete, but with wrong status"); 450 } 451 else if (glStatus != GL_FRAMEBUFFER_COMPLETE && 452 contains(statuses, GL_FRAMEBUFFER_COMPLETE)) 453 { 454 qualityWarning("Framebuffer object could have checked as complete but did not."); 455 } 456 else 457 pass(); 458 459 return ret; 460 } 461 462 IterateResult TestBase::build (FboBuilder& builder) 463 { 464 DE_UNREF(builder); 465 return STOP; 466 } 467 468 ImageFormat TestBase::getDefaultFormat (GLenum attPoint, GLenum bufType) const 469 { 470 if (bufType == GL_NONE) 471 { 472 return ImageFormat::none(); 473 } 474 475 // Prefer a standard format, if there is one, but if not, use a format 476 // provided by an extension. 477 Formats formats = m_ctx.getMinFormats().getFormats(formatFlag(attPoint) | 478 formatFlag(bufType)); 479 Formats::const_iterator it = formats.begin(); 480 if (it == formats.end()) 481 { 482 formats = m_ctx.getCtxFormats().getFormats(formatFlag(attPoint) | 483 formatFlag(bufType)); 484 it = formats.begin(); 485 } 486 if (it == formats.end()) 487 throw tcu::NotSupportedError("Unsupported attachment kind for attachment point", 488 "", __FILE__, __LINE__); 489 return *it; 490 }; 491 492 Image* makeImage (GLenum bufType, ImageFormat format, 493 GLsizei width, GLsizei height, FboBuilder& builder) 494 { 495 Image* image = DE_NULL; 496 switch (bufType) 497 { 498 case GL_NONE: 499 return DE_NULL; 500 case GL_RENDERBUFFER: 501 image = &builder.makeConfig<Renderbuffer>(); 502 break; 503 case GL_TEXTURE: 504 image = &builder.makeConfig<Texture2D>(); 505 break; 506 default: 507 DE_ASSERT(!"Impossible case"); 508 } 509 image->internalFormat = format; 510 image->width = width; 511 image->height = height; 512 return image; 513 } 514 515 Attachment* makeAttachment (GLenum bufType, ImageFormat format, 516 GLsizei width, GLsizei height, FboBuilder& builder) 517 { 518 Image* const imgCfg = makeImage (bufType, format, width, height, builder); 519 Attachment* att = DE_NULL; 520 GLuint img = 0; 521 522 if (Renderbuffer* rboCfg = dynamic_cast<Renderbuffer*>(imgCfg)) 523 { 524 img = builder.glCreateRbo(*rboCfg); 525 att = &builder.makeConfig<RenderbufferAttachment>(); 526 } 527 else if (Texture2D* texCfg = dynamic_cast<Texture2D*>(imgCfg)) 528 { 529 img = builder.glCreateTexture(*texCfg); 530 TextureFlatAttachment& texAtt = builder.makeConfig<TextureFlatAttachment>(); 531 texAtt.texTarget = GL_TEXTURE_2D; 532 att = &texAtt; 533 } 534 else 535 { 536 DE_ASSERT(imgCfg == DE_NULL); 537 return DE_NULL; 538 } 539 att->imageName = img; 540 return att; 541 } 542 543 void TestBase::attachTargetToNew (GLenum target, GLenum bufType, ImageFormat format, 544 GLsizei width, GLsizei height, FboBuilder& builder) 545 { 546 ImageFormat imgFmt = format; 547 if (imgFmt.format == GL_NONE) 548 imgFmt = getDefaultFormat(target, bufType); 549 550 const Attachment* const att = makeAttachment(bufType, imgFmt, width, height, builder); 551 builder.glAttach(target, att); 552 } 553 554 static string formatName (ImageFormat format) 555 { 556 const string s = getPixelFormatName(format.format); 557 const string fmtStr = toLower(s.substr(3)); 558 559 if (format.unsizedType != GL_NONE) 560 { 561 const string typeStr = getTypeName(format.unsizedType); 562 return fmtStr + "_" + toLower(typeStr.substr(3)); 563 } 564 565 return fmtStr; 566 } 567 568 static string formatDesc (ImageFormat format) 569 { 570 const string fmtStr = getPixelFormatName(format.format); 571 572 if (format.unsizedType != GL_NONE) 573 { 574 const string typeStr = getTypeName(format.unsizedType); 575 return fmtStr + " with type " + typeStr; 576 } 577 578 return fmtStr; 579 } 580 581 struct RenderableParams 582 { 583 GLenum attPoint; 584 GLenum bufType; 585 ImageFormat format; 586 static string getName (const RenderableParams& params) 587 { 588 return formatName(params.format); 589 } 590 static string getDescription (const RenderableParams& params) 591 { 592 return formatDesc(params.format); 593 } 594 }; 595 596 class RenderableTest : public ParamTest<RenderableParams> 597 { 598 public: 599 RenderableTest (Context& group, const Params& params) 600 : ParamTest<RenderableParams> (group, params) {} 601 IterateResult build (FboBuilder& builder); 602 }; 603 604 IterateResult RenderableTest::build (FboBuilder& builder) 605 { 606 attachTargetToNew(m_params.attPoint, m_params.bufType, m_params.format, 64, 64, builder); 607 return STOP; 608 } 609 610 string attTypeName (GLenum bufType) 611 { 612 switch (bufType) 613 { 614 case GL_NONE: 615 return "none"; 616 case GL_RENDERBUFFER: 617 return "rbo"; 618 case GL_TEXTURE: 619 return "tex"; 620 default: 621 DE_ASSERT(!"Impossible case"); 622 } 623 return ""; // Shut up compiler 624 } 625 626 struct AttachmentParams 627 { 628 GLenum color0Kind; 629 GLenum colornKind; 630 GLenum depthKind; 631 GLenum stencilKind; 632 633 static string getName (const AttachmentParams& params); 634 static string getDescription (const AttachmentParams& params) 635 { 636 return getName(params); 637 } 638 }; 639 640 string AttachmentParams::getName (const AttachmentParams& params) 641 { 642 return (attTypeName(params.color0Kind) + "_" + 643 attTypeName(params.colornKind) + "_" + 644 attTypeName(params.depthKind) + "_" + 645 attTypeName(params.stencilKind)); 646 } 647 648 //! Test for combinations of different kinds of attachments 649 class AttachmentTest : public ParamTest<AttachmentParams> 650 { 651 public: 652 AttachmentTest (Context& group, Params& params) 653 : ParamTest<AttachmentParams> (group, params) {} 654 655 protected: 656 IterateResult build (FboBuilder& builder); 657 void makeDepthAndStencil (FboBuilder& builder); 658 }; 659 660 661 void AttachmentTest::makeDepthAndStencil (FboBuilder& builder) 662 { 663 if (m_params.stencilKind == m_params.depthKind) 664 { 665 // If there is a common stencil+depth -format, try to use a common 666 // image for both attachments. 667 const FormatFlags flags = 668 DEPTH_RENDERABLE | STENCIL_RENDERABLE | formatFlag(m_params.stencilKind); 669 const Formats& formats = m_ctx.getMinFormats().getFormats(flags); 670 Formats::const_iterator it = formats.begin(); 671 if (it != formats.end()) 672 { 673 const ImageFormat format = *it; 674 Attachment* att = makeAttachment(m_params.depthKind, format, 64, 64, builder); 675 builder.glAttach(GL_DEPTH_ATTACHMENT, att); 676 builder.glAttach(GL_STENCIL_ATTACHMENT, att); 677 return; 678 } 679 } 680 // Either the kinds were separate, or a suitable format was not found. 681 // Create separate images. 682 attachTargetToNew(GL_STENCIL_ATTACHMENT, m_params.stencilKind, ImageFormat::none(), 683 64, 64, builder); 684 attachTargetToNew(GL_DEPTH_ATTACHMENT, m_params.depthKind, ImageFormat::none(), 685 64, 64, builder); 686 } 687 688 IterateResult AttachmentTest::build (FboBuilder& builder) 689 { 690 attachTargetToNew(GL_COLOR_ATTACHMENT0, m_params.color0Kind, ImageFormat::none(), 691 64, 64, builder); 692 693 if (m_params.colornKind != GL_NONE) 694 { 695 TCU_CHECK_AND_THROW(NotSupportedError, m_ctx.haveMultiColorAtts(), 696 "Multiple attachments not supported"); 697 GLint maxAttachments = 1; 698 gl(*this).getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachments); 699 GLU_EXPECT_NO_ERROR( 700 gl(*this).getError(), "Couldn't read GL_MAX_COLOR_ATTACHMENTS"); 701 702 for (int i = 1; i < maxAttachments; i++) 703 { 704 attachTargetToNew(GL_COLOR_ATTACHMENT0 + i, m_params.colornKind, 705 ImageFormat::none(), 64, 64, builder); 706 } 707 } 708 709 makeDepthAndStencil(builder); 710 711 return STOP; 712 } 713 714 class EmptyImageTest : public TestBase 715 { 716 public: 717 EmptyImageTest (Context& group, 718 const char* name, const char* desc) 719 : TestBase (group, name, desc) {} 720 721 IterateResult build (FboBuilder& builder); 722 }; 723 724 IterateResult EmptyImageTest::build (FboBuilder& builder) 725 { 726 attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 727 0, 0, builder); 728 return STOP; 729 } 730 731 732 class DistinctSizeTest : public TestBase 733 { 734 public: 735 DistinctSizeTest (Context& group, 736 const char* name, const char* desc) 737 : TestBase (group, name, desc) {} 738 739 IterateResult build (FboBuilder& builder); 740 }; 741 742 IterateResult DistinctSizeTest::build (FboBuilder& builder) 743 { 744 attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 745 64, 64, builder); 746 attachTargetToNew(GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ImageFormat::none(), 747 128, 128, builder); 748 return STOP; 749 } 750 751 TestCaseGroup* Context::createRenderableTests (void) 752 { 753 TestCaseGroup* const renderableTests = new TestCaseGroup( 754 m_testCtx, "renderable", "Tests for support of renderable image formats"); 755 756 TestCaseGroup* const rbRenderableTests = new TestCaseGroup( 757 m_testCtx, "renderbuffer", "Tests for renderbuffer formats"); 758 759 TestCaseGroup* const texRenderableTests = new TestCaseGroup( 760 m_testCtx, "texture", "Tests for texture formats"); 761 762 static const struct AttPoint { 763 GLenum attPoint; 764 const char* name; 765 const char* desc; 766 } attPoints[] = 767 { 768 { GL_COLOR_ATTACHMENT0, "color0", "Tests for color attachments" }, 769 { GL_STENCIL_ATTACHMENT, "stencil", "Tests for stencil attachments" }, 770 { GL_DEPTH_ATTACHMENT, "depth", "Tests for depth attachments" }, 771 }; 772 773 // At each attachment point, iterate through all the possible formats to 774 // detect both false positives and false negatives. 775 const Formats rboFmts = m_maxFormats.getFormats(ANY_FORMAT); 776 const Formats texFmts = m_maxFormats.getFormats(ANY_FORMAT); 777 778 for (const AttPoint* it = DE_ARRAY_BEGIN(attPoints); it != DE_ARRAY_END(attPoints); it++) 779 { 780 TestCaseGroup* const rbAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc); 781 TestCaseGroup* const texAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc); 782 783 for (Formats::const_iterator it2 = rboFmts.begin(); it2 != rboFmts.end(); it2++) 784 { 785 const RenderableParams params = { it->attPoint, GL_RENDERBUFFER, *it2 }; 786 rbAttTests->addChild(new RenderableTest(*this, params)); 787 } 788 rbRenderableTests->addChild(rbAttTests); 789 790 for (Formats::const_iterator it2 = texFmts.begin(); it2 != texFmts.end(); it2++) 791 { 792 const RenderableParams params = { it->attPoint, GL_TEXTURE, *it2 }; 793 texAttTests->addChild(new RenderableTest(*this, params)); 794 } 795 texRenderableTests->addChild(texAttTests); 796 } 797 renderableTests->addChild(rbRenderableTests); 798 renderableTests->addChild(texRenderableTests); 799 800 return renderableTests; 801 } 802 803 TestCaseGroup* Context::createAttachmentTests (void) 804 { 805 TestCaseGroup* const attCombTests = new TestCaseGroup( 806 m_testCtx, "attachment_combinations", "Tests for attachment combinations"); 807 808 static const GLenum s_bufTypes[] = { GL_NONE, GL_RENDERBUFFER, GL_TEXTURE }; 809 static const Range<GLenum> s_kinds = GLS_ARRAY_RANGE(s_bufTypes); 810 811 for (const GLenum* col0 = s_kinds.begin(); col0 != s_kinds.end(); ++col0) 812 for (const GLenum* coln = s_kinds.begin(); coln != s_kinds.end(); ++coln) 813 for (const GLenum* dep = s_kinds.begin(); dep != s_kinds.end(); ++dep) 814 for (const GLenum* stc = s_kinds.begin(); stc != s_kinds.end(); ++stc) 815 { 816 AttachmentParams params = { *col0, *coln, *dep, *stc }; 817 attCombTests->addChild(new AttachmentTest(*this, params)); 818 } 819 820 return attCombTests; 821 } 822 823 TestCaseGroup* Context::createSizeTests (void) 824 { 825 TestCaseGroup* const sizeTests = new TestCaseGroup( 826 m_testCtx, "size", "Tests for attachment sizes"); 827 sizeTests->addChild(new EmptyImageTest( 828 *this, "zero", 829 "Test for zero-sized image attachment")); 830 sizeTests->addChild(new DistinctSizeTest( 831 *this, "distinct", 832 "Test for attachments with different sizes")); 833 834 return sizeTests; 835 } 836 837 } // details 838 839 } // fboc 840 } // gls 841 } // deqp 842