1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 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 Mipmapping tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es3fTextureMipmapTests.hpp" 25 26 #include "glsTextureTestUtil.hpp" 27 #include "gluTexture.hpp" 28 #include "gluTextureUtil.hpp" 29 #include "gluPixelTransfer.hpp" 30 #include "tcuTextureUtil.hpp" 31 #include "tcuMatrix.hpp" 32 #include "tcuMatrixUtil.hpp" 33 #include "tcuTexLookupVerifier.hpp" 34 #include "tcuVectorUtil.hpp" 35 #include "deStringUtil.hpp" 36 #include "deRandom.hpp" 37 #include "deString.h" 38 #include "glwFunctions.hpp" 39 #include "glwEnums.hpp" 40 41 using std::vector; 42 using std::string; 43 using namespace deqp::gls; 44 45 namespace deqp 46 { 47 namespace gles3 48 { 49 namespace Functional 50 { 51 52 using std::string; 53 using std::vector; 54 using tcu::TestLog; 55 using tcu::Vec2; 56 using tcu::Vec3; 57 using tcu::Vec4; 58 using tcu::IVec4; 59 using namespace gls::TextureTestUtil; 60 61 static float getMinLodForCell (int cellNdx) 62 { 63 static const float s_values[] = 64 { 65 1.0f, 66 3.5f, 67 2.0f, 68 -2.0f, 69 0.0f, 70 3.0f, 71 10.0f, 72 4.8f, 73 5.8f, 74 5.7f, 75 -1.9f, 76 4.0f, 77 6.5f, 78 7.1f, 79 -1e10, 80 1000.f 81 }; 82 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)]; 83 } 84 85 static float getMaxLodForCell (int cellNdx) 86 { 87 static const float s_values[] = 88 { 89 0.0f, 90 0.2f, 91 0.7f, 92 0.4f, 93 1.3f, 94 0.0f, 95 0.5f, 96 1.2f, 97 -2.0f, 98 1.0f, 99 0.1f, 100 0.3f, 101 2.7f, 102 1.2f, 103 10.0f, 104 -1000.f, 105 1e10f 106 }; 107 return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)]; 108 } 109 110 enum CoordType 111 { 112 COORDTYPE_BASIC, //!< texCoord = translateScale(position). 113 COORDTYPE_BASIC_BIAS, //!< Like basic, but with bias values. 114 COORDTYPE_AFFINE, //!< texCoord = translateScaleRotateShear(position). 115 COORDTYPE_PROJECTED, //!< Projected coordinates, w != 1 116 117 COORDTYPE_LAST 118 }; 119 120 // Texture2DMipmapCase 121 122 class Texture2DMipmapCase : public tcu::TestCase 123 { 124 public: 125 126 Texture2DMipmapCase (tcu::TestContext& testCtx, 127 glu::RenderContext& renderCtx, 128 const glu::ContextInfo& renderCtxInfo, 129 const char* name, 130 const char* desc, 131 CoordType coordType, 132 deUint32 minFilter, 133 deUint32 wrapS, 134 deUint32 wrapT, 135 deUint32 format, 136 deUint32 dataType, 137 int width, 138 int height); 139 ~Texture2DMipmapCase (void); 140 141 void init (void); 142 void deinit (void); 143 IterateResult iterate (void); 144 145 private: 146 Texture2DMipmapCase (const Texture2DMipmapCase& other); 147 Texture2DMipmapCase& operator= (const Texture2DMipmapCase& other); 148 149 glu::RenderContext& m_renderCtx; 150 const glu::ContextInfo& m_renderCtxInfo; 151 152 CoordType m_coordType; 153 deUint32 m_minFilter; 154 deUint32 m_wrapS; 155 deUint32 m_wrapT; 156 deUint32 m_format; 157 deUint32 m_dataType; 158 int m_width; 159 int m_height; 160 161 glu::Texture2D* m_texture; 162 TextureRenderer m_renderer; 163 }; 164 165 Texture2DMipmapCase::Texture2DMipmapCase (tcu::TestContext& testCtx, 166 glu::RenderContext& renderCtx, 167 const glu::ContextInfo& renderCtxInfo, 168 const char* name, 169 const char* desc, 170 CoordType coordType, 171 deUint32 minFilter, 172 deUint32 wrapS, 173 deUint32 wrapT, 174 deUint32 format, 175 deUint32 dataType, 176 int width, 177 int height) 178 : TestCase (testCtx, name, desc) 179 , m_renderCtx (renderCtx) 180 , m_renderCtxInfo (renderCtxInfo) 181 , m_coordType (coordType) 182 , m_minFilter (minFilter) 183 , m_wrapS (wrapS) 184 , m_wrapT (wrapT) 185 , m_format (format) 186 , m_dataType (dataType) 187 , m_width (width) 188 , m_height (height) 189 , m_texture (DE_NULL) 190 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 191 { 192 } 193 194 Texture2DMipmapCase::~Texture2DMipmapCase (void) 195 { 196 deinit(); 197 } 198 199 void Texture2DMipmapCase::init (void) 200 { 201 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0) 202 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config"); 203 204 m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height); 205 206 int numLevels = deLog2Floor32(de::max(m_width, m_height))+1; 207 208 // Fill texture with colored grid. 209 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 210 { 211 deUint32 step = 0xff / (numLevels-1); 212 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 213 deUint32 dec = 0xff - inc; 214 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff; 215 deUint32 color = 0xff000000 | rgb; 216 217 m_texture->getRefTexture().allocLevel(levelNdx); 218 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), toVec4(tcu::RGBA(color))); 219 } 220 } 221 222 void Texture2DMipmapCase::deinit (void) 223 { 224 delete m_texture; 225 m_texture = DE_NULL; 226 227 m_renderer.clear(); 228 } 229 230 static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx) 231 { 232 static const struct 233 { 234 Vec2 bottomLeft; 235 Vec2 topRight; 236 } s_basicCoords[] = 237 { 238 { Vec2(-0.1f, 0.1f), Vec2( 0.8f, 1.0f) }, 239 { Vec2(-0.3f, -0.6f), Vec2( 0.7f, 0.4f) }, 240 { Vec2(-0.3f, 0.6f), Vec2( 0.7f, -0.9f) }, 241 { Vec2(-0.8f, 0.6f), Vec2( 0.7f, -0.9f) }, 242 243 { Vec2(-0.5f, -0.5f), Vec2( 1.5f, 1.5f) }, 244 { Vec2( 1.0f, -1.0f), Vec2(-1.3f, 1.0f) }, 245 { Vec2( 1.2f, -1.0f), Vec2(-1.3f, 1.6f) }, 246 { Vec2( 2.2f, -1.1f), Vec2(-1.3f, 0.8f) }, 247 248 { Vec2(-1.5f, 1.6f), Vec2( 1.7f, -1.4f) }, 249 { Vec2( 2.0f, 1.6f), Vec2( 2.3f, -1.4f) }, 250 { Vec2( 1.3f, -2.6f), Vec2(-2.7f, 2.9f) }, 251 { Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) }, 252 253 { Vec2( -8.0f, 9.0f), Vec2( 8.3f, -7.0f) }, 254 { Vec2(-16.0f, 10.0f), Vec2( 18.3f, 24.0f) }, 255 { Vec2( 30.2f, 55.0f), Vec2(-24.3f, -1.6f) }, 256 { Vec2(-33.2f, 64.1f), Vec2( 32.1f, -64.1f) }, 257 }; 258 259 DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords))); 260 261 const Vec2& bottomLeft = s_basicCoords[cellNdx].bottomLeft; 262 const Vec2& topRight = s_basicCoords[cellNdx].topRight; 263 264 computeQuadTexCoord2D(dst, bottomLeft, topRight); 265 } 266 267 static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx) 268 { 269 // Use basic coords as base. 270 getBasicTexCoord2D(dst, cellNdx); 271 272 // Rotate based on cell index. 273 float angle = 2.0f*DE_PI * ((float)cellNdx / 16.0f); 274 tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle); 275 276 // Second and third row are sheared. 277 float shearX = de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f; 278 tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f)); 279 280 tcu::Mat2 transform = rotMatrix * shearMatrix; 281 Vec2 p0 = transform * Vec2(dst[0], dst[1]); 282 Vec2 p1 = transform * Vec2(dst[2], dst[3]); 283 Vec2 p2 = transform * Vec2(dst[4], dst[5]); 284 Vec2 p3 = transform * Vec2(dst[6], dst[7]); 285 286 dst[0] = p0.x(); dst[1] = p0.y(); 287 dst[2] = p1.x(); dst[3] = p1.y(); 288 dst[4] = p2.x(); dst[5] = p2.y(); 289 dst[6] = p3.x(); dst[7] = p3.y(); 290 } 291 292 Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void) 293 { 294 const glw::Functions& gl = m_renderCtx.getFunctions(); 295 296 const tcu::Texture2D& refTexture = m_texture->getRefTexture(); 297 298 const deUint32 magFilter = GL_NEAREST; 299 const int texWidth = refTexture.getWidth(); 300 const int texHeight = refTexture.getHeight(); 301 const int defViewportWidth = texWidth*4; 302 const int defViewportHeight = texHeight*4; 303 304 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 305 ReferenceParams sampleParams (TEXTURETYPE_2D); 306 vector<float> texCoord; 307 308 const bool isProjected = m_coordType == COORDTYPE_PROJECTED; 309 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS; 310 311 tcu::Surface renderedFrame (viewport.width, viewport.height); 312 313 // Viewport is divided into 4x4 grid. 314 int gridWidth = 4; 315 int gridHeight = 4; 316 int cellWidth = viewport.width / gridWidth; 317 int cellHeight = viewport.height / gridHeight; 318 319 // Bail out if rendertarget is too small. 320 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2) 321 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 322 323 // Sampling parameters. 324 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter); 325 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat()); 326 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0); 327 sampleParams.lodMode = LODMODE_EXACT; // Use ideal lod. 328 329 // Upload texture data. 330 m_texture->upload(); 331 332 // Bind gradient texture and setup sampler parameters. 333 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture()); 334 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); 335 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); 336 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 337 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); 338 339 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 340 341 // Bias values. 342 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f }; 343 344 // Projection values. 345 static const Vec4 s_projections[] = 346 { 347 Vec4(1.2f, 1.0f, 0.7f, 1.0f), 348 Vec4(1.3f, 0.8f, 0.6f, 2.0f), 349 Vec4(0.8f, 1.0f, 1.7f, 0.6f), 350 Vec4(1.2f, 1.0f, 1.7f, 1.5f) 351 }; 352 353 // Render cells. 354 for (int gridY = 0; gridY < gridHeight; gridY++) 355 { 356 for (int gridX = 0; gridX < gridWidth; gridX++) 357 { 358 const int curX = cellWidth*gridX; 359 const int curY = cellHeight*gridY; 360 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 361 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 362 const int cellNdx = gridY*gridWidth + gridX; 363 364 // Compute texcoord. 365 switch (m_coordType) 366 { 367 case COORDTYPE_BASIC_BIAS: // Fall-through. 368 case COORDTYPE_PROJECTED: 369 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break; 370 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break; 371 default: DE_ASSERT(DE_FALSE); 372 } 373 374 if (isProjected) 375 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 376 377 if (useLodBias) 378 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 379 380 // Render with GL. 381 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 382 m_renderer.renderQuad(0, &texCoord[0], sampleParams); 383 } 384 } 385 386 // Read result. 387 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 388 389 // Compare and log. 390 { 391 const tcu::PixelFormat& pixelFormat = m_renderCtx.getRenderTarget().getPixelFormat(); 392 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR; 393 tcu::Surface referenceFrame (viewport.width, viewport.height); 394 tcu::Surface errorMask (viewport.width, viewport.height); 395 tcu::LookupPrecision lookupPrec; 396 tcu::LodPrecision lodPrec; 397 int numFailedPixels = 0; 398 399 lookupPrec.coordBits = tcu::IVec3(20, 20, 0); 400 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored. 401 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0))); 402 lookupPrec.colorMask = getCompareMask(pixelFormat); 403 lodPrec.derivateBits = 10; 404 lodPrec.lodBits = isProjected ? 6 : 8; 405 406 for (int gridY = 0; gridY < gridHeight; gridY++) 407 { 408 for (int gridX = 0; gridX < gridWidth; gridX++) 409 { 410 const int curX = cellWidth*gridX; 411 const int curY = cellHeight*gridY; 412 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 413 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 414 const int cellNdx = gridY*gridWidth + gridX; 415 416 // Compute texcoord. 417 switch (m_coordType) 418 { 419 case COORDTYPE_BASIC_BIAS: // Fall-through. 420 case COORDTYPE_PROJECTED: 421 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break; 422 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break; 423 default: DE_ASSERT(DE_FALSE); 424 } 425 426 if (isProjected) 427 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 428 429 if (useLodBias) 430 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 431 432 // Render ideal result 433 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), 434 refTexture, &texCoord[0], sampleParams); 435 436 // Compare this cell 437 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 438 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 439 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 440 m_texture->getRefTexture(), &texCoord[0], sampleParams, 441 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 442 } 443 } 444 445 if (numFailedPixels > 0) 446 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 447 448 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 449 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 450 451 if (numFailedPixels > 0) 452 { 453 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 454 << TestLog::Image("ErrorMask", "Error mask", errorMask); 455 } 456 457 m_testCtx.getLog() << TestLog::EndImageSet; 458 459 { 460 const bool isOk = numFailedPixels == 0; 461 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 462 isOk ? "Pass" : "Image verification failed"); 463 } 464 } 465 466 return STOP; 467 } 468 469 // TextureCubeMipmapCase 470 471 class TextureCubeMipmapCase : public tcu::TestCase 472 { 473 public: 474 475 TextureCubeMipmapCase (tcu::TestContext& testCtx, 476 glu::RenderContext& renderCtx, 477 const glu::ContextInfo& renderCtxInfo, 478 const char* name, 479 const char* desc, 480 CoordType coordType, 481 deUint32 minFilter, 482 deUint32 wrapS, 483 deUint32 wrapT, 484 deUint32 format, 485 deUint32 dataType, 486 int size); 487 ~TextureCubeMipmapCase (void); 488 489 void init (void); 490 void deinit (void); 491 IterateResult iterate (void); 492 493 private: 494 TextureCubeMipmapCase (const TextureCubeMipmapCase& other); 495 TextureCubeMipmapCase& operator= (const TextureCubeMipmapCase& other); 496 497 glu::RenderContext& m_renderCtx; 498 const glu::ContextInfo& m_renderCtxInfo; 499 500 CoordType m_coordType; 501 deUint32 m_minFilter; 502 deUint32 m_wrapS; 503 deUint32 m_wrapT; 504 deUint32 m_format; 505 deUint32 m_dataType; 506 int m_size; 507 508 glu::TextureCube* m_texture; 509 TextureRenderer m_renderer; 510 }; 511 512 TextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext& testCtx, 513 glu::RenderContext& renderCtx, 514 const glu::ContextInfo& renderCtxInfo, 515 const char* name, 516 const char* desc, 517 CoordType coordType, 518 deUint32 minFilter, 519 deUint32 wrapS, 520 deUint32 wrapT, 521 deUint32 format, 522 deUint32 dataType, 523 int size) 524 : TestCase (testCtx, name, desc) 525 , m_renderCtx (renderCtx) 526 , m_renderCtxInfo (renderCtxInfo) 527 , m_coordType (coordType) 528 , m_minFilter (minFilter) 529 , m_wrapS (wrapS) 530 , m_wrapT (wrapT) 531 , m_format (format) 532 , m_dataType (dataType) 533 , m_size (size) 534 , m_texture (DE_NULL) 535 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 536 { 537 } 538 539 TextureCubeMipmapCase::~TextureCubeMipmapCase (void) 540 { 541 deinit(); 542 } 543 544 void TextureCubeMipmapCase::init (void) 545 { 546 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0) 547 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config"); 548 549 m_texture = new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_size); 550 551 int numLevels = deLog2Floor32(m_size)+1; 552 553 // Fill texture with colored grid. 554 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 555 { 556 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 557 { 558 deUint32 step = 0xff / (numLevels-1); 559 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 560 deUint32 dec = 0xff - inc; 561 deUint32 rgb = 0; 562 563 switch (faceNdx) 564 { 565 case 0: rgb = (inc << 16) | (dec << 8) | 255; break; 566 case 1: rgb = (255 << 16) | (inc << 8) | dec; break; 567 case 2: rgb = (dec << 16) | (255 << 8) | inc; break; 568 case 3: rgb = (dec << 16) | (inc << 8) | 255; break; 569 case 4: rgb = (255 << 16) | (dec << 8) | inc; break; 570 case 5: rgb = (inc << 16) | (255 << 8) | dec; break; 571 } 572 573 deUint32 color = 0xff000000 | rgb; 574 575 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx); 576 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), toVec4(tcu::RGBA(color))); 577 } 578 } 579 } 580 581 void TextureCubeMipmapCase::deinit (void) 582 { 583 delete m_texture; 584 m_texture = DE_NULL; 585 586 m_renderer.clear(); 587 } 588 589 static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height) 590 { 591 const int minWidth = 8; 592 const int minHeight = 8; 593 594 bool partition = rnd.getFloat() > 0.4f; 595 bool partitionX = partition && width > minWidth && rnd.getBool(); 596 bool partitionY = partition && height > minHeight && !partitionX; 597 598 if (partitionX) 599 { 600 int split = width/2 + rnd.getInt(-width/4, +width/4); 601 randomPartition(dst, rnd, x, y, split, height); 602 randomPartition(dst, rnd, x+split, y, width-split, height); 603 } 604 else if (partitionY) 605 { 606 int split = height/2 + rnd.getInt(-height/4, +height/4); 607 randomPartition(dst, rnd, x, y, width, split); 608 randomPartition(dst, rnd, x, y+split, width, height-split); 609 } 610 else 611 dst.push_back(IVec4(x, y, width, height)); 612 } 613 614 static void computeGridLayout (vector<IVec4>& dst, int width, int height) 615 { 616 de::Random rnd(7); 617 randomPartition(dst, rnd, 0, 0, width, height); 618 } 619 620 TextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void) 621 { 622 const deUint32 magFilter = GL_NEAREST; 623 const int texWidth = m_texture->getRefTexture().getSize(); 624 const int texHeight = m_texture->getRefTexture().getSize(); 625 const int defViewportWidth = texWidth*2; 626 const int defViewportHeight = texHeight*2; 627 628 const glw::Functions& gl = m_renderCtx.getFunctions(); 629 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 630 631 const bool isProjected = m_coordType == COORDTYPE_PROJECTED; 632 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS; 633 634 vector<float> texCoord; 635 tcu::Surface renderedFrame (viewport.width, viewport.height); 636 637 // Bail out if rendertarget is too small. 638 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2) 639 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 640 641 // Upload texture data. 642 m_texture->upload(); 643 644 // Bind gradient texture and setup sampler parameters. 645 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture()); 646 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS); 647 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT); 648 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter); 649 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter); 650 651 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 652 653 // Compute grid. 654 vector<IVec4> gridLayout; 655 computeGridLayout(gridLayout, viewport.width, viewport.height); 656 657 // Bias values. 658 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f }; 659 660 // Projection values \note Less agressive than in 2D case due to smaller quads. 661 static const Vec4 s_projections[] = 662 { 663 Vec4(1.2f, 1.0f, 0.7f, 1.0f), 664 Vec4(1.3f, 0.8f, 0.6f, 1.1f), 665 Vec4(0.8f, 1.0f, 1.2f, 0.8f), 666 Vec4(1.2f, 1.0f, 1.3f, 0.9f) 667 }; 668 669 // Render with GL 670 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++) 671 { 672 const int curX = gridLayout[cellNdx].x(); 673 const int curY = gridLayout[cellNdx].y(); 674 const int curW = gridLayout[cellNdx].z(); 675 const int curH = gridLayout[cellNdx].w(); 676 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST); 677 RenderParams params (TEXTURETYPE_CUBE); 678 679 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported. 680 computeQuadTexCoordCube(texCoord, cubeFace); 681 682 if (isProjected) 683 { 684 params.flags |= ReferenceParams::PROJECTED; 685 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 686 } 687 688 if (useLodBias) 689 { 690 params.flags |= ReferenceParams::USE_BIAS; 691 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 692 } 693 694 // Render with GL. 695 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 696 m_renderer.renderQuad(0, &texCoord[0], params); 697 } 698 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 699 700 // Read result. 701 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 702 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels"); 703 704 // Render reference and compare 705 { 706 tcu::Surface referenceFrame (viewport.width, viewport.height); 707 tcu::Surface errorMask (viewport.width, viewport.height); 708 int numFailedPixels = 0; 709 ReferenceParams params (TEXTURETYPE_CUBE); 710 tcu::LookupPrecision lookupPrec; 711 tcu::LodPrecision lodPrec; 712 713 // Params for rendering reference 714 params.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter); 715 params.sampler.seamlessCubeMap = true; 716 params.lodMode = LODMODE_EXACT; 717 718 // Comparison parameters 719 lookupPrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat()); 720 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0))); 721 lookupPrec.coordBits = isProjected ? tcu::IVec3(8) : tcu::IVec3(10); 722 lookupPrec.uvwBits = tcu::IVec3(5,5,0); 723 lodPrec.derivateBits = 10; 724 lodPrec.lodBits = isProjected ? 3 : 6; 725 726 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++) 727 { 728 const int curX = gridLayout[cellNdx].x(); 729 const int curY = gridLayout[cellNdx].y(); 730 const int curW = gridLayout[cellNdx].z(); 731 const int curH = gridLayout[cellNdx].w(); 732 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST); 733 734 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported. 735 computeQuadTexCoordCube(texCoord, cubeFace); 736 737 if (isProjected) 738 { 739 params.flags |= ReferenceParams::PROJECTED; 740 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 741 } 742 743 if (useLodBias) 744 { 745 params.flags |= ReferenceParams::USE_BIAS; 746 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 747 } 748 749 // Render ideal reference. 750 { 751 SurfaceAccess idealDst(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH); 752 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params); 753 } 754 755 // Compare this cell 756 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 757 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 758 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 759 m_texture->getRefTexture(), &texCoord[0], params, 760 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 761 } 762 763 if (numFailedPixels > 0) 764 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 765 766 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 767 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 768 769 if (numFailedPixels > 0) 770 { 771 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 772 << TestLog::Image("ErrorMask", "Error mask", errorMask); 773 } 774 775 m_testCtx.getLog() << TestLog::EndImageSet; 776 777 { 778 const bool isOk = numFailedPixels == 0; 779 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 780 isOk ? "Pass" : "Image verification failed"); 781 } 782 } 783 784 return STOP; 785 } 786 787 // Texture2DGenMipmapCase 788 789 class Texture2DGenMipmapCase : public tcu::TestCase 790 { 791 public: 792 793 Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height); 794 ~Texture2DGenMipmapCase (void); 795 796 void init (void); 797 void deinit (void); 798 IterateResult iterate (void); 799 800 private: 801 Texture2DGenMipmapCase (const Texture2DGenMipmapCase& other); 802 Texture2DGenMipmapCase& operator= (const Texture2DGenMipmapCase& other); 803 804 glu::RenderContext& m_renderCtx; 805 806 deUint32 m_format; 807 deUint32 m_dataType; 808 deUint32 m_hint; 809 int m_width; 810 int m_height; 811 812 glu::Texture2D* m_texture; 813 TextureRenderer m_renderer; 814 }; 815 816 Texture2DGenMipmapCase::Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height) 817 : TestCase (testCtx, name, desc) 818 , m_renderCtx (renderCtx) 819 , m_format (format) 820 , m_dataType (dataType) 821 , m_hint (hint) 822 , m_width (width) 823 , m_height (height) 824 , m_texture (DE_NULL) 825 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 826 { 827 } 828 829 Texture2DGenMipmapCase::~Texture2DGenMipmapCase (void) 830 { 831 deinit(); 832 } 833 834 void Texture2DGenMipmapCase::init (void) 835 { 836 DE_ASSERT(!m_texture); 837 m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height); 838 } 839 840 void Texture2DGenMipmapCase::deinit (void) 841 { 842 delete m_texture; 843 m_texture = DE_NULL; 844 845 m_renderer.clear(); 846 } 847 848 Texture2DGenMipmapCase::IterateResult Texture2DGenMipmapCase::iterate (void) 849 { 850 const glw::Functions& gl = m_renderCtx.getFunctions(); 851 852 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST; 853 const deUint32 magFilter = GL_NEAREST; 854 const deUint32 wrapS = GL_CLAMP_TO_EDGE; 855 const deUint32 wrapT = GL_CLAMP_TO_EDGE; 856 857 const int numLevels = deLog2Floor32(de::max(m_width, m_height))+1; 858 const tcu::Sampler sampler = glu::mapGLSampler(wrapS, wrapT, minFilter, magFilter); 859 860 tcu::Texture2D resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight()); 861 862 vector<float> texCoord; 863 864 // Initialize texture level 0 with colored grid. 865 m_texture->getRefTexture().allocLevel(0); 866 tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 8, tcu::Vec4(1.0f, 0.5f, 0.0f, 0.5f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); 867 868 // Upload data and setup params. 869 m_texture->upload(); 870 871 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture()); 872 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 873 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 874 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); 875 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); 876 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 877 878 // Generate mipmap. 879 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint); 880 gl.generateMipmap(GL_TEXTURE_2D); 881 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()"); 882 883 // Use (0, 0) -> (1, 1) texture coordinates. 884 computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f)); 885 886 // Fetch resulting texture by rendering. 887 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 888 { 889 const int levelWidth = de::max(1, m_width >> levelNdx); 890 const int levelHeight = de::max(1, m_height >> levelNdx); 891 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth, levelHeight, deStringHash(getName()) + levelNdx); 892 893 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 894 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D); 895 896 resultTexture.allocLevel(levelNdx); 897 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevel(levelNdx)); 898 } 899 900 // Compare results 901 { 902 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)); 903 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType)); 904 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0)); 905 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask); 906 GenMipmapPrecision comparePrec; 907 908 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat()); 909 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits); 910 comparePrec.filterBits = tcu::IVec3(4, 4, 0); 911 912 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec); 913 914 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" : 915 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" : 916 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : ""); 917 } 918 919 return STOP; 920 } 921 922 // TextureCubeGenMipmapCase 923 924 class TextureCubeGenMipmapCase : public tcu::TestCase 925 { 926 public: 927 928 TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size); 929 ~TextureCubeGenMipmapCase (void); 930 931 void init (void); 932 void deinit (void); 933 IterateResult iterate (void); 934 935 private: 936 TextureCubeGenMipmapCase (const TextureCubeGenMipmapCase& other); 937 TextureCubeGenMipmapCase& operator= (const TextureCubeGenMipmapCase& other); 938 939 glu::RenderContext& m_renderCtx; 940 941 deUint32 m_format; 942 deUint32 m_dataType; 943 deUint32 m_hint; 944 int m_size; 945 946 glu::TextureCube* m_texture; 947 TextureRenderer m_renderer; 948 }; 949 950 TextureCubeGenMipmapCase::TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size) 951 : TestCase (testCtx, name, desc) 952 , m_renderCtx (renderCtx) 953 , m_format (format) 954 , m_dataType (dataType) 955 , m_hint (hint) 956 , m_size (size) 957 , m_texture (DE_NULL) 958 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 959 { 960 } 961 962 TextureCubeGenMipmapCase::~TextureCubeGenMipmapCase (void) 963 { 964 deinit(); 965 } 966 967 void TextureCubeGenMipmapCase::init (void) 968 { 969 if (m_renderCtx.getRenderTarget().getWidth() < 3*m_size || m_renderCtx.getRenderTarget().getHeight() < 2*m_size) 970 throw tcu::NotSupportedError("Render target size must be at least (" + de::toString(3*m_size) + ", " + de::toString(2*m_size) + ")"); 971 972 DE_ASSERT(!m_texture); 973 m_texture = new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_size); 974 } 975 976 void TextureCubeGenMipmapCase::deinit (void) 977 { 978 delete m_texture; 979 m_texture = DE_NULL; 980 981 m_renderer.clear(); 982 } 983 984 TextureCubeGenMipmapCase::IterateResult TextureCubeGenMipmapCase::iterate (void) 985 { 986 const glw::Functions& gl = m_renderCtx.getFunctions(); 987 988 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST; 989 const deUint32 magFilter = GL_NEAREST; 990 const deUint32 wrapS = GL_CLAMP_TO_EDGE; 991 const deUint32 wrapT = GL_CLAMP_TO_EDGE; 992 993 tcu::TextureCube resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_size); 994 995 const int numLevels = deLog2Floor32(m_size)+1; 996 tcu::Sampler sampler = glu::mapGLSampler(wrapS, wrapT, minFilter, magFilter); 997 vector<float> texCoord; 998 999 sampler.seamlessCubeMap = true; 1000 1001 // Initialize texture level 0 with colored grid. 1002 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 1003 { 1004 Vec4 ca, cb; // Grid colors. 1005 1006 switch (face) 1007 { 1008 case 0: ca = Vec4(1.0f, 0.3f, 0.0f, 0.7f); cb = Vec4(0.0f, 0.0f, 1.0f, 1.0f); break; 1009 case 1: ca = Vec4(0.0f, 1.0f, 0.5f, 0.5f); cb = Vec4(1.0f, 0.0f, 0.0f, 1.0f); break; 1010 case 2: ca = Vec4(0.7f, 0.0f, 1.0f, 0.3f); cb = Vec4(0.0f, 1.0f, 0.0f, 1.0f); break; 1011 case 3: ca = Vec4(0.0f, 0.3f, 1.0f, 1.0f); cb = Vec4(1.0f, 0.0f, 0.0f, 0.7f); break; 1012 case 4: ca = Vec4(1.0f, 0.0f, 0.5f, 1.0f); cb = Vec4(0.0f, 1.0f, 0.0f, 0.5f); break; 1013 case 5: ca = Vec4(0.7f, 1.0f, 0.0f, 1.0f); cb = Vec4(0.0f, 0.0f, 1.0f, 0.3f); break; 1014 } 1015 1016 m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0); 1017 fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), 8, ca, cb); 1018 } 1019 1020 // Upload data and setup params. 1021 m_texture->upload(); 1022 1023 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture()); 1024 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS); 1025 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT); 1026 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter); 1027 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter); 1028 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 1029 1030 // Generate mipmap. 1031 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint); 1032 gl.generateMipmap(GL_TEXTURE_CUBE_MAP); 1033 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()"); 1034 1035 // Render all levels. 1036 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 1037 { 1038 const int levelWidth = de::max(1, m_size >> levelNdx); 1039 const int levelHeight = de::max(1, m_size >> levelNdx); 1040 1041 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 1042 { 1043 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth*3, levelHeight*2, deStringHash(getName()) ^ deInt32Hash(levelNdx + faceNdx)); 1044 const tcu::CubeFace face = tcu::CubeFace(faceNdx); 1045 1046 computeQuadTexCoordCube(texCoord, face); 1047 1048 gl.viewport(viewport.x, viewport.y, levelWidth, levelHeight); 1049 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE); 1050 1051 resultTexture.allocLevel(face, levelNdx); 1052 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevelFace(levelNdx, face)); 1053 } 1054 } 1055 1056 // Compare results 1057 { 1058 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)); 1059 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType)); 1060 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0)); 1061 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask); 1062 GenMipmapPrecision comparePrec; 1063 1064 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat()); 1065 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits); 1066 comparePrec.filterBits = tcu::IVec3(4, 4, 0); 1067 1068 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec); 1069 1070 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" : 1071 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" : 1072 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : ""); 1073 } 1074 1075 return STOP; 1076 } 1077 1078 // Texture3DMipmapCase 1079 1080 class Texture3DMipmapCase : public TestCase 1081 { 1082 public: 1083 1084 Texture3DMipmapCase (Context& context, 1085 const char* name, 1086 const char* desc, 1087 CoordType coordType, 1088 deUint32 minFilter, 1089 deUint32 wrapS, 1090 deUint32 wrapT, 1091 deUint32 wrapR, 1092 deUint32 format, 1093 int width, 1094 int height, 1095 int depth); 1096 ~Texture3DMipmapCase (void); 1097 1098 void init (void); 1099 void deinit (void); 1100 IterateResult iterate (void); 1101 1102 private: 1103 Texture3DMipmapCase (const Texture3DMipmapCase& other); 1104 Texture3DMipmapCase& operator= (const Texture3DMipmapCase& other); 1105 1106 CoordType m_coordType; 1107 deUint32 m_minFilter; 1108 deUint32 m_wrapS; 1109 deUint32 m_wrapT; 1110 deUint32 m_wrapR; 1111 deUint32 m_internalFormat; 1112 int m_width; 1113 int m_height; 1114 int m_depth; 1115 1116 glu::Texture3D* m_texture; 1117 TextureTestUtil::TextureRenderer m_renderer; 1118 }; 1119 1120 Texture3DMipmapCase::Texture3DMipmapCase (Context& context, const char* name, const char* desc, CoordType coordType, deUint32 minFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR, deUint32 format, int width, int height, int depth) 1121 : TestCase (context, name, desc) 1122 , m_coordType (coordType) 1123 , m_minFilter (minFilter) 1124 , m_wrapS (wrapS) 1125 , m_wrapT (wrapT) 1126 , m_wrapR (wrapR) 1127 , m_internalFormat (format) 1128 , m_width (width) 1129 , m_height (height) 1130 , m_depth (depth) 1131 , m_texture (DE_NULL) 1132 , m_renderer (context.getRenderContext(), m_context.getTestContext(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 1133 { 1134 } 1135 1136 Texture3DMipmapCase::~Texture3DMipmapCase (void) 1137 { 1138 Texture3DMipmapCase::deinit(); 1139 } 1140 1141 void Texture3DMipmapCase::init (void) 1142 { 1143 const tcu::TextureFormat& texFmt = glu::mapGLInternalFormat(m_internalFormat); 1144 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 1145 const tcu::Vec4& cScale = fmtInfo.lookupScale; 1146 const tcu::Vec4& cBias = fmtInfo.lookupBias; 1147 int numLevels = deLog2Floor32(de::max(de::max(m_width, m_height), m_depth))+1; 1148 1149 if (m_coordType == COORDTYPE_PROJECTED && m_context.getRenderTarget().getNumSamples() > 0) 1150 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config"); 1151 1152 m_texture = new glu::Texture3D(m_context.getRenderContext(), m_internalFormat, m_width, m_height, m_depth); 1153 1154 // Fill texture with colored grid. 1155 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 1156 { 1157 deUint32 step = 0xff / (numLevels-1); 1158 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 1159 deUint32 dec = 0xff - inc; 1160 deUint32 rgb = (0xff << 16) | (dec << 8) | inc; 1161 deUint32 color = 0xff000000 | rgb; 1162 1163 m_texture->getRefTexture().allocLevel(levelNdx); 1164 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec()*cScale + cBias); 1165 } 1166 1167 m_texture->upload(); 1168 } 1169 1170 void Texture3DMipmapCase::deinit (void) 1171 { 1172 delete m_texture; 1173 m_texture = DE_NULL; 1174 1175 m_renderer.clear(); 1176 } 1177 1178 static void getBasicTexCoord3D (std::vector<float>& dst, int cellNdx) 1179 { 1180 static const struct 1181 { 1182 float sScale; 1183 float sBias; 1184 float tScale; 1185 float tBias; 1186 float rScale; 1187 float rBias; 1188 } s_params[] = 1189 { 1190 // sScale sBias tScale tBias rScale rBias 1191 { 0.9f, -0.1f, 0.7f, 0.3f, 0.8f, 0.9f }, 1192 { 1.2f, -0.1f, 1.1f, 0.3f, 1.0f, 0.9f }, 1193 { 1.5f, 0.7f, 0.9f, -0.3f, 1.1f, 0.1f }, 1194 { 1.2f, 0.7f, -2.3f, -0.3f, 1.1f, 0.2f }, 1195 { 1.1f, 0.8f, -1.3f, -0.3f, 2.9f, 0.9f }, 1196 { 3.4f, 0.8f, 4.0f, 0.0f, -3.3f, -1.0f }, 1197 { -3.4f, -0.1f, -4.0f, 0.0f, -5.1f, 1.0f }, 1198 { -4.0f, -0.1f, 3.4f, 0.1f, 5.7f, 0.0f }, 1199 { -5.6f, 0.0f, 0.5f, 1.2f, 3.9f, 4.0f }, 1200 { 5.0f, -2.0f, 3.1f, 1.2f, 5.1f, 0.2f }, 1201 { 2.5f, -2.0f, 6.3f, 3.0f, 5.1f, 0.2f }, 1202 { -8.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f }, 1203 { 3.8f, 0.0f, 9.7f, 1.0f, 7.0f, 0.7f }, 1204 { 13.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f }, 1205 { 16.0f, 8.0f, 12.7f, 1.0f, 17.1f, 0.7f }, 1206 { 15.3f, 0.0f, 20.1f, 3.0f, 33.0f, 3.2f } 1207 }; 1208 1209 float sScale = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sScale; 1210 float sBias = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sBias; 1211 float tScale = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tScale; 1212 float tBias = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tBias; 1213 float rScale = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rScale; 1214 float rBias = s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rBias; 1215 1216 dst.resize(3*4); 1217 1218 dst[0] = sBias; dst[ 1] = tBias; dst[ 2] = rBias; 1219 dst[3] = sBias; dst[ 4] = tBias+tScale; dst[ 5] = rBias+rScale*0.5f; 1220 dst[6] = sBias+sScale; dst[ 7] = tBias; dst[ 8] = rBias+rScale*0.5f; 1221 dst[9] = sBias+sScale; dst[10] = tBias+tScale; dst[11] = rBias+rScale; 1222 } 1223 1224 static void getAffineTexCoord3D (std::vector<float>& dst, int cellNdx) 1225 { 1226 // Use basic coords as base. 1227 getBasicTexCoord3D(dst, cellNdx); 1228 1229 // Rotate based on cell index. 1230 float angleX = 0.0f + 2.0f*DE_PI * ((float)cellNdx / 16.0f); 1231 float angleY = 1.0f + 2.0f*DE_PI * ((float)cellNdx / 32.0f); 1232 tcu::Mat3 rotMatrix = tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY); 1233 1234 Vec3 p0 = rotMatrix * Vec3(dst[0], dst[ 1], dst[ 2]); 1235 Vec3 p1 = rotMatrix * Vec3(dst[3], dst[ 4], dst[ 5]); 1236 Vec3 p2 = rotMatrix * Vec3(dst[6], dst[ 7], dst[ 8]); 1237 Vec3 p3 = rotMatrix * Vec3(dst[9], dst[10], dst[11]); 1238 1239 dst[0] = p0.x(); dst[ 1] = p0.y(); dst[ 2] = p0.z(); 1240 dst[3] = p1.x(); dst[ 4] = p1.y(); dst[ 5] = p1.z(); 1241 dst[6] = p2.x(); dst[ 7] = p2.y(); dst[ 8] = p2.z(); 1242 dst[9] = p3.x(); dst[10] = p3.y(); dst[11] = p3.z(); 1243 } 1244 1245 Texture3DMipmapCase::IterateResult Texture3DMipmapCase::iterate (void) 1246 { 1247 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1248 1249 const tcu::Texture3D& refTexture = m_texture->getRefTexture(); 1250 const tcu::TextureFormat& texFmt = refTexture.getFormat(); 1251 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 1252 const int texWidth = refTexture.getWidth(); 1253 const int texHeight = refTexture.getHeight(); 1254 const deUint32 magFilter = GL_NEAREST; 1255 1256 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 1257 const RandomViewport viewport (renderTarget, texWidth*4, texHeight*4, deStringHash(getName())); 1258 1259 const bool isProjected = m_coordType == COORDTYPE_PROJECTED; 1260 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS; 1261 1262 // Viewport is divided into 4x4 grid. 1263 const int gridWidth = 4; 1264 const int gridHeight = 4; 1265 const int cellWidth = viewport.width / gridWidth; 1266 const int cellHeight = viewport.height / gridHeight; 1267 1268 ReferenceParams sampleParams (TEXTURETYPE_3D); 1269 1270 tcu::Surface renderedFrame (viewport.width, viewport.height); 1271 vector<float> texCoord; 1272 1273 // Sampling parameters. 1274 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_wrapR, m_minFilter, magFilter); 1275 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(texFmt); 1276 sampleParams.colorBias = fmtInfo.lookupBias; 1277 sampleParams.colorScale = fmtInfo.lookupScale; 1278 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0); 1279 1280 // Bind texture and setup sampler parameters. 1281 gl.bindTexture (GL_TEXTURE_3D, m_texture->getGLTexture()); 1282 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, m_wrapS); 1283 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, m_wrapT); 1284 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, m_wrapR); 1285 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_minFilter); 1286 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, magFilter); 1287 1288 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 1289 1290 // Bias values. 1291 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f }; 1292 1293 // Projection values. 1294 static const Vec4 s_projections[] = 1295 { 1296 Vec4(1.2f, 1.0f, 0.7f, 1.0f), 1297 Vec4(1.3f, 0.8f, 0.6f, 2.0f), 1298 Vec4(0.8f, 1.0f, 1.7f, 0.6f), 1299 Vec4(1.2f, 1.0f, 1.7f, 1.5f) 1300 }; 1301 1302 // Render cells. 1303 for (int gridY = 0; gridY < gridHeight; gridY++) 1304 { 1305 for (int gridX = 0; gridX < gridWidth; gridX++) 1306 { 1307 const int curX = cellWidth*gridX; 1308 const int curY = cellHeight*gridY; 1309 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 1310 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 1311 const int cellNdx = gridY*gridWidth + gridX; 1312 1313 // Compute texcoord. 1314 switch (m_coordType) 1315 { 1316 case COORDTYPE_BASIC_BIAS: // Fall-through. 1317 case COORDTYPE_PROJECTED: 1318 case COORDTYPE_BASIC: getBasicTexCoord3D (texCoord, cellNdx); break; 1319 case COORDTYPE_AFFINE: getAffineTexCoord3D (texCoord, cellNdx); break; 1320 default: DE_ASSERT(DE_FALSE); 1321 } 1322 1323 // Set projection. 1324 if (isProjected) 1325 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 1326 1327 // Set LOD bias. 1328 if (useLodBias) 1329 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 1330 1331 // Render with GL. 1332 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 1333 m_renderer.renderQuad(0, &texCoord[0], sampleParams); 1334 } 1335 } 1336 1337 // Read result. 1338 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess()); 1339 1340 // Compare and log 1341 { 1342 const tcu::PixelFormat& pixelFormat = m_context.getRenderTarget().getPixelFormat(); 1343 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR; 1344 tcu::Surface referenceFrame (viewport.width, viewport.height); 1345 tcu::Surface errorMask (viewport.width, viewport.height); 1346 tcu::LookupPrecision lookupPrec; 1347 tcu::LodPrecision lodPrec; 1348 int numFailedPixels = 0; 1349 1350 lookupPrec.coordBits = tcu::IVec3(20, 20, 20); 1351 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored. 1352 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0))); 1353 lookupPrec.colorMask = getCompareMask(pixelFormat); 1354 lodPrec.derivateBits = 10; 1355 lodPrec.lodBits = isProjected ? 6 : 8; 1356 1357 for (int gridY = 0; gridY < gridHeight; gridY++) 1358 { 1359 for (int gridX = 0; gridX < gridWidth; gridX++) 1360 { 1361 const int curX = cellWidth*gridX; 1362 const int curY = cellHeight*gridY; 1363 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 1364 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 1365 const int cellNdx = gridY*gridWidth + gridX; 1366 1367 switch (m_coordType) 1368 { 1369 case COORDTYPE_BASIC_BIAS: // Fall-through. 1370 case COORDTYPE_PROJECTED: 1371 case COORDTYPE_BASIC: getBasicTexCoord3D (texCoord, cellNdx); break; 1372 case COORDTYPE_AFFINE: getAffineTexCoord3D (texCoord, cellNdx); break; 1373 default: DE_ASSERT(DE_FALSE); 1374 } 1375 1376 if (isProjected) 1377 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 1378 1379 if (useLodBias) 1380 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 1381 1382 // Render ideal result 1383 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), 1384 refTexture, &texCoord[0], sampleParams); 1385 1386 // Compare this cell 1387 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 1388 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 1389 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 1390 m_texture->getRefTexture(), &texCoord[0], sampleParams, 1391 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 1392 } 1393 } 1394 1395 if (numFailedPixels > 0) 1396 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 1397 1398 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 1399 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 1400 1401 if (numFailedPixels > 0) 1402 { 1403 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 1404 << TestLog::Image("ErrorMask", "Error mask", errorMask); 1405 } 1406 1407 m_testCtx.getLog() << TestLog::EndImageSet; 1408 1409 { 1410 const bool isOk = numFailedPixels == 0; 1411 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 1412 isOk ? "Pass" : "Image verification failed"); 1413 } 1414 } 1415 1416 return STOP; 1417 } 1418 1419 // Texture2DLodControlCase + test cases 1420 1421 class Texture2DLodControlCase : public TestCase 1422 { 1423 public: 1424 1425 Texture2DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter); 1426 ~Texture2DLodControlCase (void); 1427 1428 void init (void); 1429 void deinit (void); 1430 IterateResult iterate (void); 1431 1432 protected: 1433 virtual void setTextureParams (int cellNdx) = DE_NULL; 1434 virtual void getReferenceParams (ReferenceParams& params, int cellNdx) = DE_NULL; 1435 1436 const int m_texWidth; 1437 const int m_texHeight; 1438 1439 private: 1440 Texture2DLodControlCase (const Texture2DLodControlCase& other); 1441 Texture2DLodControlCase& operator= (const Texture2DLodControlCase& other); 1442 1443 deUint32 m_minFilter; 1444 1445 glu::Texture2D* m_texture; 1446 TextureTestUtil::TextureRenderer m_renderer; 1447 }; 1448 1449 Texture2DLodControlCase::Texture2DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1450 : TestCase (context, name, desc) 1451 , m_texWidth (64) 1452 , m_texHeight (64) 1453 , m_minFilter (minFilter) 1454 , m_texture (DE_NULL) 1455 , m_renderer (context.getRenderContext(), m_context.getTestContext(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 1456 { 1457 } 1458 1459 Texture2DLodControlCase::~Texture2DLodControlCase (void) 1460 { 1461 Texture2DLodControlCase::deinit(); 1462 } 1463 1464 void Texture2DLodControlCase::init (void) 1465 { 1466 const deUint32 format = GL_RGBA8; 1467 int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight))+1; 1468 1469 m_texture = new glu::Texture2D(m_context.getRenderContext(), format, m_texWidth, m_texHeight); 1470 1471 // Fill texture with colored grid. 1472 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 1473 { 1474 deUint32 step = 0xff / (numLevels-1); 1475 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 1476 deUint32 dec = 0xff - inc; 1477 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff; 1478 deUint32 color = 0xff000000 | rgb; 1479 1480 m_texture->getRefTexture().allocLevel(levelNdx); 1481 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec()); 1482 } 1483 } 1484 1485 void Texture2DLodControlCase::deinit (void) 1486 { 1487 delete m_texture; 1488 m_texture = DE_NULL; 1489 1490 m_renderer.clear(); 1491 } 1492 1493 Texture2DLodControlCase::IterateResult Texture2DLodControlCase::iterate (void) 1494 { 1495 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1496 1497 const deUint32 wrapS = GL_REPEAT; 1498 const deUint32 wrapT = GL_REPEAT; 1499 const deUint32 magFilter = GL_NEAREST; 1500 1501 const tcu::Texture2D& refTexture = m_texture->getRefTexture(); 1502 const int texWidth = refTexture.getWidth(); 1503 const int texHeight = refTexture.getHeight(); 1504 1505 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 1506 const RandomViewport viewport (renderTarget, texWidth*4, texHeight*4, deStringHash(getName())); 1507 1508 ReferenceParams sampleParams (gls::TextureTestUtil::TEXTURETYPE_2D, glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter)); 1509 vector<float> texCoord; 1510 tcu::Surface renderedFrame (viewport.width, viewport.height); 1511 1512 // Viewport is divided into 4x4 grid. 1513 const int gridWidth = 4; 1514 const int gridHeight = 4; 1515 const int cellWidth = viewport.width / gridWidth; 1516 const int cellHeight = viewport.height / gridHeight; 1517 1518 // Upload texture data. 1519 m_texture->upload(); 1520 1521 // Bind gradient texture and setup sampler parameters. 1522 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture()); 1523 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 1524 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 1525 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 1526 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); 1527 1528 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 1529 1530 // Render cells. 1531 for (int gridY = 0; gridY < gridHeight; gridY++) 1532 { 1533 for (int gridX = 0; gridX < gridWidth; gridX++) 1534 { 1535 int curX = cellWidth*gridX; 1536 int curY = cellHeight*gridY; 1537 int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 1538 int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 1539 int cellNdx = gridY*gridWidth + gridX; 1540 1541 // Compute texcoord. 1542 getBasicTexCoord2D(texCoord, cellNdx); 1543 1544 // Render with GL. 1545 setTextureParams(cellNdx); 1546 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 1547 m_renderer.renderQuad(0, &texCoord[0], sampleParams); 1548 } 1549 } 1550 1551 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess()); 1552 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels"); 1553 1554 // Compare and log. 1555 { 1556 const tcu::PixelFormat& pixelFormat = m_context.getRenderTarget().getPixelFormat(); 1557 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR; 1558 tcu::Surface referenceFrame (viewport.width, viewport.height); 1559 tcu::Surface errorMask (viewport.width, viewport.height); 1560 tcu::LookupPrecision lookupPrec; 1561 tcu::LodPrecision lodPrec; 1562 int numFailedPixels = 0; 1563 1564 lookupPrec.coordBits = tcu::IVec3(20, 20, 0); 1565 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored. 1566 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0))); 1567 lookupPrec.colorMask = getCompareMask(pixelFormat); 1568 lodPrec.derivateBits = 10; 1569 lodPrec.lodBits = 8; 1570 1571 for (int gridY = 0; gridY < gridHeight; gridY++) 1572 { 1573 for (int gridX = 0; gridX < gridWidth; gridX++) 1574 { 1575 const int curX = cellWidth*gridX; 1576 const int curY = cellHeight*gridY; 1577 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 1578 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 1579 const int cellNdx = gridY*gridWidth + gridX; 1580 1581 getBasicTexCoord2D(texCoord, cellNdx); 1582 getReferenceParams(sampleParams, cellNdx); 1583 1584 // Render ideal result 1585 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), 1586 refTexture, &texCoord[0], sampleParams); 1587 1588 // Compare this cell 1589 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 1590 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 1591 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 1592 m_texture->getRefTexture(), &texCoord[0], sampleParams, 1593 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 1594 } 1595 } 1596 1597 if (numFailedPixels > 0) 1598 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 1599 1600 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 1601 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 1602 1603 if (numFailedPixels > 0) 1604 { 1605 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 1606 << TestLog::Image("ErrorMask", "Error mask", errorMask); 1607 } 1608 1609 m_testCtx.getLog() << TestLog::EndImageSet; 1610 1611 { 1612 const bool isOk = numFailedPixels == 0; 1613 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 1614 isOk ? "Pass" : "Image verification failed"); 1615 } 1616 } 1617 1618 return STOP; 1619 } 1620 1621 class Texture2DMinLodCase : public Texture2DLodControlCase 1622 { 1623 public: 1624 Texture2DMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1625 : Texture2DLodControlCase(context, name, desc, minFilter) 1626 { 1627 } 1628 1629 protected: 1630 void setTextureParams (int cellNdx) 1631 { 1632 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1633 gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx)); 1634 } 1635 1636 void getReferenceParams (ReferenceParams& params, int cellNdx) 1637 { 1638 params.minLod = getMinLodForCell(cellNdx); 1639 } 1640 }; 1641 1642 class Texture2DMaxLodCase : public Texture2DLodControlCase 1643 { 1644 public: 1645 Texture2DMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1646 : Texture2DLodControlCase(context, name, desc, minFilter) 1647 { 1648 } 1649 1650 protected: 1651 void setTextureParams (int cellNdx) 1652 { 1653 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1654 gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx)); 1655 } 1656 1657 void getReferenceParams (ReferenceParams& params, int cellNdx) 1658 { 1659 params.maxLod = getMaxLodForCell(cellNdx); 1660 } 1661 }; 1662 1663 class Texture2DBaseLevelCase : public Texture2DLodControlCase 1664 { 1665 public: 1666 Texture2DBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1667 : Texture2DLodControlCase(context, name, desc, minFilter) 1668 { 1669 } 1670 1671 protected: 1672 int getBaseLevel (int cellNdx) const 1673 { 1674 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight))+1; 1675 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0xac2f274a) % numLevels; 1676 1677 return baseLevel; 1678 } 1679 1680 void setTextureParams (int cellNdx) 1681 { 1682 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1683 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx)); 1684 } 1685 1686 void getReferenceParams (ReferenceParams& params, int cellNdx) 1687 { 1688 params.baseLevel = getBaseLevel(cellNdx); 1689 } 1690 }; 1691 1692 class Texture2DMaxLevelCase : public Texture2DLodControlCase 1693 { 1694 public: 1695 Texture2DMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1696 : Texture2DLodControlCase(context, name, desc, minFilter) 1697 { 1698 } 1699 1700 protected: 1701 int getMaxLevel (int cellNdx) const 1702 { 1703 const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight))+1; 1704 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x82cfa4e) % numLevels; 1705 1706 return maxLevel; 1707 } 1708 1709 void setTextureParams (int cellNdx) 1710 { 1711 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1712 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx)); 1713 } 1714 1715 void getReferenceParams (ReferenceParams& params, int cellNdx) 1716 { 1717 params.maxLevel = getMaxLevel(cellNdx); 1718 } 1719 }; 1720 1721 // TextureCubeLodControlCase + test cases 1722 1723 class TextureCubeLodControlCase : public TestCase 1724 { 1725 public: 1726 1727 TextureCubeLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter); 1728 ~TextureCubeLodControlCase (void); 1729 1730 void init (void); 1731 void deinit (void); 1732 IterateResult iterate (void); 1733 1734 protected: 1735 virtual void setTextureParams (int cellNdx) = DE_NULL; 1736 virtual void getReferenceParams (ReferenceParams& params, int cellNdx) = DE_NULL; 1737 1738 const int m_texSize; 1739 1740 private: 1741 TextureCubeLodControlCase (const TextureCubeLodControlCase& other); 1742 TextureCubeLodControlCase& operator= (const TextureCubeLodControlCase& other); 1743 1744 deUint32 m_minFilter; 1745 1746 glu::TextureCube* m_texture; 1747 TextureTestUtil::TextureRenderer m_renderer; 1748 }; 1749 1750 TextureCubeLodControlCase::TextureCubeLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1751 : TestCase (context, name, desc) 1752 , m_texSize (64) 1753 , m_minFilter (minFilter) 1754 , m_texture (DE_NULL) 1755 , m_renderer (context.getRenderContext(), context.getTestContext(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 1756 { 1757 } 1758 1759 TextureCubeLodControlCase::~TextureCubeLodControlCase (void) 1760 { 1761 deinit(); 1762 } 1763 1764 void TextureCubeLodControlCase::init (void) 1765 { 1766 const deUint32 format = GL_RGBA8; 1767 const int numLevels = deLog2Floor32(m_texSize)+1; 1768 1769 m_texture = new glu::TextureCube(m_context.getRenderContext(), format, m_texSize); 1770 1771 // Fill texture with colored grid. 1772 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 1773 { 1774 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 1775 { 1776 deUint32 step = 0xff / (numLevels-1); 1777 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 1778 deUint32 dec = 0xff - inc; 1779 deUint32 rgb = 0; 1780 1781 switch (faceNdx) 1782 { 1783 case 0: rgb = (inc << 16) | (dec << 8) | 255; break; 1784 case 1: rgb = (255 << 16) | (inc << 8) | dec; break; 1785 case 2: rgb = (dec << 16) | (255 << 8) | inc; break; 1786 case 3: rgb = (dec << 16) | (inc << 8) | 255; break; 1787 case 4: rgb = (255 << 16) | (dec << 8) | inc; break; 1788 case 5: rgb = (inc << 16) | (255 << 8) | dec; break; 1789 } 1790 1791 deUint32 color = 0xff000000 | rgb; 1792 1793 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx); 1794 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec()); 1795 } 1796 } 1797 } 1798 1799 void TextureCubeLodControlCase::deinit (void) 1800 { 1801 delete m_texture; 1802 m_texture = DE_NULL; 1803 1804 m_renderer.clear(); 1805 } 1806 1807 TextureCubeLodControlCase::IterateResult TextureCubeLodControlCase::iterate (void) 1808 { 1809 const deUint32 wrapS = GL_CLAMP_TO_EDGE; 1810 const deUint32 wrapT = GL_CLAMP_TO_EDGE; 1811 const deUint32 magFilter = GL_NEAREST; 1812 1813 const int texWidth = m_texture->getRefTexture().getSize(); 1814 const int texHeight = m_texture->getRefTexture().getSize(); 1815 1816 const int defViewportWidth = texWidth*2; 1817 const int defViewportHeight = texHeight*2; 1818 1819 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1820 const RandomViewport viewport (m_context.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 1821 1822 vector<float> texCoord; 1823 1824 tcu::Surface renderedFrame (viewport.width, viewport.height); 1825 1826 // Upload texture data. 1827 m_texture->upload(); 1828 1829 // Bind gradient texture and setup sampler parameters. 1830 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture()); 1831 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS); 1832 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT); 1833 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter); 1834 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter); 1835 1836 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 1837 1838 // Compute grid. 1839 vector<tcu::IVec4> gridLayout; 1840 computeGridLayout(gridLayout, viewport.width, viewport.height); 1841 1842 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++) 1843 { 1844 const int curX = gridLayout[cellNdx].x(); 1845 const int curY = gridLayout[cellNdx].y(); 1846 const int curW = gridLayout[cellNdx].z(); 1847 const int curH = gridLayout[cellNdx].w(); 1848 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST); 1849 RenderParams params (TEXTURETYPE_CUBE); 1850 1851 TextureTestUtil::computeQuadTexCoordCube(texCoord, cubeFace); 1852 1853 setTextureParams(cellNdx); 1854 1855 // Render with GL. 1856 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 1857 m_renderer.renderQuad(0, &texCoord[0], params); 1858 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 1859 } 1860 1861 // Read result. 1862 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess()); 1863 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels"); 1864 1865 // Render reference and compare 1866 { 1867 tcu::Surface referenceFrame (viewport.width, viewport.height); 1868 tcu::Surface errorMask (viewport.width, viewport.height); 1869 int numFailedPixels = 0; 1870 ReferenceParams params (TEXTURETYPE_CUBE); 1871 tcu::LookupPrecision lookupPrec; 1872 tcu::LodPrecision lodPrec; 1873 1874 // Params for rendering reference 1875 params.sampler = glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter); 1876 params.sampler.seamlessCubeMap = true; 1877 params.lodMode = LODMODE_EXACT; 1878 1879 // Comparison parameters 1880 lookupPrec.colorMask = getCompareMask(m_context.getRenderTarget().getPixelFormat()); 1881 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(m_context.getRenderTarget().getPixelFormat())-2, IVec4(0))); 1882 lookupPrec.coordBits = tcu::IVec3(10); 1883 lookupPrec.uvwBits = tcu::IVec3(5,5,0); 1884 lodPrec.derivateBits = 10; 1885 lodPrec.lodBits = 6; 1886 1887 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++) 1888 { 1889 const int curX = gridLayout[cellNdx].x(); 1890 const int curY = gridLayout[cellNdx].y(); 1891 const int curW = gridLayout[cellNdx].z(); 1892 const int curH = gridLayout[cellNdx].w(); 1893 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST); 1894 1895 computeQuadTexCoordCube(texCoord, cubeFace); 1896 getReferenceParams(params, cellNdx); 1897 1898 // Render ideal reference. 1899 { 1900 SurfaceAccess idealDst(referenceFrame, m_context.getRenderTarget().getPixelFormat(), curX, curY, curW, curH); 1901 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params); 1902 } 1903 1904 // Compare this cell 1905 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 1906 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 1907 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 1908 m_texture->getRefTexture(), &texCoord[0], params, 1909 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 1910 } 1911 1912 if (numFailedPixels > 0) 1913 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 1914 1915 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 1916 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 1917 1918 if (numFailedPixels > 0) 1919 { 1920 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 1921 << TestLog::Image("ErrorMask", "Error mask", errorMask); 1922 } 1923 1924 m_testCtx.getLog() << TestLog::EndImageSet; 1925 1926 { 1927 const bool isOk = numFailedPixels == 0; 1928 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 1929 isOk ? "Pass" : "Image verification failed"); 1930 } 1931 } 1932 1933 return STOP; 1934 } 1935 1936 class TextureCubeMinLodCase : public TextureCubeLodControlCase 1937 { 1938 public: 1939 TextureCubeMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1940 : TextureCubeLodControlCase(context, name, desc, minFilter) 1941 { 1942 } 1943 1944 protected: 1945 void setTextureParams (int cellNdx) 1946 { 1947 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1948 gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx)); 1949 } 1950 1951 void getReferenceParams (ReferenceParams& params, int cellNdx) 1952 { 1953 params.minLod = getMinLodForCell(cellNdx); 1954 } 1955 }; 1956 1957 class TextureCubeMaxLodCase : public TextureCubeLodControlCase 1958 { 1959 public: 1960 TextureCubeMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1961 : TextureCubeLodControlCase(context, name, desc, minFilter) 1962 { 1963 } 1964 1965 protected: 1966 void setTextureParams (int cellNdx) 1967 { 1968 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1969 gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx)); 1970 } 1971 1972 void getReferenceParams (ReferenceParams& params, int cellNdx) 1973 { 1974 params.maxLod = getMaxLodForCell(cellNdx); 1975 } 1976 }; 1977 1978 class TextureCubeBaseLevelCase : public TextureCubeLodControlCase 1979 { 1980 public: 1981 TextureCubeBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 1982 : TextureCubeLodControlCase(context, name, desc, minFilter) 1983 { 1984 } 1985 1986 protected: 1987 int getBaseLevel (int cellNdx) const 1988 { 1989 const int numLevels = deLog2Floor32(m_texSize)+1; 1990 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x23fae13) % numLevels; 1991 1992 return baseLevel; 1993 } 1994 1995 void setTextureParams (int cellNdx) 1996 { 1997 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1998 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx)); 1999 } 2000 2001 void getReferenceParams (ReferenceParams& params, int cellNdx) 2002 { 2003 params.baseLevel = getBaseLevel(cellNdx); 2004 } 2005 }; 2006 2007 class TextureCubeMaxLevelCase : public TextureCubeLodControlCase 2008 { 2009 public: 2010 TextureCubeMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 2011 : TextureCubeLodControlCase(context, name, desc, minFilter) 2012 { 2013 } 2014 2015 protected: 2016 int getMaxLevel (int cellNdx) const 2017 { 2018 const int numLevels = deLog2Floor32(m_texSize)+1; 2019 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x974e21) % numLevels; 2020 2021 return maxLevel; 2022 } 2023 2024 void setTextureParams (int cellNdx) 2025 { 2026 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2027 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx)); 2028 } 2029 2030 void getReferenceParams (ReferenceParams& params, int cellNdx) 2031 { 2032 params.maxLevel = getMaxLevel(cellNdx); 2033 } 2034 }; 2035 2036 // Texture3DLodControlCase + test cases 2037 2038 class Texture3DLodControlCase : public TestCase 2039 { 2040 public: 2041 2042 Texture3DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter); 2043 ~Texture3DLodControlCase (void); 2044 2045 void init (void); 2046 void deinit (void); 2047 IterateResult iterate (void); 2048 2049 protected: 2050 virtual void setTextureParams (int cellNdx) = DE_NULL; 2051 virtual void getReferenceParams (ReferenceParams& params, int cellNdx) = DE_NULL; 2052 2053 const int m_texWidth; 2054 const int m_texHeight; 2055 const int m_texDepth; 2056 2057 private: 2058 Texture3DLodControlCase (const Texture3DLodControlCase& other); 2059 Texture3DLodControlCase& operator= (const Texture3DLodControlCase& other); 2060 2061 deUint32 m_minFilter; 2062 2063 glu::Texture3D* m_texture; 2064 TextureTestUtil::TextureRenderer m_renderer; 2065 }; 2066 2067 Texture3DLodControlCase::Texture3DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 2068 : TestCase (context, name, desc) 2069 , m_texWidth (32) 2070 , m_texHeight (32) 2071 , m_texDepth (32) 2072 , m_minFilter (minFilter) 2073 , m_texture (DE_NULL) 2074 , m_renderer (context.getRenderContext(), m_context.getTestContext(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP) 2075 { 2076 } 2077 2078 Texture3DLodControlCase::~Texture3DLodControlCase (void) 2079 { 2080 Texture3DLodControlCase::deinit(); 2081 } 2082 2083 void Texture3DLodControlCase::init (void) 2084 { 2085 const deUint32 format = GL_RGBA8; 2086 const tcu::TextureFormat& texFmt = glu::mapGLInternalFormat(format); 2087 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 2088 const tcu::Vec4& cScale = fmtInfo.lookupScale; 2089 const tcu::Vec4& cBias = fmtInfo.lookupBias; 2090 int numLevels = deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth))+1; 2091 2092 m_texture = new glu::Texture3D(m_context.getRenderContext(), format, m_texWidth, m_texHeight, m_texDepth); 2093 2094 // Fill texture with colored grid. 2095 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 2096 { 2097 deUint32 step = 0xff / (numLevels-1); 2098 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 2099 deUint32 dec = 0xff - inc; 2100 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff; 2101 deUint32 color = 0xff000000 | rgb; 2102 2103 m_texture->getRefTexture().allocLevel(levelNdx); 2104 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec()*cScale + cBias); 2105 } 2106 2107 m_texture->upload(); 2108 } 2109 2110 void Texture3DLodControlCase::deinit (void) 2111 { 2112 delete m_texture; 2113 m_texture = DE_NULL; 2114 2115 m_renderer.clear(); 2116 } 2117 2118 Texture3DLodControlCase::IterateResult Texture3DLodControlCase::iterate (void) 2119 { 2120 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2121 2122 const deUint32 wrapS = GL_CLAMP_TO_EDGE; 2123 const deUint32 wrapT = GL_CLAMP_TO_EDGE; 2124 const deUint32 wrapR = GL_CLAMP_TO_EDGE; 2125 const deUint32 magFilter = GL_NEAREST; 2126 const tcu::Texture3D& refTexture = m_texture->getRefTexture(); 2127 const tcu::TextureFormat& texFmt = refTexture.getFormat(); 2128 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 2129 const int texWidth = refTexture.getWidth(); 2130 const int texHeight = refTexture.getHeight(); 2131 2132 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget(); 2133 const RandomViewport viewport (renderTarget, texWidth*4, texHeight*4, deStringHash(getName())); 2134 2135 // Viewport is divided into 4x4 grid. 2136 const int gridWidth = 4; 2137 const int gridHeight = 4; 2138 const int cellWidth = viewport.width / gridWidth; 2139 const int cellHeight = viewport.height / gridHeight; 2140 2141 tcu::Surface renderedFrame (viewport.width, viewport.height); 2142 vector<float> texCoord; 2143 ReferenceParams sampleParams (gls::TextureTestUtil::TEXTURETYPE_3D); 2144 2145 // Sampling parameters. 2146 sampleParams.sampler = glu::mapGLSampler(wrapS, wrapT, wrapR, m_minFilter, magFilter); 2147 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(texFmt); 2148 sampleParams.colorBias = fmtInfo.lookupBias; 2149 sampleParams.colorScale = fmtInfo.lookupScale; 2150 2151 // Bind texture and setup sampler parameters. 2152 gl.bindTexture (GL_TEXTURE_3D, m_texture->getGLTexture()); 2153 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrapS); 2154 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrapT); 2155 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrapR); 2156 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_minFilter); 2157 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, magFilter); 2158 2159 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 2160 2161 // Render cells. 2162 for (int gridY = 0; gridY < gridHeight; gridY++) 2163 { 2164 for (int gridX = 0; gridX < gridWidth; gridX++) 2165 { 2166 int curX = cellWidth*gridX; 2167 int curY = cellHeight*gridY; 2168 int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 2169 int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 2170 int cellNdx = gridY*gridWidth + gridX; 2171 2172 // Compute texcoord. 2173 getBasicTexCoord3D(texCoord, cellNdx); 2174 2175 setTextureParams(cellNdx); 2176 2177 // Render with GL. 2178 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 2179 m_renderer.renderQuad(0, &texCoord[0], sampleParams); 2180 } 2181 } 2182 2183 // Read result. 2184 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess()); 2185 2186 // Compare and log 2187 { 2188 const tcu::PixelFormat& pixelFormat = m_context.getRenderTarget().getPixelFormat(); 2189 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR; 2190 tcu::Surface referenceFrame (viewport.width, viewport.height); 2191 tcu::Surface errorMask (viewport.width, viewport.height); 2192 tcu::LookupPrecision lookupPrec; 2193 tcu::LodPrecision lodPrec; 2194 int numFailedPixels = 0; 2195 2196 lookupPrec.coordBits = tcu::IVec3(20, 20, 20); 2197 lookupPrec.uvwBits = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored. 2198 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0))); 2199 lookupPrec.colorMask = getCompareMask(pixelFormat); 2200 lodPrec.derivateBits = 10; 2201 lodPrec.lodBits = 8; 2202 2203 for (int gridY = 0; gridY < gridHeight; gridY++) 2204 { 2205 for (int gridX = 0; gridX < gridWidth; gridX++) 2206 { 2207 const int curX = cellWidth*gridX; 2208 const int curY = cellHeight*gridY; 2209 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 2210 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 2211 const int cellNdx = gridY*gridWidth + gridX; 2212 2213 getBasicTexCoord3D(texCoord, cellNdx); 2214 getReferenceParams(sampleParams, cellNdx); 2215 2216 // Render ideal result 2217 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), 2218 refTexture, &texCoord[0], sampleParams); 2219 2220 // Compare this cell 2221 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 2222 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 2223 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 2224 m_texture->getRefTexture(), &texCoord[0], sampleParams, 2225 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 2226 } 2227 } 2228 2229 if (numFailedPixels > 0) 2230 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 2231 2232 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 2233 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 2234 2235 if (numFailedPixels > 0) 2236 { 2237 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 2238 << TestLog::Image("ErrorMask", "Error mask", errorMask); 2239 } 2240 2241 m_testCtx.getLog() << TestLog::EndImageSet; 2242 2243 { 2244 const bool isOk = numFailedPixels == 0; 2245 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 2246 isOk ? "Pass" : "Image verification failed"); 2247 } 2248 } 2249 2250 return STOP; 2251 } 2252 2253 class Texture3DMinLodCase : public Texture3DLodControlCase 2254 { 2255 public: 2256 Texture3DMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 2257 : Texture3DLodControlCase(context, name, desc, minFilter) 2258 { 2259 } 2260 2261 protected: 2262 void setTextureParams (int cellNdx) 2263 { 2264 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2265 gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx)); 2266 } 2267 2268 void getReferenceParams (ReferenceParams& params, int cellNdx) 2269 { 2270 params.minLod = getMinLodForCell(cellNdx); 2271 } 2272 }; 2273 2274 class Texture3DMaxLodCase : public Texture3DLodControlCase 2275 { 2276 public: 2277 Texture3DMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 2278 : Texture3DLodControlCase(context, name, desc, minFilter) 2279 { 2280 } 2281 2282 protected: 2283 void setTextureParams (int cellNdx) 2284 { 2285 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2286 gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx)); 2287 } 2288 2289 void getReferenceParams (ReferenceParams& params, int cellNdx) 2290 { 2291 params.maxLod = getMaxLodForCell(cellNdx); 2292 } 2293 }; 2294 2295 class Texture3DBaseLevelCase : public Texture3DLodControlCase 2296 { 2297 public: 2298 Texture3DBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 2299 : Texture3DLodControlCase(context, name, desc, minFilter) 2300 { 2301 } 2302 2303 protected: 2304 int getBaseLevel (int cellNdx) const 2305 { 2306 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1; 2307 const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x7347e9) % numLevels; 2308 2309 return baseLevel; 2310 } 2311 2312 void setTextureParams (int cellNdx) 2313 { 2314 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2315 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx)); 2316 } 2317 2318 void getReferenceParams (ReferenceParams& params, int cellNdx) 2319 { 2320 params.baseLevel = getBaseLevel(cellNdx); 2321 } 2322 }; 2323 2324 class Texture3DMaxLevelCase : public Texture3DLodControlCase 2325 { 2326 public: 2327 Texture3DMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter) 2328 : Texture3DLodControlCase(context, name, desc, minFilter) 2329 { 2330 } 2331 2332 protected: 2333 int getMaxLevel (int cellNdx) const 2334 { 2335 const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1; 2336 const int maxLevel = (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x9111e7) % numLevels; 2337 2338 return maxLevel; 2339 } 2340 2341 void setTextureParams (int cellNdx) 2342 { 2343 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2344 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx)); 2345 } 2346 2347 void getReferenceParams (ReferenceParams& params, int cellNdx) 2348 { 2349 params.maxLevel = getMaxLevel(cellNdx); 2350 } 2351 }; 2352 2353 TextureMipmapTests::TextureMipmapTests (Context& context) 2354 : TestCaseGroup(context, "mipmap", "Mipmapping tests") 2355 { 2356 } 2357 2358 TextureMipmapTests::~TextureMipmapTests (void) 2359 { 2360 } 2361 2362 void TextureMipmapTests::init (void) 2363 { 2364 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Mipmapping"); 2365 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Mipmapping"); 2366 tcu::TestCaseGroup* group3D = new tcu::TestCaseGroup(m_testCtx, "3d", "3D Texture Mipmapping"); 2367 addChild(group2D); 2368 addChild(groupCube); 2369 addChild(group3D); 2370 2371 static const struct 2372 { 2373 const char* name; 2374 deUint32 mode; 2375 } wrapModes[] = 2376 { 2377 { "clamp", GL_CLAMP_TO_EDGE }, 2378 { "repeat", GL_REPEAT }, 2379 { "mirror", GL_MIRRORED_REPEAT } 2380 }; 2381 2382 static const struct 2383 { 2384 const char* name; 2385 deUint32 mode; 2386 } minFilterModes[] = 2387 { 2388 { "nearest_nearest", GL_NEAREST_MIPMAP_NEAREST }, 2389 { "linear_nearest", GL_LINEAR_MIPMAP_NEAREST }, 2390 { "nearest_linear", GL_NEAREST_MIPMAP_LINEAR }, 2391 { "linear_linear", GL_LINEAR_MIPMAP_LINEAR } 2392 }; 2393 2394 static const struct 2395 { 2396 CoordType type; 2397 const char* name; 2398 const char* desc; 2399 } coordTypes[] = 2400 { 2401 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" }, 2402 { COORDTYPE_AFFINE, "affine", "Mipmapping with affine coordinate transform" }, 2403 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" } 2404 }; 2405 2406 static const struct 2407 { 2408 const char* name; 2409 deUint32 format; 2410 deUint32 dataType; 2411 } formats[] = 2412 { 2413 { "a8", GL_ALPHA, GL_UNSIGNED_BYTE }, 2414 { "l8", GL_LUMINANCE, GL_UNSIGNED_BYTE }, 2415 { "la88", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE }, 2416 { "rgb565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, 2417 { "rgb888", GL_RGB, GL_UNSIGNED_BYTE }, 2418 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, 2419 { "rgba5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, 2420 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE } 2421 }; 2422 2423 static const struct 2424 { 2425 const char* name; 2426 deUint32 hint; 2427 } genHints[] = 2428 { 2429 { "fastest", GL_FASTEST }, 2430 { "nicest", GL_NICEST } 2431 }; 2432 2433 static const struct 2434 { 2435 const char* name; 2436 int width; 2437 int height; 2438 } tex2DSizes[] = 2439 { 2440 { DE_NULL, 64, 64 }, // Default. 2441 { "npot", 63, 57 }, 2442 { "non_square", 32, 64 } 2443 }; 2444 2445 static const struct 2446 { 2447 const char* name; 2448 int width; 2449 int height; 2450 int depth; 2451 } tex3DSizes[] = 2452 { 2453 { DE_NULL, 32, 32, 32 }, // Default. 2454 { "npot", 33, 29, 27 } 2455 }; 2456 2457 const int cubeMapSize = 64; 2458 2459 static const struct 2460 { 2461 CoordType type; 2462 const char* name; 2463 const char* desc; 2464 } cubeCoordTypes[] = 2465 { 2466 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" }, 2467 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" }, 2468 { COORDTYPE_BASIC_BIAS, "bias", "User-supplied bias value" } 2469 }; 2470 2471 // 2D cases. 2472 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++) 2473 { 2474 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc); 2475 group2D->addChild(coordTypeGroup); 2476 2477 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2478 { 2479 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++) 2480 { 2481 // Add non_square variants to basic cases only. 2482 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1; 2483 2484 for (int size = 0; size < sizeEnd; size++) 2485 { 2486 std::ostringstream name; 2487 name << minFilterModes[minFilter].name 2488 << "_" << wrapModes[wrapMode].name; 2489 2490 if (tex2DSizes[size].name) 2491 name << "_" << tex2DSizes[size].name; 2492 2493 coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 2494 name.str().c_str(), "", 2495 coordTypes[coordType].type, 2496 minFilterModes[minFilter].mode, 2497 wrapModes[wrapMode].mode, 2498 wrapModes[wrapMode].mode, 2499 GL_RGBA, GL_UNSIGNED_BYTE, 2500 tex2DSizes[size].width, tex2DSizes[size].height)); 2501 } 2502 } 2503 } 2504 } 2505 2506 // 2D bias variants. 2507 { 2508 tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value"); 2509 group2D->addChild(biasGroup); 2510 2511 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2512 biasGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 2513 minFilterModes[minFilter].name, "", 2514 COORDTYPE_BASIC_BIAS, 2515 minFilterModes[minFilter].mode, 2516 GL_REPEAT, GL_REPEAT, 2517 GL_RGBA, GL_UNSIGNED_BYTE, 2518 tex2DSizes[0].width, tex2DSizes[0].height)); 2519 } 2520 2521 // 2D mipmap generation variants. 2522 { 2523 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests"); 2524 group2D->addChild(genMipmapGroup); 2525 2526 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++) 2527 { 2528 for (int size = 0; size < DE_LENGTH_OF_ARRAY(tex2DSizes); size++) 2529 { 2530 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++) 2531 { 2532 std::ostringstream name; 2533 name << formats[format].name; 2534 2535 if (tex2DSizes[size].name) 2536 name << "_" << tex2DSizes[size].name; 2537 2538 name << "_" << genHints[hint].name; 2539 2540 genMipmapGroup->addChild(new Texture2DGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", 2541 formats[format].format, formats[format].dataType, genHints[hint].hint, 2542 tex2DSizes[size].width, tex2DSizes[size].height)); 2543 } 2544 } 2545 } 2546 } 2547 2548 // 2D LOD controls. 2549 { 2550 // MIN_LOD 2551 tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod"); 2552 group2D->addChild(minLodGroup); 2553 2554 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2555 minLodGroup->addChild(new Texture2DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2556 2557 // MAX_LOD 2558 tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod"); 2559 group2D->addChild(maxLodGroup); 2560 2561 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2562 maxLodGroup->addChild(new Texture2DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2563 2564 // BASE_LEVEL 2565 tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level"); 2566 group2D->addChild(baseLevelGroup); 2567 2568 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2569 baseLevelGroup->addChild(new Texture2DBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2570 2571 // MAX_LEVEL 2572 tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level"); 2573 group2D->addChild(maxLevelGroup); 2574 2575 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2576 maxLevelGroup->addChild(new Texture2DMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2577 } 2578 2579 // Cubemap cases. 2580 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++) 2581 { 2582 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc); 2583 groupCube->addChild(coordTypeGroup); 2584 2585 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2586 { 2587 coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 2588 minFilterModes[minFilter].name, "", 2589 cubeCoordTypes[coordType].type, 2590 minFilterModes[minFilter].mode, 2591 GL_CLAMP_TO_EDGE, 2592 GL_CLAMP_TO_EDGE, 2593 GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize)); 2594 } 2595 } 2596 2597 // Cubemap mipmap generation variants. 2598 { 2599 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests"); 2600 groupCube->addChild(genMipmapGroup); 2601 2602 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++) 2603 { 2604 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++) 2605 { 2606 std::ostringstream name; 2607 name << formats[format].name 2608 << "_" << genHints[hint].name; 2609 2610 genMipmapGroup->addChild(new TextureCubeGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format, formats[format].dataType, genHints[hint].hint, cubeMapSize)); 2611 } 2612 } 2613 } 2614 2615 // Cubemap LOD controls. 2616 { 2617 // MIN_LOD 2618 tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod"); 2619 groupCube->addChild(minLodGroup); 2620 2621 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2622 minLodGroup->addChild(new TextureCubeMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2623 2624 // MAX_LOD 2625 tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod"); 2626 groupCube->addChild(maxLodGroup); 2627 2628 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2629 maxLodGroup->addChild(new TextureCubeMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2630 2631 // BASE_LEVEL 2632 tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level"); 2633 groupCube->addChild(baseLevelGroup); 2634 2635 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2636 baseLevelGroup->addChild(new TextureCubeBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2637 2638 // MAX_LEVEL 2639 tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level"); 2640 groupCube->addChild(maxLevelGroup); 2641 2642 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2643 maxLevelGroup->addChild(new TextureCubeMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2644 } 2645 2646 // 3D cases. 2647 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++) 2648 { 2649 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc); 2650 group3D->addChild(coordTypeGroup); 2651 2652 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2653 { 2654 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++) 2655 { 2656 // Add other size variants to basic cases only. 2657 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1; 2658 2659 for (int size = 0; size < sizeEnd; size++) 2660 { 2661 std::ostringstream name; 2662 name << minFilterModes[minFilter].name 2663 << "_" << wrapModes[wrapMode].name; 2664 2665 if (tex3DSizes[size].name) 2666 name << "_" << tex3DSizes[size].name; 2667 2668 coordTypeGroup->addChild(new Texture3DMipmapCase(m_context, 2669 name.str().c_str(), "", 2670 coordTypes[coordType].type, 2671 minFilterModes[minFilter].mode, 2672 wrapModes[wrapMode].mode, 2673 wrapModes[wrapMode].mode, 2674 wrapModes[wrapMode].mode, 2675 GL_RGBA8, 2676 tex3DSizes[size].width, tex3DSizes[size].height, tex3DSizes[size].depth)); 2677 } 2678 } 2679 } 2680 } 2681 2682 // 3D bias variants. 2683 { 2684 tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value"); 2685 group3D->addChild(biasGroup); 2686 2687 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2688 biasGroup->addChild(new Texture3DMipmapCase(m_context, 2689 minFilterModes[minFilter].name, "", 2690 COORDTYPE_BASIC_BIAS, 2691 minFilterModes[minFilter].mode, 2692 GL_REPEAT, GL_REPEAT, GL_REPEAT, 2693 GL_RGBA8, 2694 tex3DSizes[0].width, tex3DSizes[0].height, tex3DSizes[0].depth)); 2695 } 2696 2697 // 3D LOD controls. 2698 { 2699 // MIN_LOD 2700 tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod"); 2701 group3D->addChild(minLodGroup); 2702 2703 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2704 minLodGroup->addChild(new Texture3DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2705 2706 // MAX_LOD 2707 tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod"); 2708 group3D->addChild(maxLodGroup); 2709 2710 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2711 maxLodGroup->addChild(new Texture3DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2712 2713 // BASE_LEVEL 2714 tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level"); 2715 group3D->addChild(baseLevelGroup); 2716 2717 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2718 baseLevelGroup->addChild(new Texture3DBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2719 2720 // MAX_LEVEL 2721 tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level"); 2722 group3D->addChild(maxLevelGroup); 2723 2724 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 2725 maxLevelGroup->addChild(new Texture3DMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode)); 2726 } 2727 } 2728 2729 } // Functional 2730 } // gles3 2731 } // deqp 2732