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 size tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es2fTextureSizeTests.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 33#include "glwEnums.hpp" 34#include "glwFunctions.hpp" 35 36namespace deqp 37{ 38namespace gles2 39{ 40namespace Functional 41{ 42 43using tcu::TestLog; 44using std::vector; 45using std::string; 46using tcu::Sampler; 47using namespace glu; 48using namespace gls::TextureTestUtil; 49using namespace glu::TextureTestUtil; 50 51class Texture2DSizeCase : public tcu::TestCase 52{ 53public: 54 Texture2DSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps); 55 ~Texture2DSizeCase (void); 56 57 void init (void); 58 void deinit (void); 59 IterateResult iterate (void); 60 61private: 62 Texture2DSizeCase (const Texture2DSizeCase& other); 63 Texture2DSizeCase& operator= (const Texture2DSizeCase& other); 64 65 glu::RenderContext& m_renderCtx; 66 67 deUint32 m_format; 68 deUint32 m_dataType; 69 int m_width; 70 int m_height; 71 bool m_useMipmaps; 72 73 glu::Texture2D* m_texture; 74 TextureRenderer m_renderer; 75}; 76 77Texture2DSizeCase::Texture2DSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps) 78 : TestCase (testCtx, name, description) 79 , m_renderCtx (renderCtx) 80 , m_format (format) 81 , m_dataType (dataType) 82 , m_width (width) 83 , m_height (height) 84 , m_useMipmaps (mipmaps) 85 , m_texture (DE_NULL) 86 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 87{ 88} 89 90Texture2DSizeCase::~Texture2DSizeCase (void) 91{ 92 Texture2DSizeCase::deinit(); 93} 94 95void Texture2DSizeCase::init (void) 96{ 97 DE_ASSERT(!m_texture); 98 m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height); 99 100 int numLevels = m_useMipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1; 101 102 // Fill levels. 103 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 104 { 105 m_texture->getRefTexture().allocLevel(levelNdx); 106 tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(levelNdx), tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); 107 } 108} 109 110void Texture2DSizeCase::deinit (void) 111{ 112 delete m_texture; 113 m_texture = DE_NULL; 114 115 m_renderer.clear(); 116} 117 118Texture2DSizeCase::IterateResult Texture2DSizeCase::iterate (void) 119{ 120 const glw::Functions& gl = m_renderCtx.getFunctions(); 121 TestLog& log = m_testCtx.getLog(); 122 RandomViewport viewport (m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName())); 123 tcu::Surface renderedFrame (viewport.width, viewport.height); 124 tcu::Surface referenceFrame (viewport.width, viewport.height); 125 tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7); 126 deUint32 wrapS = GL_CLAMP_TO_EDGE; 127 deUint32 wrapT = GL_CLAMP_TO_EDGE; 128 deUint32 minFilter = m_useMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST; 129 deUint32 magFilter = GL_NEAREST; 130 vector<float> texCoord; 131 132 computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f)); 133 134 // Setup base viewport. 135 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 136 137 // Upload texture data to GL. 138 m_texture->upload(); 139 140 // Bind to unit 0. 141 gl.activeTexture(GL_TEXTURE0); 142 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture()); 143 144 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); 145 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); 146 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); 147 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); 148 GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state"); 149 150 // Draw. 151 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D); 152 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 153 154 // Compute reference. 155 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], ReferenceParams(TEXTURETYPE_2D, mapGLSampler(wrapS, wrapT, minFilter, magFilter))); 156 157 // Compare and log. 158 bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold); 159 160 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 161 isOk ? "Pass" : "Image comparison failed"); 162 163 return STOP; 164} 165 166class TextureCubeSizeCase : public tcu::TestCase 167{ 168public: 169 TextureCubeSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps); 170 ~TextureCubeSizeCase (void); 171 172 void init (void); 173 void deinit (void); 174 IterateResult iterate (void); 175 176private: 177 TextureCubeSizeCase (const TextureCubeSizeCase& other); 178 TextureCubeSizeCase& operator= (const TextureCubeSizeCase& other); 179 180 bool testFace (tcu::CubeFace face); 181 182 glu::RenderContext& m_renderCtx; 183 184 deUint32 m_format; 185 deUint32 m_dataType; 186 int m_width; 187 int m_height; 188 bool m_useMipmaps; 189 190 glu::TextureCube* m_texture; 191 TextureRenderer m_renderer; 192 193 int m_curFace; 194 bool m_isOk; 195}; 196 197TextureCubeSizeCase::TextureCubeSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps) 198 : TestCase (testCtx, name, description) 199 , m_renderCtx (renderCtx) 200 , m_format (format) 201 , m_dataType (dataType) 202 , m_width (width) 203 , m_height (height) 204 , m_useMipmaps (mipmaps) 205 , m_texture (DE_NULL) 206 , m_renderer (renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP) 207 , m_curFace (0) 208 , m_isOk (false) 209{ 210} 211 212TextureCubeSizeCase::~TextureCubeSizeCase (void) 213{ 214 TextureCubeSizeCase::deinit(); 215} 216 217void TextureCubeSizeCase::init (void) 218{ 219 DE_ASSERT(!m_texture); 220 DE_ASSERT(m_width == m_height); 221 m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_width); 222 223 static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] = 224 { 225 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x 226 { tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x 227 { tcu::Vec4(-1.0f, 0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y 228 { tcu::Vec4(-1.0f, -1.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y 229 { tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z 230 { tcu::Vec4( 0.0f, 0.0f, 0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z 231 }; 232 233 int numLevels = m_useMipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1; 234 235 // Fill levels. 236 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 237 { 238 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 239 { 240 m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx); 241 fillWithComponentGradients(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0], gradients[face][1]); 242 } 243 } 244 245 // Upload texture data to GL. 246 m_texture->upload(); 247 248 // Initialize iteration state. 249 m_curFace = 0; 250 m_isOk = true; 251} 252 253void TextureCubeSizeCase::deinit (void) 254{ 255 delete m_texture; 256 m_texture = DE_NULL; 257 258 m_renderer.clear(); 259} 260 261bool TextureCubeSizeCase::testFace (tcu::CubeFace face) 262{ 263 const glw::Functions& gl = m_renderCtx.getFunctions(); 264 TestLog& log = m_testCtx.getLog(); 265 RandomViewport viewport (m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName())+(deUint32)face); 266 tcu::Surface renderedFrame (viewport.width, viewport.height); 267 tcu::Surface referenceFrame (viewport.width, viewport.height); 268 tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7); 269 deUint32 wrapS = GL_CLAMP_TO_EDGE; 270 deUint32 wrapT = GL_CLAMP_TO_EDGE; 271 deUint32 minFilter = m_useMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST; 272 deUint32 magFilter = GL_NEAREST; 273 vector<float> texCoord; 274 275 computeQuadTexCoordCube(texCoord, face); 276 277 // \todo [2011-10-28 pyry] Image set name / section? 278 log << TestLog::Message << face << TestLog::EndMessage; 279 280 // Setup base viewport. 281 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 282 283 // Bind to unit 0. 284 gl.activeTexture(GL_TEXTURE0); 285 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture()); 286 287 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS); 288 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT); 289 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter); 290 gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter); 291 GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state"); 292 293 m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE); 294 glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess()); 295 296 // Compute reference. 297 Sampler sampler = mapGLSampler(wrapS, wrapT, minFilter, magFilter); 298 sampler.seamlessCubeMap = false; 299 sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], ReferenceParams(TEXTURETYPE_CUBE, sampler)); 300 301 // Compare and log. 302 return compareImages(log, referenceFrame, renderedFrame, threshold); 303} 304 305TextureCubeSizeCase::IterateResult TextureCubeSizeCase::iterate (void) 306{ 307 // Execute test for all faces. 308 if (!testFace((tcu::CubeFace)m_curFace)) 309 m_isOk = false; 310 311 m_curFace += 1; 312 313 if (m_curFace == tcu::CUBEFACE_LAST) 314 { 315 m_testCtx.setTestResult(m_isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 316 m_isOk ? "Pass" : "Image comparison failed"); 317 return STOP; 318 } 319 else 320 return CONTINUE; 321} 322 323TextureSizeTests::TextureSizeTests (Context& context) 324 : TestCaseGroup(context, "size", "Texture Size Tests") 325{ 326} 327 328TextureSizeTests::~TextureSizeTests (void) 329{ 330} 331 332void TextureSizeTests::init (void) 333{ 334 struct 335 { 336 int width; 337 int height; 338 } sizes2D[] = 339 { 340 { 64, 64 }, // Spec-mandated minimum. 341 { 65, 63 }, 342 { 512, 512 }, 343 { 1024, 1024 }, 344 { 2048, 2048 } 345 }; 346 347 struct 348 { 349 int width; 350 int height; 351 } sizesCube[] = 352 { 353 { 15, 15 }, 354 { 16, 16 }, // Spec-mandated minimum 355 { 64, 64 }, 356 { 128, 128 }, 357 { 256, 256 }, 358 { 512, 512 } 359 }; 360 361 struct 362 { 363 const char* name; 364 deUint32 format; 365 deUint32 dataType; 366 } formats[] = 367 { 368 { "l8", GL_LUMINANCE, GL_UNSIGNED_BYTE }, 369 { "rgba4444", GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, 370 { "rgb888", GL_RGB, GL_UNSIGNED_BYTE }, 371 { "rgba8888", GL_RGBA, GL_UNSIGNED_BYTE } 372 }; 373 374 // 2D cases. 375 tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Size Tests"); 376 addChild(group2D); 377 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++) 378 { 379 int width = sizes2D[sizeNdx].width; 380 int height = sizes2D[sizeNdx].height; 381 bool isPOT = deIsPowerOfTwo32(width) && deIsPowerOfTwo32(height); 382 383 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 384 { 385 for (int mipmap = 0; mipmap < (isPOT ? 2 : 1); mipmap++) 386 { 387 std::ostringstream name; 388 name << width << "x" << height << "_" << formats[formatNdx].name << (mipmap ? "_mipmap" : ""); 389 390 group2D->addChild(new Texture2DSizeCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", 391 formats[formatNdx].format, formats[formatNdx].dataType, 392 width, height, mipmap != 0)); 393 } 394 } 395 } 396 397 // Cubemap cases. 398 tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cubemap Texture Size Tests"); 399 addChild(groupCube); 400 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++) 401 { 402 int width = sizesCube[sizeNdx].width; 403 int height = sizesCube[sizeNdx].height; 404 bool isPOT = deIsPowerOfTwo32(width) && deIsPowerOfTwo32(height); 405 406 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 407 { 408 for (int mipmap = 0; mipmap < (isPOT ? 2 : 1); mipmap++) 409 { 410 std::ostringstream name; 411 name << width << "x" << height << "_" << formats[formatNdx].name << (mipmap ? "_mipmap" : ""); 412 413 groupCube->addChild(new TextureCubeSizeCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", 414 formats[formatNdx].format, formats[formatNdx].dataType, 415 width, height, mipmap != 0)); 416 } 417 } 418 } 419} 420 421} // Functional 422} // gles2 423} // deqp 424