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::getTextureFormatName; 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 de::toLower; 49 using namespace deqp::gls::FboUtil; 50 using namespace deqp::gls::FboUtil::config; 51 typedef TestCase::IterateResult IterateResult; 52 53 namespace deqp 54 { 55 namespace gls 56 { 57 namespace fboc 58 { 59 60 namespace details 61 { 62 63 // The following extensions are applicable both to ES2 and ES3. 64 65 // GL_OES_depth_texture 66 static const FormatKey s_oesDepthTextureFormats[] = 67 { 68 GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT), 69 GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT), 70 }; 71 72 // GL_OES_packed_depth_stencil 73 static const FormatKey s_oesPackedDepthStencilSizedFormats[] = 74 { 75 GL_DEPTH24_STENCIL8, 76 }; 77 78 static const FormatKey s_oesPackedDepthStencilTexFormats[] = 79 { 80 GLS_UNSIZED_FORMATKEY(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8), 81 }; 82 83 // GL_OES_required_internalformat 84 static const FormatKey s_oesRequiredInternalFormatColorFormats[] = 85 { 86 // Same as ES2 RBO formats, plus RGBA8 (even without OES_rgb8_rgba8) 87 GL_RGB5_A1, GL_RGBA8, GL_RGBA4, GL_RGB565 88 }; 89 90 static const FormatKey s_oesRequiredInternalFormatDepthFormats[] = 91 { 92 GL_DEPTH_COMPONENT16, 93 }; 94 95 // GL_EXT_color_buffer_half_float 96 static const FormatKey s_extColorBufferHalfFloatFormats[] = 97 { 98 GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F, 99 }; 100 101 static const FormatKey s_oesDepth24SizedFormats[] = 102 { 103 GL_DEPTH_COMPONENT24 104 }; 105 106 static const FormatKey s_oesDepth32SizedFormats[] = 107 { 108 GL_DEPTH_COMPONENT32 109 }; 110 111 static const FormatKey s_oesRgb8Rgba8RboFormats[] = 112 { 113 GL_RGB8, 114 GL_RGBA8, 115 }; 116 117 static const FormatKey s_oesRequiredInternalFormatRgb8ColorFormat[] = 118 { 119 GL_RGB8, 120 }; 121 122 static const FormatKey s_extTextureType2101010RevFormats[] = 123 { 124 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV), 125 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV), 126 }; 127 128 static const FormatKey s_oesRequiredInternalFormat10bitColorFormats[] = 129 { 130 GL_RGB10_A2, GL_RGB10, 131 }; 132 133 static const FormatKey s_extTextureRgRboFormats[] = 134 { 135 GL_R8, GL_RG8, 136 }; 137 138 static const FormatKey s_extTextureRgTexFormats[] = 139 { 140 GLS_UNSIZED_FORMATKEY(GL_RED, GL_UNSIGNED_BYTE), 141 GLS_UNSIZED_FORMATKEY(GL_RG, GL_UNSIGNED_BYTE), 142 }; 143 144 static const FormatKey s_extTextureRgFloatTexFormats[] = 145 { 146 GLS_UNSIZED_FORMATKEY(GL_RED, GL_FLOAT), 147 GLS_UNSIZED_FORMATKEY(GL_RG, GL_FLOAT), 148 }; 149 150 static const FormatKey s_extTextureRgHalfFloatTexFormats[] = 151 { 152 GLS_UNSIZED_FORMATKEY(GL_RED, GL_HALF_FLOAT_OES), 153 GLS_UNSIZED_FORMATKEY(GL_RG, GL_HALF_FLOAT_OES), 154 }; 155 156 static const FormatKey s_nvPackedFloatRboFormats[] = 157 { 158 GL_R11F_G11F_B10F, 159 }; 160 161 static const FormatKey s_nvPackedFloatTexFormats[] = 162 { 163 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV), 164 }; 165 166 static const FormatKey s_extSrgbRboFormats[] = 167 { 168 GL_SRGB8_ALPHA8, 169 }; 170 171 static const FormatKey s_extSrgbRenderableTexFormats[] = 172 { 173 GLS_UNSIZED_FORMATKEY(GL_SRGB_ALPHA, GL_UNSIGNED_BYTE), 174 }; 175 176 static const FormatKey s_extSrgbNonRenderableTexFormats[] = 177 { 178 GLS_UNSIZED_FORMATKEY(GL_SRGB, GL_UNSIGNED_BYTE), 179 GL_SRGB8, 180 }; 181 182 static const FormatKey s_nvSrgbFormatsRboFormats[] = 183 { 184 GL_SRGB8, 185 }; 186 187 static const FormatKey s_nvSrgbFormatsTextureFormats[] = 188 { 189 GL_SRGB8, 190 191 // The extension does not actually require any unsized format 192 // to be renderable. However, the renderablility of unsized 193 // SRGB,UBYTE internalformat-type pair is implied. 194 GLS_UNSIZED_FORMATKEY(GL_SRGB, GL_UNSIGNED_BYTE), 195 }; 196 197 static const FormatKey s_oesRgb8Rgba8TexFormats[] = 198 { 199 GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_BYTE), 200 GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_BYTE), 201 }; 202 203 static const FormatKey s_extTextureSRGBR8Formats[] = 204 { 205 GL_SR8_EXT, 206 }; 207 208 static const FormatKey s_extTextureSRGBRG8Formats[] = 209 { 210 GL_SRG8_EXT, 211 }; 212 213 static const FormatExtEntry s_esExtFormats[] = 214 { 215 { 216 "GL_OES_depth_texture", 217 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID, 218 GLS_ARRAY_RANGE(s_oesDepthTextureFormats), 219 }, 220 { 221 "GL_OES_packed_depth_stencil", 222 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID, 223 GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats) 224 }, 225 { 226 "GL_OES_packed_depth_stencil GL_OES_required_internalformat", 227 TEXTURE_VALID, 228 GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats) 229 }, 230 { 231 "GL_OES_packed_depth_stencil", 232 DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID, 233 GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats) 234 }, 235 // \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a 236 // requirement on ES3 also. Or is color_buffer_half_float applicatble at 237 // all on ES3, since there's also EXT_color_buffer_float? 238 { 239 "GL_OES_texture_half_float GL_EXT_color_buffer_half_float", 240 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 241 GLS_ARRAY_RANGE(s_extColorBufferHalfFloatFormats) 242 }, 243 244 // OES_required_internalformat doesn't actually specify that these are renderable, 245 // since it was written against ES 1.1. 246 { 247 "GL_OES_required_internalformat", 248 // Allow but don't require RGBA8 to be color-renderable if 249 // OES_rgb8_rgba8 is not present. 250 COLOR_RENDERABLE | TEXTURE_VALID, 251 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatColorFormats) 252 }, 253 { 254 "GL_OES_required_internalformat", 255 DEPTH_RENDERABLE | TEXTURE_VALID, 256 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatDepthFormats) 257 }, 258 { 259 "GL_EXT_texture_rg", 260 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 261 GLS_ARRAY_RANGE(s_extTextureRgRboFormats) 262 }, 263 // These are not specified to be color-renderable, but the wording is 264 // exactly as ambiguous as the wording in the ES2 spec. 265 { 266 "GL_EXT_texture_rg", 267 COLOR_RENDERABLE | TEXTURE_VALID, 268 GLS_ARRAY_RANGE(s_extTextureRgTexFormats) 269 }, 270 { 271 "GL_EXT_texture_rg GL_OES_texture_float", 272 COLOR_RENDERABLE | TEXTURE_VALID, 273 GLS_ARRAY_RANGE(s_extTextureRgFloatTexFormats) 274 }, 275 { 276 "GL_EXT_texture_rg GL_OES_texture_half_float", 277 COLOR_RENDERABLE | TEXTURE_VALID, 278 GLS_ARRAY_RANGE(s_extTextureRgHalfFloatTexFormats) 279 }, 280 281 { 282 "GL_NV_packed_float", 283 COLOR_RENDERABLE | TEXTURE_VALID, 284 GLS_ARRAY_RANGE(s_nvPackedFloatTexFormats) 285 }, 286 { 287 "GL_NV_packed_float GL_EXT_color_buffer_half_float", 288 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 289 GLS_ARRAY_RANGE(s_nvPackedFloatRboFormats) 290 }, 291 292 { 293 "GL_EXT_sRGB", 294 COLOR_RENDERABLE | TEXTURE_VALID, 295 GLS_ARRAY_RANGE(s_extSrgbRenderableTexFormats) 296 }, 297 { 298 "GL_EXT_sRGB", 299 TEXTURE_VALID, 300 GLS_ARRAY_RANGE(s_extSrgbNonRenderableTexFormats) 301 }, 302 { 303 "GL_EXT_sRGB", 304 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 305 GLS_ARRAY_RANGE(s_extSrgbRboFormats) 306 }, 307 { 308 "GL_NV_sRGB_formats", 309 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 310 GLS_ARRAY_RANGE(s_nvSrgbFormatsRboFormats) 311 }, 312 { 313 "GL_NV_sRGB_formats", 314 REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID, 315 GLS_ARRAY_RANGE(s_nvSrgbFormatsTextureFormats) 316 }, 317 318 // In Khronos bug 7333 discussion, the consensus is that these texture 319 // formats, at least, should be color-renderable. Still, that cannot be 320 // found in any extension specs, so only allow it, not require it. 321 { 322 "GL_OES_rgb8_rgba8", 323 COLOR_RENDERABLE | TEXTURE_VALID, 324 GLS_ARRAY_RANGE(s_oesRgb8Rgba8TexFormats) 325 }, 326 { 327 "GL_OES_rgb8_rgba8", 328 REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, 329 GLS_ARRAY_RANGE(s_oesRgb8Rgba8RboFormats) 330 }, 331 { 332 "GL_OES_rgb8_rgba8 GL_OES_required_internalformat", 333 TEXTURE_VALID, 334 GLS_ARRAY_RANGE(s_oesRequiredInternalFormatRgb8ColorFormat) 335 }, 336 337 // The depth-renderability of the depth RBO formats is not explicitly 338 // spelled out, but all renderbuffer formats are meant to be renderable. 339 { 340 "GL_OES_depth24", 341 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, 342 GLS_ARRAY_RANGE(s_oesDepth24SizedFormats) 343 }, 344 { 345 "GL_OES_depth24 GL_OES_required_internalformat GL_OES_depth_texture", 346 TEXTURE_VALID, 347 GLS_ARRAY_RANGE(s_oesDepth24SizedFormats) 348 }, 349 350 { 351 "GL_OES_depth32", 352 REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, 353 GLS_ARRAY_RANGE(s_oesDepth32SizedFormats) 354 }, 355 { 356 "GL_OES_depth32 GL_OES_required_internalformat GL_OES_depth_texture", 357 TEXTURE_VALID, 358 GLS_ARRAY_RANGE(s_oesDepth32SizedFormats) 359 }, 360 361 { 362 "GL_EXT_texture_type_2_10_10_10_REV", 363 TEXTURE_VALID, // explicitly unrenderable 364 GLS_ARRAY_RANGE(s_extTextureType2101010RevFormats) 365 }, 366 { 367 "GL_EXT_texture_type_2_10_10_10_REV GL_OES_required_internalformat", 368 TEXTURE_VALID, // explicitly unrenderable 369 GLS_ARRAY_RANGE(s_oesRequiredInternalFormat10bitColorFormats) 370 }, 371 372 { 373 "GL_EXT_texture_sRGB_R8", 374 TEXTURE_VALID, 375 GLS_ARRAY_RANGE(s_extTextureSRGBR8Formats) 376 }, 377 { 378 "GL_EXT_texture_sRGB_RG8", 379 TEXTURE_VALID, 380 GLS_ARRAY_RANGE(s_extTextureSRGBRG8Formats) 381 }, 382 }; 383 384 Context::Context (TestContext& testCtx, 385 RenderContext& renderCtx, 386 CheckerFactory& factory) 387 : m_testCtx (testCtx) 388 , m_renderCtx (renderCtx) 389 , m_verifier (m_ctxFormats, factory, renderCtx) 390 , m_haveMultiColorAtts (false) 391 { 392 FormatExtEntries extRange = GLS_ARRAY_RANGE(s_esExtFormats); 393 addExtFormats(extRange); 394 } 395 396 void Context::addFormats (FormatEntries fmtRange) 397 { 398 FboUtil::addFormats(m_coreFormats, fmtRange); 399 FboUtil::addFormats(m_ctxFormats, fmtRange); 400 FboUtil::addFormats(m_allFormats, fmtRange); 401 } 402 403 void Context::addExtFormats (FormatExtEntries extRange) 404 { 405 FboUtil::addExtFormats(m_ctxFormats, extRange, &m_renderCtx); 406 FboUtil::addExtFormats(m_allFormats, extRange, DE_NULL); 407 } 408 409 void TestBase::pass (void) 410 { 411 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 412 } 413 414 void TestBase::qualityWarning (const char* msg) 415 { 416 m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, msg); 417 } 418 419 void TestBase::fail (const char* msg) 420 { 421 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, msg); 422 } 423 424 const glw::Functions& gl (const TestBase& test) 425 { 426 return test.getContext().getRenderContext().getFunctions(); 427 } 428 429 static bool isFormatFeatureSupported (const FormatDB& db, const ImageFormat& format, FormatFlags feature) 430 { 431 return db.isKnownFormat(format) && ((db.getFormatInfo(format) & feature) == feature); 432 } 433 434 static void logAffectingExtensions (const char* prefix, const FormatDB& db, const ImageFormat& format, FormatFlags feature, tcu::MessageBuilder& msg) 435 { 436 const std::set<std::set<std::string> > rows = db.getFormatFeatureExtensions(format, feature); 437 438 for (std::set<std::set<std::string> >::const_iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt) 439 { 440 const std::set<std::string>& requiredExtensions = *rowIt; 441 std::set<std::string>::const_iterator it = requiredExtensions.begin(); 442 std::string extName; 443 444 msg << prefix; 445 446 extName = *it++; 447 while (it != requiredExtensions.end()) 448 { 449 msg << getExtensionDescription(extName); 450 extName = *it++; 451 msg << (it == requiredExtensions.end() ? " and " : ", "); 452 } 453 454 msg << getExtensionDescription(extName) << '\n'; 455 } 456 } 457 458 static void logFormatInfo (const config::Framebuffer& fbo, const FormatDB& ctxFormats, const FormatDB& coreFormats, const FormatDB& allFormats, tcu::TestLog& log) 459 { 460 static const struct 461 { 462 const char* name; 463 const FormatFlags flag; 464 } s_renderability[] = 465 { 466 { "color-renderable", COLOR_RENDERABLE }, 467 { "depth-renderable", DEPTH_RENDERABLE }, 468 { "stencil-renderable", STENCIL_RENDERABLE }, 469 }; 470 471 std::set<ImageFormat> formats; 472 473 for (config::TextureMap::const_iterator it = fbo.textures.begin(); it != fbo.textures.end(); ++it) 474 formats.insert(it->second->internalFormat); 475 for (config::RboMap::const_iterator it = fbo.rbos.begin(); it != fbo.rbos.end(); ++it) 476 formats.insert(it->second->internalFormat); 477 478 if (!formats.empty()) 479 { 480 const tcu::ScopedLogSection supersection(log, "Format", "Format info"); 481 482 for (std::set<ImageFormat>::const_iterator it = formats.begin(); it != formats.end(); ++it) 483 { 484 const tcu::ScopedLogSection section(log, "FormatInfo", de::toString(*it)); 485 486 // texture validity 487 if (isFormatFeatureSupported(ctxFormats, *it, TEXTURE_VALID)) 488 { 489 tcu::MessageBuilder msg(&log); 490 msg << "* Valid texture format\n"; 491 492 if (isFormatFeatureSupported(coreFormats, *it, TEXTURE_VALID)) 493 msg << "\t* core feature"; 494 else 495 { 496 msg << "\t* defined in supported extension(s):\n"; 497 logAffectingExtensions("\t\t- ", ctxFormats, *it, TEXTURE_VALID, msg); 498 } 499 500 msg << tcu::TestLog::EndMessage; 501 } 502 else 503 { 504 tcu::MessageBuilder msg(&log); 505 msg << "* Unsupported texture format\n"; 506 507 if (isFormatFeatureSupported(allFormats, *it, TEXTURE_VALID)) 508 { 509 msg << "\t* requires any of the extensions or combinations:\n"; 510 logAffectingExtensions("\t\t- ", allFormats, *it, TEXTURE_VALID, msg); 511 } 512 else 513 msg << "\t* no extension can make this format valid"; 514 515 msg << tcu::TestLog::EndMessage; 516 } 517 518 // RBO validity 519 if (isFormatFeatureSupported(ctxFormats, *it, RENDERBUFFER_VALID)) 520 { 521 tcu::MessageBuilder msg(&log); 522 msg << "* Valid renderbuffer format\n"; 523 524 if (isFormatFeatureSupported(coreFormats, *it, RENDERBUFFER_VALID)) 525 msg << "\t* core feature"; 526 else 527 { 528 msg << "\t* defined in supported extension(s):\n"; 529 logAffectingExtensions("\t\t- ", ctxFormats, *it, RENDERBUFFER_VALID, msg); 530 } 531 532 msg << tcu::TestLog::EndMessage; 533 } 534 else 535 { 536 tcu::MessageBuilder msg(&log); 537 msg << "* Unsupported renderbuffer format\n"; 538 539 if (isFormatFeatureSupported(allFormats, *it, RENDERBUFFER_VALID)) 540 { 541 msg << "\t* requires any of the extensions or combinations:\n"; 542 logAffectingExtensions("\t\t- ", allFormats, *it, RENDERBUFFER_VALID, msg); 543 } 544 else 545 msg << "\t* no extension can make this format valid"; 546 547 msg << tcu::TestLog::EndMessage; 548 } 549 550 // renderability 551 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_renderability); ++ndx) 552 { 553 if (isFormatFeatureSupported(ctxFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE)) 554 { 555 tcu::MessageBuilder msg(&log); 556 msg << "* Format is " << s_renderability[ndx].name << "\n"; 557 558 if (isFormatFeatureSupported(coreFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE)) 559 msg << "\t* core feature"; 560 else 561 { 562 msg << "\t* defined in supported extension(s):\n"; 563 logAffectingExtensions("\t\t- ", ctxFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE, msg); 564 } 565 566 msg << tcu::TestLog::EndMessage; 567 } 568 else if (isFormatFeatureSupported(ctxFormats, *it, s_renderability[ndx].flag)) 569 { 570 tcu::MessageBuilder msg(&log); 571 msg << "* Format is allowed to be " << s_renderability[ndx].name << " but not required\n"; 572 573 if (isFormatFeatureSupported(coreFormats, *it, s_renderability[ndx].flag)) 574 msg << "\t* core feature"; 575 else if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag)) 576 { 577 msg << "\t* extensions that would make format " << s_renderability[ndx].name << ":\n"; 578 logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag, msg); 579 } 580 else 581 msg << "\t* no extension can make this format " << s_renderability[ndx].name; 582 583 msg << tcu::TestLog::EndMessage; 584 } 585 else 586 { 587 tcu::MessageBuilder msg(&log); 588 msg << "* Format is NOT " << s_renderability[ndx].name << "\n"; 589 590 if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag)) 591 { 592 if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE)) 593 { 594 msg << "\t* extensions that would make format " << s_renderability[ndx].name << ":\n"; 595 logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE, msg); 596 } 597 else 598 { 599 msg << "\t* extensions that are allowed to make format " << s_renderability[ndx].name << ":\n"; 600 logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag, msg); 601 } 602 } 603 else 604 msg << "\t* no extension can make this format " << s_renderability[ndx].name; 605 606 msg << tcu::TestLog::EndMessage; 607 } 608 } 609 } 610 } 611 } 612 613 IterateResult TestBase::iterate (void) 614 { 615 glu::Framebuffer fbo (m_ctx.getRenderContext()); 616 FboBuilder builder (*fbo, GL_FRAMEBUFFER, gl(*this)); 617 const IterateResult ret = build(builder); 618 const ValidStatusCodes reference = m_ctx.getVerifier().validStatusCodes(builder); 619 const GLenum errorCode = builder.getError(); 620 621 logFramebufferConfig(builder, m_testCtx.getLog()); 622 logFormatInfo(builder, m_ctx.getCtxFormats(), m_ctx.getCoreFormats(), m_ctx.getAllFormats(), m_testCtx.getLog()); 623 reference.logRules(m_testCtx.getLog()); 624 reference.logLegalResults(m_testCtx.getLog()); 625 626 // \todo [2013-12-04 lauri] Check if drawing operations succeed. 627 628 if (errorCode != GL_NO_ERROR) 629 { 630 m_testCtx.getLog() 631 << TestLog::Message 632 << "Received " << glu::getErrorStr(errorCode) << " (during FBO initialization)." 633 << TestLog::EndMessage; 634 635 if (reference.isErrorCodeValid(errorCode)) 636 pass(); 637 else if (reference.isErrorCodeRequired(GL_NO_ERROR)) 638 fail(("Expected no error but got " + de::toString(glu::getErrorStr(errorCode))).c_str()); 639 else 640 fail("Got wrong error code"); 641 } 642 else 643 { 644 const GLenum fboStatus = gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER); 645 const bool validStatus = reference.isFBOStatusValid(fboStatus); 646 647 m_testCtx.getLog() 648 << TestLog::Message 649 << "Received " << glu::getFramebufferStatusStr(fboStatus) << "." 650 << TestLog::EndMessage; 651 652 if (!validStatus) 653 { 654 if (fboStatus == GL_FRAMEBUFFER_COMPLETE) 655 fail("Framebuffer checked as complete, expected incomplete"); 656 else if (reference.isFBOStatusRequired(GL_FRAMEBUFFER_COMPLETE)) 657 fail("Framebuffer checked is incomplete, expected complete"); 658 else 659 // An incomplete status is allowed, but not _this_ incomplete status. 660 fail("Framebuffer checked as incomplete, but with wrong status"); 661 } 662 else if (fboStatus != GL_FRAMEBUFFER_COMPLETE && reference.isFBOStatusValid(GL_FRAMEBUFFER_COMPLETE)) 663 qualityWarning("Framebuffer object could have checked as complete but did not."); 664 else 665 pass(); 666 } 667 668 return ret; 669 } 670 671 IterateResult TestBase::build (FboBuilder& builder) 672 { 673 DE_UNREF(builder); 674 return STOP; 675 } 676 677 ImageFormat TestBase::getDefaultFormat (GLenum attPoint, GLenum bufType) const 678 { 679 if (bufType == GL_NONE) 680 { 681 return ImageFormat::none(); 682 } 683 684 // Prefer a standard format, if there is one, but if not, use a format 685 // provided by an extension. 686 Formats formats = m_ctx.getCoreFormats().getFormats(formatFlag(attPoint) | 687 formatFlag(bufType)); 688 Formats::const_iterator it = formats.begin(); 689 if (it == formats.end()) 690 { 691 formats = m_ctx.getCtxFormats().getFormats(formatFlag(attPoint) | 692 formatFlag(bufType)); 693 it = formats.begin(); 694 } 695 if (it == formats.end()) 696 throw tcu::NotSupportedError("Unsupported attachment kind for attachment point", 697 "", __FILE__, __LINE__); 698 return *it; 699 }; 700 701 Image* makeImage (GLenum bufType, ImageFormat format, 702 GLsizei width, GLsizei height, FboBuilder& builder) 703 { 704 Image* image = DE_NULL; 705 switch (bufType) 706 { 707 case GL_NONE: 708 return DE_NULL; 709 case GL_RENDERBUFFER: 710 image = &builder.makeConfig<Renderbuffer>(); 711 break; 712 case GL_TEXTURE: 713 image = &builder.makeConfig<Texture2D>(); 714 break; 715 default: 716 DE_FATAL("Impossible case"); 717 } 718 image->internalFormat = format; 719 image->width = width; 720 image->height = height; 721 return image; 722 } 723 724 Attachment* makeAttachment (GLenum bufType, ImageFormat format, 725 GLsizei width, GLsizei height, FboBuilder& builder) 726 { 727 Image* const imgCfg = makeImage (bufType, format, width, height, builder); 728 Attachment* att = DE_NULL; 729 GLuint img = 0; 730 731 if (Renderbuffer* rboCfg = dynamic_cast<Renderbuffer*>(imgCfg)) 732 { 733 img = builder.glCreateRbo(*rboCfg); 734 att = &builder.makeConfig<RenderbufferAttachment>(); 735 } 736 else if (Texture2D* texCfg = dynamic_cast<Texture2D*>(imgCfg)) 737 { 738 img = builder.glCreateTexture(*texCfg); 739 TextureFlatAttachment& texAtt = builder.makeConfig<TextureFlatAttachment>(); 740 texAtt.texTarget = GL_TEXTURE_2D; 741 att = &texAtt; 742 } 743 else 744 { 745 DE_ASSERT(imgCfg == DE_NULL); 746 return DE_NULL; 747 } 748 att->imageName = img; 749 return att; 750 } 751 752 void TestBase::attachTargetToNew (GLenum target, GLenum bufType, ImageFormat format, 753 GLsizei width, GLsizei height, FboBuilder& builder) 754 { 755 ImageFormat imgFmt = format; 756 if (imgFmt.format == GL_NONE) 757 imgFmt = getDefaultFormat(target, bufType); 758 759 const Attachment* const att = makeAttachment(bufType, imgFmt, width, height, builder); 760 builder.glAttach(target, att); 761 } 762 763 static string formatName (ImageFormat format) 764 { 765 const string s = getTextureFormatName(format.format); 766 const string fmtStr = toLower(s.substr(3)); 767 768 if (format.unsizedType != GL_NONE) 769 { 770 const string typeStr = getTypeName(format.unsizedType); 771 return fmtStr + "_" + toLower(typeStr.substr(3)); 772 } 773 774 return fmtStr; 775 } 776 777 static string formatDesc (ImageFormat format) 778 { 779 const string fmtStr = getTextureFormatName(format.format); 780 781 if (format.unsizedType != GL_NONE) 782 { 783 const string typeStr = getTypeName(format.unsizedType); 784 return fmtStr + " with type " + typeStr; 785 } 786 787 return fmtStr; 788 } 789 790 struct RenderableParams 791 { 792 GLenum attPoint; 793 GLenum bufType; 794 ImageFormat format; 795 static string getName (const RenderableParams& params) 796 { 797 return formatName(params.format); 798 } 799 static string getDescription (const RenderableParams& params) 800 { 801 return formatDesc(params.format); 802 } 803 }; 804 805 class RenderableTest : public ParamTest<RenderableParams> 806 { 807 public: 808 RenderableTest (Context& group, const Params& params) 809 : ParamTest<RenderableParams> (group, params) {} 810 IterateResult build (FboBuilder& builder); 811 }; 812 813 IterateResult RenderableTest::build (FboBuilder& builder) 814 { 815 attachTargetToNew(m_params.attPoint, m_params.bufType, m_params.format, 64, 64, builder); 816 return STOP; 817 } 818 819 string attTypeName (GLenum bufType) 820 { 821 switch (bufType) 822 { 823 case GL_NONE: 824 return "none"; 825 case GL_RENDERBUFFER: 826 return "rbo"; 827 case GL_TEXTURE: 828 return "tex"; 829 default: 830 DE_FATAL("Impossible case"); 831 } 832 return ""; // Shut up compiler 833 } 834 835 struct AttachmentParams 836 { 837 GLenum color0Kind; 838 GLenum colornKind; 839 GLenum depthKind; 840 GLenum stencilKind; 841 842 static string getName (const AttachmentParams& params); 843 static string getDescription (const AttachmentParams& params) 844 { 845 return getName(params); 846 } 847 }; 848 849 string AttachmentParams::getName (const AttachmentParams& params) 850 { 851 return (attTypeName(params.color0Kind) + "_" + 852 attTypeName(params.colornKind) + "_" + 853 attTypeName(params.depthKind) + "_" + 854 attTypeName(params.stencilKind)); 855 } 856 857 //! Test for combinations of different kinds of attachments 858 class AttachmentTest : public ParamTest<AttachmentParams> 859 { 860 public: 861 AttachmentTest (Context& group, Params& params) 862 : ParamTest<AttachmentParams> (group, params) {} 863 864 protected: 865 IterateResult build (FboBuilder& builder); 866 void makeDepthAndStencil (FboBuilder& builder); 867 }; 868 869 870 void AttachmentTest::makeDepthAndStencil (FboBuilder& builder) 871 { 872 if (m_params.stencilKind == m_params.depthKind) 873 { 874 // If there is a common stencil+depth -format, try to use a common 875 // image for both attachments. 876 const FormatFlags flags = 877 DEPTH_RENDERABLE | STENCIL_RENDERABLE | formatFlag(m_params.stencilKind); 878 const Formats& formats = m_ctx.getCoreFormats().getFormats(flags); 879 Formats::const_iterator it = formats.begin(); 880 if (it != formats.end()) 881 { 882 const ImageFormat format = *it; 883 Attachment* att = makeAttachment(m_params.depthKind, format, 64, 64, builder); 884 builder.glAttach(GL_DEPTH_ATTACHMENT, att); 885 builder.glAttach(GL_STENCIL_ATTACHMENT, att); 886 return; 887 } 888 } 889 // Either the kinds were separate, or a suitable format was not found. 890 // Create separate images. 891 attachTargetToNew(GL_STENCIL_ATTACHMENT, m_params.stencilKind, ImageFormat::none(), 892 64, 64, builder); 893 attachTargetToNew(GL_DEPTH_ATTACHMENT, m_params.depthKind, ImageFormat::none(), 894 64, 64, builder); 895 } 896 897 IterateResult AttachmentTest::build (FboBuilder& builder) 898 { 899 attachTargetToNew(GL_COLOR_ATTACHMENT0, m_params.color0Kind, ImageFormat::none(), 900 64, 64, builder); 901 902 if (m_params.colornKind != GL_NONE) 903 { 904 TCU_CHECK_AND_THROW(NotSupportedError, m_ctx.haveMultiColorAtts(), 905 "Multiple attachments not supported"); 906 GLint maxAttachments = 1; 907 gl(*this).getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachments); 908 GLU_EXPECT_NO_ERROR( 909 gl(*this).getError(), "Couldn't read GL_MAX_COLOR_ATTACHMENTS"); 910 911 for (int i = 1; i < maxAttachments; i++) 912 { 913 attachTargetToNew(GL_COLOR_ATTACHMENT0 + i, m_params.colornKind, 914 ImageFormat::none(), 64, 64, builder); 915 } 916 } 917 918 makeDepthAndStencil(builder); 919 920 return STOP; 921 } 922 923 class EmptyImageTest : public TestBase 924 { 925 public: 926 EmptyImageTest (Context& group, 927 const char* name, const char* desc) 928 : TestBase (group, name, desc) {} 929 930 IterateResult build (FboBuilder& builder); 931 }; 932 933 IterateResult EmptyImageTest::build (FboBuilder& builder) 934 { 935 attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 936 0, 0, builder); 937 return STOP; 938 } 939 940 941 class DistinctSizeTest : public TestBase 942 { 943 public: 944 DistinctSizeTest (Context& group, 945 const char* name, const char* desc) 946 : TestBase (group, name, desc) {} 947 948 IterateResult build (FboBuilder& builder); 949 }; 950 951 IterateResult DistinctSizeTest::build (FboBuilder& builder) 952 { 953 attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 954 64, 64, builder); 955 attachTargetToNew(GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ImageFormat::none(), 956 128, 128, builder); 957 return STOP; 958 } 959 960 TestCaseGroup* Context::createRenderableTests (void) 961 { 962 TestCaseGroup* const renderableTests = new TestCaseGroup( 963 m_testCtx, "renderable", "Tests for support of renderable image formats"); 964 965 TestCaseGroup* const rbRenderableTests = new TestCaseGroup( 966 m_testCtx, "renderbuffer", "Tests for renderbuffer formats"); 967 968 TestCaseGroup* const texRenderableTests = new TestCaseGroup( 969 m_testCtx, "texture", "Tests for texture formats"); 970 971 static const struct AttPoint { 972 GLenum attPoint; 973 const char* name; 974 const char* desc; 975 } attPoints[] = 976 { 977 { GL_COLOR_ATTACHMENT0, "color0", "Tests for color attachments" }, 978 { GL_STENCIL_ATTACHMENT, "stencil", "Tests for stencil attachments" }, 979 { GL_DEPTH_ATTACHMENT, "depth", "Tests for depth attachments" }, 980 }; 981 982 // At each attachment point, iterate through all the possible formats to 983 // detect both false positives and false negatives. 984 const Formats rboFmts = m_allFormats.getFormats(ANY_FORMAT); 985 const Formats texFmts = m_allFormats.getFormats(ANY_FORMAT); 986 987 for (const AttPoint* it = DE_ARRAY_BEGIN(attPoints); it != DE_ARRAY_END(attPoints); it++) 988 { 989 TestCaseGroup* const rbAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc); 990 TestCaseGroup* const texAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc); 991 992 for (Formats::const_iterator it2 = rboFmts.begin(); it2 != rboFmts.end(); it2++) 993 { 994 const RenderableParams params = { it->attPoint, GL_RENDERBUFFER, *it2 }; 995 rbAttTests->addChild(new RenderableTest(*this, params)); 996 } 997 rbRenderableTests->addChild(rbAttTests); 998 999 for (Formats::const_iterator it2 = texFmts.begin(); it2 != texFmts.end(); it2++) 1000 { 1001 const RenderableParams params = { it->attPoint, GL_TEXTURE, *it2 }; 1002 texAttTests->addChild(new RenderableTest(*this, params)); 1003 } 1004 texRenderableTests->addChild(texAttTests); 1005 } 1006 renderableTests->addChild(rbRenderableTests); 1007 renderableTests->addChild(texRenderableTests); 1008 1009 return renderableTests; 1010 } 1011 1012 TestCaseGroup* Context::createAttachmentTests (void) 1013 { 1014 TestCaseGroup* const attCombTests = new TestCaseGroup( 1015 m_testCtx, "attachment_combinations", "Tests for attachment combinations"); 1016 1017 static const GLenum s_bufTypes[] = { GL_NONE, GL_RENDERBUFFER, GL_TEXTURE }; 1018 static const Range<GLenum> s_kinds = GLS_ARRAY_RANGE(s_bufTypes); 1019 1020 for (const GLenum* col0 = s_kinds.begin(); col0 != s_kinds.end(); ++col0) 1021 for (const GLenum* coln = s_kinds.begin(); coln != s_kinds.end(); ++coln) 1022 for (const GLenum* dep = s_kinds.begin(); dep != s_kinds.end(); ++dep) 1023 for (const GLenum* stc = s_kinds.begin(); stc != s_kinds.end(); ++stc) 1024 { 1025 AttachmentParams params = { *col0, *coln, *dep, *stc }; 1026 attCombTests->addChild(new AttachmentTest(*this, params)); 1027 } 1028 1029 return attCombTests; 1030 } 1031 1032 TestCaseGroup* Context::createSizeTests (void) 1033 { 1034 TestCaseGroup* const sizeTests = new TestCaseGroup( 1035 m_testCtx, "size", "Tests for attachment sizes"); 1036 sizeTests->addChild(new EmptyImageTest( 1037 *this, "zero", 1038 "Test for zero-sized image attachment")); 1039 sizeTests->addChild(new DistinctSizeTest( 1040 *this, "distinct", 1041 "Test for attachments with different sizes")); 1042 1043 return sizeTests; 1044 } 1045 1046 } // details 1047 1048 } // fboc 1049 } // gls 1050 } // deqp 1051