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