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 Texture filtering accuracy tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es2aTextureFilteringTests.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 "deStringUtil.hpp" 33 34#include "glwFunctions.hpp" 35#include "glwEnums.hpp" 36 37using std::string; 38 39namespace deqp 40{ 41namespace gles2 42{ 43namespace Accuracy 44{ 45 46using tcu::TestLog; 47using std::vector; 48using std::string; 49using tcu::Sampler; 50using namespace glu; 51using namespace gls::TextureTestUtil; 52 53class Texture2DFilteringCase : public tcu::TestCase 54{ 55public: 56 Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height); 57 Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames); 58 ~Texture2DFilteringCase (void); 59 60 void init (void); 61 void deinit (void); 62 IterateResult iterate (void); 63 64private: 65 Texture2DFilteringCase (const Texture2DFilteringCase& other); 66 Texture2DFilteringCase& operator= (const Texture2DFilteringCase& other); 67 68 glu::RenderContext& m_renderCtx; 69 const glu::ContextInfo& m_renderCtxInfo; 70 71 deUint32 m_minFilter; 72 deUint32 m_magFilter; 73 deUint32 m_wrapS; 74 deUint32 m_wrapT; 75 76 deUint32 m_format; 77 deUint32 m_dataType; 78 int m_width; 79 int m_height; 80 81 std::vector<std::string> m_filenames; 82 83 std::vector<glu::Texture2D*> m_textures; 84 TextureRenderer m_renderer; 85}; 86 87 88Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height) 89 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc) 90 , m_renderCtx (renderCtx) 91 , m_renderCtxInfo (ctxInfo) 92 , m_minFilter (minFilter) 93 , m_magFilter (magFilter) 94 , m_wrapS (wrapS) 95 , m_wrapT (wrapT) 96 , m_format (format) 97 , m_dataType (dataType) 98 , m_width (width) 99 , m_height (height) 100 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 101{ 102} 103 104Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames) 105 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc) 106 , m_renderCtx (renderCtx) 107 , m_renderCtxInfo (ctxInfo) 108 , m_minFilter (minFilter) 109 , m_magFilter (magFilter) 110 , m_wrapS (wrapS) 111 , m_wrapT (wrapT) 112 , m_format (GL_NONE) 113 , m_dataType (GL_NONE) 114 , m_width (0) 115 , m_height (0) 116 , m_filenames (filenames) 117 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 118{ 119} 120 121Texture2DFilteringCase::~Texture2DFilteringCase (void) 122{ 123 deinit(); 124} 125 126void Texture2DFilteringCase::init (void) 127{ 128 try 129 { 130 if (!m_filenames.empty()) 131 { 132 m_textures.reserve(1); 133 m_textures.push_back(glu::Texture2D::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size(), m_filenames)); 134 } 135 else 136 { 137 // Create 2 textures. 138 m_textures.reserve(2); 139 for (int ndx = 0; ndx < 2; ndx++) 140 m_textures.push_back(new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height)); 141 142 const bool mipmaps = deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height); 143 const int numLevels = mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1; 144 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat()); 145 tcu::Vec4 cBias = fmtInfo.valueMin; 146 tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 147 148 // Fill first gradient texture. 149 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 150 { 151 tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias; 152 tcu::Vec4 gMax = tcu::Vec4( 1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias; 153 154 m_textures[0]->getRefTexture().allocLevel(levelNdx); 155 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax); 156 } 157 158 // Fill second with grid texture. 159 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 160 { 161 deUint32 step = 0x00ffffff / numLevels; 162 deUint32 rgb = step*levelNdx; 163 deUint32 colorA = 0xff000000 | rgb; 164 deUint32 colorB = 0xff000000 | ~rgb; 165 166 m_textures[1]->getRefTexture().allocLevel(levelNdx); 167 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, toVec4(tcu::RGBA(colorA))*cScale + cBias, toVec4(tcu::RGBA(colorB))*cScale + cBias); 168 } 169 170 // Upload. 171 for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) 172 (*i)->upload(); 173 } 174 } 175 catch (...) 176 { 177 // Clean up to save memory. 178 Texture2DFilteringCase::deinit(); 179 throw; 180 } 181} 182 183void Texture2DFilteringCase::deinit (void) 184{ 185 for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) 186 delete *i; 187 m_textures.clear(); 188 189 m_renderer.clear(); 190} 191 192Texture2DFilteringCase::IterateResult Texture2DFilteringCase::iterate (void) 193{ 194 const glw::Functions& gl = m_renderCtx.getFunctions(); 195 TestLog& log = m_testCtx.getLog(); 196 const int defViewportWidth = 256; 197 const int defViewportHeight = 256; 198 RandomViewport viewport (m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName())); 199 tcu::Surface renderedFrame (viewport.width, viewport.height); 200 tcu::Surface referenceFrame (viewport.width, viewport.height); 201 const tcu::TextureFormat& texFmt = m_textures[0]->getRefTexture().getFormat(); 202 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 203 ReferenceParams refParams (TEXTURETYPE_2D); 204 vector<float> texCoord; 205 206 // Accuracy measurements are off unless viewport size is 256x256 207 if (viewport.width < defViewportWidth || viewport.height < defViewportHeight) 208 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 209 210 // Viewport is divided into 4 sections. 211 int leftWidth = viewport.width / 2; 212 int rightWidth = viewport.width - leftWidth; 213 int bottomHeight = viewport.height / 2; 214 int topHeight = viewport.height - bottomHeight; 215 216 int curTexNdx = 0; 217 218 // Use unit 0. 219 gl.activeTexture(GL_TEXTURE0); 220 221 // Bind gradient texture and setup sampler parameters. 222 gl.bindTexture(GL_TEXTURE_2D, m_textures[curTexNdx]->getGLTexture()); 223 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); 224 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); 225 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 226 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter); 227 228 // Setup params for reference. 229 refParams.sampler = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter); 230 refParams.samplerType = getSamplerType(texFmt); 231 refParams.lodMode = LODMODE_EXACT; 232 refParams.colorBias = fmtInfo.lookupBias; 233 refParams.colorScale = fmtInfo.lookupScale; 234 235 // Bottom left: Minification 236 { 237 gl.viewport(viewport.x, viewport.y, leftWidth, bottomHeight); 238 239 computeQuadTexCoord2D(texCoord, tcu::Vec2(-4.0f, -4.5f), tcu::Vec2(4.0f, 2.5f)); 240 241 m_renderer.renderQuad(0, &texCoord[0], refParams); 242 sampleTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, leftWidth, bottomHeight), 243 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams); 244 } 245 246 // Bottom right: Magnification 247 { 248 gl.viewport(viewport.x+leftWidth, viewport.y, rightWidth, bottomHeight); 249 250 computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f)); 251 252 m_renderer.renderQuad(0, &texCoord[0], refParams); 253 sampleTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, 0, rightWidth, bottomHeight), 254 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams); 255 } 256 257 if (m_textures.size() >= 2) 258 { 259 curTexNdx += 1; 260 261 // Setup second texture. 262 gl.bindTexture(GL_TEXTURE_2D, m_textures[curTexNdx]->getGLTexture()); 263 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS); 264 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT); 265 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter); 266 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter); 267 } 268 269 // Top left: Minification 270 // \note Minification is chosen so that 0.0 < lod <= 0.5. This way special minification threshold rule will be triggered. 271 { 272 gl.viewport(viewport.x, viewport.y+bottomHeight, leftWidth, topHeight); 273 274 float sMin = -0.5f; 275 float tMin = -0.2f; 276 float sRange = ((float)leftWidth * 1.2f) / (float)m_textures[curTexNdx]->getRefTexture().getWidth(); 277 float tRange = ((float)topHeight * 1.1f) / (float)m_textures[curTexNdx]->getRefTexture().getHeight(); 278 279 computeQuadTexCoord2D(texCoord, tcu::Vec2(sMin, tMin), tcu::Vec2(sMin+sRange, tMin+tRange)); 280 281 m_renderer.renderQuad(0, &texCoord[0], refParams); 282 sampleTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, bottomHeight, leftWidth, topHeight), 283 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams); 284 } 285 286 // Top right: Magnification 287 { 288 gl.viewport(viewport.x+leftWidth, viewport.y+bottomHeight, rightWidth, topHeight); 289 290 computeQuadTexCoord2D(texCoord, tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f)); 291 292 m_renderer.renderQuad(0, &texCoord[0], refParams); 293 sampleTexture(SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, bottomHeight, rightWidth, topHeight), 294 m_textures[curTexNdx]->getRefTexture(), &texCoord[0], refParams); 295 } 296 297 // Read result. 298 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 299 300 // Compare and log. 301 { 302 DE_ASSERT(getNodeType() == tcu::NODETYPE_ACCURACY); 303 304 const int bestScoreDiff = 16; 305 const int worstScoreDiff = 3200; 306 307 int score = measureAccuracy(log, referenceFrame, renderedFrame, bestScoreDiff, worstScoreDiff); 308 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str()); 309 } 310 311 return STOP; 312} 313 314class TextureCubeFilteringCase : public tcu::TestCase 315{ 316public: 317 TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height); 318 TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames); 319 ~TextureCubeFilteringCase (void); 320 321 void init (void); 322 void deinit (void); 323 IterateResult iterate (void); 324 325private: 326 TextureCubeFilteringCase (const TextureCubeFilteringCase& other); 327 TextureCubeFilteringCase& operator= (const TextureCubeFilteringCase& other); 328 329 glu::RenderContext& m_renderCtx; 330 const glu::ContextInfo& m_renderCtxInfo; 331 332 deUint32 m_minFilter; 333 deUint32 m_magFilter; 334 deUint32 m_wrapS; 335 deUint32 m_wrapT; 336 337 deUint32 m_format; 338 deUint32 m_dataType; 339 int m_width; 340 int m_height; 341 342 std::vector<std::string> m_filenames; 343 344 std::vector<glu::TextureCube*> m_textures; 345 TextureRenderer m_renderer; 346}; 347 348 349TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height) 350 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc) 351 , m_renderCtx (renderCtx) 352 , m_renderCtxInfo (ctxInfo) 353 , m_minFilter (minFilter) 354 , m_magFilter (magFilter) 355 , m_wrapS (wrapS) 356 , m_wrapT (wrapT) 357 , m_format (format) 358 , m_dataType (dataType) 359 , m_width (width) 360 , m_height (height) 361 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 362{ 363} 364 365TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames) 366 : TestCase (testCtx, tcu::NODETYPE_ACCURACY, name, desc) 367 , m_renderCtx (renderCtx) 368 , m_renderCtxInfo (ctxInfo) 369 , m_minFilter (minFilter) 370 , m_magFilter (magFilter) 371 , m_wrapS (wrapS) 372 , m_wrapT (wrapT) 373 , m_format (GL_NONE) 374 , m_dataType (GL_NONE) 375 , m_width (0) 376 , m_height (0) 377 , m_filenames (filenames) 378 , m_renderer (renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 379{ 380} 381 382TextureCubeFilteringCase::~TextureCubeFilteringCase (void) 383{ 384 deinit(); 385} 386 387void TextureCubeFilteringCase::init (void) 388{ 389 try 390 { 391 if (!m_filenames.empty()) 392 { 393 m_textures.reserve(1); 394 m_textures.push_back(glu::TextureCube::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size() / 6, m_filenames)); 395 } 396 else 397 { 398 m_textures.reserve(2); 399 DE_ASSERT(m_width == m_height); 400 for (int ndx = 0; ndx < 2; ndx++) 401 m_textures.push_back(new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_width)); 402 403 const bool mipmaps = deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height); 404 const int numLevels = mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1; 405 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat()); 406 tcu::Vec4 cBias = fmtInfo.valueMin; 407 tcu::Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 408 409 // Fill first with gradient texture. 410 static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] = 411 { 412 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x 413 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x 414 { tcu::Vec4(-1.0f, 0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y 415 { tcu::Vec4(-1.0f, -1.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y 416 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z 417 { tcu::Vec4( 0.0f, 0.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z 418 }; 419 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 420 { 421 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 422 { 423 m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx); 424 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias); 425 } 426 } 427 428 // Fill second with grid texture. 429 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 430 { 431 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 432 { 433 deUint32 step = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST); 434 deUint32 rgb = step*levelNdx*face; 435 deUint32 colorA = 0xff000000 | rgb; 436 deUint32 colorB = 0xff000000 | ~rgb; 437 438 m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx); 439 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, toVec4(tcu::RGBA(colorA))*cScale + cBias, toVec4(tcu::RGBA(colorB))*cScale + cBias); 440 } 441 } 442 443 // Upload. 444 for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) 445 (*i)->upload(); 446 } 447 } 448 catch (const std::exception&) 449 { 450 // Clean up to save memory. 451 TextureCubeFilteringCase::deinit(); 452 throw; 453 } 454} 455 456void TextureCubeFilteringCase::deinit (void) 457{ 458 for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++) 459 delete *i; 460 m_textures.clear(); 461 462 m_renderer.clear(); 463} 464 465static void renderFaces ( 466 const glw::Functions& gl, 467 const SurfaceAccess& dstRef, 468 const tcu::TextureCube& refTexture, 469 const ReferenceParams& params, 470 TextureRenderer& renderer, 471 int x, 472 int y, 473 int width, 474 int height, 475 const tcu::Vec2& bottomLeft, 476 const tcu::Vec2& topRight, 477 const tcu::Vec2& texCoordTopRightFactor) 478{ 479 DE_ASSERT(width == dstRef.getWidth() && height == dstRef.getHeight()); 480 481 vector<float> texCoord; 482 483 DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6); 484 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 485 { 486 bool isRightmost = (face == 2) || (face == 5); 487 bool isTop = face >= 3; 488 int curX = (face % 3) * (width / 3); 489 int curY = (face / 3) * (height / 2); 490 int curW = isRightmost ? (width-curX) : (width / 3); 491 int curH = isTop ? (height-curY) : (height / 2); 492 493 computeQuadTexCoordCube(texCoord, (tcu::CubeFace)face, bottomLeft, topRight); 494 495 { 496 // Move the top and right edges of the texture coord quad. This is useful when we want a cube edge visible. 497 int texCoordSRow = face == tcu::CUBEFACE_NEGATIVE_X || face == tcu::CUBEFACE_POSITIVE_X ? 2 : 0; 498 int texCoordTRow = face == tcu::CUBEFACE_NEGATIVE_Y || face == tcu::CUBEFACE_POSITIVE_Y ? 2 : 1; 499 texCoord[6 + texCoordSRow] *= texCoordTopRightFactor.x(); 500 texCoord[9 + texCoordSRow] *= texCoordTopRightFactor.x(); 501 texCoord[3 + texCoordTRow] *= texCoordTopRightFactor.y(); 502 texCoord[9 + texCoordTRow] *= texCoordTopRightFactor.y(); 503 } 504 505 gl.viewport(x+curX, y+curY, curW, curH); 506 507 renderer.renderQuad(0, &texCoord[0], params); 508 509 sampleTexture(SurfaceAccess(dstRef, curX, curY, curW, curH), refTexture, &texCoord[0], params); 510 } 511 512 GLU_EXPECT_NO_ERROR(gl.getError(), "Post render"); 513} 514 515TextureCubeFilteringCase::IterateResult TextureCubeFilteringCase::iterate (void) 516{ 517 const glw::Functions& gl = m_renderCtx.getFunctions(); 518 TestLog& log = m_testCtx.getLog(); 519 const int cellSize = 28; 520 const int defViewportWidth = cellSize*6; 521 const int defViewportHeight = cellSize*4; 522 RandomViewport viewport (m_renderCtx.getRenderTarget(), cellSize*6, cellSize*4, deStringHash(getName())); 523 tcu::Surface renderedFrame (viewport.width, viewport.height); 524 tcu::Surface referenceFrame (viewport.width, viewport.height); 525 ReferenceParams sampleParams (TEXTURETYPE_CUBE); 526 const tcu::TextureFormat& texFmt = m_textures[0]->getRefTexture().getFormat(); 527 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 528 529 // Accuracy measurements are off unless viewport size is exactly as expected. 530 if (viewport.width < defViewportWidth || viewport.height < defViewportHeight) 531 throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__); 532 533 // Viewport is divided into 4 sections. 534 int leftWidth = viewport.width / 2; 535 int rightWidth = viewport.width - leftWidth; 536 int bottomHeight = viewport.height / 2; 537 int topHeight = viewport.height - bottomHeight; 538 539 int curTexNdx = 0; 540 541 // Sampling parameters. 542 sampleParams.sampler = mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter); 543 sampleParams.sampler.seamlessCubeMap = false; 544 sampleParams.samplerType = getSamplerType(texFmt); 545 sampleParams.colorBias = fmtInfo.lookupBias; 546 sampleParams.colorScale = fmtInfo.lookupScale; 547 sampleParams.lodMode = LODMODE_EXACT; 548 549 // Use unit 0. 550 gl.activeTexture(GL_TEXTURE0); 551 552 // Setup gradient texture. 553 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textures[curTexNdx]->getGLTexture()); 554 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS); 555 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT); 556 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter); 557 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, m_magFilter); 558 559 // Bottom left: Minification 560 renderFaces(gl, 561 SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, leftWidth, bottomHeight), 562 m_textures[curTexNdx]->getRefTexture(), sampleParams, 563 m_renderer, 564 viewport.x, viewport.y, leftWidth, bottomHeight, 565 tcu::Vec2(-0.81f, -0.81f), 566 tcu::Vec2( 0.8f, 0.8f), 567 tcu::Vec2(1.0f, 1.0f)); 568 569 // Bottom right: Magnification 570 renderFaces(gl, 571 SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, 0, rightWidth, bottomHeight), 572 m_textures[curTexNdx]->getRefTexture(), sampleParams, 573 m_renderer, 574 viewport.x+leftWidth, viewport.y, rightWidth, bottomHeight, 575 tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f), 576 tcu::Vec2(1.0f, 1.0f)); 577 578 if (m_textures.size() >= 2) 579 { 580 curTexNdx += 1; 581 582 // Setup second texture. 583 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_textures[curTexNdx]->getGLTexture()); 584 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS); 585 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT); 586 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter); 587 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, m_magFilter); 588 } 589 590 // Top left: Minification 591 renderFaces(gl, 592 SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), 0, bottomHeight, leftWidth, topHeight), 593 m_textures[curTexNdx]->getRefTexture(), sampleParams, 594 m_renderer, 595 viewport.x, viewport.y+bottomHeight, leftWidth, topHeight, 596 tcu::Vec2(-0.81f, -0.81f), 597 tcu::Vec2( 0.8f, 0.8f), 598 tcu::Vec2(1.0f, 1.0f)); 599 600 // Top right: Magnification 601 renderFaces(gl, 602 SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), leftWidth, bottomHeight, rightWidth, topHeight), 603 m_textures[curTexNdx]->getRefTexture(), sampleParams, 604 m_renderer, 605 viewport.x+leftWidth, viewport.y+bottomHeight, rightWidth, topHeight, 606 tcu::Vec2(0.5f, -0.65f), tcu::Vec2(0.8f, -0.8f), 607 tcu::Vec2(1.0f, 1.0f)); 608 609 // Read result. 610 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 611 612 // Compare and log. 613 { 614 DE_ASSERT(getNodeType() == tcu::NODETYPE_ACCURACY); 615 616 const int bestScoreDiff = 16; 617 const int worstScoreDiff = 10000; 618 619 int score = measureAccuracy(log, referenceFrame, renderedFrame, bestScoreDiff, worstScoreDiff); 620 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str()); 621 } 622 623 return STOP; 624} 625 626TextureFilteringTests::TextureFilteringTests (Context& context) 627 : TestCaseGroup(context, "filter", "Texture Filtering Accuracy Tests") 628{ 629} 630 631TextureFilteringTests::~TextureFilteringTests (void) 632{ 633} 634 635void TextureFilteringTests::init (void) 636{ 637 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Filtering"); 638 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cube Map Filtering"); 639 addChild(group2D); 640 addChild(groupCube); 641 642 static const struct 643 { 644 const char* name; 645 deUint32 mode; 646 } wrapModes[] = 647 { 648 { "clamp", GL_CLAMP_TO_EDGE }, 649 { "repeat", GL_REPEAT }, 650 { "mirror", GL_MIRRORED_REPEAT } 651 }; 652 653 static const struct 654 { 655 const char* name; 656 deUint32 mode; 657 } minFilterModes[] = 658 { 659 { "nearest", GL_NEAREST }, 660 { "linear", GL_LINEAR }, 661 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST }, 662 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST }, 663 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR }, 664 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR } 665 }; 666 667 static const struct 668 { 669 const char* name; 670 deUint32 mode; 671 } magFilterModes[] = 672 { 673 { "nearest", GL_NEAREST }, 674 { "linear", GL_LINEAR } 675 }; 676 677 static const struct 678 { 679 const char* name; 680 int width; 681 int height; 682 } sizes2D[] = 683 { 684 { "pot", 32, 64 }, 685 { "npot", 31, 55 } 686 }; 687 688 static const struct 689 { 690 const char* name; 691 int width; 692 int height; 693 } sizesCube[] = 694 { 695 { "pot", 64, 64 }, 696 { "npot", 63, 63 } 697 }; 698 699 static const struct 700 { 701 const char* name; 702 deUint32 format; 703 deUint32 dataType; 704 } formats[] = 705 { 706 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE }, 707 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 } 708 }; 709 710#define FOR_EACH(ITERATOR, ARRAY, BODY) \ 711 for (int ITERATOR = 0; ITERATOR < DE_LENGTH_OF_ARRAY(ARRAY); ITERATOR++) \ 712 BODY 713 714 // 2D cases. 715 FOR_EACH(minFilter, minFilterModes, 716 FOR_EACH(magFilter, magFilterModes, 717 FOR_EACH(wrapMode, wrapModes, 718 FOR_EACH(format, formats, 719 FOR_EACH(size, sizes2D, 720 { 721 bool isMipmap = minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR; 722 bool isClamp = wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE; 723 bool isRepeat = wrapModes[wrapMode].mode == GL_REPEAT; 724 bool isMagNearest = magFilterModes[magFilter].mode == GL_NEAREST; 725 bool isPotSize = deIsPowerOfTwo32(sizes2D[size].width) && deIsPowerOfTwo32(sizes2D[size].height); 726 727 if ((isMipmap || !isClamp) && !isPotSize) 728 continue; // Not supported. 729 730 if ((format != 0) && !(!isMipmap || (isRepeat && isMagNearest))) 731 continue; // Skip. 732 733 string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name; 734 735 if (!isMipmap) 736 name += string("_") + sizes2D[size].name; 737 738 group2D->addChild(new Texture2DFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 739 name.c_str(), "", 740 minFilterModes[minFilter].mode, 741 magFilterModes[magFilter].mode, 742 wrapModes[wrapMode].mode, 743 wrapModes[wrapMode].mode, 744 formats[format].format, formats[format].dataType, 745 sizes2D[size].width, sizes2D[size].height)); 746 }))))); 747 748 // Cubemap cases. 749 FOR_EACH(minFilter, minFilterModes, 750 FOR_EACH(magFilter, magFilterModes, 751 FOR_EACH(wrapMode, wrapModes, 752 FOR_EACH(format, formats, 753 FOR_EACH(size, sizesCube, 754 { 755 bool isMipmap = minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR; 756 bool isClamp = wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE; 757 bool isRepeat = wrapModes[wrapMode].mode == GL_REPEAT; 758 bool isMagNearest = magFilterModes[magFilter].mode == GL_NEAREST; 759 bool isPotSize = deIsPowerOfTwo32(sizesCube[size].width) && deIsPowerOfTwo32(sizesCube[size].height); 760 761 if ((isMipmap || !isClamp) && !isPotSize) 762 continue; // Not supported. 763 764 if (format != 0 && !(!isMipmap || (isRepeat && isMagNearest))) 765 continue; // Skip. 766 767 string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name; 768 769 if (!isMipmap) 770 name += string("_") + sizesCube[size].name; 771 772 groupCube->addChild(new TextureCubeFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), 773 name.c_str(), "", 774 minFilterModes[minFilter].mode, 775 magFilterModes[magFilter].mode, 776 wrapModes[wrapMode].mode, 777 wrapModes[wrapMode].mode, 778 formats[format].format, formats[format].dataType, 779 sizesCube[size].width, sizesCube[size].height)); 780 }))))); 781} 782 783} // Accuracy 784} // gles2 785} // deqp 786