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 accuracy tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es2aTextureMipmapTests.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 "tcuTexVerifierUtil.hpp" 33#include "tcuVector.hpp" 34#include "tcuMatrix.hpp" 35#include "tcuMatrixUtil.hpp" 36#include "deStringUtil.hpp" 37#include "deRandom.hpp" 38 39#include "glwEnums.hpp" 40#include "glwFunctions.hpp" 41 42namespace deqp 43{ 44namespace gles2 45{ 46namespace Accuracy 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, tcu::NODETYPE_ACCURACY, 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 m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height); 159 160 int numLevels = deLog2Floor32(de::max(m_width, m_height))+1; 161 162 // Fill texture with colored grid. 163 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 164 { 165 deUint32 step = 0xff / (numLevels-1); 166 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 167 deUint32 dec = 0xff - inc; 168 deUint32 rgb = (inc << 16) | (dec << 8) | 0xff; 169 deUint32 color = 0xff000000 | rgb; 170 171 m_texture->getRefTexture().allocLevel(levelNdx); 172 tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec()); 173 } 174} 175 176void Texture2DMipmapCase::deinit (void) 177{ 178 delete m_texture; 179 m_texture = DE_NULL; 180 181 m_renderer.clear(); 182} 183 184static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx) 185{ 186 static const struct 187 { 188 Vec2 bottomLeft; 189 Vec2 topRight; 190 } s_basicCoords[] = 191 { 192 { Vec2(-0.1f, 0.1f), Vec2( 0.8f, 1.0f) }, 193 { Vec2(-0.3f, -0.6f), Vec2( 0.7f, 0.4f) }, 194 { Vec2(-0.3f, 0.6f), Vec2( 0.7f, -0.9f) }, 195 { Vec2(-0.8f, 0.6f), Vec2( 0.7f, -0.9f) }, 196 197 { Vec2(-0.5f, -0.5f), Vec2( 1.5f, 1.5f) }, 198 { Vec2( 1.0f, -1.0f), Vec2(-1.3f, 1.0f) }, 199 { Vec2( 1.2f, -1.0f), Vec2(-1.3f, 1.6f) }, 200 { Vec2( 2.2f, -1.1f), Vec2(-1.3f, 0.8f) }, 201 202 { Vec2(-1.5f, 1.6f), Vec2( 1.7f, -1.4f) }, 203 { Vec2( 2.0f, 1.6f), Vec2( 2.3f, -1.4f) }, 204 { Vec2( 1.3f, -2.6f), Vec2(-2.7f, 2.9f) }, 205 { Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) }, 206 207 { Vec2( -8.0f, 9.0f), Vec2( 8.3f, -7.0f) }, 208 { Vec2(-16.0f, 10.0f), Vec2( 18.3f, 24.0f) }, 209 { Vec2( 30.2f, 55.0f), Vec2(-24.3f, -1.6f) }, 210 { Vec2(-33.2f, 64.1f), Vec2( 32.1f, -64.1f) }, 211 }; 212 213 DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords))); 214 215 const Vec2& bottomLeft = s_basicCoords[cellNdx].bottomLeft; 216 const Vec2& topRight = s_basicCoords[cellNdx].topRight; 217 218 computeQuadTexCoord2D(dst, bottomLeft, topRight); 219} 220 221static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx) 222{ 223 // Use basic coords as base. 224 getBasicTexCoord2D(dst, cellNdx); 225 226 // Rotate based on cell index. 227 float angle = 2.0f*DE_PI * ((float)cellNdx / 16.0f); 228 tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle); 229 230 // Second and third row are sheared. 231 float shearX = de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f; 232 tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f)); 233 234 tcu::Mat2 transform = rotMatrix * shearMatrix; 235 Vec2 p0 = transform * Vec2(dst[0], dst[1]); 236 Vec2 p1 = transform * Vec2(dst[2], dst[3]); 237 Vec2 p2 = transform * Vec2(dst[4], dst[5]); 238 Vec2 p3 = transform * Vec2(dst[6], dst[7]); 239 240 dst[0] = p0.x(); dst[1] = p0.y(); 241 dst[2] = p1.x(); dst[3] = p1.y(); 242 dst[4] = p2.x(); dst[5] = p2.y(); 243 dst[6] = p3.x(); dst[7] = p3.y(); 244} 245 246Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void) 247{ 248 // Constants. 249 const deUint32 magFilter = GL_NEAREST; 250 251 const glw::Functions& gl = m_renderCtx.getFunctions(); 252 TestLog& log = m_testCtx.getLog(); 253 254 const tcu::Texture2D& refTexture = m_texture->getRefTexture(); 255 const tcu::TextureFormat& texFmt = refTexture.getFormat(); 256 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 257 258 int texWidth = refTexture.getWidth(); 259 int texHeight = refTexture.getHeight(); 260 int defViewportWidth = texWidth*4; 261 int defViewportHeight = texHeight*4; 262 263 RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 264 ReferenceParams sampleParams (TEXTURETYPE_2D); 265 vector<float> texCoord; 266 bool isProjected = m_coordType == COORDTYPE_PROJECTED; 267 bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS; 268 269 tcu::Surface renderedFrame (viewport.width, viewport.height); 270 271 // Accuracy cases test against ideal lod computation. 272 tcu::Surface idealFrame (viewport.width, viewport.height); 273 274 // Viewport is divided into 4x4 grid. 275 int gridWidth = 4; 276 int gridHeight = 4; 277 int cellWidth = viewport.width / gridWidth; 278 int cellHeight = viewport.height / gridHeight; 279 280 // Accuracy measurements are off unless we get the expected viewport size. 281 if (viewport.width < defViewportWidth || viewport.height < defViewportHeight) 282 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 283 284 // Sampling parameters. 285 sampleParams.sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter); 286 sampleParams.samplerType = glu::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat()); 287 sampleParams.colorBias = fmtInfo.lookupBias; 288 sampleParams.colorScale = fmtInfo.lookupScale; 289 sampleParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0); 290 291 // Upload texture data. 292 m_texture->upload(); 293 294 // Use unit 0. 295 gl.activeTexture(GL_TEXTURE0); 296 297 // Bind gradient texture and setup sampler parameters. 298 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture()); 299 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); 300 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); 301 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 302 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); 303 304 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 305 306 // Bias values. 307 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f }; 308 309 // Projection values. 310 static const Vec4 s_projections[] = 311 { 312 Vec4(1.2f, 1.0f, 0.7f, 1.0f), 313 Vec4(1.3f, 0.8f, 0.6f, 2.0f), 314 Vec4(0.8f, 1.0f, 1.7f, 0.6f), 315 Vec4(1.2f, 1.0f, 1.7f, 1.5f) 316 }; 317 318 // Render cells. 319 for (int gridY = 0; gridY < gridHeight; gridY++) 320 { 321 for (int gridX = 0; gridX < gridWidth; gridX++) 322 { 323 int curX = cellWidth*gridX; 324 int curY = cellHeight*gridY; 325 int curW = gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth; 326 int curH = gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight; 327 int cellNdx = gridY*gridWidth + gridX; 328 329 // Compute texcoord. 330 switch (m_coordType) 331 { 332 case COORDTYPE_BASIC_BIAS: // Fall-through. 333 case COORDTYPE_PROJECTED: 334 case COORDTYPE_BASIC: getBasicTexCoord2D (texCoord, cellNdx); break; 335 case COORDTYPE_AFFINE: getAffineTexCoord2D (texCoord, cellNdx); break; 336 default: DE_ASSERT(DE_FALSE); 337 } 338 339 if (isProjected) 340 sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 341 342 if (useLodBias) 343 sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 344 345 // Render with GL. 346 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 347 m_renderer.renderQuad(0, &texCoord[0], sampleParams); 348 349 // Render reference(s). 350 { 351 tcu::SurfaceAccess idealDst(idealFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH); 352 sampleParams.lodMode = LODMODE_EXACT; 353 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], sampleParams); 354 } 355 } 356 } 357 358 // Read result. 359 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 360 361 // Compare and log. 362 { 363 const int bestScoreDiff = (texWidth/16)*(texHeight/16); 364 const int worstScoreDiff = texWidth*texHeight; 365 366 int score = measureAccuracy(log, idealFrame, renderedFrame, bestScoreDiff, worstScoreDiff); 367 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str()); 368 } 369 370 return STOP; 371} 372 373// TextureCubeMipmapCase 374 375class TextureCubeMipmapCase : public tcu::TestCase 376{ 377public: 378 379 TextureCubeMipmapCase (tcu::TestContext& testCtx, 380 glu::RenderContext& renderCtx, 381 const glu::ContextInfo& renderCtxInfo, 382 const char* name, 383 const char* desc, 384 CoordType coordType, 385 deUint32 minFilter, 386 deUint32 wrapS, 387 deUint32 wrapT, 388 deUint32 format, 389 deUint32 dataType, 390 int size); 391 ~TextureCubeMipmapCase (void); 392 393 void init (void); 394 void deinit (void); 395 IterateResult iterate (void); 396 397private: 398 TextureCubeMipmapCase (const TextureCubeMipmapCase& other); 399 TextureCubeMipmapCase& operator= (const TextureCubeMipmapCase& other); 400 401 glu::RenderContext& m_renderCtx; 402 const glu::ContextInfo& m_renderCtxInfo; 403 404 CoordType m_coordType; 405 deUint32 m_minFilter; 406 deUint32 m_wrapS; 407 deUint32 m_wrapT; 408 deUint32 m_format; 409 deUint32 m_dataType; 410 int m_size; 411 412 glu::TextureCube* m_texture; 413 TextureRenderer m_renderer; 414}; 415 416TextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext& testCtx, 417 glu::RenderContext& renderCtx, 418 const glu::ContextInfo& renderCtxInfo, 419 const char* name, 420 const char* desc, 421 CoordType coordType, 422 deUint32 minFilter, 423 deUint32 wrapS, 424 deUint32 wrapT, 425 deUint32 format, 426 deUint32 dataType, 427 int size) 428 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc) 429 , m_renderCtx (renderCtx) 430 , m_renderCtxInfo (renderCtxInfo) 431 , m_coordType (coordType) 432 , m_minFilter (minFilter) 433 , m_wrapS (wrapS) 434 , m_wrapT (wrapT) 435 , m_format (format) 436 , m_dataType (dataType) 437 , m_size (size) 438 , m_texture (DE_NULL) 439 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, 440 renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available. 441 : glu::PRECISION_MEDIUMP) 442{ 443} 444 445TextureCubeMipmapCase::~TextureCubeMipmapCase (void) 446{ 447 deinit(); 448} 449 450void TextureCubeMipmapCase::init (void) 451{ 452 if (!m_renderCtxInfo.isFragmentHighPrecisionSupported()) 453 m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage; 454 455 m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size); 456 457 int numLevels = deLog2Floor32(m_size)+1; 458 459 // Fill texture with colored grid. 460 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 461 { 462 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 463 { 464 deUint32 step = 0xff / (numLevels-1); 465 deUint32 inc = deClamp32(step*levelNdx, 0x00, 0xff); 466 deUint32 dec = 0xff - inc; 467 deUint32 rgb = 0; 468 469 switch (faceNdx) 470 { 471 case 0: rgb = (inc << 16) | (dec << 8) | 255; break; 472 case 1: rgb = (255 << 16) | (inc << 8) | dec; break; 473 case 2: rgb = (dec << 16) | (255 << 8) | inc; break; 474 case 3: rgb = (dec << 16) | (inc << 8) | 255; break; 475 case 4: rgb = (255 << 16) | (dec << 8) | inc; break; 476 case 5: rgb = (inc << 16) | (255 << 8) | dec; break; 477 } 478 479 deUint32 color = 0xff000000 | rgb; 480 481 m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx); 482 tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec()); 483 } 484 } 485} 486 487void TextureCubeMipmapCase::deinit (void) 488{ 489 delete m_texture; 490 m_texture = DE_NULL; 491 492 m_renderer.clear(); 493} 494 495static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height) 496{ 497 const int minWidth = 8; 498 const int minHeight = 8; 499 500 bool partition = rnd.getFloat() > 0.4f; 501 bool partitionX = partition && width > minWidth && rnd.getBool(); 502 bool partitionY = partition && height > minHeight && !partitionX; 503 504 if (partitionX) 505 { 506 int split = width/2 + rnd.getInt(-width/4, +width/4); 507 randomPartition(dst, rnd, x, y, split, height); 508 randomPartition(dst, rnd, x+split, y, width-split, height); 509 } 510 else if (partitionY) 511 { 512 int split = height/2 + rnd.getInt(-height/4, +height/4); 513 randomPartition(dst, rnd, x, y, width, split); 514 randomPartition(dst, rnd, x, y+split, width, height-split); 515 } 516 else 517 dst.push_back(IVec4(x, y, width, height)); 518} 519 520static void computeGridLayout (vector<IVec4>& dst, int width, int height) 521{ 522 de::Random rnd(7); 523 randomPartition(dst, rnd, 0, 0, width, height); 524} 525 526TextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void) 527{ 528 // Constants. 529 const deUint32 magFilter = GL_NEAREST; 530 531 int texWidth = m_texture->getRefTexture().getSize(); 532 int texHeight = m_texture->getRefTexture().getSize(); 533 534 int defViewportWidth = texWidth*2; 535 int defViewportHeight = texHeight*2; 536 537 const glw::Functions& gl = m_renderCtx.getFunctions(); 538 TestLog& log = m_testCtx.getLog(); 539 RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 540 tcu::Sampler sampler = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter); 541 542 vector<float> texCoord; 543 544 bool isProjected = m_coordType == COORDTYPE_PROJECTED; 545 bool useLodBias = m_coordType == COORDTYPE_BASIC_BIAS; 546 547 tcu::Surface renderedFrame (viewport.width, viewport.height); 548 549 // Accuracy cases test against ideal lod computation. 550 tcu::Surface idealFrame (viewport.width, viewport.height); 551 552 // Accuracy measurements are off unless we get the expected viewport size. 553 if (viewport.width < defViewportWidth || viewport.height < defViewportHeight) 554 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 555 556 // Upload texture data. 557 m_texture->upload(); 558 559 // Use unit 0. 560 gl.activeTexture(GL_TEXTURE0); 561 562 // Bind gradient texture and setup sampler parameters. 563 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture()); 564 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS); 565 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT); 566 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter); 567 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter); 568 569 GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup"); 570 571 // Compute grid. 572 vector<IVec4> gridLayout; 573 computeGridLayout(gridLayout, viewport.width, viewport.height); 574 575 // Bias values. 576 static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f }; 577 578 // Projection values \note Less agressive than in 2D case due to smaller quads. 579 static const Vec4 s_projections[] = 580 { 581 Vec4(1.2f, 1.0f, 0.7f, 1.0f), 582 Vec4(1.3f, 0.8f, 0.6f, 1.1f), 583 Vec4(0.8f, 1.0f, 1.2f, 0.8f), 584 Vec4(1.2f, 1.0f, 1.3f, 0.9f) 585 }; 586 587 for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++) 588 { 589 int curX = gridLayout[cellNdx].x(); 590 int curY = gridLayout[cellNdx].y(); 591 int curW = gridLayout[cellNdx].z(); 592 int curH = gridLayout[cellNdx].w(); 593 tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST); 594 ReferenceParams params (TEXTURETYPE_CUBE); 595 596 params.sampler = sampler; 597 598 DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported. 599 computeQuadTexCoordCube(texCoord, cubeFace); 600 601 if (isProjected) 602 { 603 params.flags |= ReferenceParams::PROJECTED; 604 params.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)]; 605 } 606 607 if (useLodBias) 608 { 609 params.flags |= ReferenceParams::USE_BIAS; 610 params.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)]; 611 } 612 613 // Render with GL. 614 gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH); 615 m_renderer.renderQuad(0, &texCoord[0], params); 616 617 // Render reference(s). 618 { 619 tcu::SurfaceAccess idealDst(idealFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH); 620 params.lodMode = LODMODE_EXACT; 621 sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params); 622 } 623 } 624 625 // Read result. 626 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 627 628 // Compare and log. 629 { 630 const int bestScoreDiff = (texWidth/16)*(texHeight/16); 631 const int worstScoreDiff = texWidth*texHeight; 632 633 int score = measureAccuracy(log, idealFrame, renderedFrame, bestScoreDiff, worstScoreDiff); 634 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str()); 635 } 636 637 return STOP; 638} 639 640TextureMipmapTests::TextureMipmapTests (Context& context) 641 : TestCaseGroup(context, "mipmap", "Mipmapping accuracy tests") 642{ 643} 644 645TextureMipmapTests::~TextureMipmapTests (void) 646{ 647} 648 649void TextureMipmapTests::init (void) 650{ 651 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Mipmapping"); 652 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Filtering"); 653 addChild(group2D); 654 addChild(groupCube); 655 656 static const struct 657 { 658 const char* name; 659 deUint32 mode; 660 } wrapModes[] = 661 { 662 { "clamp", GL_CLAMP_TO_EDGE }, 663 { "repeat", GL_REPEAT }, 664 { "mirror", GL_MIRRORED_REPEAT } 665 }; 666 667 static const struct 668 { 669 const char* name; 670 deUint32 mode; 671 } minFilterModes[] = 672 { 673 { "nearest_nearest", GL_NEAREST_MIPMAP_NEAREST }, 674 { "linear_nearest", GL_LINEAR_MIPMAP_NEAREST }, 675 { "nearest_linear", GL_NEAREST_MIPMAP_LINEAR }, 676 { "linear_linear", GL_LINEAR_MIPMAP_LINEAR } 677 }; 678 679 static const struct 680 { 681 CoordType type; 682 const char* name; 683 const char* desc; 684 } coordTypes[] = 685 { 686 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" }, 687 { COORDTYPE_AFFINE, "affine", "Mipmapping with affine coordinate transform" }, 688 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" } 689 }; 690 691 const int tex2DWidth = 64; 692 const int tex2DHeight = 64; 693 694 // 2D cases. 695 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++) 696 { 697 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc); 698 group2D->addChild(coordTypeGroup); 699 700 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 701 { 702 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++) 703 { 704 std::ostringstream name; 705 name << minFilterModes[minFilter].name 706 << "_" << wrapModes[wrapMode].name; 707 708 coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 709 name.str().c_str(), "", 710 coordTypes[coordType].type, 711 minFilterModes[minFilter].mode, 712 wrapModes[wrapMode].mode, 713 wrapModes[wrapMode].mode, 714 GL_RGBA, GL_UNSIGNED_BYTE, 715 tex2DWidth, tex2DHeight)); 716 } 717 } 718 } 719 720 const int cubeMapSize = 64; 721 722 static const struct 723 { 724 CoordType type; 725 const char* name; 726 const char* desc; 727 } cubeCoordTypes[] = 728 { 729 { COORDTYPE_BASIC, "basic", "Mipmapping with translated and scaled coordinates" }, 730 { COORDTYPE_PROJECTED, "projected", "Mipmapping with perspective projection" } 731 }; 732 733 // Cubemap cases. 734 for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++) 735 { 736 tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc); 737 groupCube->addChild(coordTypeGroup); 738 739 for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++) 740 { 741 coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 742 minFilterModes[minFilter].name, "", 743 cubeCoordTypes[coordType].type, 744 minFilterModes[minFilter].mode, 745 GL_CLAMP_TO_EDGE, 746 GL_CLAMP_TO_EDGE, 747 GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize)); 748 } 749 } 750} 751 752} // Accuracy 753} // gles2 754} // deqp 755