Add CTS_EXT_texture_filter_anisotropic tests implementation

This is tests implementation for GL_EXT_texture_filter_anisotropic
extesnion.

affects:

KHR-GL44.texture_filter_anisotropic.*
KHR-GLES3.texture_filter_anisotropic.*

Components: Framework, OpenGL

VK-GL-CTS issue: 387

Change-Id: I1744454f0e148f99d2faad9905ab4d76d1edecd6
diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt
index be01dc9..9aaa364 100644
--- a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt
+++ b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt
@@ -4306,6 +4306,8 @@
 KHR-GL44.shader_texture_image_samples_tests.texture_functional_test
 KHR-GL44.shader_texture_image_samples_tests.glsl_extension_enable
 KHR-GL44.shader_texture_image_samples_tests.glsl_extension_require
+KHR-GL44.texture_filter_anisotropic.queries
+KHR-GL44.texture_filter_anisotropic.drawing
 KHR-GL44.geometry_shader.adjacency.adjacency_non_indiced_lines
 KHR-GL44.geometry_shader.adjacency.adjacency_indiced_lines
 KHR-GL44.geometry_shader.adjacency.adjacency_non_indiced_line_strip
diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt
index 52c7993..10cc83b 100644
--- a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt
+++ b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt
@@ -4306,6 +4306,8 @@
 KHR-GL45.shader_texture_image_samples_tests.texture_functional_test
 KHR-GL45.shader_texture_image_samples_tests.glsl_extension_enable
 KHR-GL45.shader_texture_image_samples_tests.glsl_extension_require
+KHR-GL45.texture_filter_anisotropic.queries
+KHR-GL45.texture_filter_anisotropic.drawing
 KHR-GL45.geometry_shader.adjacency.adjacency_non_indiced_lines
 KHR-GL45.geometry_shader.adjacency.adjacency_indiced_lines
 KHR-GL45.geometry_shader.adjacency.adjacency_non_indiced_line_strip
diff --git a/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles3-khr-master.txt b/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles3-khr-master.txt
index a7ebebd..d8ad627 100644
--- a/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles3-khr-master.txt
+++ b/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles3-khr-master.txt
@@ -2558,3 +2558,5 @@
 KHR-GLES3.shaders.shader_integer_mix.mix-bvec4
 KHR-GLES3.shaders.negative.initialize
 KHR-GLES3.shaders.negative.constant_sequence
+KHR-GLES3.texture_filter_anisotropic.queries
+KHR-GLES3.texture_filter_anisotropic.drawing
diff --git a/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles3-khr-master.txt b/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles3-khr-master.txt
index a7ebebd..d8ad627 100644
--- a/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles3-khr-master.txt
+++ b/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles3-khr-master.txt
@@ -2558,3 +2558,5 @@
 KHR-GLES3.shaders.shader_integer_mix.mix-bvec4
 KHR-GLES3.shaders.negative.initialize
 KHR-GLES3.shaders.negative.constant_sequence
+KHR-GLES3.texture_filter_anisotropic.queries
+KHR-GLES3.texture_filter_anisotropic.drawing
diff --git a/external/openglcts/modules/common/CMakeLists.txt b/external/openglcts/modules/common/CMakeLists.txt
index 39aa52f..6d1528b 100644
--- a/external/openglcts/modules/common/CMakeLists.txt
+++ b/external/openglcts/modules/common/CMakeLists.txt
@@ -56,6 +56,8 @@
 	glcTestCaseWrapper.hpp
 	glcTestPackage.cpp
 	glcTestPackage.hpp
+	glcTextureFilterAnisotropicTests.cpp
+	glcTextureFilterAnisotropicTests.hpp
 	glcUniformBlockCase.cpp
 	glcUniformBlockCase.hpp
 	glcUniformBlockTests.cpp
diff --git a/external/openglcts/modules/common/glcTextureFilterAnisotropicTests.cpp b/external/openglcts/modules/common/glcTextureFilterAnisotropicTests.cpp
new file mode 100644
index 0000000..7565b1c
--- /dev/null
+++ b/external/openglcts/modules/common/glcTextureFilterAnisotropicTests.cpp
@@ -0,0 +1,808 @@
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file
+ * \brief
+ */ /*-------------------------------------------------------------------*/
+
+/**
+ */ /*!
+ * \file  glcTextureFilterAnisotropicTests.cpp
+ * \brief Conformance tests for the GL_EXT_texture_filter_anisotropic functionality.
+ */ /*-------------------------------------------------------------------*/
+
+#include "deMath.h"
+
+#include "glcTextureFilterAnisotropicTests.hpp"
+#include "gluContextInfo.hpp"
+#include "gluDefs.hpp"
+#include "gluShaderProgram.hpp"
+#include "gluStrUtil.hpp"
+#include "gluTextureUtil.hpp"
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+#include "tcuRGBA.hpp"
+#include "tcuRenderTarget.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuTexture.hpp"
+
+using namespace glw;
+using namespace glu;
+
+namespace glcts
+{
+
+namespace TextureFilterAnisotropicUtils
+{
+
+/** Replace all occurrence of <token> with <text> in <str>
+ *
+ * @param token           Token string
+ * @param text            String that will be used as replacement for <token>
+ * @param string          String to work on
+ **/
+void replaceToken(const GLchar* token, const GLchar* text, std::string& str)
+{
+	const size_t text_length  = strlen(text);
+	const size_t token_length = strlen(token);
+
+	size_t token_position;
+	while ((token_position = str.find(token, 0)) != std::string::npos)
+	{
+		str.replace(token_position, token_length, text, text_length);
+	}
+}
+
+/** Allocate storage for texture
+ *
+ * @param target           Texture target
+ * @param refTexCoordType  GLSL texture coord type
+ * @param refSamplerType   GLSL texture sampler type
+ **/
+void generateTokens(GLenum target, std::string& refTexCoordType, std::string& refSamplerType)
+{
+	switch (target)
+	{
+	case GL_TEXTURE_2D:
+		refTexCoordType = "vec2";
+		refSamplerType  = "sampler2D";
+		break;
+	case GL_TEXTURE_2D_ARRAY:
+		refTexCoordType = "vec3";
+		refSamplerType  = "sampler2DArray";
+		break;
+	default:
+		refTexCoordType = "vec2";
+		refSamplerType  = "sampler2D";
+		break;
+	}
+}
+
+/** Set contents of texture
+ *
+ * @param gl              GL functions
+ * @param target          Texture target
+ * @param level           Mipmap level
+ * @param internal_format Format of data
+ * @param width           Width of texture
+ * @param height          Height of texture
+ * @param depth           Depth of texture
+ * @param format          Format of data
+ * @param type            Type of data
+ * @param data            Buffer with image data
+ **/
+void texImage(const Functions& gl, GLenum target, GLint level, GLenum internal_format, GLuint width, GLuint height,
+			  GLuint depth, GLenum format, GLenum type, const GLvoid* data)
+{
+	switch (target)
+	{
+	case GL_TEXTURE_2D:
+		gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "texImage");
+		break;
+	case GL_TEXTURE_2D_ARRAY:
+		gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "texImage");
+		break;
+	default:
+		TCU_FAIL("Invalid enum");
+		break;
+	}
+}
+
+/** Set contents of texture
+ *
+ * @param gl              GL functions
+ * @param target          Texture target
+ * @param level           Mipmap level
+ * @param x               X offset
+ * @param y               Y offset
+ * @param z               Z offset
+ * @param width           Width of texture
+ * @param height          Height of texture
+ * @param depth           Depth of texture
+ * @param format          Format of data
+ * @param type            Type of data
+ * @param pixels          Buffer with image data
+ **/
+void subImage(const Functions& gl, GLenum target, GLint level, GLint x, GLint y, GLint z, GLsizei width, GLsizei height,
+			  GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
+{
+	switch (target)
+	{
+	case GL_TEXTURE_2D:
+		gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
+		break;
+	case GL_TEXTURE_2D_ARRAY:
+		gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
+		break;
+	default:
+		TCU_FAIL("Invalid enum");
+		break;
+	}
+}
+
+} // TextureFilterAnisotropicUtils namespace
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ */
+TextureFilterAnisotropicQueriesTestCase::TextureFilterAnisotropicQueriesTestCase(deqp::Context& context)
+	: TestCase(context, "queries", "Verifies if queries for GL_EXT_texture_filter_anisotropic tokens works as expected")
+{
+	/* Left blank intentionally */
+}
+
+/** Stub deinit method. */
+void TextureFilterAnisotropicQueriesTestCase::deinit()
+{
+}
+
+/** Stub init method */
+void TextureFilterAnisotropicQueriesTestCase::init()
+{
+	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic"))
+		TCU_THROW(NotSupportedError, "GL_EXT_texture_filter_anisotropic not supported");
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult TextureFilterAnisotropicQueriesTestCase::iterate()
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	GLuint texture;
+	gl.genTextures(1, &texture);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+	gl.bindTexture(GL_TEXTURE_2D, texture);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+	TextureFilterAnisotropicUtils::texImage(gl, GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+	if (verifyTexParameters(gl) && verifyGet(gl))
+		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	else
+		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+	gl.deleteTextures(1, &texture);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
+
+	return STOP;
+}
+
+/** Verify if texParameter*, getTexParameter* queries for GL_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected.
+ *
+ *  @param gl   OpenGL functions wrapper
+ *
+ *  @return Returns true if queries test passed, false otherwise.
+ */
+bool TextureFilterAnisotropicQueriesTestCase::verifyTexParameters(const glw::Functions& gl)
+{
+	GLint iValue;
+	gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
+
+	// Verify initial integer value which should be equal to 1
+	if (iValue != 1)
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message
+						   << "GetTexParameteriv failed. Expected value: 1, Queried value: " << iValue
+						   << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	GLfloat fValue;
+	gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
+
+	// Verify initial float value which should be equal to 1.0f
+	if (fValue != 1.0f)
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message
+						   << "GetTexParameterfv failed. Expected value: 1.0, Queried value: " << iValue
+						   << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	// Set custom integer value and verify it
+	iValue = 2;
+	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, iValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
+
+	gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
+
+	if (iValue != 2)
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message
+						   << "texParameteri failed. Expected value: 2, Queried value: " << iValue
+						   << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	// Set custom float value and verify it
+	fValue = 1.5f;
+	gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterf");
+
+	gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
+
+	if (fValue != 1.5f)
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message
+						   << "texParameterf failed. Expected value: 1.5, Queried value: " << fValue
+						   << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	// Set custom integer value and verify it
+	iValue = 1;
+	gl.texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteriv");
+
+	gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
+
+	if (iValue != 1)
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message
+						   << "texParameteriv failed. Expected value: 1, Queried value: " << iValue
+						   << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	// Set custom float value and verify it
+	fValue = 2.0f;
+	gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv");
+
+	gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
+
+	if (fValue != 2.0f)
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message
+						   << "texParameterfv failed. Expected value: 2.0, Queried value: " << fValue
+						   << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	// Set texture filter anisotropic to 0.9f and check if INVALID_VALUE error is generated
+	fValue = 0.9f;
+	gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
+	GLint error = gl.getError();
+	if (error != GL_INVALID_VALUE)
+	{
+		m_testCtx.getLog()
+			<< tcu::TestLog::Message
+			<< "texParameterfv failed for values less then 1.0f. Expected INVALID_VALUE error. Generated error: "
+			<< glu::getErrorName(error) << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	return true;
+}
+
+/** Verify if get* queries for GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected.
+ *
+ *  @param gl   OpenGL functions wrapper
+ *
+ *  @return Returns true if queries test passed, false otherwise.
+ */
+bool TextureFilterAnisotropicQueriesTestCase::verifyGet(const glw::Functions& gl)
+{
+	GLboolean bValue;
+	GLint	 iValue;
+	GLfloat   fValue;
+	GLdouble  dValue;
+
+	gl.getBooleanv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &bValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
+
+	gl.getIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
+
+	gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
+
+	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
+	{
+		gl.getDoublev(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dValue);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublev");
+	}
+
+	return true;
+}
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ */
+TextureFilterAnisotropicDrawingTestCase::TextureFilterAnisotropicDrawingTestCase(deqp::Context& context)
+	: TestCase(context, "drawing", "Verifies if drawing texture with anisotropic filtering is performed as expected")
+	, m_vertex(DE_NULL)
+	, m_fragment(DE_NULL)
+	, m_texture(0)
+{
+	/* Left blank intentionally */
+}
+
+/** Stub deinit method. */
+void TextureFilterAnisotropicDrawingTestCase::deinit()
+{
+	/* Left blank intentionally */
+}
+
+/** Stub init method */
+void TextureFilterAnisotropicDrawingTestCase::init()
+{
+	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic"))
+		TCU_THROW(NotSupportedError, "GL_EXT_texture_filter_anisotropic not supported");
+
+	const tcu::RenderTarget& rt = m_context.getRenderTarget();
+
+	GLint width  = rt.getWidth();
+	GLint height = rt.getHeight();
+
+	if (width < 32 || height < 32)
+		TCU_THROW(NotSupportedError, "Config not supported - render buffer size should be at least 32x32");
+
+	m_vertex = "#version <VERSION>\n"
+			   "\n"
+			   "in highp vec3 vertex;\n"
+			   "in highp <TEXCOORD_TYPE> inTexCoord;\n"
+			   "out highp <TEXCOORD_TYPE> commonTexCoord;\n"
+			   "\n"
+			   "uniform highp mat4 projectionMatrix;\n"
+			   "\n"
+			   "void main()\n"
+			   "{\n"
+			   "    commonTexCoord = inTexCoord;\n"
+			   "    gl_Position = vec4(vertex, 1.0) * projectionMatrix;\n"
+			   "}\n";
+
+	m_fragment = "#version <VERSION>\n"
+				 "\n"
+				 "in highp <TEXCOORD_TYPE> commonTexCoord;\n"
+				 "out highp vec4 fragColor;\n"
+				 "\n"
+				 "uniform highp <SAMPLER_TYPE> tex;\n"
+				 "\n"
+				 "void main()\n"
+				 "{\n"
+				 "    fragColor = texture(tex, commonTexCoord);\n"
+				 "}\n"
+				 "\n";
+
+	m_supportedTargets.clear();
+	m_supportedTargets.push_back(GL_TEXTURE_2D);
+	m_supportedTargets.push_back(GL_TEXTURE_2D_ARRAY);
+
+	m_supportedInternalFormats.clear();
+	m_supportedInternalFormats.push_back(GL_R8);
+	m_supportedInternalFormats.push_back(GL_R8_SNORM);
+	m_supportedInternalFormats.push_back(GL_RG8);
+	m_supportedInternalFormats.push_back(GL_RG8_SNORM);
+	m_supportedInternalFormats.push_back(GL_RGB8);
+	m_supportedInternalFormats.push_back(GL_RGB8_SNORM);
+	m_supportedInternalFormats.push_back(GL_RGB565);
+	m_supportedInternalFormats.push_back(GL_RGBA4);
+	m_supportedInternalFormats.push_back(GL_RGB5_A1);
+	m_supportedInternalFormats.push_back(GL_RGBA8);
+	m_supportedInternalFormats.push_back(GL_RGBA8_SNORM);
+	m_supportedInternalFormats.push_back(GL_RGB10_A2);
+	m_supportedInternalFormats.push_back(GL_SRGB8);
+	m_supportedInternalFormats.push_back(GL_SRGB8_ALPHA8);
+	m_supportedInternalFormats.push_back(GL_R16F);
+	m_supportedInternalFormats.push_back(GL_RG16F);
+	m_supportedInternalFormats.push_back(GL_RGB16F);
+	m_supportedInternalFormats.push_back(GL_RGBA16F);
+	m_supportedInternalFormats.push_back(GL_R11F_G11F_B10F);
+	m_supportedInternalFormats.push_back(GL_RGB9_E5);
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult TextureFilterAnisotropicDrawingTestCase::iterate()
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	bool result = true;
+
+	GLfloat maxAnisoDegree = 2.0;
+
+	gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisoDegree);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
+
+	std::vector<GLfloat> anisoVec;
+	anisoVec.push_back(1.0f);
+	anisoVec.push_back(2.0f);
+	if (maxAnisoDegree > 2.0f)
+		anisoVec.push_back(maxAnisoDegree);
+
+	for (deUint32 iTarget = 0; iTarget < m_supportedTargets.size(); ++iTarget)
+	{
+		GLenum target = m_supportedTargets[iTarget];
+
+		for (deUint32 iFormat = 0; iFormat < m_supportedInternalFormats.size(); ++iFormat)
+		{
+			GLenum format = m_supportedInternalFormats[iFormat];
+
+			// Generate texture
+			generateTexture(gl, target);
+
+			// Fill texture with strips pattern
+			fillTexture(gl, target, format);
+
+			// Draw scene
+			GLuint lastPoints = 0xFFFFFFFF;
+			for (deUint32 i = 0; i < anisoVec.size(); ++i)
+			{
+				GLfloat aniso = anisoVec[i];
+
+				if (result)
+					result = result && drawTexture(gl, target, aniso);
+
+				// Verify result
+				if (result)
+				{
+					GLuint currentPoints = verifyScene(gl);
+
+					if (lastPoints <= currentPoints)
+					{
+						m_testCtx.getLog()
+							<< tcu::TestLog::Message
+							<< "Anisotropy verification failed (lastPoints <= currentPoints) for "
+							<< "anisotropy: " << aniso << ", "
+							<< "target: " << glu::getTextureTargetName(target) << ", "
+							<< "internalFormat: " << glu::getUncompressedTextureFormatName(format) << ", "
+							<< "lastPoints: " << lastPoints << ", "
+							<< "currentPoints: " << currentPoints << tcu::TestLog::EndMessage;
+
+						result = false;
+						break;
+					}
+
+					lastPoints = currentPoints;
+				}
+			}
+
+			// Release texture
+			releaseTexture(gl);
+
+			if (!result)
+			{
+				// Stop loops
+				iTarget = m_supportedTargets.size();
+				iFormat = m_supportedInternalFormats.size();
+			}
+		}
+	}
+
+	if (result)
+		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	else
+		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+	return STOP;
+}
+
+/** Generate texture and set filtering parameters.
+ *
+ *  @param gl              OpenGL functions wrapper
+ *  @param target          Texture target
+ *  @param internalFormat  Texture internal format
+ */
+void TextureFilterAnisotropicDrawingTestCase::generateTexture(const glw::Functions& gl, GLenum target)
+{
+	gl.genTextures(1, &m_texture);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures");
+	gl.bindTexture(target, m_texture);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
+
+	gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
+	gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
+	gl.texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
+	gl.texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
+	gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, 1);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
+}
+
+/** Fill texture with strips pattern.
+ *
+ *  @param gl              OpenGL functions wrapper
+ *  @param target          Texture target
+ *  @param internalFormat  Texture internal format
+ */
+void TextureFilterAnisotropicDrawingTestCase::fillTexture(const glw::Functions& gl, GLenum target,
+														  GLenum internalFormat)
+{
+	tcu::TextureFormat  texFormat   = glu::mapGLInternalFormat(internalFormat);
+	glu::TransferFormat transFormat = glu::getTransferFormat(texFormat);
+
+	for (int l = 0; l < 2; ++l)
+	{
+		GLuint texSize = 32 / (l + 1);
+
+		std::vector<GLubyte> vecData;
+		vecData.resize(texSize * texSize * texFormat.getPixelSize() * 2);
+
+		tcu::PixelBufferAccess bufferAccess(texFormat, texSize, texSize, 1, vecData.data());
+
+		for (GLuint x = 0; x < texSize; ++x)
+		{
+			for (GLuint y = 0; y < texSize; ++y)
+			{
+				int		  value = ((x * (l + 1)) % 8 < 4) ? 255 : 0;
+				tcu::RGBA rgbaColor(value, value, value, 255);
+				tcu::Vec4 color = rgbaColor.toVec();
+				bufferAccess.setPixel(color, x, y);
+			}
+		}
+
+		TextureFilterAnisotropicUtils::texImage(gl, target, l, internalFormat, texSize, texSize, 1, transFormat.format,
+												transFormat.dataType, vecData.data());
+	}
+}
+
+/** Render polygon with anisotropic filtering.
+ *
+ *  @param gl           OpenGL functions wrapper
+ *  @param target       Texture target
+ *  @param anisoDegree  Degree of anisotropy
+ *
+ *  @return Returns true if no error occured, false otherwise.
+ */
+bool TextureFilterAnisotropicDrawingTestCase::drawTexture(const glw::Functions& gl, GLenum target, GLfloat anisoDegree)
+{
+	const GLfloat vertices2[] = { -1.0f, 0.0f, -0.5f, 0.0f, 0.0f, -4.0f, 4.0f, -2.0f, 0.0f, 1.0f,
+								  1.0f,  0.0f, -0.5f, 1.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f };
+	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,
+								  1.0f,  0.0f, -0.5f, 1.0f, 0.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f, 0.0f };
+
+	// Projection values.
+	const GLfloat projectionMatrix[] = { 0.5f, 0.0f, 0.0f,		   0.0f,		 0.0f, 0.5f, 0.0f,  0.0f,
+										 0.0f, 0.0f, -2.5f / 1.5f, -2.0f / 1.5f, 0.0f, 0.0f, -1.0f, 0.0f };
+
+	gl.viewport(0, 0, 32, 32);
+
+	std::string vertexShader   = m_vertex;
+	std::string fragmentShader = m_fragment;
+
+	std::string texCoordType;
+	std::string samplerType;
+	TextureFilterAnisotropicUtils::generateTokens(target, texCoordType, samplerType);
+
+	TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), vertexShader);
+	TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), fragmentShader);
+	TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), vertexShader);
+	TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), fragmentShader);
+
+	if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
+	{
+		TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", vertexShader);
+		TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", fragmentShader);
+	}
+	else
+	{
+		TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", vertexShader);
+		TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", fragmentShader);
+	}
+
+	ProgramSources sources = makeVtxFragSources(vertexShader, fragmentShader);
+	ShaderProgram  program(gl, sources);
+
+	if (!program.isOk())
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
+						   << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
+						   << vertexShader << "\n"
+						   << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
+						   << fragmentShader << "\n"
+						   << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
+		return false;
+	}
+
+	GLuint vao;
+	gl.genVertexArrays(1, &vao);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
+	gl.bindVertexArray(vao);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
+
+	GLuint vbo;
+	gl.genBuffers(1, &vbo);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
+	gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
+
+	std::vector<GLfloat> vboData;
+	vboData.resize(24);
+
+	GLuint texCoordDim;
+	if (texCoordType == "vec2")
+	{
+		texCoordDim = 2;
+		deMemcpy((void*)vboData.data(), (void*)vertices2, sizeof(vertices2));
+	}
+	else
+	{
+		texCoordDim = 3;
+		deMemcpy((void*)vboData.data(), (void*)vertices3, sizeof(vertices3));
+	}
+
+	gl.bufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(GLfloat), (GLvoid*)vboData.data(), GL_DYNAMIC_DRAW);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+	gl.useProgram(program.getProgram());
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
+
+	GLuint matrixLocation = gl.getUniformLocation(program.getProgram(), "projectionMatrix");
+	GLuint texLocation	= gl.getUniformLocation(program.getProgram(), "tex");
+
+	gl.activeTexture(GL_TEXTURE0);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
+	gl.bindTexture(target, m_texture);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
+	gl.uniformMatrix4fv(matrixLocation, 1, GL_FALSE, projectionMatrix);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformMatrix4fv");
+	gl.uniform1i(texLocation, 0);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
+
+	gl.texParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoDegree);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv");
+
+	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+	gl.clear(GL_COLOR_BUFFER_BIT);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+	gl.enableVertexAttribArray(0);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+	gl.enableVertexAttribArray(1);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+	GLint attrLocationVertex = gl.getAttribLocation(program.getProgram(), "vertex");
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation");
+	GLint attrLocationInTexCoord = gl.getAttribLocation(program.getProgram(), "inTexCoord");
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation");
+
+	GLuint strideSize = (3 + texCoordDim) * sizeof(GLfloat);
+	gl.vertexAttribPointer(attrLocationVertex, 3, GL_FLOAT, GL_FALSE, strideSize, DE_NULL);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+	gl.vertexAttribPointer(attrLocationInTexCoord, texCoordDim, GL_FLOAT, GL_FALSE, strideSize,
+						   (GLvoid*)(3 * sizeof(GLfloat)));
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+	gl.disableVertexAttribArray(0);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+	gl.disableVertexAttribArray(1);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+	if (vbo)
+	{
+		gl.deleteBuffers(1, &vbo);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
+	}
+
+	if (vao)
+	{
+		gl.deleteVertexArrays(1, &vao);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
+	}
+
+	return true;
+}
+
+/** Verify rendered polygon anisotropy.
+ *
+ *  @param gl  OpenGL functions wrapper
+ *
+ *  @return Returns points value. Less points means better anisotropy (smoother strips).
+ */
+GLuint TextureFilterAnisotropicDrawingTestCase::verifyScene(const glw::Functions& gl)
+{
+	std::vector<GLubyte> pixels;
+	pixels.resize(32 * 8 * 4);
+
+	gl.readPixels(0, 23, 32, 8, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+	GLuint sum = 0;
+
+	GLubyte last	= 0;
+	GLubyte current = 0;
+	for (int j = 0; j < 8; ++j)
+	{
+		for (int i = 0; i < 32; ++i)
+		{
+			current = pixels[(i + j * 32) * 4];
+
+			if (i > 0)
+				sum += deAbs32((int)current - (int)last);
+
+			last = current;
+		}
+	}
+
+	return sum;
+}
+
+/** Release texture.
+ *
+ *  @param gl  OpenGL functions wrapper
+ */
+void TextureFilterAnisotropicDrawingTestCase::releaseTexture(const glw::Functions& gl)
+{
+	if (m_texture)
+		gl.deleteTextures(1, &m_texture);
+
+	m_texture = 0;
+}
+
+/** Constructor.
+ *
+ *  @param context Rendering context.
+ */
+TextureFilterAnisotropicTests::TextureFilterAnisotropicTests(deqp::Context& context)
+	: TestCaseGroup(context, "texture_filter_anisotropic",
+					"Verify conformance of CTS_EXT_texture_filter_anisotropic implementation")
+{
+}
+
+/** Initializes the test group contents. */
+void TextureFilterAnisotropicTests::init()
+{
+	addChild(new TextureFilterAnisotropicQueriesTestCase(m_context));
+	addChild(new TextureFilterAnisotropicDrawingTestCase(m_context));
+}
+
+} /* glcts namespace */
diff --git a/external/openglcts/modules/common/glcTextureFilterAnisotropicTests.hpp b/external/openglcts/modules/common/glcTextureFilterAnisotropicTests.hpp
new file mode 100644
index 0000000..44c18d3
--- /dev/null
+++ b/external/openglcts/modules/common/glcTextureFilterAnisotropicTests.hpp
@@ -0,0 +1,105 @@
+#ifndef _GLCTEXTUREFILTERANISOTROPICTESTS_HPP
+#define _GLCTEXTUREFILTERANISOTROPICTESTS_HPP
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file
+ * \brief
+ */ /*-------------------------------------------------------------------*/
+
+/**
+ */ /*!
+ * \file  glcTextureFilterAnisotropicTests.hpp
+ * \brief Conformance tests for the GL_EXT_texture_filter_anisotropic functionality.
+ */ /*-------------------------------------------------------------------*/
+#include "glcTestCase.hpp"
+#include "glwDefs.hpp"
+#include "tcuDefs.hpp"
+
+using namespace glw;
+using namespace glu;
+
+namespace glcts
+{
+
+class TextureFilterAnisotropicQueriesTestCase : public deqp::TestCase
+{
+public:
+	/* Public methods */
+	TextureFilterAnisotropicQueriesTestCase(deqp::Context& context);
+
+	void						 deinit();
+	void						 init();
+	tcu::TestNode::IterateResult iterate();
+
+private:
+	/* Private methods */
+	bool verifyTexParameters(const glw::Functions& gl);
+	bool verifyGet(const glw::Functions& gl);
+
+	/* Private members */
+};
+
+class TextureFilterAnisotropicDrawingTestCase : public deqp::TestCase
+{
+public:
+	/* Public methods */
+	TextureFilterAnisotropicDrawingTestCase(deqp::Context& context);
+
+	void						 deinit();
+	void						 init();
+	tcu::TestNode::IterateResult iterate();
+
+private:
+	/* Private methods */
+	void generateTexture(const glw::Functions& gl, GLenum target);
+	void fillTexture(const glw::Functions& gl, GLenum target, GLenum internalFormat);
+	bool drawTexture(const glw::Functions& gl, GLenum target, GLfloat anisoDegree);
+	GLuint verifyScene(const glw::Functions& gl);
+	void releaseTexture(const glw::Functions& gl);
+
+	void generateTokens(GLenum target, std::string& refTexCoordType, std::string& refSamplerType);
+
+	/* Private members */
+	const char* m_vertex;
+	const char* m_fragment;
+
+	std::vector<GLenum> m_supportedTargets;
+	std::vector<GLenum> m_supportedInternalFormats;
+
+	GLuint m_texture;
+};
+
+/** Test group which encapsulates all conformance tests */
+class TextureFilterAnisotropicTests : public deqp::TestCaseGroup
+{
+public:
+	/* Public methods */
+	TextureFilterAnisotropicTests(deqp::Context& context);
+
+	void init();
+
+private:
+	TextureFilterAnisotropicTests(const TextureFilterAnisotropicTests& other);
+	TextureFilterAnisotropicTests& operator=(const TextureFilterAnisotropicTests& other);
+};
+
+} /* glcts namespace */
+
+#endif // _GLCTEXTUREFILTERANISOTROPICTESTS_HPP
diff --git a/external/openglcts/modules/gl/gl4cTestPackages.cpp b/external/openglcts/modules/gl/gl4cTestPackages.cpp
index 4e0fb8b..96ad0c7 100644
--- a/external/openglcts/modules/gl/gl4cTestPackages.cpp
+++ b/external/openglcts/modules/gl/gl4cTestPackages.cpp
@@ -75,6 +75,7 @@
 #include "glcShaderIntegerMixTests.hpp"
 #include "glcShaderLibrary.hpp"
 #include "glcShaderMultisampleInterpolationTests.hpp"
+#include "glcTextureFilterAnisotropicTests.hpp"
 #include "glcViewportArrayTests.hpp"
 
 #include "../gles31/es31cArrayOfArraysTests.hpp"
@@ -290,6 +291,7 @@
 		addChild(new deqp::SampleVariablesTests(getContext(), glu::GLSL_VERSION_440));
 		addChild(new deqp::ShaderMultisampleInterpolationTests(getContext(), glu::GLSL_VERSION_440));
 		addChild(new glcts::ShaderTextureImageSamplesTests(getContext()));
+		addChild(new glcts::TextureFilterAnisotropicTests(getContext()));
 
 		glcts::ExtParameters extParams(glu::GLSL_VERSION_440, glcts::EXTENSIONTYPE_NONE);
 		addChild(new glcts::GeometryShaderTests(getContext(), extParams));
diff --git a/external/openglcts/modules/gles3/es3cTestPackage.cpp b/external/openglcts/modules/gles3/es3cTestPackage.cpp
index f631e6e..348d7bd 100644
--- a/external/openglcts/modules/gles3/es3cTestPackage.cpp
+++ b/external/openglcts/modules/gles3/es3cTestPackage.cpp
@@ -32,6 +32,7 @@
 #include "glcShaderNegativeTests.hpp"
 #include "glcShaderStructTests.hpp"
 #include "glcShaderSwitchTests.hpp"
+#include "glcTextureFilterAnisotropicTests.hpp"
 #include "glcUniformBlockTests.hpp"
 #include "gluStateReset.hpp"
 #include "glwEnums.hpp"
@@ -151,6 +152,7 @@
 	try
 	{
 		addChild(new ShaderTests(getContext()));
+		addChild(new glcts::TextureFilterAnisotropicTests(getContext()));
 	}
 	catch (...)
 	{
diff --git a/framework/opengl/wrapper/glwEnums.inl b/framework/opengl/wrapper/glwEnums.inl
index bb5d4b9..60711f7 100644
--- a/framework/opengl/wrapper/glwEnums.inl
+++ b/framework/opengl/wrapper/glwEnums.inl
@@ -707,6 +707,8 @@
 #define GL_UNSIGNED_INT_24_8											0x84FA
 #define GL_UNSIGNED_INT_24_8_OES										0x84FA
 #define GL_MAX_TEXTURE_LOD_BIAS											0x84FD
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT									0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT								0x84FF
 #define GL_TEXTURE_LOD_BIAS												0x8501
 #define GL_INCR_WRAP													0x8507
 #define GL_DECR_WRAP													0x8508
diff --git a/scripts/opengl/src_util.py b/scripts/opengl/src_util.py
index 2140dba..3a2bf34 100644
--- a/scripts/opengl/src_util.py
+++ b/scripts/opengl/src_util.py
@@ -53,6 +53,7 @@
 	'GL_EXT_geometry_shader',
 	'GL_EXT_robustness',
 	'GL_EXT_texture_buffer',
+	'GL_EXT_texture_filter_anisotropic',
 	'GL_EXT_texture_cube_map_array',
 	'GL_EXT_texture_snorm',
 	'GL_EXT_primitive_bounding_box',