1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2017 The Khronos Group Inc. 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 22 */ /*-------------------------------------------------------------------*/ 23 24 /** 25 */ /*! 26 * \file glcTextureFilterAnisotropicTests.cpp 27 * \brief Conformance tests for the GL_EXT_texture_filter_anisotropic functionality. 28 */ /*-------------------------------------------------------------------*/ 29 30 #include "deMath.h" 31 32 #include "glcTextureFilterAnisotropicTests.hpp" 33 #include "gluContextInfo.hpp" 34 #include "gluDefs.hpp" 35 #include "gluShaderProgram.hpp" 36 #include "gluStrUtil.hpp" 37 #include "gluTextureUtil.hpp" 38 #include "glwEnums.hpp" 39 #include "glwFunctions.hpp" 40 #include "tcuRGBA.hpp" 41 #include "tcuRenderTarget.hpp" 42 #include "tcuTestLog.hpp" 43 #include "tcuTexture.hpp" 44 45 using namespace glw; 46 using namespace glu; 47 48 namespace glcts 49 { 50 51 namespace TextureFilterAnisotropicUtils 52 { 53 54 /** Replace all occurrence of <token> with <text> in <str> 55 * 56 * @param token Token string 57 * @param text String that will be used as replacement for <token> 58 * @param string String to work on 59 **/ 60 void replaceToken(const GLchar* token, const GLchar* text, std::string& str) 61 { 62 const size_t text_length = strlen(text); 63 const size_t token_length = strlen(token); 64 65 size_t token_position; 66 while ((token_position = str.find(token, 0)) != std::string::npos) 67 { 68 str.replace(token_position, token_length, text, text_length); 69 } 70 } 71 72 /** Allocate storage for texture 73 * 74 * @param target Texture target 75 * @param refTexCoordType GLSL texture coord type 76 * @param refSamplerType GLSL texture sampler type 77 **/ 78 void generateTokens(GLenum target, std::string& refTexCoordType, std::string& refSamplerType) 79 { 80 switch (target) 81 { 82 case GL_TEXTURE_2D: 83 refTexCoordType = "vec2"; 84 refSamplerType = "sampler2D"; 85 break; 86 case GL_TEXTURE_2D_ARRAY: 87 refTexCoordType = "vec3"; 88 refSamplerType = "sampler2DArray"; 89 break; 90 default: 91 refTexCoordType = "vec2"; 92 refSamplerType = "sampler2D"; 93 break; 94 } 95 } 96 97 /** Set contents of texture 98 * 99 * @param gl GL functions 100 * @param target Texture target 101 * @param level Mipmap level 102 * @param internal_format Format of data 103 * @param width Width of texture 104 * @param height Height of texture 105 * @param depth Depth of texture 106 * @param format Format of data 107 * @param type Type of data 108 * @param data Buffer with image data 109 **/ 110 void texImage(const Functions& gl, GLenum target, GLint level, GLenum internal_format, GLuint width, GLuint height, 111 GLuint depth, GLenum format, GLenum type, const GLvoid* data) 112 { 113 switch (target) 114 { 115 case GL_TEXTURE_2D: 116 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data); 117 GLU_EXPECT_NO_ERROR(gl.getError(), "texImage"); 118 break; 119 case GL_TEXTURE_2D_ARRAY: 120 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data); 121 GLU_EXPECT_NO_ERROR(gl.getError(), "texImage"); 122 break; 123 default: 124 TCU_FAIL("Invalid enum"); 125 break; 126 } 127 } 128 129 /** Set contents of texture 130 * 131 * @param gl GL functions 132 * @param target Texture target 133 * @param level Mipmap level 134 * @param x X offset 135 * @param y Y offset 136 * @param z Z offset 137 * @param width Width of texture 138 * @param height Height of texture 139 * @param depth Depth of texture 140 * @param format Format of data 141 * @param type Type of data 142 * @param pixels Buffer with image data 143 **/ 144 void subImage(const Functions& gl, GLenum target, GLint level, GLint x, GLint y, GLint z, GLsizei width, GLsizei height, 145 GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) 146 { 147 switch (target) 148 { 149 case GL_TEXTURE_2D: 150 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels); 151 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D"); 152 break; 153 case GL_TEXTURE_2D_ARRAY: 154 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels); 155 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D"); 156 break; 157 default: 158 TCU_FAIL("Invalid enum"); 159 break; 160 } 161 } 162 163 } // TextureFilterAnisotropicUtils namespace 164 165 /** Constructor. 166 * 167 * @param context Rendering context 168 */ 169 TextureFilterAnisotropicQueriesTestCase::TextureFilterAnisotropicQueriesTestCase(deqp::Context& context) 170 : TestCase(context, "queries", "Verifies if queries for GL_EXT_texture_filter_anisotropic tokens works as expected") 171 { 172 /* Left blank intentionally */ 173 } 174 175 /** Stub deinit method. */ 176 void TextureFilterAnisotropicQueriesTestCase::deinit() 177 { 178 } 179 180 /** Stub init method */ 181 void TextureFilterAnisotropicQueriesTestCase::init() 182 { 183 glu::ContextType contextType = m_context.getRenderContext().getType(); 184 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) && 185 !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic") && 186 !m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_anisotropic")) 187 { 188 TCU_THROW(NotSupportedError, "texture filter anisotropic functionality not supported"); 189 } 190 } 191 192 /** Executes test iteration. 193 * 194 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 195 */ 196 tcu::TestNode::IterateResult TextureFilterAnisotropicQueriesTestCase::iterate() 197 { 198 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 199 200 GLuint texture; 201 gl.genTextures(1, &texture); 202 GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures"); 203 gl.bindTexture(GL_TEXTURE_2D, texture); 204 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture"); 205 TextureFilterAnisotropicUtils::texImage(gl, GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 206 207 if (verifyTexParameters(gl) && verifyGet(gl)) 208 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 209 else 210 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 211 212 gl.deleteTextures(1, &texture); 213 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures"); 214 215 return STOP; 216 } 217 218 /** Verify if texParameter*, getTexParameter* queries for GL_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected. 219 * 220 * @param gl OpenGL functions wrapper 221 * 222 * @return Returns true if queries test passed, false otherwise. 223 */ 224 bool TextureFilterAnisotropicQueriesTestCase::verifyTexParameters(const glw::Functions& gl) 225 { 226 GLint iValue; 227 gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue); 228 GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv"); 229 230 // Verify initial integer value which should be equal to 1 231 if (iValue != 1) 232 { 233 m_testCtx.getLog() << tcu::TestLog::Message 234 << "GetTexParameteriv failed. Expected value: 1, Queried value: " << iValue 235 << tcu::TestLog::EndMessage; 236 return false; 237 } 238 239 GLfloat fValue; 240 gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue); 241 GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv"); 242 243 // Verify initial float value which should be equal to 1.0f 244 if (fValue != 1.0f) 245 { 246 m_testCtx.getLog() << tcu::TestLog::Message 247 << "GetTexParameterfv failed. Expected value: 1.0, Queried value: " << iValue 248 << tcu::TestLog::EndMessage; 249 return false; 250 } 251 252 // Set custom integer value and verify it 253 iValue = 2; 254 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, iValue); 255 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri"); 256 257 gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue); 258 GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv"); 259 260 if (iValue != 2) 261 { 262 m_testCtx.getLog() << tcu::TestLog::Message 263 << "texParameteri failed. Expected value: 2, Queried value: " << iValue 264 << tcu::TestLog::EndMessage; 265 return false; 266 } 267 268 // Set custom float value and verify it 269 fValue = 1.5f; 270 gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fValue); 271 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterf"); 272 273 gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue); 274 GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv"); 275 276 if (fValue != 1.5f) 277 { 278 m_testCtx.getLog() << tcu::TestLog::Message 279 << "texParameterf failed. Expected value: 1.5, Queried value: " << fValue 280 << tcu::TestLog::EndMessage; 281 return false; 282 } 283 284 // Set custom integer value and verify it 285 iValue = 1; 286 gl.texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue); 287 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteriv"); 288 289 gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue); 290 GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv"); 291 292 if (iValue != 1) 293 { 294 m_testCtx.getLog() << tcu::TestLog::Message 295 << "texParameteriv failed. Expected value: 1, Queried value: " << iValue 296 << tcu::TestLog::EndMessage; 297 return false; 298 } 299 300 // Set custom float value and verify it 301 fValue = 2.0f; 302 gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue); 303 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv"); 304 305 gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue); 306 GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv"); 307 308 if (fValue != 2.0f) 309 { 310 m_testCtx.getLog() << tcu::TestLog::Message 311 << "texParameterfv failed. Expected value: 2.0, Queried value: " << fValue 312 << tcu::TestLog::EndMessage; 313 return false; 314 } 315 316 // Set texture filter anisotropic to 0.9f and check if INVALID_VALUE error is generated 317 fValue = 0.9f; 318 gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue); 319 GLint error = gl.getError(); 320 if (error != GL_INVALID_VALUE) 321 { 322 m_testCtx.getLog() 323 << tcu::TestLog::Message 324 << "texParameterfv failed for values less then 1.0f. Expected INVALID_VALUE error. Generated error: " 325 << glu::getErrorName(error) << tcu::TestLog::EndMessage; 326 return false; 327 } 328 329 return true; 330 } 331 332 /** Verify if get* queries for GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected. 333 * 334 * @param gl OpenGL functions wrapper 335 * 336 * @return Returns true if queries test passed, false otherwise. 337 */ 338 bool TextureFilterAnisotropicQueriesTestCase::verifyGet(const glw::Functions& gl) 339 { 340 GLboolean bValue; 341 GLint iValue; 342 GLfloat fValue; 343 GLdouble dValue; 344 345 gl.getBooleanv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &bValue); 346 GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv"); 347 348 gl.getIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &iValue); 349 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv"); 350 351 gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fValue); 352 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv"); 353 354 if (glu::isContextTypeGLCore(m_context.getRenderContext().getType())) 355 { 356 gl.getDoublev(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dValue); 357 GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublev"); 358 } 359 360 return true; 361 } 362 363 /** Constructor. 364 * 365 * @param context Rendering context 366 */ 367 TextureFilterAnisotropicDrawingTestCase::TextureFilterAnisotropicDrawingTestCase(deqp::Context& context) 368 : TestCase(context, "drawing", "Verifies if drawing texture with anisotropic filtering is performed as expected") 369 , m_vertex(DE_NULL) 370 , m_fragment(DE_NULL) 371 , m_texture(0) 372 { 373 /* Left blank intentionally */ 374 } 375 376 /** Stub deinit method. */ 377 void TextureFilterAnisotropicDrawingTestCase::deinit() 378 { 379 /* Left blank intentionally */ 380 } 381 382 /** Stub init method */ 383 void TextureFilterAnisotropicDrawingTestCase::init() 384 { 385 glu::ContextType contextType = m_context.getRenderContext().getType(); 386 if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) && 387 !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic") && 388 !m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_anisotropic")) 389 { 390 TCU_THROW(NotSupportedError, "texture filter anisotropic functionality not supported"); 391 } 392 393 const tcu::RenderTarget& rt = m_context.getRenderTarget(); 394 395 GLint width = rt.getWidth(); 396 GLint height = rt.getHeight(); 397 398 if (width < 32 || height < 32) 399 TCU_THROW(NotSupportedError, "Config not supported - render buffer size should be at least 32x32"); 400 401 m_vertex = "#version <VERSION>\n" 402 "\n" 403 "in highp vec3 vertex;\n" 404 "in highp <TEXCOORD_TYPE> inTexCoord;\n" 405 "out highp <TEXCOORD_TYPE> commonTexCoord;\n" 406 "\n" 407 "uniform highp mat4 projectionMatrix;\n" 408 "\n" 409 "void main()\n" 410 "{\n" 411 " commonTexCoord = inTexCoord;\n" 412 " gl_Position = vec4(vertex, 1.0) * projectionMatrix;\n" 413 "}\n"; 414 415 m_fragment = "#version <VERSION>\n" 416 "\n" 417 "in highp <TEXCOORD_TYPE> commonTexCoord;\n" 418 "out highp vec4 fragColor;\n" 419 "\n" 420 "uniform highp <SAMPLER_TYPE> tex;\n" 421 "\n" 422 "void main()\n" 423 "{\n" 424 " fragColor = texture(tex, commonTexCoord);\n" 425 "}\n" 426 "\n"; 427 428 m_supportedTargets.clear(); 429 m_supportedTargets.push_back(GL_TEXTURE_2D); 430 m_supportedTargets.push_back(GL_TEXTURE_2D_ARRAY); 431 432 m_supportedInternalFormats.clear(); 433 m_supportedInternalFormats.push_back(GL_R8); 434 m_supportedInternalFormats.push_back(GL_R8_SNORM); 435 m_supportedInternalFormats.push_back(GL_RG8); 436 m_supportedInternalFormats.push_back(GL_RG8_SNORM); 437 m_supportedInternalFormats.push_back(GL_RGB8); 438 m_supportedInternalFormats.push_back(GL_RGB8_SNORM); 439 m_supportedInternalFormats.push_back(GL_RGB565); 440 m_supportedInternalFormats.push_back(GL_RGBA4); 441 m_supportedInternalFormats.push_back(GL_RGB5_A1); 442 m_supportedInternalFormats.push_back(GL_RGBA8); 443 m_supportedInternalFormats.push_back(GL_RGBA8_SNORM); 444 m_supportedInternalFormats.push_back(GL_RGB10_A2); 445 m_supportedInternalFormats.push_back(GL_SRGB8); 446 m_supportedInternalFormats.push_back(GL_SRGB8_ALPHA8); 447 m_supportedInternalFormats.push_back(GL_R16F); 448 m_supportedInternalFormats.push_back(GL_RG16F); 449 m_supportedInternalFormats.push_back(GL_RGB16F); 450 m_supportedInternalFormats.push_back(GL_RGBA16F); 451 m_supportedInternalFormats.push_back(GL_R11F_G11F_B10F); 452 m_supportedInternalFormats.push_back(GL_RGB9_E5); 453 } 454 455 /** Executes test iteration. 456 * 457 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 458 */ 459 tcu::TestNode::IterateResult TextureFilterAnisotropicDrawingTestCase::iterate() 460 { 461 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 462 463 bool result = true; 464 465 GLfloat maxAnisoDegree = 2.0; 466 467 gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisoDegree); 468 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv"); 469 470 std::vector<GLfloat> anisoVec; 471 anisoVec.push_back(1.0f); 472 anisoVec.push_back(2.0f); 473 474 for (deUint32 iTarget = 0; iTarget < m_supportedTargets.size(); ++iTarget) 475 { 476 GLenum target = m_supportedTargets[iTarget]; 477 478 for (deUint32 iFormat = 0; iFormat < m_supportedInternalFormats.size(); ++iFormat) 479 { 480 GLenum format = m_supportedInternalFormats[iFormat]; 481 482 // Generate texture 483 generateTexture(gl, target); 484 485 // Fill texture with strips pattern 486 fillTexture(gl, target, format); 487 488 // Draw scene 489 GLuint lastPoints = 0xFFFFFFFF; 490 for (deUint32 i = 0; i < anisoVec.size(); ++i) 491 { 492 GLfloat aniso = anisoVec[i]; 493 494 if (result) 495 result = result && drawTexture(gl, target, aniso); 496 497 // Verify result 498 if (result) 499 { 500 GLuint currentPoints = verifyScene(gl); 501 502 if (lastPoints <= currentPoints) 503 { 504 m_testCtx.getLog() 505 << tcu::TestLog::Message 506 << "Anisotropy verification failed (lastPoints <= currentPoints) for " 507 << "anisotropy: " << aniso << ", " 508 << "target: " << glu::getTextureTargetName(target) << ", " 509 << "internalFormat: " << glu::getUncompressedTextureFormatName(format) << ", " 510 << "lastPoints: " << lastPoints << ", " 511 << "currentPoints: " << currentPoints << tcu::TestLog::EndMessage; 512 513 result = false; 514 break; 515 } 516 517 lastPoints = currentPoints; 518 } 519 } 520 521 // Release texture 522 releaseTexture(gl); 523 524 if (!result) 525 { 526 // Stop loops 527 iTarget = m_supportedTargets.size(); 528 iFormat = m_supportedInternalFormats.size(); 529 } 530 } 531 } 532 533 if (result) 534 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 535 else 536 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 537 return STOP; 538 } 539 540 /** Generate texture and set filtering parameters. 541 * 542 * @param gl OpenGL functions wrapper 543 * @param target Texture target 544 * @param internalFormat Texture internal format 545 */ 546 void TextureFilterAnisotropicDrawingTestCase::generateTexture(const glw::Functions& gl, GLenum target) 547 { 548 gl.genTextures(1, &m_texture); 549 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures"); 550 gl.bindTexture(target, m_texture); 551 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture"); 552 553 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 554 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); 555 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 556 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); 557 gl.texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 558 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); 559 gl.texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 560 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); 561 gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, 1); 562 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri"); 563 } 564 565 /** Fill texture with strips pattern. 566 * 567 * @param gl OpenGL functions wrapper 568 * @param target Texture target 569 * @param internalFormat Texture internal format 570 */ 571 void TextureFilterAnisotropicDrawingTestCase::fillTexture(const glw::Functions& gl, GLenum target, 572 GLenum internalFormat) 573 { 574 tcu::TextureFormat texFormat = glu::mapGLInternalFormat(internalFormat); 575 glu::TransferFormat transFormat = glu::getTransferFormat(texFormat); 576 577 for (int l = 0; l < 2; ++l) 578 { 579 GLuint texSize = 32 / (l + 1); 580 581 std::vector<GLubyte> vecData; 582 vecData.resize(texSize * texSize * texFormat.getPixelSize() * 2); 583 584 tcu::PixelBufferAccess bufferAccess(texFormat, texSize, texSize, 1, vecData.data()); 585 586 for (GLuint x = 0; x < texSize; ++x) 587 { 588 for (GLuint y = 0; y < texSize; ++y) 589 { 590 int value = ((x * (l + 1)) % 8 < 4) ? 255 : 0; 591 tcu::RGBA rgbaColor(value, value, value, 255); 592 tcu::Vec4 color = rgbaColor.toVec(); 593 bufferAccess.setPixel(color, x, y); 594 } 595 } 596 597 TextureFilterAnisotropicUtils::texImage(gl, target, l, internalFormat, texSize, texSize, 1, transFormat.format, 598 transFormat.dataType, vecData.data()); 599 } 600 } 601 602 /** Render polygon with anisotropic filtering. 603 * 604 * @param gl OpenGL functions wrapper 605 * @param target Texture target 606 * @param anisoDegree Degree of anisotropy 607 * 608 * @return Returns true if no error occured, false otherwise. 609 */ 610 bool TextureFilterAnisotropicDrawingTestCase::drawTexture(const glw::Functions& gl, GLenum target, GLfloat anisoDegree) 611 { 612 const GLfloat vertices2[] = { -1.0f, 0.0f, -0.5f, 0.0f, 0.0f, -4.0f, 4.0f, -2.0f, 0.0f, 1.0f, 613 1.0f, 0.0f, -0.5f, 1.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f }; 614 const GLfloat vertices3[] = { -1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, -4.0f, 4.0f, -2.0f, 0.0f, 1.0f, 0.0f, 615 1.0f, 0.0f, -0.5f, 1.0f, 0.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f, 0.0f }; 616 617 // Projection values. 618 const GLfloat projectionMatrix[] = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 619 0.0f, 0.0f, -2.5f / 1.5f, -2.0f / 1.5f, 0.0f, 0.0f, -1.0f, 0.0f }; 620 621 gl.viewport(0, 0, 32, 32); 622 623 std::string vertexShader = m_vertex; 624 std::string fragmentShader = m_fragment; 625 626 std::string texCoordType; 627 std::string samplerType; 628 TextureFilterAnisotropicUtils::generateTokens(target, texCoordType, samplerType); 629 630 TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), vertexShader); 631 TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), fragmentShader); 632 TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), vertexShader); 633 TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), fragmentShader); 634 635 if (glu::isContextTypeGLCore(m_context.getRenderContext().getType())) 636 { 637 TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", vertexShader); 638 TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", fragmentShader); 639 } 640 else 641 { 642 TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", vertexShader); 643 TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", fragmentShader); 644 } 645 646 ProgramSources sources = makeVtxFragSources(vertexShader, fragmentShader); 647 ShaderProgram program(gl, sources); 648 649 if (!program.isOk()) 650 { 651 m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n" 652 << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n" 653 << vertexShader << "\n" 654 << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n" 655 << fragmentShader << "\n" 656 << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage; 657 return false; 658 } 659 660 GLuint vao; 661 gl.genVertexArrays(1, &vao); 662 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays"); 663 gl.bindVertexArray(vao); 664 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray"); 665 666 GLuint vbo; 667 gl.genBuffers(1, &vbo); 668 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers"); 669 gl.bindBuffer(GL_ARRAY_BUFFER, vbo); 670 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer"); 671 672 std::vector<GLfloat> vboData; 673 vboData.resize(24); 674 675 GLuint texCoordDim; 676 if (texCoordType == "vec2") 677 { 678 texCoordDim = 2; 679 deMemcpy((void*)vboData.data(), (void*)vertices2, sizeof(vertices2)); 680 } 681 else 682 { 683 texCoordDim = 3; 684 deMemcpy((void*)vboData.data(), (void*)vertices3, sizeof(vertices3)); 685 } 686 687 gl.bufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(GLfloat), (GLvoid*)vboData.data(), GL_DYNAMIC_DRAW); 688 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData"); 689 690 gl.useProgram(program.getProgram()); 691 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram"); 692 693 GLuint matrixLocation = gl.getUniformLocation(program.getProgram(), "projectionMatrix"); 694 GLuint texLocation = gl.getUniformLocation(program.getProgram(), "tex"); 695 696 gl.activeTexture(GL_TEXTURE0); 697 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture"); 698 gl.bindTexture(target, m_texture); 699 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture"); 700 gl.uniformMatrix4fv(matrixLocation, 1, GL_FALSE, projectionMatrix); 701 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformMatrix4fv"); 702 gl.uniform1i(texLocation, 0); 703 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i"); 704 705 gl.texParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoDegree); 706 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv"); 707 708 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 709 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor"); 710 gl.clear(GL_COLOR_BUFFER_BIT); 711 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear"); 712 713 gl.enableVertexAttribArray(0); 714 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray"); 715 gl.enableVertexAttribArray(1); 716 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray"); 717 718 GLint attrLocationVertex = gl.getAttribLocation(program.getProgram(), "vertex"); 719 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation"); 720 GLint attrLocationInTexCoord = gl.getAttribLocation(program.getProgram(), "inTexCoord"); 721 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation"); 722 723 GLuint strideSize = (3 + texCoordDim) * sizeof(GLfloat); 724 gl.vertexAttribPointer(attrLocationVertex, 3, GL_FLOAT, GL_FALSE, strideSize, DE_NULL); 725 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer"); 726 gl.vertexAttribPointer(attrLocationInTexCoord, texCoordDim, GL_FLOAT, GL_FALSE, strideSize, 727 (GLvoid*)(3 * sizeof(GLfloat))); 728 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer"); 729 730 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 731 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray"); 732 733 gl.disableVertexAttribArray(0); 734 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray"); 735 gl.disableVertexAttribArray(1); 736 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray"); 737 738 if (vbo) 739 { 740 gl.deleteBuffers(1, &vbo); 741 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers"); 742 } 743 744 if (vao) 745 { 746 gl.deleteVertexArrays(1, &vao); 747 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays"); 748 } 749 750 return true; 751 } 752 753 /** Verify rendered polygon anisotropy. 754 * 755 * @param gl OpenGL functions wrapper 756 * 757 * @return Returns points value. Less points means better anisotropy (smoother strips). 758 */ 759 GLuint TextureFilterAnisotropicDrawingTestCase::verifyScene(const glw::Functions& gl) 760 { 761 std::vector<GLubyte> pixels; 762 pixels.resize(32 * 8 * 4); 763 764 gl.readPixels(0, 23, 32, 8, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); 765 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels"); 766 767 GLuint sum = 0; 768 769 GLubyte last = 0; 770 GLubyte current = 0; 771 for (int j = 0; j < 8; ++j) 772 { 773 for (int i = 0; i < 32; ++i) 774 { 775 current = pixels[(i + j * 32) * 4]; 776 777 if (i > 0) 778 sum += deAbs32((int)current - (int)last); 779 780 last = current; 781 } 782 } 783 784 return sum; 785 } 786 787 /** Release texture. 788 * 789 * @param gl OpenGL functions wrapper 790 */ 791 void TextureFilterAnisotropicDrawingTestCase::releaseTexture(const glw::Functions& gl) 792 { 793 if (m_texture) 794 gl.deleteTextures(1, &m_texture); 795 796 m_texture = 0; 797 } 798 799 /** Constructor. 800 * 801 * @param context Rendering context. 802 */ 803 TextureFilterAnisotropicTests::TextureFilterAnisotropicTests(deqp::Context& context) 804 : TestCaseGroup(context, "texture_filter_anisotropic", 805 "Verify conformance of CTS_EXT_texture_filter_anisotropic implementation") 806 { 807 } 808 809 /** Initializes the test group contents. */ 810 void TextureFilterAnisotropicTests::init() 811 { 812 addChild(new TextureFilterAnisotropicQueriesTestCase(m_context)); 813 addChild(new TextureFilterAnisotropicDrawingTestCase(m_context)); 814 } 815 816 } /* glcts namespace */ 817