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