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