/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 2.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * 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 Texture filtering tests.
 *//*--------------------------------------------------------------------*/

#include "es2fTextureFilteringTests.hpp"
#include "glsTextureTestUtil.hpp"
#include "gluTexture.hpp"
#include "gluStrUtil.hpp"
#include "gluTextureUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "tcuTestLog.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuTexLookupVerifier.hpp"
#include "tcuVectorUtil.hpp"
#include "deStringUtil.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"

namespace deqp
{
namespace gles2
{
namespace Functional
{

using tcu::TestLog;
using std::vector;
using std::string;
using tcu::Sampler;
using namespace glu;
using namespace gls::TextureTestUtil;

enum
{
	VIEWPORT_WIDTH		= 64,
	VIEWPORT_HEIGHT		= 64,
	MIN_VIEWPORT_WIDTH	= 64,
	MIN_VIEWPORT_HEIGHT	= 64
};

class Texture2DFilteringCase : public tcu::TestCase
{
public:
									Texture2DFilteringCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height);
									Texture2DFilteringCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames);
									~Texture2DFilteringCase		(void);

	void							init						(void);
	void							deinit						(void);
	IterateResult					iterate						(void);

private:
									Texture2DFilteringCase		(const Texture2DFilteringCase& other);
	Texture2DFilteringCase&			operator=					(const Texture2DFilteringCase& other);

	glu::RenderContext&				m_renderCtx;
	const glu::ContextInfo&			m_renderCtxInfo;

	const deUint32					m_minFilter;
	const deUint32					m_magFilter;
	const deUint32					m_wrapS;
	const deUint32					m_wrapT;

	const deUint32					m_format;
	const deUint32					m_dataType;
	const int						m_width;
	const int						m_height;

	const std::vector<std::string>	m_filenames;

	struct FilterCase
	{
		const glu::Texture2D*	texture;
		tcu::Vec2				minCoord;
		tcu::Vec2				maxCoord;

		FilterCase (void)
			: texture(DE_NULL)
		{
		}

		FilterCase (const glu::Texture2D* tex_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
			: texture	(tex_)
			, minCoord	(minCoord_)
			, maxCoord	(maxCoord_)
		{
		}
	};

	std::vector<glu::Texture2D*>	m_textures;
	std::vector<FilterCase>			m_cases;

	TextureRenderer					m_renderer;

	int								m_caseNdx;
};

Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height)
	: TestCase			(testCtx, name, desc)
	, m_renderCtx		(renderCtx)
	, m_renderCtxInfo	(ctxInfo)
	, m_minFilter		(minFilter)
	, m_magFilter		(magFilter)
	, m_wrapS			(wrapS)
	, m_wrapT			(wrapT)
	, m_format			(format)
	, m_dataType		(dataType)
	, m_width			(width)
	, m_height			(height)
	, m_renderer		(renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
	, m_caseNdx			(0)
{
}

Texture2DFilteringCase::Texture2DFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames)
	: TestCase			(testCtx, name, desc)
	, m_renderCtx		(renderCtx)
	, m_renderCtxInfo	(ctxInfo)
	, m_minFilter		(minFilter)
	, m_magFilter		(magFilter)
	, m_wrapS			(wrapS)
	, m_wrapT			(wrapT)
	, m_format			(GL_NONE)
	, m_dataType		(GL_NONE)
	, m_width			(0)
	, m_height			(0)
	, m_filenames		(filenames)
	, m_renderer		(renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
	, m_caseNdx			(0)
{
}

Texture2DFilteringCase::~Texture2DFilteringCase (void)
{
	deinit();
}

void Texture2DFilteringCase::init (void)
{
	try
	{
		if (!m_filenames.empty())
		{
			m_textures.reserve(1);
			m_textures.push_back(glu::Texture2D::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size(), m_filenames));
		}
		else
		{
			// Create 2 textures.
			m_textures.reserve(2);
			for (int ndx = 0; ndx < 2; ndx++)
				m_textures.push_back(new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height));

			bool					mipmaps		= deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height);
			int						numLevels	= mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
			tcu::Vec4				cBias		= fmtInfo.valueMin;
			tcu::Vec4				cScale		= fmtInfo.valueMax-fmtInfo.valueMin;

			// Fill first gradient texture.
			for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
			{
				tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
				tcu::Vec4 gMax = tcu::Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;

				m_textures[0]->getRefTexture().allocLevel(levelNdx);
				tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
			}

			// Fill second with grid texture.
			for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
			{
				deUint32	step	= 0x00ffffff / numLevels;
				deUint32	rgb		= step*levelNdx;
				deUint32	colorA	= 0xff000000 | rgb;
				deUint32	colorB	= 0xff000000 | ~rgb;

				m_textures[1]->getRefTexture().allocLevel(levelNdx);
				tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, toVec4(tcu::RGBA(colorA))*cScale + cBias, toVec4(tcu::RGBA(colorB))*cScale + cBias);
			}

			// Upload.
			for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
				(*i)->upload();
		}

		// Compute cases.
		{
			const struct
			{
				int		texNdx;
				float	lodX;
				float	lodY;
				float	oX;
				float	oY;
			} cases[] =
			{
				{ 0,	1.6f,	2.9f,	-1.0f,	-2.7f	},
				{ 0,	-2.0f,	-1.35f,	-0.2f,	0.7f	},
				{ 1,	0.14f,	0.275f,	-1.5f,	-1.1f	},
				{ 1,	-0.92f,	-2.64f,	0.4f,	-0.1f	},
			};

			const float	viewportW	= (float)de::min<int>(VIEWPORT_WIDTH, m_renderCtx.getRenderTarget().getWidth());
			const float	viewportH	= (float)de::min<int>(VIEWPORT_HEIGHT, m_renderCtx.getRenderTarget().getHeight());

			for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
			{
				const int	texNdx	= de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
				const float	lodX	= cases[caseNdx].lodX;
				const float	lodY	= cases[caseNdx].lodY;
				const float	oX		= cases[caseNdx].oX;
				const float	oY		= cases[caseNdx].oY;
				const float	sX		= deFloatExp2(lodX)*viewportW / float(m_textures[texNdx]->getRefTexture().getWidth());
				const float	sY		= deFloatExp2(lodY)*viewportH / float(m_textures[texNdx]->getRefTexture().getHeight());

				m_cases.push_back(FilterCase(m_textures[texNdx], tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY)));
			}
		}

		m_caseNdx = 0;
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	}
	catch (...)
	{
		// Clean up to save memory.
		Texture2DFilteringCase::deinit();
		throw;
	}
}

void Texture2DFilteringCase::deinit (void)
{
	for (std::vector<glu::Texture2D*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
		delete *i;
	m_textures.clear();

	m_renderer.clear();
	m_cases.clear();
}

Texture2DFilteringCase::IterateResult Texture2DFilteringCase::iterate (void)
{
	const glw::Functions&			gl			= m_renderCtx.getFunctions();
	const RandomViewport			viewport	(m_renderCtx.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, deStringHash(getName()) ^ deInt32Hash(m_caseNdx));
	const tcu::TextureFormat		texFmt		= m_textures[0]->getRefTexture().getFormat();
	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFmt);
	const FilterCase&				curCase		= m_cases[m_caseNdx];
	const tcu::ScopedLogSection		section		(m_testCtx.getLog(), string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
	ReferenceParams					refParams	(TEXTURETYPE_2D);
	tcu::Surface					rendered	(viewport.width, viewport.height);
	vector<float>					texCoord;

	if (viewport.width < MIN_VIEWPORT_WIDTH || viewport.height < MIN_VIEWPORT_HEIGHT)
		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);

	// Setup params for reference.
	refParams.sampler		= mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
	refParams.samplerType	= getSamplerType(texFmt);
	refParams.lodMode		= LODMODE_EXACT;
	refParams.colorBias		= fmtInfo.lookupBias;
	refParams.colorScale	= fmtInfo.lookupScale;

	// Compute texture coordinates.
	m_testCtx.getLog() << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
	computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);

	gl.bindTexture	(GL_TEXTURE_2D, curCase.texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	m_magFilter);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		m_wrapS);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		m_wrapT);

	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
	m_renderer.renderQuad(0, &texCoord[0], refParams);
	glu::readPixels(m_renderCtx, viewport.x, viewport.y, rendered.getAccess());

	{
		const bool				isNearestOnly	= m_minFilter == GL_NEAREST && m_magFilter == GL_NEAREST;
		const tcu::PixelFormat	pixelFormat		= m_renderCtx.getRenderTarget().getPixelFormat();
		const tcu::IVec4		colorBits		= max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
		tcu::LodPrecision		lodPrecision;
		tcu::LookupPrecision	lookupPrecision;

		lodPrecision.derivateBits		= 8;
		lodPrecision.lodBits			= 6;
		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
		lookupPrecision.coordBits		= tcu::IVec3(20,20,0);
		lookupPrecision.uvwBits			= tcu::IVec3(7,7,0);
		lookupPrecision.colorMask		= getCompareMask(pixelFormat);

		const bool isOk = verifyTextureResult(m_testCtx, rendered.getAccess(), curCase.texture->getRefTexture(),
											  &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);

		if (!isOk)
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
	}

	m_caseNdx += 1;
	return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP;
}


class TextureCubeFilteringCase : public tcu::TestCase
{
public:
									TextureCubeFilteringCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height);
									TextureCubeFilteringCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames);
									~TextureCubeFilteringCase	(void);

	void							init						(void);
	void							deinit						(void);
	IterateResult					iterate						(void);

private:
									TextureCubeFilteringCase	(const TextureCubeFilteringCase& other);
	TextureCubeFilteringCase&		operator=					(const TextureCubeFilteringCase& other);

	glu::RenderContext&				m_renderCtx;
	const glu::ContextInfo&			m_renderCtxInfo;

	const deUint32					m_minFilter;
	const deUint32					m_magFilter;
	const deUint32					m_wrapS;
	const deUint32					m_wrapT;

	const deUint32					m_format;
	const deUint32					m_dataType;
	const int						m_width;
	const int						m_height;

	const std::vector<std::string>	m_filenames;

	struct FilterCase
	{
		const glu::TextureCube*	texture;
		tcu::Vec2				bottomLeft;
		tcu::Vec2				topRight;

		FilterCase (void)
			: texture(DE_NULL)
		{
		}

		FilterCase (const glu::TextureCube* tex_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
			: texture	(tex_)
			, bottomLeft(bottomLeft_)
			, topRight	(topRight_)
		{
		}
	};

	std::vector<glu::TextureCube*>	m_textures;
	std::vector<FilterCase>			m_cases;

	TextureRenderer					m_renderer;

	int								m_caseNdx;
};

TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 format, deUint32 dataType, int width, int height)
	: TestCase					(testCtx, name, desc)
	, m_renderCtx				(renderCtx)
	, m_renderCtxInfo			(ctxInfo)
	, m_minFilter				(minFilter)
	, m_magFilter				(magFilter)
	, m_wrapS					(wrapS)
	, m_wrapT					(wrapT)
	, m_format					(format)
	, m_dataType				(dataType)
	, m_width					(width)
	, m_height					(height)
	, m_renderer				(renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
	, m_caseNdx					(0)
{
}

TextureCubeFilteringCase::TextureCubeFilteringCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, const std::vector<std::string>& filenames)
	: TestCase					(testCtx, name, desc)
	, m_renderCtx				(renderCtx)
	, m_renderCtxInfo			(ctxInfo)
	, m_minFilter				(minFilter)
	, m_magFilter				(magFilter)
	, m_wrapS					(wrapS)
	, m_wrapT					(wrapT)
	, m_format					(GL_NONE)
	, m_dataType				(GL_NONE)
	, m_width					(0)
	, m_height					(0)
	, m_filenames				(filenames)
	, m_renderer				(renderCtx, testCtx, glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
	, m_caseNdx					(0)
{
}

TextureCubeFilteringCase::~TextureCubeFilteringCase (void)
{
	deinit();
}

void TextureCubeFilteringCase::init (void)
{
	try
	{
		if (!m_filenames.empty())
		{
			m_textures.reserve(1);
			m_textures.push_back(glu::TextureCube::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size() / 6, m_filenames));
		}
		else
		{
			DE_ASSERT(m_width == m_height);
			m_textures.reserve(2);
			for (int ndx = 0; ndx < 2; ndx++)
				m_textures.push_back(new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_width));

			const bool				mipmaps		= deIsPowerOfTwo32(m_width) && deIsPowerOfTwo32(m_height);
			const int				numLevels	= mipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
			tcu::Vec4				cBias		= fmtInfo.valueMin;
			tcu::Vec4				cScale		= fmtInfo.valueMax-fmtInfo.valueMin;

			// Fill first with gradient texture.
			static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
			{
				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
				{ tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
				{ tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
				{ tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
				{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
				{ tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
			};
			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
			{
				for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
				{
					m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
					tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
				}
			}

			// Fill second with grid texture.
			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
			{
				for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
				{
					deUint32	step	= 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
					deUint32	rgb		= step*levelNdx*face;
					deUint32	colorA	= 0xff000000 | rgb;
					deUint32	colorB	= 0xff000000 | ~rgb;

					m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
					tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, toVec4(tcu::RGBA(colorA))*cScale + cBias, toVec4(tcu::RGBA(colorB))*cScale + cBias);
				}
			}

			// Upload.
			for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
				(*i)->upload();
		}

		// Compute cases
		{
			const glu::TextureCube*	tex0	= m_textures[0];
			const glu::TextureCube* tex1	= m_textures.size() > 1 ? m_textures[1] : tex0;

			// \note Coordinates are chosen so that they only sample face interior. ES3 has changed edge sampling behavior
			//		 and hw is not expected to implement both modes.
			m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f)));	// minification
			m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f)));		// magnification
			m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f)));	// minification
			m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f), tcu::Vec2(0.6f, 0.5f)));		// magnification
		}

		m_caseNdx = 0;
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	}
	catch (...)
	{
		// Clean up to save memory.
		TextureCubeFilteringCase::deinit();
		throw;
	}
}

void TextureCubeFilteringCase::deinit (void)
{
	for (std::vector<glu::TextureCube*>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
		delete *i;
	m_textures.clear();

	m_renderer.clear();
	m_cases.clear();
}

static const char* getFaceDesc (const tcu::CubeFace face)
{
	switch (face)
	{
		case tcu::CUBEFACE_NEGATIVE_X:	return "-X";
		case tcu::CUBEFACE_POSITIVE_X:	return "+X";
		case tcu::CUBEFACE_NEGATIVE_Y:	return "-Y";
		case tcu::CUBEFACE_POSITIVE_Y:	return "+Y";
		case tcu::CUBEFACE_NEGATIVE_Z:	return "-Z";
		case tcu::CUBEFACE_POSITIVE_Z:	return "+Z";
		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

TextureCubeFilteringCase::IterateResult TextureCubeFilteringCase::iterate (void)
{
	const glw::Functions&			gl				= m_renderCtx.getFunctions();
	const int						viewportSize	= 28;
	const RandomViewport			viewport		(m_renderCtx.getRenderTarget(), viewportSize, viewportSize, deStringHash(getName()) ^ deInt32Hash(m_caseNdx));
	const tcu::ScopedLogSection		iterSection		(m_testCtx.getLog(), string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
	const FilterCase&				curCase			= m_cases[m_caseNdx];
	const tcu::TextureFormat&		texFmt			= curCase.texture->getRefTexture().getFormat();
	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
	ReferenceParams					sampleParams	(TEXTURETYPE_CUBE);

	if (viewport.width < viewportSize || viewport.height < viewportSize)
		throw tcu::NotSupportedError("Too small render target", DE_NULL, __FILE__, __LINE__);

	// Setup texture
	gl.bindTexture	(GL_TEXTURE_CUBE_MAP, curCase.texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	m_minFilter);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	m_magFilter);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		m_wrapS);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		m_wrapT);

	// Other state
	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

	// Params for reference computation.
	sampleParams.sampler					= glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
	sampleParams.sampler.seamlessCubeMap	= true;
	sampleParams.samplerType				= getSamplerType(texFmt);
	sampleParams.colorBias					= fmtInfo.lookupBias;
	sampleParams.colorScale					= fmtInfo.lookupScale;
	sampleParams.lodMode					= LODMODE_EXACT;

	m_testCtx.getLog() << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight << TestLog::EndMessage;

	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
	{
		const tcu::CubeFace		face		= tcu::CubeFace(faceNdx);
		tcu::Surface			result		(viewport.width, viewport.height);
		vector<float>			texCoord;

		computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);

		m_testCtx.getLog() << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;

		// \todo Log texture coordinates.

		m_renderer.renderQuad(0, &texCoord[0], sampleParams);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");

		glu::readPixels(m_renderCtx, viewport.x, viewport.y, result.getAccess());
		GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");

		{
			const bool				isNearestOnly	= m_minFilter == GL_NEAREST && m_magFilter == GL_NEAREST;
			const tcu::PixelFormat	pixelFormat		= m_renderCtx.getRenderTarget().getPixelFormat();
			const tcu::IVec4		colorBits		= max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
			tcu::LodPrecision		lodPrecision;
			tcu::LookupPrecision	lookupPrecision;

			lodPrecision.derivateBits		= 5;
			lodPrecision.lodBits			= 3;
			lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / sampleParams.colorScale;
			lookupPrecision.coordBits		= tcu::IVec3(10,10,10);
			lookupPrecision.uvwBits			= tcu::IVec3(6,6,0);
			lookupPrecision.colorMask		= getCompareMask(pixelFormat);

			const bool isOk = verifyTextureResult(m_testCtx, result.getAccess(), curCase.texture->getRefTexture(),
												  &texCoord[0], sampleParams, lookupPrecision, lodPrecision, pixelFormat);

			if (!isOk)
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
		}
	}

	m_caseNdx += 1;
	return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP;
}

TextureFilteringTests::TextureFilteringTests (Context& context)
	: TestCaseGroup(context, "filtering", "Texture Filtering Tests")
{
}

TextureFilteringTests::~TextureFilteringTests (void)
{
}

void TextureFilteringTests::init (void)
{
	tcu::TestCaseGroup* group2D		= new tcu::TestCaseGroup(m_testCtx, "2d",	"2D Texture Filtering");
	tcu::TestCaseGroup*	groupCube	= new tcu::TestCaseGroup(m_testCtx, "cube",	"Cube Map Filtering");
	addChild(group2D);
	addChild(groupCube);

	static const struct
	{
		const char*		name;
		deUint32		mode;
	} wrapModes[] =
	{
		{ "clamp",		GL_CLAMP_TO_EDGE },
		{ "repeat",		GL_REPEAT },
		{ "mirror",		GL_MIRRORED_REPEAT }
	};

	static const struct
	{
		const char*		name;
		deUint32		mode;
	} minFilterModes[] =
	{
		{ "nearest",				GL_NEAREST					},
		{ "linear",					GL_LINEAR					},
		{ "nearest_mipmap_nearest",	GL_NEAREST_MIPMAP_NEAREST	},
		{ "linear_mipmap_nearest",	GL_LINEAR_MIPMAP_NEAREST	},
		{ "nearest_mipmap_linear",	GL_NEAREST_MIPMAP_LINEAR	},
		{ "linear_mipmap_linear",	GL_LINEAR_MIPMAP_LINEAR		}
	};

	static const struct
	{
		const char*		name;
		deUint32		mode;
	} magFilterModes[] =
	{
		{ "nearest",	GL_NEAREST },
		{ "linear",		GL_LINEAR }
	};

	static const struct
	{
		const char*		name;
		int				width;
		int				height;
	} sizes2D[] =
	{
		{ "pot",		32, 64 },
		{ "npot",		31, 55 }
	};

	static const struct
	{
		const char*		name;
		int				width;
		int				height;
	} sizesCube[] =
	{
		{ "pot",		64, 64 },
		{ "npot",		63, 63 }
	};

	static const struct
	{
		const char*		name;
		deUint32		format;
		deUint32		dataType;
	} formats[] =
	{
		{ "rgba8888",	GL_RGBA,			GL_UNSIGNED_BYTE			},
		{ "rgb888",		GL_RGB,				GL_UNSIGNED_BYTE			},
		{ "rgba4444",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4	},
		{ "l8",			GL_LUMINANCE,		GL_UNSIGNED_BYTE			}
	};

#define FOR_EACH(ITERATOR, ARRAY, BODY)	\
	for (int ITERATOR = 0; ITERATOR < DE_LENGTH_OF_ARRAY(ARRAY); ITERATOR++)	\
		BODY

	// 2D cases.
	FOR_EACH(minFilter,		minFilterModes,
	FOR_EACH(magFilter,		magFilterModes,
	FOR_EACH(wrapMode,		wrapModes,
	FOR_EACH(format,		formats,
	FOR_EACH(size,			sizes2D,
		{
			bool isMipmap		= minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR;
			bool isClamp		= wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE;
			bool isRepeat		= wrapModes[wrapMode].mode == GL_REPEAT;
			bool isMagNearest	= magFilterModes[magFilter].mode == GL_NEAREST;
			bool isPotSize		= deIsPowerOfTwo32(sizes2D[size].width) && deIsPowerOfTwo32(sizes2D[size].height);

			if ((isMipmap || !isClamp) && !isPotSize)
				continue; // Not supported.

			if ((format != 0) && !(!isMipmap || (isRepeat && isMagNearest)))
				continue; // Skip.

			string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name;

			if (!isMipmap)
				name += string("_") + sizes2D[size].name;

			group2D->addChild(new Texture2DFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
														 name.c_str(), "",
														 minFilterModes[minFilter].mode,
														 magFilterModes[magFilter].mode,
														 wrapModes[wrapMode].mode,
														 wrapModes[wrapMode].mode,
														 formats[format].format, formats[format].dataType,
														 sizes2D[size].width, sizes2D[size].height));
		})))));

	// 2D ETC1 texture cases.
	{
		std::vector<std::string> filenames;
		for (int i = 0; i <= 7; i++)
			filenames.push_back(string("data/etc1/photo_helsinki_mip_") + de::toString(i) + ".pkm");

		FOR_EACH(minFilter,		minFilterModes,
		FOR_EACH(magFilter,		magFilterModes,
		FOR_EACH(wrapMode,		wrapModes,
			{
				string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_etc1";

				group2D->addChild(new Texture2DFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
															 name.c_str(), "",
															 minFilterModes[minFilter].mode,
															 magFilterModes[magFilter].mode,
															 wrapModes[wrapMode].mode,
															 wrapModes[wrapMode].mode,
															 filenames));
			})));
	}

	// Cubemap cases.
	FOR_EACH(minFilter,		minFilterModes,
	FOR_EACH(magFilter,		magFilterModes,
	FOR_EACH(wrapMode,		wrapModes,
	FOR_EACH(format,		formats,
	FOR_EACH(size,			sizesCube,
		{
			bool isMipmap		= minFilterModes[minFilter].mode != GL_NEAREST && minFilterModes[minFilter].mode != GL_LINEAR;
			bool isClamp		= wrapModes[wrapMode].mode == GL_CLAMP_TO_EDGE;
			bool isRepeat		= wrapModes[wrapMode].mode == GL_REPEAT;
			bool isMagNearest	= magFilterModes[magFilter].mode == GL_NEAREST;
			bool isPotSize		= deIsPowerOfTwo32(sizesCube[size].width) && deIsPowerOfTwo32(sizesCube[size].height);

			if ((isMipmap || !isClamp) && !isPotSize)
				continue; // Not supported.

			if (format != 0 && !(!isMipmap || (isRepeat && isMagNearest)))
				continue; // Skip.

			string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name + "_" + formats[format].name;

			if (!isMipmap)
				name += string("_") + sizesCube[size].name;

			groupCube->addChild(new TextureCubeFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
															 name.c_str(), "",
															 minFilterModes[minFilter].mode,
															 magFilterModes[magFilter].mode,
															 wrapModes[wrapMode].mode,
															 wrapModes[wrapMode].mode,
															 formats[format].format, formats[format].dataType,
															 sizesCube[size].width, sizesCube[size].height));
		})))));

	// Cubemap ETC1 cases
	{
		static const char* faceExt[] = { "neg_x", "pos_x", "neg_y", "pos_y", "neg_z", "pos_z" };

		const int		numLevels	= 7;
		vector<string>	filenames;
		for (int level = 0; level < numLevels; level++)
			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
				filenames.push_back(string("data/etc1/skybox_") + faceExt[face] + "_mip_" + de::toString(level) + ".pkm");

		FOR_EACH(minFilter,		minFilterModes,
		FOR_EACH(magFilter,		magFilterModes,
			{
				string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_clamp_etc1";

				groupCube->addChild(new TextureCubeFilteringCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
																 name.c_str(), "",
																 minFilterModes[minFilter].mode,
																 magFilterModes[magFilter].mode,
																 GL_CLAMP_TO_EDGE,
																 GL_CLAMP_TO_EDGE,
																 filenames));
			}));
	}
}

} // Functional
} // gles2
} // deqp
