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