Home | History | Annotate | Download | only in common
      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