/*-------------------------------------------------------------------------
 * 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;


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), toVec4(tcu::RGBA(color)));
	}
}

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	= gls::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).
			{
				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), toVec4(tcu::RGBA(color)));
		}
	}
}

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).
		{
			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
