/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.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 Mipmapping accuracy tests.
 *//*--------------------------------------------------------------------*/

#include "es3aTextureMipmapTests.hpp"

#include "glsTextureTestUtil.hpp"
#include "gluTexture.hpp"
#include "gluTextureUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuMatrix.hpp"
#include "tcuMatrixUtil.hpp"
#include "deStringUtil.hpp"
#include "deRandom.hpp"
#include "deString.h"

#include "glwFunctions.hpp"
#include "glwEnums.hpp"

namespace deqp
{
namespace gles3
{
namespace Accuracy
{

using std::string;
using std::vector;
using tcu::TestLog;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec4;
using namespace gls::TextureTestUtil;
using namespace glu::TextureTestUtil;


enum CoordType
{
	COORDTYPE_BASIC,		//!< texCoord = translateScale(position).
	COORDTYPE_BASIC_BIAS,	//!< Like basic, but with bias values.
	COORDTYPE_AFFINE,		//!< texCoord = translateScaleRotateShear(position).
	COORDTYPE_PROJECTED,	//!< Projected coordinates, w != 1

	COORDTYPE_LAST
};

// Texture2DMipmapCase

class Texture2DMipmapCase : public tcu::TestCase
{
public:

								Texture2DMipmapCase			(tcu::TestContext&			testCtx,
															 glu::RenderContext&		renderCtx,
															 const glu::ContextInfo&	renderCtxInfo,
															 const char*				name,
															 const char*				desc,
															 CoordType					coordType,
															 deUint32					minFilter,
															 deUint32					wrapS,
															 deUint32					wrapT,
															 deUint32					format,
															 deUint32					dataType,
															 int						width,
															 int						height);
								~Texture2DMipmapCase		(void);

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

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

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

	CoordType					m_coordType;
	deUint32					m_minFilter;
	deUint32					m_wrapS;
	deUint32					m_wrapT;
	deUint32					m_format;
	deUint32					m_dataType;
	int							m_width;
	int							m_height;

	glu::Texture2D*				m_texture;
	TextureRenderer				m_renderer;
};

Texture2DMipmapCase::Texture2DMipmapCase (tcu::TestContext&			testCtx,
										  glu::RenderContext&		renderCtx,
										  const glu::ContextInfo&	renderCtxInfo,
										  const char*				name,
										  const char*				desc,
										  CoordType					coordType,
										  deUint32					minFilter,
										  deUint32					wrapS,
										  deUint32					wrapT,
										  deUint32					format,
										  deUint32					dataType,
										  int						width,
										  int						height)
	: TestCase			(testCtx, tcu::NODETYPE_ACCURACY, name, desc)
	, m_renderCtx		(renderCtx)
	, m_renderCtxInfo	(renderCtxInfo)
	, m_coordType		(coordType)
	, m_minFilter		(minFilter)
	, m_wrapS			(wrapS)
	, m_wrapT			(wrapT)
	, m_format			(format)
	, m_dataType		(dataType)
	, m_width			(width)
	, m_height			(height)
	, m_texture			(DE_NULL)
	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void Texture2DMipmapCase::init (void)
{
	m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);

	int numLevels = deLog2Floor32(de::max(m_width, m_height))+1;

	// Fill texture with colored grid.
	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
	{
		deUint32	step		= 0xff / (numLevels-1);
		deUint32	inc			= deClamp32(step*levelNdx, 0x00, 0xff);
		deUint32	dec			= 0xff - inc;
		deUint32	rgb			= (inc << 16) | (dec << 8) | 0xff;
		deUint32	color		= 0xff000000 | rgb;

		m_texture->getRefTexture().allocLevel(levelNdx);
		tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec());
	}
}

void Texture2DMipmapCase::deinit (void)
{
	delete m_texture;
	m_texture = DE_NULL;

	m_renderer.clear();
}

static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx)
{
	static const struct
	{
		Vec2 bottomLeft;
		Vec2 topRight;
	} s_basicCoords[] =
	{
		{ Vec2(-0.1f,  0.1f), Vec2( 0.8f,  1.0f) },
		{ Vec2(-0.3f, -0.6f), Vec2( 0.7f,  0.4f) },
		{ Vec2(-0.3f,  0.6f), Vec2( 0.7f, -0.9f) },
		{ Vec2(-0.8f,  0.6f), Vec2( 0.7f, -0.9f) },

		{ Vec2(-0.5f, -0.5f), Vec2( 1.5f,  1.5f) },
		{ Vec2( 1.0f, -1.0f), Vec2(-1.3f,  1.0f) },
		{ Vec2( 1.2f, -1.0f), Vec2(-1.3f,  1.6f) },
		{ Vec2( 2.2f, -1.1f), Vec2(-1.3f,  0.8f) },

		{ Vec2(-1.5f,  1.6f), Vec2( 1.7f, -1.4f) },
		{ Vec2( 2.0f,  1.6f), Vec2( 2.3f, -1.4f) },
		{ Vec2( 1.3f, -2.6f), Vec2(-2.7f,  2.9f) },
		{ Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) },

		{ Vec2( -8.0f,   9.0f), Vec2(  8.3f,  -7.0f) },
		{ Vec2(-16.0f,  10.0f), Vec2( 18.3f,  24.0f) },
		{ Vec2( 30.2f,  55.0f), Vec2(-24.3f,  -1.6f) },
		{ Vec2(-33.2f,  64.1f), Vec2( 32.1f, -64.1f) },
	};

	DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));

	const Vec2& bottomLeft	= s_basicCoords[cellNdx].bottomLeft;
	const Vec2& topRight	= s_basicCoords[cellNdx].topRight;

	computeQuadTexCoord2D(dst, bottomLeft, topRight);
}

static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx)
{
	// Use basic coords as base.
	getBasicTexCoord2D(dst, cellNdx);

	// Rotate based on cell index.
	float		angle		= 2.0f*DE_PI * ((float)cellNdx / 16.0f);
	tcu::Mat2	rotMatrix	= tcu::rotationMatrix(angle);

	// Second and third row are sheared.
	float		shearX		= de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f;
	tcu::Mat2	shearMatrix	= tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));

	tcu::Mat2	transform	= rotMatrix * shearMatrix;
	Vec2		p0			= transform * Vec2(dst[0], dst[1]);
	Vec2		p1			= transform * Vec2(dst[2], dst[3]);
	Vec2		p2			= transform * Vec2(dst[4], dst[5]);
	Vec2		p3			= transform * Vec2(dst[6], dst[7]);

	dst[0] = p0.x();	dst[1] = p0.y();
	dst[2] = p1.x();	dst[3] = p1.y();
	dst[4] = p2.x();	dst[5] = p2.y();
	dst[6] = p3.x();	dst[7] = p3.y();
}

Texture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void)
{
	// Constants.
	const deUint32				magFilter			= GL_NEAREST;

	const glw::Functions&		gl					= m_renderCtx.getFunctions();
	TestLog&					log					= m_testCtx.getLog();

	const tcu::Texture2D&		refTexture			= m_texture->getRefTexture();
	const tcu::TextureFormat&	texFmt				= refTexture.getFormat();
	tcu::TextureFormatInfo		fmtInfo				= tcu::getTextureFormatInfo(texFmt);

	int							texWidth			= refTexture.getWidth();
	int							texHeight			= refTexture.getHeight();
	int							defViewportWidth	= texWidth*4;
	int							defViewportHeight	= texHeight*4;

	RandomViewport				viewport			(m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
	ReferenceParams				sampleParams		(TEXTURETYPE_2D);
	vector<float>				texCoord;

	bool						isProjected			= m_coordType == COORDTYPE_PROJECTED;
	bool						useLodBias			= m_coordType == COORDTYPE_BASIC_BIAS;

	tcu::Surface				renderedFrame		(viewport.width, viewport.height);

	// Accuracy cases test against ideal lod computation.
	tcu::Surface				idealFrame			(viewport.width, viewport.height);

	// Viewport is divided into 4x4 grid.
	int							gridWidth			= 4;
	int							gridHeight			= 4;
	int							cellWidth			= viewport.width / gridWidth;
	int							cellHeight			= viewport.height / gridHeight;

	// Accuracy measurements are off unless we get the expected viewport size.
	if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);

	// Sampling parameters.
	sampleParams.sampler		= glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
	sampleParams.samplerType	= glu::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat());
	sampleParams.colorBias		= fmtInfo.lookupBias;
	sampleParams.colorScale		= fmtInfo.lookupScale;
	sampleParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);

	// Upload texture data.
	m_texture->upload();

	// Use unit 0.
	gl.activeTexture(GL_TEXTURE0);

	// Bind gradient texture and setup sampler parameters.
	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		m_wrapS);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		m_wrapT);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	magFilter);

	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");

	// Bias values.
	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };

	// Projection values.
	static const Vec4 s_projections[] =
	{
		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
		Vec4(1.3f, 0.8f, 0.6f, 2.0f),
		Vec4(0.8f, 1.0f, 1.7f, 0.6f),
		Vec4(1.2f, 1.0f, 1.7f, 1.5f)
	};

	// Render cells.
	for (int gridY = 0; gridY < gridHeight; gridY++)
	{
		for (int gridX = 0; gridX < gridWidth; gridX++)
		{
			int				curX		= cellWidth*gridX;
			int				curY		= cellHeight*gridY;
			int				curW		= gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
			int				curH		= gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
			int				cellNdx		= gridY*gridWidth + gridX;

			// Compute texcoord.
			switch (m_coordType)
			{
				case COORDTYPE_BASIC_BIAS:	// Fall-through.
				case COORDTYPE_PROJECTED:
				case COORDTYPE_BASIC:		getBasicTexCoord2D	(texCoord, cellNdx);	break;
				case COORDTYPE_AFFINE:		getAffineTexCoord2D	(texCoord, cellNdx);	break;
				default:					DE_ASSERT(DE_FALSE);
			}

			if (isProjected)
				sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];

			if (useLodBias)
				sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];

			// Render with GL.
			gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
			m_renderer.renderQuad(0, &texCoord[0], sampleParams);

			// Render reference(s).
			{
				tcu::SurfaceAccess idealDst(idealFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
				sampleParams.lodMode = LODMODE_EXACT;
				sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], sampleParams);
			}
		}
	}

	// Read result.
	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());

	// Compare and log.
	{
		const int	bestScoreDiff	= (texWidth/16)*(texHeight/16);
		const int	worstScoreDiff	= texWidth*texHeight;

		int score = measureAccuracy(log, idealFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
	}

	return STOP;
}

// TextureCubeMipmapCase

class TextureCubeMipmapCase : public tcu::TestCase
{
public:

								TextureCubeMipmapCase		(tcu::TestContext&			testCtx,
															 glu::RenderContext&		renderCtx,
															 const glu::ContextInfo&	renderCtxInfo,
															 const char*				name,
															 const char*				desc,
															 CoordType					coordType,
															 deUint32					minFilter,
															 deUint32					wrapS,
															 deUint32					wrapT,
															 deUint32					format,
															 deUint32					dataType,
															 int						size);
								~TextureCubeMipmapCase		(void);

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

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

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

	CoordType					m_coordType;
	deUint32					m_minFilter;
	deUint32					m_wrapS;
	deUint32					m_wrapT;
	deUint32					m_format;
	deUint32					m_dataType;
	int							m_size;

	glu::TextureCube*			m_texture;
	TextureRenderer				m_renderer;
};

TextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext&			testCtx,
											  glu::RenderContext&		renderCtx,
											  const glu::ContextInfo&	renderCtxInfo,
											  const char*				name,
											  const char*				desc,
											  CoordType					coordType,
											  deUint32					minFilter,
											  deUint32					wrapS,
											  deUint32					wrapT,
											  deUint32					format,
											  deUint32					dataType,
											  int						size)
	: TestCase			(testCtx, tcu::NODETYPE_ACCURACY, name, desc)
	, m_renderCtx		(renderCtx)
	, m_renderCtxInfo	(renderCtxInfo)
	, m_coordType		(coordType)
	, m_minFilter		(minFilter)
	, m_wrapS			(wrapS)
	, m_wrapT			(wrapT)
	, m_format			(format)
	, m_dataType		(dataType)
	, m_size			(size)
	, m_texture			(DE_NULL)
	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void TextureCubeMipmapCase::init (void)
{
	m_texture = new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_size);

	int numLevels = deLog2Floor32(m_size)+1;

	// Fill texture with colored grid.
	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
	{
		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
		{
			deUint32	step		= 0xff / (numLevels-1);
			deUint32	inc			= deClamp32(step*levelNdx, 0x00, 0xff);
			deUint32	dec			= 0xff - inc;
			deUint32	rgb			= 0;

			switch (faceNdx)
			{
				case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
				case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
				case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
				case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
				case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
				case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
			}

			deUint32	color		= 0xff000000 | rgb;

			m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx);
			tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
		}
	}
}

void TextureCubeMipmapCase::deinit (void)
{
	delete m_texture;
	m_texture = DE_NULL;

	m_renderer.clear();
}

static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height)
{
	const int minWidth	= 8;
	const int minHeight	= 8;

	bool	partition		= rnd.getFloat() > 0.4f;
	bool	partitionX		= partition && width > minWidth && rnd.getBool();
	bool	partitionY		= partition && height > minHeight && !partitionX;

	if (partitionX)
	{
		int split = width/2 + rnd.getInt(-width/4, +width/4);
		randomPartition(dst, rnd, x, y, split, height);
		randomPartition(dst, rnd, x+split, y, width-split, height);
	}
	else if (partitionY)
	{
		int split = height/2 + rnd.getInt(-height/4, +height/4);
		randomPartition(dst, rnd, x, y, width, split);
		randomPartition(dst, rnd, x, y+split, width, height-split);
	}
	else
		dst.push_back(IVec4(x, y, width, height));
}

static void computeGridLayout (vector<IVec4>& dst, int width, int height)
{
	de::Random rnd(7);
	randomPartition(dst, rnd, 0, 0, width, height);
}

TextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void)
{
	// Constants.
	const deUint32			magFilter			= GL_NEAREST;

	int						texWidth			= m_texture->getRefTexture().getSize();
	int						texHeight			= m_texture->getRefTexture().getSize();

	int						defViewportWidth	= texWidth*2;
	int						defViewportHeight	= texHeight*2;

	const glw::Functions&	gl					= m_renderCtx.getFunctions();
	TestLog&				log					= m_testCtx.getLog();
	RandomViewport			viewport			(m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
	tcu::Sampler			sampler				= glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
	sampler.seamlessCubeMap = true;

	vector<float>			texCoord;

	bool					isProjected			= m_coordType == COORDTYPE_PROJECTED;
	bool					useLodBias			= m_coordType == COORDTYPE_BASIC_BIAS;

	tcu::Surface			renderedFrame		(viewport.width, viewport.height);

	// Accuracy cases test against ideal lod computation.
	tcu::Surface			idealFrame			(viewport.width, viewport.height);

	// Accuracy measurements are off unless we get the expected viewport size.
	if (viewport.width < defViewportWidth || viewport.height < defViewportHeight)
		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);

	// Upload texture data.
	m_texture->upload();

	// Use unit 0.
	gl.activeTexture(GL_TEXTURE0);

	// Bind gradient texture and setup sampler parameters.
	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		m_wrapS);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		m_wrapT);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	m_minFilter);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	magFilter);

	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");

	// Compute grid.
	vector<IVec4> gridLayout;
	computeGridLayout(gridLayout, viewport.width, viewport.height);

	// Bias values.
	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };

	// Projection values \note Less agressive than in 2D case due to smaller quads.
	static const Vec4 s_projections[] =
	{
		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
		Vec4(1.3f, 0.8f, 0.6f, 1.1f),
		Vec4(0.8f, 1.0f, 1.2f, 0.8f),
		Vec4(1.2f, 1.0f, 1.3f, 0.9f)
	};

	for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
	{
		int				curX		= gridLayout[cellNdx].x();
		int				curY		= gridLayout[cellNdx].y();
		int				curW		= gridLayout[cellNdx].z();
		int				curH		= gridLayout[cellNdx].w();
		tcu::CubeFace	cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
		ReferenceParams	params		(TEXTURETYPE_CUBE);

		params.sampler = sampler;

		DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
		computeQuadTexCoordCube(texCoord, cubeFace);

		if (isProjected)
		{
			params.flags	|= ReferenceParams::PROJECTED;
			params.w		 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
		}

		if (useLodBias)
		{
			params.flags	|= ReferenceParams::USE_BIAS;
			params.bias		 = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
		}

		// Render with GL.
		gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
		m_renderer.renderQuad(0, &texCoord[0], params);

		// Render reference(s).
		{
			tcu::SurfaceAccess idealDst(idealFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
			params.lodMode = LODMODE_EXACT;
			sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
		}
	}

	// Read result.
	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());

	// Compare and log.
	{
		const int	bestScoreDiff	= (texWidth/16)*(texHeight/16);
		const int	worstScoreDiff	= texWidth*texHeight;

		int score = measureAccuracy(log, idealFrame, renderedFrame, bestScoreDiff, worstScoreDiff);
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::toString(score).c_str());
	}

	return STOP;
}

TextureMipmapTests::TextureMipmapTests (Context& context)
	: TestCaseGroup(context, "mipmap", "Mipmapping accuracy tests")
{
}

TextureMipmapTests::~TextureMipmapTests (void)
{
}

void TextureMipmapTests::init (void)
{
	tcu::TestCaseGroup* group2D		= new tcu::TestCaseGroup(m_testCtx, "2d",	"2D Texture Mipmapping");
	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_nearest",	GL_NEAREST_MIPMAP_NEAREST	},
		{ "linear_nearest",		GL_LINEAR_MIPMAP_NEAREST	},
		{ "nearest_linear",		GL_NEAREST_MIPMAP_LINEAR	},
		{ "linear_linear",		GL_LINEAR_MIPMAP_LINEAR		}
	};

	static const struct
	{
		CoordType		type;
		const char*		name;
		const char*		desc;
	} coordTypes[] =
	{
		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
		{ COORDTYPE_AFFINE,		"affine",		"Mipmapping with affine coordinate transform"		},
		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			}
	};

	const int tex2DWidth	= 64;
	const int tex2DHeight	= 64;

	// 2D cases.
	for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
	{
		tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
		group2D->addChild(coordTypeGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
		{
			for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
			{
				std::ostringstream name;
				name << minFilterModes[minFilter].name
						<< "_" << wrapModes[wrapMode].name;

				coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
																	name.str().c_str(), "",
																	coordTypes[coordType].type,
																	minFilterModes[minFilter].mode,
																	wrapModes[wrapMode].mode,
																	wrapModes[wrapMode].mode,
																	GL_RGBA, GL_UNSIGNED_BYTE,
																	tex2DWidth, tex2DHeight));
			}
		}
	}

	const int cubeMapSize = 64;

	static const struct
	{
		CoordType		type;
		const char*		name;
		const char*		desc;
	} cubeCoordTypes[] =
	{
		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			}
	};

	// Cubemap cases.
	for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
	{
		tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc);
		groupCube->addChild(coordTypeGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
		{
			coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
															   minFilterModes[minFilter].name, "",
															   cubeCoordTypes[coordType].type,
															   minFilterModes[minFilter].mode,
															   GL_CLAMP_TO_EDGE,
															   GL_CLAMP_TO_EDGE,
															   GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize));
		}
	}
}

} // Accuracy
} // gles3
} // deqp
