1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.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 "es2fTextureMipmapTests.hpp" 25 #include "glsTextureTestUtil.hpp" 26 #include "gluTexture.hpp" 27 #include "gluStrUtil.hpp" 28 #include "gluTextureUtil.hpp" 29 #include "gluPixelTransfer.hpp" 30 #include "tcuTestLog.hpp" 31 #include "tcuTextureUtil.hpp" 32 #include "tcuVector.hpp" 33 #include "tcuMatrix.hpp" 34 #include "tcuMatrixUtil.hpp" 35 #include "tcuTexLookupVerifier.hpp" 36 #include "tcuVectorUtil.hpp" 37 #include "deStringUtil.hpp" 38 #include "deRandom.hpp" 39 #include "glwFunctions.hpp" 40 #include "glwEnums.hpp" 41 42 namespace deqp 43 { 44 namespace gles2 45 { 46 namespace Functional 47 { 48 49 using tcu::TestLog; 50 using std::vector; 51 using std::string; 52 using tcu::Sampler; 53 using tcu::Vec2; 54 using tcu::Mat2; 55 using tcu::Vec4; 56 using tcu::IVec2; 57 using tcu::IVec4; 58 using namespace glu; 59 using namespace gls::TextureTestUtil; 60 61 enum CoordType 62 { 63 COORDTYPE_BASIC, //!< texCoord = translateScale(position). 64 COORDTYPE_BASIC_BIAS, //!< Like basic, but with bias values. 65 COORDTYPE_AFFINE, //!< texCoord = translateScaleRotateShear(position). 66 COORDTYPE_PROJECTED, //!< Projected coordinates, w != 1 67 68 COORDTYPE_LAST 69 }; 70 71 // Texture2DMipmapCase 72 73 class Texture2DMipmapCase : public tcu::TestCase 74 { 75 public: 76 77 Texture2DMipmapCase (tcu::TestContext& testCtx, 78 glu::RenderContext& renderCtx, 79 const glu::ContextInfo& renderCtxInfo, 80 const char* name, 81 const char* desc, 82 CoordType coordType, 83 deUint32 minFilter, 84 deUint32 wrapS, 85 deUint32 wrapT, 86 deUint32 format, 87 deUint32 dataType, 88 int width, 89 int height); 90 ~Texture2DMipmapCase (void); 91 92 void init (void); 93 void deinit (void); 94 IterateResult iterate (void); 95 96 private: 97 Texture2DMipmapCase (const Texture2DMipmapCase& other); 98 Texture2DMipmapCase& operator= (const Texture2DMipmapCase& other); 99 100 glu::RenderContext& m_renderCtx; 101 const glu::ContextInfo& m_renderCtxInfo; 102 103 CoordType m_coordType; 104 deUint32 m_minFilter; 105 deUint32 m_wrapS; 106 deUint32 m_wrapT; 107 deUint32 m_format; 108 deUint32 m_dataType; 109 int m_width; 110 int m_height; 111 112 glu::Texture2D* m_texture; 113 TextureRenderer m_renderer; 114 }; 115 116 Texture2DMipmapCase::Texture2DMipmapCase (tcu::TestContext& testCtx, 117 glu::RenderContext& renderCtx, 118 const glu::ContextInfo& renderCtxInfo, 119 const char* name, 120 const char* desc, 121 CoordType coordType, 122 deUint32 minFilter, 123 deUint32 wrapS, 124 deUint32 wrapT, 125 deUint32 format, 126 deUint32 dataType, 127 int width, 128 int height) 129 : TestCase (testCtx, name, desc) 130 , m_renderCtx (renderCtx) 131 , m_renderCtxInfo (renderCtxInfo) 132 , m_coordType (coordType) 133 , m_minFilter (minFilter) 134 , m_wrapS (wrapS) 135 , m_wrapT (wrapT) 136 , m_format (format) 137 , m_dataType (dataType) 138 , m_width (width) 139 , m_height (height) 140 , m_texture (DE_NULL) 141 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, 142 renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available. 143 : glu::PRECISION_MEDIUMP) 144 { 145 } 146 147 Texture2DMipmapCase::~Texture2DMipmapCase (void) 148 { 149 deinit(); 150 } 151 152 void Texture2DMipmapCase::init (void) 153 { 154 if (!m_renderCtxInfo.isFragmentHighPrecisionSupported()) 155 m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage; 156 157 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0) 158 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config"); 159 160 m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height); 161 162 int numLevels = deLog2Floor32(de::max(m_width, m_height))+1; 163 164 // Fill texture with colored grid. 165 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 166 { 167 deUint32 step = 0xff / (numLevels-1); 168 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 169 deUint32 dec = 0xff - inc; 170 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff; 171 deUint32 color = 0xff000000 | rgb; 172 173 m_texture->getRefTexture().allocLevel(levelNdx); 174 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), toVec4(tcu::RGBA(color))); 175 } 176 } 177 178 void Texture2DMipmapCase::deinit (void) 179 { 180 delete m_texture; 181 m_texture = DE_NULL; 182 183 m_renderer.clear(); 184 } 185 186 static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx) 187 { 188 static const struct 189 { 190 Vec2 bottomLeft; 191 Vec2 topRight; 192 } s_basicCoords[] = 193 { 194 { Vec2(-0.1f, 0.1f), Vec2( 0.8f, 1.0f) }, 195 { Vec2(-0.3f, -0.6f), Vec2( 0.7f, 0.4f) }, 196 { Vec2(-0.3f, 0.6f), Vec2( 0.7f, -0.9f) }, 197 { Vec2(-0.8f, 0.6f), Vec2( 0.7f, -0.9f) }, 198 199 { Vec2(-0.5f, -0.5f), Vec2( 1.5f, 1.5f) }, 200 { Vec2( 1.0f, -1.0f), Vec2(-1.3f, 1.0f) }, 201 { Vec2( 1.2f, -1.0f), Vec2(-1.3f, 1.6f) }, 202 { Vec2( 2.2f, -1.1f), Vec2(-1.3f, 0.8f) }, 203 204 { Vec2(-1.5f, 1.6f), Vec2( 1.7f, -1.4f) }, 205 { Vec2( 2.0f, 1.6f), Vec2( 2.3f, -1.4f) }, 206 { Vec2( 1.3f, -2.6f), Vec2(-2.7f, 2.9f) }, 207 { Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) }, 208 209 { Vec2( -8.0f, 9.0f), Vec2( 8.3f, -7.0f) }, 210 { Vec2(-16.0f, 10.0f), Vec2( 18.3f, 24.0f) }, 211 { Vec2( 30.2f, 55.0f), Vec2(-24.3f, -1.6f) }, 212 { Vec2(-33.2f, 64.1f), Vec2( 32.1f, -64.1f) }, 213 }; 214 215 DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords))); 216 217 const Vec2& bottomLeft = s_basicCoords[cellNdx].bottomLeft; 218 const Vec2& topRight = s_basicCoords[cellNdx].topRight; 219 220 computeQuadTexCoord2D(dst, bottomLeft, topRight); 221 } 222 223 static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx) 224 { 225 // Use basic coords as base. 226 getBasicTexCoord2D(dst, cellNdx); 227 228 // Rotate based on cell index. 229 float angle = 2.0f*DE_PI * ((float)cellNdx / 16.0f); 230 tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle); 231 232 // Second and third row are sheared. 233 float shearX = de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f; 234 tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f)); 235 236 tcu::Mat2 transform = rotMatrix * shearMatrix; 237 Vec2 p0 = transform * Vec2(dst[0], dst[1]); 238 Vec2 p1 = transform * Vec2(dst[2], dst[3]); 239 Vec2 p2 = transform * Vec2(dst[4], dst[5]); 240 Vec2 p3 = transform * Vec2(dst[6], dst[7]); 241 242 dst[0] = p0.x(); dst[1] = p0.y(); 243 dst[2] = p1.x(); dst[3] = p1.y(); 244 dst[4] = p2.x(); dst[5] = p2.y(); 245 dst[6] = p3.x(); dst[7] = p3.y(); 246 } 247 248 Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void) 249 { 250 const glw::Functions& gl = m_renderCtx.getFunctions(); 251 252 const tcu::Texture2D& refTexture = m_texture->getRefTexture(); 253 254 const deUint32 magFilter = GL_NEAREST; 255 const int texWidth = refTexture.getWidth(); 256 const int texHeight = refTexture.getHeight(); 257 const int defViewportWidth = texWidth*4; 258 const int defViewportHeight = texHeight*4; 259 260 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 261 ReferenceParams sampleParams (TEXTURETYPE_2D); 262 vector<float> texCoord; 263 264 const bool isProjected = m_coordType == COORDTYPE_PROJECTED; 265 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS; 266 267 tcu::Surface renderedFrame (viewport.width, viewport.height); 268 269 // Viewport is divided into 4x4 grid. 270 int gridWidth = 4; 271 int gridHeight = 4; 272 int cellWidth = viewport.width / gridWidth; 273 int cellHeight = viewport.height / gridHeight; 274 275 // Bail out if rendertarget is too small. 276 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2) 277 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 278 279 // Sampling parameters. 280 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter); 281 sampleParams.samplerType = gls::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat()); 282 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0); 283 sampleParams.lodMode = LODMODE_EXACT; // Use ideal lod. 284 285 // Upload texture data. 286 m_texture->upload(); 287 288 // Bind gradient texture and setup sampler parameters. 289 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture()); 290 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); 291 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); 292 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 293 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); 294 295 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 296 297 // Bias values. 298 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f }; 299 300 // Projection values. 301 static const Vec4 s_projections[] = 302 { 303 Vec4(1.2f, 1.0f, 0.7f, 1.0f), 304 Vec4(1.3f, 0.8f, 0.6f, 2.0f), 305 Vec4(0.8f, 1.0f, 1.7f, 0.6f), 306 Vec4(1.2f, 1.0f, 1.7f, 1.5f) 307 }; 308 309 // Render cells. 310 for (int gridY = 0; gridY < gridHeight; gridY++) 311 { 312 for (int gridX = 0; gridX < gridWidth; gridX++) 313 { 314 const int curX = cellWidth*gridX; 315 const int curY = cellHeight*gridY; 316 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 317 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 318 const int cellNdx = gridY*gridWidth + gridX; 319 320 // Compute texcoord. 321 switch (m_coordType) 322 { 323 case COORDTYPE_BASIC_BIAS: // Fall-through. 324 case COORDTYPE_PROJECTED: 325 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break; 326 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break; 327 default: DE_ASSERT(DE_FALSE); 328 } 329 330 if (isProjected) 331 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 332 333 if (useLodBias) 334 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 335 336 // Render with GL. 337 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 338 m_renderer.renderQuad(0, &texCoord[0], sampleParams); 339 } 340 } 341 342 // Read result. 343 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 344 345 // Compare and log. 346 { 347 const tcu::PixelFormat& pixelFormat = m_renderCtx.getRenderTarget().getPixelFormat(); 348 const bool isTrilinear = m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR; 349 tcu::Surface referenceFrame (viewport.width, viewport.height); 350 tcu::Surface errorMask (viewport.width, viewport.height); 351 tcu::LookupPrecision lookupPrec; 352 tcu::LodPrecision lodPrec; 353 int numFailedPixels = 0; 354 355 lookupPrec.coordBits = tcu::IVec3(20, 20, 0); 356 lookupPrec.uvwBits = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored. 357 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0))); 358 lookupPrec.colorMask = getCompareMask(pixelFormat); 359 lodPrec.derivateBits = 10; 360 lodPrec.lodBits = isProjected ? 6 : 8; 361 362 for (int gridY = 0; gridY < gridHeight; gridY++) 363 { 364 for (int gridX = 0; gridX < gridWidth; gridX++) 365 { 366 const int curX = cellWidth*gridX; 367 const int curY = cellHeight*gridY; 368 const int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 369 const int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 370 const int cellNdx = gridY*gridWidth + gridX; 371 372 // Compute texcoord. 373 switch (m_coordType) 374 { 375 case COORDTYPE_BASIC_BIAS: // Fall-through. 376 case COORDTYPE_PROJECTED: 377 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break; 378 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break; 379 default: DE_ASSERT(DE_FALSE); 380 } 381 382 if (isProjected) 383 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 384 385 if (useLodBias) 386 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 387 388 // Render ideal result 389 sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), 390 refTexture, &texCoord[0], sampleParams); 391 392 // Compare this cell 393 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 394 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 395 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 396 m_texture->getRefTexture(), &texCoord[0], sampleParams, 397 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 398 } 399 } 400 401 if (numFailedPixels > 0) 402 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 403 404 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 405 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 406 407 if (numFailedPixels > 0) 408 { 409 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 410 << TestLog::Image("ErrorMask", "Error mask", errorMask); 411 } 412 413 m_testCtx.getLog() << TestLog::EndImageSet; 414 415 { 416 const bool isOk = numFailedPixels == 0; 417 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 418 isOk ? "Pass" : "Image verification failed"); 419 } 420 } 421 422 return STOP; 423 } 424 425 // TextureCubeMipmapCase 426 427 class TextureCubeMipmapCase : public tcu::TestCase 428 { 429 public: 430 431 TextureCubeMipmapCase (tcu::TestContext& testCtx, 432 glu::RenderContext& renderCtx, 433 const glu::ContextInfo& renderCtxInfo, 434 const char* name, 435 const char* desc, 436 CoordType coordType, 437 deUint32 minFilter, 438 deUint32 wrapS, 439 deUint32 wrapT, 440 deUint32 format, 441 deUint32 dataType, 442 int size); 443 ~TextureCubeMipmapCase (void); 444 445 void init (void); 446 void deinit (void); 447 IterateResult iterate (void); 448 449 private: 450 TextureCubeMipmapCase (const TextureCubeMipmapCase& other); 451 TextureCubeMipmapCase& operator= (const TextureCubeMipmapCase& other); 452 453 glu::RenderContext& m_renderCtx; 454 const glu::ContextInfo& m_renderCtxInfo; 455 456 CoordType m_coordType; 457 deUint32 m_minFilter; 458 deUint32 m_wrapS; 459 deUint32 m_wrapT; 460 deUint32 m_format; 461 deUint32 m_dataType; 462 int m_size; 463 464 glu::TextureCube* m_texture; 465 TextureRenderer m_renderer; 466 }; 467 468 TextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext& testCtx, 469 glu::RenderContext& renderCtx, 470 const glu::ContextInfo& renderCtxInfo, 471 const char* name, 472 const char* desc, 473 CoordType coordType, 474 deUint32 minFilter, 475 deUint32 wrapS, 476 deUint32 wrapT, 477 deUint32 format, 478 deUint32 dataType, 479 int size) 480 : TestCase (testCtx, name, desc) 481 , m_renderCtx (renderCtx) 482 , m_renderCtxInfo (renderCtxInfo) 483 , m_coordType (coordType) 484 , m_minFilter (minFilter) 485 , m_wrapS (wrapS) 486 , m_wrapT (wrapT) 487 , m_format (format) 488 , m_dataType (dataType) 489 , m_size (size) 490 , m_texture (DE_NULL) 491 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, 492 renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available. 493 : glu::PRECISION_MEDIUMP) 494 { 495 } 496 497 TextureCubeMipmapCase::~TextureCubeMipmapCase (void) 498 { 499 deinit(); 500 } 501 502 void TextureCubeMipmapCase::init (void) 503 { 504 if (!m_renderCtxInfo.isFragmentHighPrecisionSupported()) 505 m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage; 506 507 if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0) 508 throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config"); 509 510 m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size); 511 512 int numLevels = deLog2Floor32(m_size)+1; 513 514 // Fill texture with colored grid. 515 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 516 { 517 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 518 { 519 deUint32 step = 0xff / (numLevels-1); 520 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 521 deUint32 dec = 0xff - inc; 522 deUint32 rgb = 0; 523 524 switch (faceNdx) 525 { 526 case 0: rgb = (inc << 16) | (dec << 8) | 255; break; 527 case 1: rgb = (255 << 16) | (inc << 8) | dec; break; 528 case 2: rgb = (dec << 16) | (255 << 8) | inc; break; 529 case 3: rgb = (dec << 16) | (inc << 8) | 255; break; 530 case 4: rgb = (255 << 16) | (dec << 8) | inc; break; 531 case 5: rgb = (inc << 16) | (255 << 8) | dec; break; 532 } 533 534 deUint32 color = 0xff000000 | rgb; 535 536 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx); 537 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), toVec4(tcu::RGBA(color))); 538 } 539 } 540 } 541 542 void TextureCubeMipmapCase::deinit (void) 543 { 544 delete m_texture; 545 m_texture = DE_NULL; 546 547 m_renderer.clear(); 548 } 549 550 static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height) 551 { 552 const int minWidth = 8; 553 const int minHeight = 8; 554 555 bool partition = rnd.getFloat() > 0.4f; 556 bool partitionX = partition && width > minWidth && rnd.getBool(); 557 bool partitionY = partition && height > minHeight && !partitionX; 558 559 if (partitionX) 560 { 561 int split = width/2 + rnd.getInt(-width/4, +width/4); 562 randomPartition(dst, rnd, x, y, split, height); 563 randomPartition(dst, rnd, x+split, y, width-split, height); 564 } 565 else if (partitionY) 566 { 567 int split = height/2 + rnd.getInt(-height/4, +height/4); 568 randomPartition(dst, rnd, x, y, width, split); 569 randomPartition(dst, rnd, x, y+split, width, height-split); 570 } 571 else 572 dst.push_back(IVec4(x, y, width, height)); 573 } 574 575 static void computeGridLayout (vector<IVec4>& dst, int width, int height) 576 { 577 de::Random rnd(7); 578 randomPartition(dst, rnd, 0, 0, width, height); 579 } 580 581 TextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void) 582 { 583 const deUint32 magFilter = GL_NEAREST; 584 const int texWidth = m_texture->getRefTexture().getSize(); 585 const int texHeight = m_texture->getRefTexture().getSize(); 586 const int defViewportWidth = texWidth*2; 587 const int defViewportHeight = texHeight*2; 588 589 const glw::Functions& gl = m_renderCtx.getFunctions(); 590 const RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 591 592 const bool isProjected = m_coordType == COORDTYPE_PROJECTED; 593 const bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS; 594 595 vector<float> texCoord; 596 tcu::Surface renderedFrame (viewport.width, viewport.height); 597 598 // Bail out if rendertarget is too small. 599 if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2) 600 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 601 602 // Upload texture data. 603 m_texture->upload(); 604 605 // Bind gradient texture and setup sampler parameters. 606 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture()); 607 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS); 608 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT); 609 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter); 610 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter); 611 612 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 613 614 // Compute grid. 615 vector<IVec4> gridLayout; 616 computeGridLayout(gridLayout, viewport.width, viewport.height); 617 618 // Bias values. 619 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f }; 620 621 // Projection values \note Less agressive than in 2D case due to smaller quads. 622 static const Vec4 s_projections[] = 623 { 624 Vec4(1.2f, 1.0f, 0.7f, 1.0f), 625 Vec4(1.3f, 0.8f, 0.6f, 1.1f), 626 Vec4(0.8f, 1.0f, 1.2f, 0.8f), 627 Vec4(1.2f, 1.0f, 1.3f, 0.9f) 628 }; 629 630 // Render with GL 631 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++) 632 { 633 const int curX = gridLayout[cellNdx].x(); 634 const int curY = gridLayout[cellNdx].y(); 635 const int curW = gridLayout[cellNdx].z(); 636 const int curH = gridLayout[cellNdx].w(); 637 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST); 638 RenderParams params (TEXTURETYPE_CUBE); 639 640 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported. 641 computeQuadTexCoordCube(texCoord, cubeFace); 642 643 if (isProjected) 644 { 645 params.flags |= ReferenceParams::PROJECTED; 646 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 647 } 648 649 if (useLodBias) 650 { 651 params.flags |= ReferenceParams::USE_BIAS; 652 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 653 } 654 655 // Render with GL. 656 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 657 m_renderer.renderQuad(0, &texCoord[0], params); 658 } 659 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 660 661 // Read result. 662 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 663 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels"); 664 665 // Render reference and compare 666 { 667 tcu::Surface referenceFrame (viewport.width, viewport.height); 668 tcu::Surface errorMask (viewport.width, viewport.height); 669 int numFailedPixels = 0; 670 ReferenceParams params (TEXTURETYPE_CUBE); 671 tcu::LookupPrecision lookupPrec; 672 tcu::LodPrecision lodPrec; 673 674 // Params for rendering reference 675 params.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter); 676 params.sampler.seamlessCubeMap = false; 677 params.lodMode = LODMODE_EXACT; 678 679 // Comparison parameters 680 lookupPrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat()); 681 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0))); 682 lookupPrec.coordBits = isProjected ? tcu::IVec3(8) : tcu::IVec3(10); 683 lookupPrec.uvwBits = tcu::IVec3(5,5,0); 684 lodPrec.derivateBits = 10; 685 lodPrec.lodBits = isProjected ? 4 : 6; 686 687 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++) 688 { 689 const int curX = gridLayout[cellNdx].x(); 690 const int curY = gridLayout[cellNdx].y(); 691 const int curW = gridLayout[cellNdx].z(); 692 const int curH = gridLayout[cellNdx].w(); 693 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST); 694 695 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported. 696 computeQuadTexCoordCube(texCoord, cubeFace); 697 698 if (isProjected) 699 { 700 params.flags |= ReferenceParams::PROJECTED; 701 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 702 } 703 704 if (useLodBias) 705 { 706 params.flags |= ReferenceParams::USE_BIAS; 707 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 708 } 709 710 // Render ideal reference. 711 { 712 SurfaceAccess idealDst(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH); 713 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params); 714 } 715 716 // Compare this cell 717 numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH), 718 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH), 719 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), 720 m_texture->getRefTexture(), &texCoord[0], params, 721 lookupPrec, lodPrec, m_testCtx.getWatchDog()); 722 } 723 724 if (numFailedPixels > 0) 725 m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage; 726 727 m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result") 728 << TestLog::Image("Rendered", "Rendered image", renderedFrame); 729 730 if (numFailedPixels > 0) 731 { 732 m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame) 733 << TestLog::Image("ErrorMask", "Error mask", errorMask); 734 } 735 736 m_testCtx.getLog() << TestLog::EndImageSet; 737 738 { 739 const bool isOk = numFailedPixels == 0; 740 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 741 isOk ? "Pass" : "Image verification failed"); 742 } 743 } 744 745 return STOP; 746 } 747 748 // Texture2DGenMipmapCase 749 750 class Texture2DGenMipmapCase : public tcu::TestCase 751 { 752 public: 753 754 Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height); 755 ~Texture2DGenMipmapCase (void); 756 757 void init (void); 758 void deinit (void); 759 IterateResult iterate (void); 760 761 private: 762 Texture2DGenMipmapCase (const Texture2DGenMipmapCase& other); 763 Texture2DGenMipmapCase& operator= (const Texture2DGenMipmapCase& other); 764 765 glu::RenderContext& m_renderCtx; 766 767 deUint32 m_format; 768 deUint32 m_dataType; 769 deUint32 m_hint; 770 int m_width; 771 int m_height; 772 773 glu::Texture2D* m_texture; 774 TextureRenderer m_renderer; 775 }; 776 777 Texture2DGenMipmapCase::Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height) 778 : TestCase (testCtx, name, desc) 779 , m_renderCtx (renderCtx) 780 , m_format (format) 781 , m_dataType (dataType) 782 , m_hint (hint) 783 , m_width (width) 784 , m_height (height) 785 , m_texture (DE_NULL) 786 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 787 { 788 } 789 790 Texture2DGenMipmapCase::~Texture2DGenMipmapCase (void) 791 { 792 deinit(); 793 } 794 795 void Texture2DGenMipmapCase::init (void) 796 { 797 DE_ASSERT(!m_texture); 798 m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height); 799 } 800 801 void Texture2DGenMipmapCase::deinit (void) 802 { 803 delete m_texture; 804 m_texture = DE_NULL; 805 806 m_renderer.clear(); 807 } 808 809 Texture2DGenMipmapCase::IterateResult Texture2DGenMipmapCase::iterate (void) 810 { 811 const glw::Functions& gl = m_renderCtx.getFunctions(); 812 813 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST; 814 const deUint32 magFilter = GL_NEAREST; 815 const deUint32 wrapS = GL_CLAMP_TO_EDGE; 816 const deUint32 wrapT = GL_CLAMP_TO_EDGE; 817 818 const int numLevels = deLog2Floor32(de::max(m_width, m_height))+1; 819 820 tcu::Texture2D resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight()); 821 822 vector<float> texCoord; 823 824 // Initialize texture level 0 with colored grid. 825 m_texture->getRefTexture().allocLevel(0); 826 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)); 827 828 // Upload data and setup params. 829 m_texture->upload(); 830 831 gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture()); 832 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 833 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 834 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); 835 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); 836 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 837 838 // Generate mipmap. 839 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint); 840 gl.generateMipmap(GL_TEXTURE_2D); 841 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()"); 842 843 // Use (0, 0) -> (1, 1) texture coordinates. 844 computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f)); 845 846 // Fetch resulting texture by rendering. 847 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 848 { 849 const int levelWidth = de::max(1, m_width >> levelNdx); 850 const int levelHeight = de::max(1, m_height >> levelNdx); 851 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth, levelHeight, deStringHash(getName()) + levelNdx); 852 853 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 854 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D); 855 856 resultTexture.allocLevel(levelNdx); 857 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevel(levelNdx)); 858 } 859 860 // Compare results 861 { 862 863 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)); 864 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType)); 865 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0)); 866 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask); 867 GenMipmapPrecision comparePrec; 868 869 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat()); 870 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits); 871 comparePrec.filterBits = tcu::IVec3(4, 4, 0); 872 873 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec); 874 875 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" : 876 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" : 877 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : ""); 878 } 879 880 return STOP; 881 } 882 883 // TextureCubeGenMipmapCase 884 885 class TextureCubeGenMipmapCase : public tcu::TestCase 886 { 887 public: 888 889 TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size); 890 ~TextureCubeGenMipmapCase (void); 891 892 void init (void); 893 void deinit (void); 894 IterateResult iterate (void); 895 896 private: 897 TextureCubeGenMipmapCase (const TextureCubeGenMipmapCase& other); 898 TextureCubeGenMipmapCase& operator= (const TextureCubeGenMipmapCase& other); 899 900 glu::RenderContext& m_renderCtx; 901 902 deUint32 m_format; 903 deUint32 m_dataType; 904 deUint32 m_hint; 905 int m_size; 906 907 glu::TextureCube* m_texture; 908 TextureRenderer m_renderer; 909 }; 910 911 TextureCubeGenMipmapCase::TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size) 912 : TestCase (testCtx, name, desc) 913 , m_renderCtx (renderCtx) 914 , m_format (format) 915 , m_dataType (dataType) 916 , m_hint (hint) 917 , m_size (size) 918 , m_texture (DE_NULL) 919 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 920 { 921 } 922 923 TextureCubeGenMipmapCase::~TextureCubeGenMipmapCase (void) 924 { 925 deinit(); 926 } 927 928 void TextureCubeGenMipmapCase::init (void) 929 { 930 if (m_renderCtx.getRenderTarget().getWidth() < 3*m_size || m_renderCtx.getRenderTarget().getHeight() < 2*m_size) 931 throw tcu::NotSupportedError("Render target size must be at least (" + de::toString(3*m_size) + ", " + de::toString(2*m_size) + ")"); 932 933 DE_ASSERT(!m_texture); 934 m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size); 935 } 936 937 void TextureCubeGenMipmapCase::deinit (void) 938 { 939 delete m_texture; 940 m_texture = DE_NULL; 941 942 m_renderer.clear(); 943 } 944 945 TextureCubeGenMipmapCase::IterateResult TextureCubeGenMipmapCase::iterate (void) 946 { 947 const glw::Functions& gl = m_renderCtx.getFunctions(); 948 949 const deUint32 minFilter = GL_NEAREST_MIPMAP_NEAREST; 950 const deUint32 magFilter = GL_NEAREST; 951 const deUint32 wrapS = GL_CLAMP_TO_EDGE; 952 const deUint32 wrapT = GL_CLAMP_TO_EDGE; 953 954 tcu::TextureCube resultTexture (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_size); 955 956 const int numLevels = deLog2Floor32(m_size)+1; 957 vector<float> texCoord; 958 959 // Initialize texture level 0 with colored grid. 960 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 961 { 962 Vec4 ca, cb; // Grid colors. 963 964 switch (face) 965 { 966 case 0: ca = Vec4(1.0f, 0.3f, 0.0f, 0.7f); cb = Vec4(0.0f, 0.0f, 1.0f, 1.0f); break; 967 case 1: ca = Vec4(0.0f, 1.0f, 0.5f, 0.5f); cb = Vec4(1.0f, 0.0f, 0.0f, 1.0f); break; 968 case 2: ca = Vec4(0.7f, 0.0f, 1.0f, 0.3f); cb = Vec4(0.0f, 1.0f, 0.0f, 1.0f); break; 969 case 3: ca = Vec4(0.0f, 0.3f, 1.0f, 1.0f); cb = Vec4(1.0f, 0.0f, 0.0f, 0.7f); break; 970 case 4: ca = Vec4(1.0f, 0.0f, 0.5f, 1.0f); cb = Vec4(0.0f, 1.0f, 0.0f, 0.5f); break; 971 case 5: ca = Vec4(0.7f, 1.0f, 0.0f, 1.0f); cb = Vec4(0.0f, 0.0f, 1.0f, 0.3f); break; 972 } 973 974 m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0); 975 fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), 8, ca, cb); 976 } 977 978 // Upload data and setup params. 979 m_texture->upload(); 980 981 gl.bindTexture (GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture()); 982 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS); 983 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT); 984 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter); 985 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter); 986 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 987 988 // Generate mipmap. 989 gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint); 990 gl.generateMipmap(GL_TEXTURE_CUBE_MAP); 991 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()"); 992 993 // Render all levels. 994 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 995 { 996 const int levelWidth = de::max(1, m_size >> levelNdx); 997 const int levelHeight = de::max(1, m_size >> levelNdx); 998 999 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 1000 { 1001 const RandomViewport viewport (m_renderCtx.getRenderTarget(), levelWidth*3, levelHeight*2, deStringHash(getName()) ^ deInt32Hash(levelNdx + faceNdx)); 1002 const tcu::CubeFace face = tcu::CubeFace(faceNdx); 1003 1004 computeQuadTexCoordCube(texCoord, face); 1005 1006 gl.viewport(viewport.x, viewport.y, levelWidth, levelHeight); 1007 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE); 1008 1009 resultTexture.allocLevel(face, levelNdx); 1010 glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevelFace(levelNdx, face)); 1011 } 1012 } 1013 1014 // Compare results 1015 { 1016 const IVec4 framebufferBits = max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)); 1017 const IVec4 formatBits = tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType)); 1018 const tcu::BVec4 formatMask = greaterThan(formatBits, IVec4(0)); 1019 const IVec4 cmpBits = select(min(framebufferBits, formatBits), framebufferBits, formatMask); 1020 GenMipmapPrecision comparePrec; 1021 1022 comparePrec.colorMask = getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat()); 1023 comparePrec.colorThreshold = tcu::computeFixedPointThreshold(cmpBits); 1024 comparePrec.filterBits = tcu::IVec3(4, 4, 0); 1025 1026 const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec); 1027 1028 m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS ? "Pass" : 1029 compareResult == QP_TEST_RESULT_QUALITY_WARNING ? "Low-quality method used" : 1030 compareResult == QP_TEST_RESULT_FAIL ? "Image comparison failed" : ""); 1031 } 1032 1033 return STOP; 1034 } 1035 1036 TextureMipmapTests::TextureMipmapTests (Context& context) 1037 : TestCaseGroup(context, "mipmap", "Mipmapping tests") 1038 { 1039 } 1040 1041 TextureMipmapTests::~TextureMipmapTests (void) 1042 { 1043 } 1044 1045 void TextureMipmapTests::init (void) 1046 { 1047 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Mipmapping"); 1048 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Filtering"); 1049 addChild(group2D); 1050 addChild(groupCube); 1051 1052 static const struct 1053 { 1054 const char* name; 1055 deUint32 mode; 1056 } wrapModes[] = 1057 { 1058 { "clamp", GL_CLAMP_TO_EDGE }, 1059 { "repeat", GL_REPEAT }, 1060 { "mirror", GL_MIRRORED_REPEAT } 1061 }; 1062 1063 static const struct 1064 { 1065 const char* name; 1066 deUint32 mode; 1067 } minFilterModes[] = 1068 { 1069 { "nearest_nearest", GL_NEAREST_MIPMAP_NEAREST }, 1070 { "linear_nearest", GL_LINEAR_MIPMAP_NEAREST }, 1071 { "nearest_linear", GL_NEAREST_MIPMAP_LINEAR }, 1072 { "linear_linear", GL_LINEAR_MIPMAP_LINEAR } 1073 }; 1074 1075 static const struct 1076 { 1077 CoordType type; 1078 const char* name; 1079 const char* desc; 1080 } coordTypes[] = 1081 { 1082 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" }, 1083 { COORDTYPE_AFFINE, "affine", "Mipmapping with affine coordinate transform" }, 1084 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" } 1085 }; 1086 1087 static const struct 1088 { 1089 const char* name; 1090 deUint32 format; 1091 deUint32 dataType; 1092 } formats[] = 1093 { 1094 { "a8", GL_ALPHA, GL_UNSIGNED_BYTE }, 1095 { "l8", GL_LUMINANCE, GL_UNSIGNED_BYTE }, 1096 { "la88", GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE }, 1097 { "rgb565", GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, 1098 { "rgb888", GL_RGB, GL_UNSIGNED_BYTE }, 1099 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, 1100 { "rgba5551", GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, 1101 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE } 1102 }; 1103 1104 static const struct 1105 { 1106 const char* name; 1107 deUint32 hint; 1108 } genHints[] = 1109 { 1110 { "fastest", GL_FASTEST }, 1111 { "nicest", GL_NICEST } 1112 }; 1113 1114 static const struct 1115 { 1116 const char* name; 1117 int width; 1118 int height; 1119 } tex2DSizes[] = 1120 { 1121 { DE_NULL, 64, 64 }, // Default. 1122 { "non_square", 32, 64 } 1123 }; 1124 1125 // 2D cases. 1126 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++) 1127 { 1128 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc); 1129 group2D->addChild(coordTypeGroup); 1130 1131 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 1132 { 1133 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++) 1134 { 1135 // Add non_square variants to basic cases only. 1136 int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1; 1137 1138 for (int size = 0; size < sizeEnd; size++) 1139 { 1140 std::ostringstream name; 1141 name << minFilterModes[minFilter].name 1142 << "_" << wrapModes[wrapMode].name; 1143 1144 if (tex2DSizes[size].name) 1145 name << "_" << tex2DSizes[size].name; 1146 1147 coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 1148 name.str().c_str(), "", 1149 coordTypes[coordType].type, 1150 minFilterModes[minFilter].mode, 1151 wrapModes[wrapMode].mode, 1152 wrapModes[wrapMode].mode, 1153 GL_RGBA, GL_UNSIGNED_BYTE, 1154 tex2DSizes[size].width, tex2DSizes[size].height)); 1155 } 1156 } 1157 } 1158 } 1159 1160 // 2D bias variants. 1161 { 1162 tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value"); 1163 group2D->addChild(biasGroup); 1164 1165 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 1166 biasGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 1167 minFilterModes[minFilter].name, "", 1168 COORDTYPE_BASIC_BIAS, 1169 minFilterModes[minFilter].mode, 1170 GL_REPEAT, GL_REPEAT, 1171 GL_RGBA, GL_UNSIGNED_BYTE, 1172 tex2DSizes[0].width, tex2DSizes[0].height)); 1173 } 1174 1175 // 2D mipmap generation variants. 1176 { 1177 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests"); 1178 group2D->addChild(genMipmapGroup); 1179 1180 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++) 1181 { 1182 for (int size = 0; size < DE_LENGTH_OF_ARRAY(tex2DSizes); size++) 1183 { 1184 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++) 1185 { 1186 std::ostringstream name; 1187 name << formats[format].name; 1188 1189 if (tex2DSizes[size].name) 1190 name << "_" << tex2DSizes[size].name; 1191 1192 name << "_" << genHints[hint].name; 1193 1194 genMipmapGroup->addChild(new Texture2DGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", 1195 formats[format].format, formats[format].dataType, genHints[hint].hint, 1196 tex2DSizes[size].width, tex2DSizes[size].height)); 1197 } 1198 } 1199 } 1200 } 1201 1202 const int cubeMapSize = 64; 1203 1204 static const struct 1205 { 1206 CoordType type; 1207 const char* name; 1208 const char* desc; 1209 } cubeCoordTypes[] = 1210 { 1211 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" }, 1212 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" }, 1213 { COORDTYPE_BASIC_BIAS, "bias", "User-supplied bias value" } 1214 }; 1215 1216 // Cubemap cases. 1217 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++) 1218 { 1219 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc); 1220 groupCube->addChild(coordTypeGroup); 1221 1222 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 1223 { 1224 coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 1225 minFilterModes[minFilter].name, "", 1226 cubeCoordTypes[coordType].type, 1227 minFilterModes[minFilter].mode, 1228 GL_CLAMP_TO_EDGE, 1229 GL_CLAMP_TO_EDGE, 1230 GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize)); 1231 } 1232 } 1233 1234 // Cubemap mipmap generation variants. 1235 { 1236 tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests"); 1237 groupCube->addChild(genMipmapGroup); 1238 1239 for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++) 1240 { 1241 for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++) 1242 { 1243 std::ostringstream name; 1244 name << formats[format].name 1245 << "_" << genHints[hint].name; 1246 1247 genMipmapGroup->addChild(new TextureCubeGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format, formats[format].dataType, genHints[hint].hint, cubeMapSize)); 1248 } 1249 } 1250 } 1251 } 1252 1253 } // Functional 1254 } // gles2 1255 } // deqp 1256