/*-------------------------------------------------------------------------
 * 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 tests.
 *//*--------------------------------------------------------------------*/

#include "es3fTextureMipmapTests.hpp"

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

using std::vector;
using std::string;
using namespace deqp::gls;

namespace deqp
{
namespace gles3
{
namespace Functional
{

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;

static float getMinLodForCell (int cellNdx)
{
	static const float s_values[] =
	{
		1.0f,
		3.5f,
		2.0f,
		-2.0f,
		0.0f,
		3.0f,
		10.0f,
		4.8f,
		5.8f,
		5.7f,
		-1.9f,
		4.0f,
		6.5f,
		7.1f,
		-1e10,
		1000.f
	};
	return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
}

static float getMaxLodForCell (int cellNdx)
{
	static const float s_values[] =
	{
		0.0f,
		0.2f,
		0.7f,
		0.4f,
		1.3f,
		0.0f,
		0.5f,
		1.2f,
		-2.0f,
		1.0f,
		0.1f,
		0.3f,
		2.7f,
		1.2f,
		10.0f,
		-1000.f,
		1e10f
	};
	return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
}

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, 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)
{
	if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
		throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");

	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)
{
	const glw::Functions&		gl					= m_renderCtx.getFunctions();

	const tcu::Texture2D&		refTexture			= m_texture->getRefTexture();

	const deUint32				magFilter			= GL_NEAREST;
	const int					texWidth			= refTexture.getWidth();
	const int					texHeight			= refTexture.getHeight();
	const int					defViewportWidth	= texWidth*4;
	const int					defViewportHeight	= texHeight*4;

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

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

	tcu::Surface				renderedFrame		(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;

	// Bail out if rendertarget is too small.
	if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
		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.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
	sampleParams.lodMode		= LODMODE_EXACT; // Use ideal lod.

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

	// 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++)
		{
			const int		curX		= cellWidth*gridX;
			const int		curY		= cellHeight*gridY;
			const int		curW		= gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
			const int		curH		= gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
			const 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);
		}
	}

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

	// Compare and log.
	{
		const tcu::PixelFormat&	pixelFormat		= m_renderCtx.getRenderTarget().getPixelFormat();
		const bool				isTrilinear		= m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
		tcu::Surface			referenceFrame	(viewport.width, viewport.height);
		tcu::Surface			errorMask		(viewport.width, viewport.height);
		tcu::LookupPrecision	lookupPrec;
		tcu::LodPrecision		lodPrec;
		int						numFailedPixels	= 0;

		lookupPrec.coordBits		= tcu::IVec3(20, 20, 0);
		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
		lookupPrec.colorMask		= getCompareMask(pixelFormat);
		lodPrec.derivateBits		= 10;
		lodPrec.lodBits				= isProjected ? 6 : 8;

		for (int gridY = 0; gridY < gridHeight; gridY++)
		{
			for (int gridX = 0; gridX < gridWidth; gridX++)
			{
				const int		curX		= cellWidth*gridX;
				const int		curY		= cellHeight*gridY;
				const int		curW		= gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
				const int		curH		= gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
				const 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 ideal result
				sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
							  refTexture, &texCoord[0], sampleParams);

				// Compare this cell
				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
															m_texture->getRefTexture(), &texCoord[0], sampleParams,
															lookupPrec, lodPrec, m_testCtx.getWatchDog());
			}
		}

		if (numFailedPixels > 0)
			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
							<< TestLog::Image("Rendered", "Rendered image", renderedFrame);

		if (numFailedPixels > 0)
		{
			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
								<< TestLog::Image("ErrorMask", "Error mask", errorMask);
		}

		m_testCtx.getLog() << TestLog::EndImageSet;

		{
			const bool isOk = numFailedPixels == 0;
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image verification failed");
		}
	}

	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, 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)
{
	if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
		throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");

	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)
{
	const deUint32			magFilter			= GL_NEAREST;
	const int				texWidth			= m_texture->getRefTexture().getSize();
	const int				texHeight			= m_texture->getRefTexture().getSize();
	const int				defViewportWidth	= texWidth*2;
	const int				defViewportHeight	= texHeight*2;

	const glw::Functions&	gl					= m_renderCtx.getFunctions();
	const RandomViewport	viewport			(m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));

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

	vector<float>			texCoord;
	tcu::Surface			renderedFrame		(viewport.width, viewport.height);

	// Bail out if rendertarget is too small.
	if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);

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

	// 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)
	};

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

		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);
	}
	GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");

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

	// Render reference and compare
	{
		tcu::Surface			referenceFrame		(viewport.width, viewport.height);
		tcu::Surface			errorMask			(viewport.width, viewport.height);
		int						numFailedPixels		= 0;
		ReferenceParams			params				(TEXTURETYPE_CUBE);
		tcu::LookupPrecision	lookupPrec;
		tcu::LodPrecision		lodPrec;

		// Params for rendering reference
		params.sampler					= glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
		params.sampler.seamlessCubeMap	= true;
		params.lodMode					= LODMODE_EXACT;

		// Comparison parameters
		lookupPrec.colorMask			= getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
		lookupPrec.colorThreshold		= tcu::computeFixedPointThreshold(max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)));
		lookupPrec.coordBits			= isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
		lookupPrec.uvwBits				= tcu::IVec3(5,5,0);
		lodPrec.derivateBits			= 10;
		lodPrec.lodBits					= isProjected ? 3 : 6;

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

			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 ideal reference.
			{
				SurfaceAccess idealDst(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
				sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
			}

			// Compare this cell
			numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
														tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
														tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
														m_texture->getRefTexture(), &texCoord[0], params,
														lookupPrec, lodPrec, m_testCtx.getWatchDog());
		}

		if (numFailedPixels > 0)
			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
						   << TestLog::Image("Rendered", "Rendered image", renderedFrame);

		if (numFailedPixels > 0)
		{
			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
							   << TestLog::Image("ErrorMask", "Error mask", errorMask);
		}

		m_testCtx.getLog() << TestLog::EndImageSet;

		{
			const bool isOk = numFailedPixels == 0;
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image verification failed");
		}
	}

	return STOP;
}

// Texture2DGenMipmapCase

class Texture2DGenMipmapCase : public tcu::TestCase
{
public:

								Texture2DGenMipmapCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height);
								~Texture2DGenMipmapCase		(void);

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

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

	glu::RenderContext&			m_renderCtx;

	deUint32					m_format;
	deUint32					m_dataType;
	deUint32					m_hint;
	int							m_width;
	int							m_height;

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

Texture2DGenMipmapCase::Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height)
	: TestCase			(testCtx, name, desc)
	, m_renderCtx		(renderCtx)
	, m_format			(format)
	, m_dataType		(dataType)
	, m_hint			(hint)
	, m_width			(width)
	, m_height			(height)
	, m_texture			(DE_NULL)
	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void Texture2DGenMipmapCase::init (void)
{
	DE_ASSERT(!m_texture);
	m_texture = new glu::Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
}

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

	m_renderer.clear();
}

Texture2DGenMipmapCase::IterateResult Texture2DGenMipmapCase::iterate (void)
{
	const glw::Functions&	gl					= m_renderCtx.getFunctions();

	const deUint32			minFilter			= GL_NEAREST_MIPMAP_NEAREST;
	const deUint32			magFilter			= GL_NEAREST;
	const deUint32			wrapS				= GL_CLAMP_TO_EDGE;
	const deUint32			wrapT				= GL_CLAMP_TO_EDGE;

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

	tcu::Texture2D			resultTexture		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight());

	vector<float>			texCoord;

	// Initialize texture level 0 with colored grid.
	m_texture->getRefTexture().allocLevel(0);
	tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 8, tcu::Vec4(1.0f, 0.5f, 0.0f, 0.5f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));

	// Upload data and setup params.
	m_texture->upload();

	gl.bindTexture	(GL_TEXTURE_2D, m_texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		wrapS);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		wrapT);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	minFilter);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	magFilter);
	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");

	// Generate mipmap.
	gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
	gl.generateMipmap(GL_TEXTURE_2D);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");

	// Use (0, 0) -> (1, 1) texture coordinates.
	computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));

	// Fetch resulting texture by rendering.
	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
	{
		const int				levelWidth		= de::max(1, m_width >> levelNdx);
		const int				levelHeight		= de::max(1, m_height >> levelNdx);
		const RandomViewport	viewport		(m_renderCtx.getRenderTarget(), levelWidth, levelHeight, deStringHash(getName()) + levelNdx);

		gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
		m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);

		resultTexture.allocLevel(levelNdx);
		glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevel(levelNdx));
	}

	// Compare results
	{
		const IVec4			framebufferBits		= max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
		const IVec4			formatBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
		const tcu::BVec4	formatMask			= greaterThan(formatBits, IVec4(0));
		const IVec4			cmpBits				= select(min(framebufferBits, formatBits), framebufferBits, formatMask);
		GenMipmapPrecision	comparePrec;

		comparePrec.colorMask		= getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
		comparePrec.colorThreshold	= tcu::computeFixedPointThreshold(cmpBits);
		comparePrec.filterBits		= tcu::IVec3(4, 4, 0);

		const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);

		m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS				? "Pass" :
											   compareResult == QP_TEST_RESULT_QUALITY_WARNING	? "Low-quality method used"	:
											   compareResult == QP_TEST_RESULT_FAIL				? "Image comparison failed"	: "");
	}

	return STOP;
}

// TextureCubeGenMipmapCase

class TextureCubeGenMipmapCase : public tcu::TestCase
{
public:

								TextureCubeGenMipmapCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size);
								~TextureCubeGenMipmapCase		(void);

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

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

	glu::RenderContext&			m_renderCtx;

	deUint32					m_format;
	deUint32					m_dataType;
	deUint32					m_hint;
	int							m_size;

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

TextureCubeGenMipmapCase::TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size)
	: TestCase			(testCtx, name, desc)
	, m_renderCtx		(renderCtx)
	, m_format			(format)
	, m_dataType		(dataType)
	, m_hint			(hint)
	, m_size			(size)
	, m_texture			(DE_NULL)
	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void TextureCubeGenMipmapCase::init (void)
{
	if (m_renderCtx.getRenderTarget().getWidth() < 3*m_size || m_renderCtx.getRenderTarget().getHeight() < 2*m_size)
		throw tcu::NotSupportedError("Render target size must be at least (" + de::toString(3*m_size) + ", " + de::toString(2*m_size) + ")");

	DE_ASSERT(!m_texture);
	m_texture = new glu::TextureCube(m_renderCtx, m_format, m_dataType, m_size);
}

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

	m_renderer.clear();
}

TextureCubeGenMipmapCase::IterateResult TextureCubeGenMipmapCase::iterate (void)
{
	const glw::Functions&	gl					= m_renderCtx.getFunctions();

	const deUint32			minFilter			= GL_NEAREST_MIPMAP_NEAREST;
	const deUint32			magFilter			= GL_NEAREST;
	const deUint32			wrapS				= GL_CLAMP_TO_EDGE;
	const deUint32			wrapT				= GL_CLAMP_TO_EDGE;

	tcu::TextureCube		resultTexture		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_size);

	const int				numLevels			= deLog2Floor32(m_size)+1;
	vector<float>			texCoord;

	// Initialize texture level 0 with colored grid.
	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
	{
		Vec4 ca, cb; // Grid colors.

		switch (face)
		{
			case 0: ca = Vec4(1.0f, 0.3f, 0.0f, 0.7f); cb = Vec4(0.0f, 0.0f, 1.0f, 1.0f); break;
			case 1: ca = Vec4(0.0f, 1.0f, 0.5f, 0.5f); cb = Vec4(1.0f, 0.0f, 0.0f, 1.0f); break;
			case 2: ca = Vec4(0.7f, 0.0f, 1.0f, 0.3f); cb = Vec4(0.0f, 1.0f, 0.0f, 1.0f); break;
			case 3: ca = Vec4(0.0f, 0.3f, 1.0f, 1.0f); cb = Vec4(1.0f, 0.0f, 0.0f, 0.7f); break;
			case 4: ca = Vec4(1.0f, 0.0f, 0.5f, 1.0f); cb = Vec4(0.0f, 1.0f, 0.0f, 0.5f); break;
			case 5: ca = Vec4(0.7f, 1.0f, 0.0f, 1.0f); cb = Vec4(0.0f, 0.0f, 1.0f, 0.3f); break;
		}

		m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
		fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), 8, ca, cb);
	}

	// Upload data and setup params.
	m_texture->upload();

	gl.bindTexture	(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		wrapS);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		wrapT);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	minFilter);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	magFilter);
	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");

	// Generate mipmap.
	gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
	gl.generateMipmap(GL_TEXTURE_CUBE_MAP);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");

	// Render all levels.
	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
	{
		const int	levelWidth	= de::max(1, m_size >> levelNdx);
		const int	levelHeight	= de::max(1, m_size >> levelNdx);

		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
		{
			const RandomViewport	viewport	(m_renderCtx.getRenderTarget(), levelWidth*3, levelHeight*2, deStringHash(getName()) ^ deInt32Hash(levelNdx + faceNdx));
			const tcu::CubeFace		face		= tcu::CubeFace(faceNdx);

			computeQuadTexCoordCube(texCoord, face);

			gl.viewport(viewport.x, viewport.y, levelWidth, levelHeight);
			m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);

			resultTexture.allocLevel(face, levelNdx);
			glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevelFace(levelNdx, face));
		}
	}

	// Compare results
	{
		const IVec4			framebufferBits		= max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
		const IVec4			formatBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
		const tcu::BVec4	formatMask			= greaterThan(formatBits, IVec4(0));
		const IVec4			cmpBits				= select(min(framebufferBits, formatBits), framebufferBits, formatMask);
		GenMipmapPrecision	comparePrec;

		comparePrec.colorMask		= getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
		comparePrec.colorThreshold	= tcu::computeFixedPointThreshold(cmpBits);
		comparePrec.filterBits		= tcu::IVec3(4, 4, 0);

		const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);

		m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS				? "Pass" :
											   compareResult == QP_TEST_RESULT_QUALITY_WARNING	? "Low-quality method used"	:
											   compareResult == QP_TEST_RESULT_FAIL				? "Image comparison failed"	: "");
	}

	return STOP;
}

// Texture3DMipmapCase

class Texture3DMipmapCase : public TestCase
{
public:

								Texture3DMipmapCase			(Context&					context,
															 const char*				name,
															 const char*				desc,
															 CoordType					coordType,
															 deUint32					minFilter,
															 deUint32					wrapS,
															 deUint32					wrapT,
															 deUint32					wrapR,
															 deUint32					format,
															 int						width,
															 int						height,
															 int						depth);
								~Texture3DMipmapCase		(void);

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

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

	CoordType					m_coordType;
	deUint32					m_minFilter;
	deUint32					m_wrapS;
	deUint32					m_wrapT;
	deUint32					m_wrapR;
	deUint32					m_internalFormat;
	int							m_width;
	int							m_height;
	int							m_depth;

	glu::Texture3D*						m_texture;
	TextureTestUtil::TextureRenderer	m_renderer;
};

Texture3DMipmapCase::Texture3DMipmapCase (Context& context, const char* name, const char* desc, CoordType coordType, deUint32 minFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR, deUint32 format, int width, int height, int depth)
	: TestCase			(context, name, desc)
	, m_coordType		(coordType)
	, m_minFilter		(minFilter)
	, m_wrapS			(wrapS)
	, m_wrapT			(wrapT)
	, m_wrapR			(wrapR)
	, m_internalFormat	(format)
	, m_width			(width)
	, m_height			(height)
	, m_depth			(depth)
	, m_texture			(DE_NULL)
	, m_renderer		(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void Texture3DMipmapCase::init (void)
{
	const tcu::TextureFormat&		texFmt			= glu::mapGLInternalFormat(m_internalFormat);
	tcu::TextureFormatInfo			fmtInfo			= tcu::getTextureFormatInfo(texFmt);
	const tcu::Vec4&				cScale			= fmtInfo.lookupScale;
	const tcu::Vec4&				cBias			= fmtInfo.lookupBias;
	int								numLevels		= deLog2Floor32(de::max(de::max(m_width, m_height), m_depth))+1;

	if (m_coordType == COORDTYPE_PROJECTED && m_context.getRenderTarget().getNumSamples() > 0)
		throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");

	m_texture = new glu::Texture3D(m_context.getRenderContext(), m_internalFormat, m_width, m_height, m_depth);

	// 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			= (0xff << 16) | (dec << 8) | inc;
		deUint32	color		= 0xff000000 | rgb;

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

	m_texture->upload();
}

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

	m_renderer.clear();
}

static void getBasicTexCoord3D (std::vector<float>& dst, int cellNdx)
{
	static const struct
	{
		float sScale;
		float sBias;
		float tScale;
		float tBias;
		float rScale;
		float rBias;
	} s_params[] =
	{
	//		sScale	sBias	tScale	tBias	rScale	rBias
		{	 0.9f,	-0.1f,	 0.7f,	 0.3f,	 0.8f,	 0.9f	},
		{	 1.2f,	-0.1f,	 1.1f,	 0.3f,	 1.0f,	 0.9f	},
		{	 1.5f,	 0.7f,	 0.9f,	-0.3f,	 1.1f,	 0.1f	},
		{	 1.2f,	 0.7f,	-2.3f,	-0.3f,	 1.1f,	 0.2f	},
		{	 1.1f,	 0.8f,	-1.3f,	-0.3f,	 2.9f,	 0.9f	},
		{	 3.4f,	 0.8f,	 4.0f,	 0.0f,	-3.3f,	-1.0f	},
		{	-3.4f,	-0.1f,	-4.0f,	 0.0f,	-5.1f,	 1.0f	},
		{	-4.0f,	-0.1f,	 3.4f,	 0.1f,	 5.7f,	 0.0f	},
		{	-5.6f,	 0.0f,	 0.5f,	 1.2f,	 3.9f,	 4.0f	},
		{	 5.0f,	-2.0f,	 3.1f,	 1.2f,	 5.1f,	 0.2f	},
		{	 2.5f,	-2.0f,	 6.3f,	 3.0f,	 5.1f,	 0.2f	},
		{	-8.3f,	 0.0f,	 7.1f,	 3.0f,	 2.0f,	 0.2f	},
		{    3.8f,	 0.0f,	 9.7f,	 1.0f,	 7.0f,	 0.7f	},
		{	13.3f,	 0.0f,	 7.1f,	 3.0f,	 2.0f,	 0.2f	},
		{   16.0f,	 8.0f,	12.7f,	 1.0f,	17.1f,	 0.7f	},
		{	15.3f,	 0.0f,	20.1f,	 3.0f,	33.0f,	 3.2f	}
	};

	float sScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sScale;
	float sBias		= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sBias;
	float tScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tScale;
	float tBias		= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tBias;
	float rScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rScale;
	float rBias		= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rBias;

	dst.resize(3*4);

	dst[0] = sBias;			dst[ 1] = tBias;			dst[ 2] = rBias;
	dst[3] = sBias;			dst[ 4] = tBias+tScale;		dst[ 5] = rBias+rScale*0.5f;
	dst[6] = sBias+sScale;	dst[ 7] = tBias;			dst[ 8] = rBias+rScale*0.5f;
	dst[9] = sBias+sScale;	dst[10] = tBias+tScale;		dst[11] = rBias+rScale;
}

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

	// Rotate based on cell index.
	float		angleX		= 0.0f + 2.0f*DE_PI * ((float)cellNdx / 16.0f);
	float		angleY		= 1.0f + 2.0f*DE_PI * ((float)cellNdx / 32.0f);
	tcu::Mat3	rotMatrix	= tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY);

	Vec3		p0			= rotMatrix * Vec3(dst[0], dst[ 1], dst[ 2]);
	Vec3		p1			= rotMatrix * Vec3(dst[3], dst[ 4], dst[ 5]);
	Vec3		p2			= rotMatrix * Vec3(dst[6], dst[ 7], dst[ 8]);
	Vec3		p3			= rotMatrix * Vec3(dst[9], dst[10], dst[11]);

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

Texture3DMipmapCase::IterateResult Texture3DMipmapCase::iterate (void)
{
	const glw::Functions&			gl					= m_context.getRenderContext().getFunctions();

	const tcu::Texture3D&			refTexture			= m_texture->getRefTexture();
	const tcu::TextureFormat&		texFmt				= refTexture.getFormat();
	const tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
	const int						texWidth			= refTexture.getWidth();
	const int						texHeight			= refTexture.getHeight();
	const deUint32					magFilter			= GL_NEAREST;

	const tcu::RenderTarget&		renderTarget		= m_context.getRenderContext().getRenderTarget();
	const RandomViewport			viewport			(renderTarget, texWidth*4, texHeight*4, deStringHash(getName()));

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

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

	ReferenceParams					sampleParams		(TEXTURETYPE_3D);

	tcu::Surface					renderedFrame		(viewport.width, viewport.height);
	vector<float>					texCoord;

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

	// Bind texture and setup sampler parameters.
	gl.bindTexture	(GL_TEXTURE_3D, m_texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,		m_wrapS);
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,		m_wrapT);
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,		m_wrapR);
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
	gl.texParameteri(GL_TEXTURE_3D, 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++)
		{
			const int		curX		= cellWidth*gridX;
			const int		curY		= cellHeight*gridY;
			const int		curW		= gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
			const int		curH		= gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
			const int		cellNdx		= gridY*gridWidth + gridX;

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

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

			// Set LOD bias.
			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);
		}
	}

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

	// Compare and log
	{
		const tcu::PixelFormat&	pixelFormat		= m_context.getRenderTarget().getPixelFormat();
		const bool				isTrilinear		= m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
		tcu::Surface			referenceFrame	(viewport.width, viewport.height);
		tcu::Surface			errorMask		(viewport.width, viewport.height);
		tcu::LookupPrecision	lookupPrec;
		tcu::LodPrecision		lodPrec;
		int						numFailedPixels	= 0;

		lookupPrec.coordBits		= tcu::IVec3(20, 20, 20);
		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
		lookupPrec.colorMask		= getCompareMask(pixelFormat);
		lodPrec.derivateBits		= 10;
		lodPrec.lodBits				= isProjected ? 6 : 8;

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

				switch (m_coordType)
				{
					case COORDTYPE_BASIC_BIAS:	// Fall-through.
					case COORDTYPE_PROJECTED:
					case COORDTYPE_BASIC:		getBasicTexCoord3D	(texCoord, cellNdx);	break;
					case COORDTYPE_AFFINE:		getAffineTexCoord3D	(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 ideal result
				sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
							  refTexture, &texCoord[0], sampleParams);

				// Compare this cell
				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
															m_texture->getRefTexture(), &texCoord[0], sampleParams,
															lookupPrec, lodPrec, m_testCtx.getWatchDog());
			}
		}

		if (numFailedPixels > 0)
			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
							<< TestLog::Image("Rendered", "Rendered image", renderedFrame);

		if (numFailedPixels > 0)
		{
			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
								<< TestLog::Image("ErrorMask", "Error mask", errorMask);
		}

		m_testCtx.getLog() << TestLog::EndImageSet;

		{
			const bool isOk = numFailedPixels == 0;
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image verification failed");
		}
	}

	return STOP;
}

// Texture2DLodControlCase + test cases

class Texture2DLodControlCase : public TestCase
{
public:

										Texture2DLodControlCase		(Context& context, const char* name, const char* desc, deUint32 minFilter);
										~Texture2DLodControlCase	(void);

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

protected:
	virtual void						setTextureParams			(int cellNdx)							= DE_NULL;
	virtual void						getReferenceParams			(ReferenceParams& params, int cellNdx)	= DE_NULL;

	const int							m_texWidth;
	const int							m_texHeight;

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

	deUint32							m_minFilter;

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

Texture2DLodControlCase::Texture2DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
	: TestCase		(context, name, desc)
	, m_texWidth	(64)
	, m_texHeight	(64)
	, m_minFilter	(minFilter)
	, m_texture		(DE_NULL)
	, m_renderer	(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void Texture2DLodControlCase::init (void)
{
	const deUint32	format		= GL_RGBA8;
	int				numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;

	m_texture = new glu::Texture2D(m_context.getRenderContext(), format, m_texWidth, m_texHeight);

	// 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 Texture2DLodControlCase::deinit (void)
{
	delete m_texture;
	m_texture = DE_NULL;

	m_renderer.clear();
}

Texture2DLodControlCase::IterateResult Texture2DLodControlCase::iterate (void)
{
	const glw::Functions&		gl					= m_context.getRenderContext().getFunctions();

	const deUint32				wrapS				= GL_REPEAT;
	const deUint32				wrapT				= GL_REPEAT;
	const deUint32				magFilter			= GL_NEAREST;

	const tcu::Texture2D&		refTexture			= m_texture->getRefTexture();
	const int					texWidth			= refTexture.getWidth();
	const int					texHeight			= refTexture.getHeight();

	const tcu::RenderTarget&	renderTarget		= m_context.getRenderContext().getRenderTarget();
	const RandomViewport		viewport			(renderTarget, texWidth*4, texHeight*4, deStringHash(getName()));

	ReferenceParams				sampleParams		(gls::TextureTestUtil::TEXTURETYPE_2D, glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter));
	vector<float>				texCoord;
	tcu::Surface				renderedFrame		(viewport.width, viewport.height);

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

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

	// Bind gradient texture and setup sampler parameters.
	gl.bindTexture	(GL_TEXTURE_2D, m_texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		wrapS);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		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");

	// 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.
			getBasicTexCoord2D(texCoord, cellNdx);

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

	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
	GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");

	// Compare and log.
	{
		const tcu::PixelFormat&	pixelFormat		= m_context.getRenderTarget().getPixelFormat();
		const bool				isTrilinear		= m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
		tcu::Surface			referenceFrame	(viewport.width, viewport.height);
		tcu::Surface			errorMask		(viewport.width, viewport.height);
		tcu::LookupPrecision	lookupPrec;
		tcu::LodPrecision		lodPrec;
		int						numFailedPixels	= 0;

		lookupPrec.coordBits		= tcu::IVec3(20, 20, 0);
		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
		lookupPrec.colorMask		= getCompareMask(pixelFormat);
		lodPrec.derivateBits		= 10;
		lodPrec.lodBits				= 8;

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

				getBasicTexCoord2D(texCoord, cellNdx);
				getReferenceParams(sampleParams, cellNdx);

				// Render ideal result
				sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
							  refTexture, &texCoord[0], sampleParams);

				// Compare this cell
				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
															m_texture->getRefTexture(), &texCoord[0], sampleParams,
															lookupPrec, lodPrec, m_testCtx.getWatchDog());
			}
		}

		if (numFailedPixels > 0)
			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
							<< TestLog::Image("Rendered", "Rendered image", renderedFrame);

		if (numFailedPixels > 0)
		{
			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
								<< TestLog::Image("ErrorMask", "Error mask", errorMask);
		}

		m_testCtx.getLog() << TestLog::EndImageSet;

		{
			const bool isOk = numFailedPixels == 0;
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image verification failed");
		}
	}

	return STOP;
}

class Texture2DMinLodCase : public Texture2DLodControlCase
{
public:
	Texture2DMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture2DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.minLod = getMinLodForCell(cellNdx);
	}
};

class Texture2DMaxLodCase : public Texture2DLodControlCase
{
public:
	Texture2DMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture2DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.maxLod = getMaxLodForCell(cellNdx);
	}
};

class Texture2DBaseLevelCase : public Texture2DLodControlCase
{
public:
	Texture2DBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture2DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	int getBaseLevel (int cellNdx) const
	{
		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0xac2f274a) % numLevels;

		return baseLevel;
	}

	void setTextureParams (int cellNdx)
	{
		const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.baseLevel = getBaseLevel(cellNdx);
	}
};

class Texture2DMaxLevelCase : public Texture2DLodControlCase
{
public:
	Texture2DMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture2DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	int getMaxLevel (int cellNdx) const
	{
		const int		numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
		const int		maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x82cfa4e) % numLevels;

		return maxLevel;
	}

	void setTextureParams (int cellNdx)
	{
		const glw::Functions&	gl	= m_context.getRenderContext().getFunctions();
		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.maxLevel = getMaxLevel(cellNdx);
	}
};

// TextureCubeLodControlCase + test cases

class TextureCubeLodControlCase : public TestCase
{
public:

										TextureCubeLodControlCase	(Context& context, const char* name, const char* desc, deUint32 minFilter);
										~TextureCubeLodControlCase	(void);

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

protected:
	virtual void						setTextureParams			(int cellNdx)							= DE_NULL;
	virtual void						getReferenceParams			(ReferenceParams& params, int cellNdx)	= DE_NULL;

	const int							m_texSize;

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

	deUint32							m_minFilter;

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

TextureCubeLodControlCase::TextureCubeLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
	: TestCase			(context, name, desc)
	, m_texSize			(64)
	, m_minFilter		(minFilter)
	, m_texture			(DE_NULL)
	, m_renderer		(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void TextureCubeLodControlCase::init (void)
{
	const deUint32	format		= GL_RGBA8;
	const int		numLevels	= deLog2Floor32(m_texSize)+1;

	m_texture = new glu::TextureCube(m_context.getRenderContext(), format, m_texSize);

	// 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 TextureCubeLodControlCase::deinit (void)
{
	delete m_texture;
	m_texture = DE_NULL;

	m_renderer.clear();
}

TextureCubeLodControlCase::IterateResult TextureCubeLodControlCase::iterate (void)
{
	const deUint32			wrapS				= GL_CLAMP_TO_EDGE;
	const deUint32			wrapT				= GL_CLAMP_TO_EDGE;
	const deUint32			magFilter			= GL_NEAREST;

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

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

	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
	const RandomViewport	viewport			(m_context.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));

	vector<float>			texCoord;

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

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

	// 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,		wrapS);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		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<tcu::IVec4> gridLayout;
	computeGridLayout(gridLayout, viewport.width, viewport.height);

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

		TextureTestUtil::computeQuadTexCoordCube(texCoord, cubeFace);

		setTextureParams(cellNdx);

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

	// Read result.
	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, renderedFrame.getAccess());
	GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");

	// Render reference and compare
	{
		tcu::Surface			referenceFrame		(viewport.width, viewport.height);
		tcu::Surface			errorMask			(viewport.width, viewport.height);
		int						numFailedPixels		= 0;
		ReferenceParams			params				(TEXTURETYPE_CUBE);
		tcu::LookupPrecision	lookupPrec;
		tcu::LodPrecision		lodPrec;

		// Params for rendering reference
		params.sampler					= glu::mapGLSampler(wrapS, wrapT, m_minFilter, magFilter);
		params.sampler.seamlessCubeMap	= true;
		params.lodMode					= LODMODE_EXACT;

		// Comparison parameters
		lookupPrec.colorMask			= getCompareMask(m_context.getRenderTarget().getPixelFormat());
		lookupPrec.colorThreshold		= tcu::computeFixedPointThreshold(max(getBitsVec(m_context.getRenderTarget().getPixelFormat())-2, IVec4(0)));
		lookupPrec.coordBits			= tcu::IVec3(10);
		lookupPrec.uvwBits				= tcu::IVec3(5,5,0);
		lodPrec.derivateBits			= 10;
		lodPrec.lodBits					= 6;

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

			computeQuadTexCoordCube(texCoord, cubeFace);
			getReferenceParams(params, cellNdx);

			// Render ideal reference.
			{
				SurfaceAccess idealDst(referenceFrame, m_context.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
				sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
			}

			// Compare this cell
			numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
														tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
														tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
														m_texture->getRefTexture(), &texCoord[0], params,
														lookupPrec, lodPrec, m_testCtx.getWatchDog());
		}

		if (numFailedPixels > 0)
			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
						   << TestLog::Image("Rendered", "Rendered image", renderedFrame);

		if (numFailedPixels > 0)
		{
			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
							   << TestLog::Image("ErrorMask", "Error mask", errorMask);
		}

		m_testCtx.getLog() << TestLog::EndImageSet;

		{
			const bool isOk = numFailedPixels == 0;
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image verification failed");
		}
	}

	return STOP;
}

class TextureCubeMinLodCase : public TextureCubeLodControlCase
{
public:
	TextureCubeMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: TextureCubeLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.minLod = getMinLodForCell(cellNdx);
	}
};

class TextureCubeMaxLodCase : public TextureCubeLodControlCase
{
public:
	TextureCubeMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: TextureCubeLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.maxLod = getMaxLodForCell(cellNdx);
	}
};

class TextureCubeBaseLevelCase : public TextureCubeLodControlCase
{
public:
	TextureCubeBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: TextureCubeLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	int getBaseLevel (int cellNdx) const
	{
		const int	numLevels	= deLog2Floor32(m_texSize)+1;
		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x23fae13) % numLevels;

		return baseLevel;
	}

	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.baseLevel = getBaseLevel(cellNdx);
	}
};

class TextureCubeMaxLevelCase : public TextureCubeLodControlCase
{
public:
	TextureCubeMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: TextureCubeLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	int getMaxLevel (int cellNdx) const
	{
		const int	numLevels	= deLog2Floor32(m_texSize)+1;
		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x974e21) % numLevels;

		return maxLevel;
	}

	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.maxLevel = getMaxLevel(cellNdx);
	}
};

// Texture3DLodControlCase + test cases

class Texture3DLodControlCase : public TestCase
{
public:

										Texture3DLodControlCase		(Context& context, const char* name, const char* desc, deUint32 minFilter);
										~Texture3DLodControlCase	(void);

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

protected:
	virtual void						setTextureParams			(int cellNdx)						= DE_NULL;
	virtual void						getReferenceParams			(ReferenceParams& params, int cellNdx)	= DE_NULL;

	const int							m_texWidth;
	const int							m_texHeight;
	const int							m_texDepth;

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

	deUint32							m_minFilter;

	glu::Texture3D*						m_texture;
	TextureTestUtil::TextureRenderer	m_renderer;
};

Texture3DLodControlCase::Texture3DLodControlCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
	: TestCase			(context, name, desc)
	, m_texWidth		(32)
	, m_texHeight		(32)
	, m_texDepth		(32)
	, m_minFilter		(minFilter)
	, m_texture			(DE_NULL)
	, m_renderer		(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
{
}

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

void Texture3DLodControlCase::init (void)
{
	const deUint32					format			= GL_RGBA8;
	const tcu::TextureFormat&		texFmt			= glu::mapGLInternalFormat(format);
	tcu::TextureFormatInfo			fmtInfo			= tcu::getTextureFormatInfo(texFmt);
	const tcu::Vec4&				cScale			= fmtInfo.lookupScale;
	const tcu::Vec4&				cBias			= fmtInfo.lookupBias;
	int								numLevels		= deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth))+1;

	m_texture = new glu::Texture3D(m_context.getRenderContext(), format, m_texWidth, m_texHeight, m_texDepth);

	// 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()*cScale + cBias);
	}

	m_texture->upload();
}

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

	m_renderer.clear();
}

Texture3DLodControlCase::IterateResult Texture3DLodControlCase::iterate (void)
{
	const glw::Functions&			gl					= m_context.getRenderContext().getFunctions();

	const deUint32					wrapS				= GL_CLAMP_TO_EDGE;
	const deUint32					wrapT				= GL_CLAMP_TO_EDGE;
	const deUint32					wrapR				= GL_CLAMP_TO_EDGE;
	const deUint32					magFilter			= GL_NEAREST;
	const tcu::Texture3D&			refTexture			= m_texture->getRefTexture();
	const tcu::TextureFormat&		texFmt				= refTexture.getFormat();
	const tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
	const int						texWidth			= refTexture.getWidth();
	const int						texHeight			= refTexture.getHeight();

	const tcu::RenderTarget&		renderTarget		= m_context.getRenderContext().getRenderTarget();
	const RandomViewport			viewport			(renderTarget, texWidth*4, texHeight*4, deStringHash(getName()));

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

	tcu::Surface					renderedFrame		(viewport.width, viewport.height);
	vector<float>					texCoord;
	ReferenceParams					sampleParams		(gls::TextureTestUtil::TEXTURETYPE_3D);

	// Sampling parameters.
	sampleParams.sampler		= glu::mapGLSampler(wrapS, wrapT, wrapR, m_minFilter, magFilter);
	sampleParams.samplerType	= gls::TextureTestUtil::getSamplerType(texFmt);
	sampleParams.colorBias		= fmtInfo.lookupBias;
	sampleParams.colorScale		= fmtInfo.lookupScale;

	// Bind texture and setup sampler parameters.
	gl.bindTexture	(GL_TEXTURE_3D, m_texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,		wrapS);
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,		wrapT);
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,		wrapR);
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,	magFilter);

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

	// 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.
			getBasicTexCoord3D(texCoord, cellNdx);

			setTextureParams(cellNdx);

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

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

	// Compare and log
	{
		const tcu::PixelFormat&	pixelFormat		= m_context.getRenderTarget().getPixelFormat();
		const bool				isTrilinear		= m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
		tcu::Surface			referenceFrame	(viewport.width, viewport.height);
		tcu::Surface			errorMask		(viewport.width, viewport.height);
		tcu::LookupPrecision	lookupPrec;
		tcu::LodPrecision		lodPrec;
		int						numFailedPixels	= 0;

		lookupPrec.coordBits		= tcu::IVec3(20, 20, 20);
		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
		lookupPrec.colorMask		= getCompareMask(pixelFormat);
		lodPrec.derivateBits		= 10;
		lodPrec.lodBits				= 8;

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

				getBasicTexCoord3D(texCoord, cellNdx);
				getReferenceParams(sampleParams, cellNdx);

				// Render ideal result
				sampleTexture(SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
							  refTexture, &texCoord[0], sampleParams);

				// Compare this cell
				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
															m_texture->getRefTexture(), &texCoord[0], sampleParams,
															lookupPrec, lodPrec, m_testCtx.getWatchDog());
			}
		}

		if (numFailedPixels > 0)
			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;

		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
							<< TestLog::Image("Rendered", "Rendered image", renderedFrame);

		if (numFailedPixels > 0)
		{
			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
								<< TestLog::Image("ErrorMask", "Error mask", errorMask);
		}

		m_testCtx.getLog() << TestLog::EndImageSet;

		{
			const bool isOk = numFailedPixels == 0;
			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
									isOk ? "Pass"				: "Image verification failed");
		}
	}

	return STOP;
}

class Texture3DMinLodCase : public Texture3DLodControlCase
{
public:
	Texture3DMinLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture3DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_LOD, getMinLodForCell(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.minLod = getMinLodForCell(cellNdx);
	}
};

class Texture3DMaxLodCase : public Texture3DLodControlCase
{
public:
	Texture3DMaxLodCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture3DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAX_LOD, getMaxLodForCell(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.maxLod = getMaxLodForCell(cellNdx);
	}
};

class Texture3DBaseLevelCase : public Texture3DLodControlCase
{
public:
	Texture3DBaseLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture3DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	int getBaseLevel (int cellNdx) const
	{
		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x7347e9) % numLevels;

		return baseLevel;
	}

	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, getBaseLevel(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.baseLevel = getBaseLevel(cellNdx);
	}
};

class Texture3DMaxLevelCase : public Texture3DLodControlCase
{
public:
	Texture3DMaxLevelCase (Context& context, const char* name, const char* desc, deUint32 minFilter)
		: Texture3DLodControlCase(context, name, desc, minFilter)
	{
	}

protected:
	int getMaxLevel (int cellNdx) const
	{
		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(getName()) ^ 0x9111e7) % numLevels;

		return maxLevel;
	}

	void setTextureParams (int cellNdx)
	{
		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
		gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, getMaxLevel(cellNdx));
	}

	void getReferenceParams (ReferenceParams& params, int cellNdx)
	{
		params.maxLevel = getMaxLevel(cellNdx);
	}
};

TextureMipmapTests::TextureMipmapTests (Context& context)
	: TestCaseGroup(context, "mipmap", "Mipmapping 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 Mipmapping");
	tcu::TestCaseGroup*	group3D		= new tcu::TestCaseGroup(m_testCtx, "3d",	"3D Texture Mipmapping");
	addChild(group2D);
	addChild(groupCube);
	addChild(group3D);

	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"			}
	};

	static const struct
	{
		const char*		name;
		deUint32		format;
		deUint32		dataType;
	} formats[] =
	{
		{ "a8",			GL_ALPHA,			GL_UNSIGNED_BYTE },
		{ "l8",			GL_LUMINANCE,		GL_UNSIGNED_BYTE },
		{ "la88",		GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
		{ "rgb565",		GL_RGB,				GL_UNSIGNED_SHORT_5_6_5 },
		{ "rgb888",		GL_RGB,				GL_UNSIGNED_BYTE },
		{ "rgba4444",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4 },
		{ "rgba5551",	GL_RGBA,			GL_UNSIGNED_SHORT_5_5_5_1 },
		{ "rgba8888",	GL_RGBA,			GL_UNSIGNED_BYTE }
	};

	static const struct
	{
		const char*		name;
		deUint32		hint;
	} genHints[] =
	{
		{ "fastest",	GL_FASTEST },
		{ "nicest",		GL_NICEST }
	};

	static const struct
	{
		const char*		name;
		int				width;
		int				height;
	} tex2DSizes[] =
	{
		{ DE_NULL,		64, 64 }, // Default.
		{ "npot",		63, 57 },
		{ "non_square",	32, 64 }
	};

	static const struct
	{
		const char*		name;
		int				width;
		int				height;
		int				depth;
	} tex3DSizes[] =
	{
		{ DE_NULL,		32, 32, 32 }, // Default.
		{ "npot",		33, 29, 27 }
	};

	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"			},
		{ COORDTYPE_BASIC_BIAS,	"bias",			"User-supplied bias value"							}
	};

	// 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++)
			{
				// Add non_square variants to basic cases only.
				int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;

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

					if (tex2DSizes[size].name)
						name << "_" << tex2DSizes[size].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,
																	 tex2DSizes[size].width, tex2DSizes[size].height));
				}
			}
		}
	}

	// 2D bias variants.
	{
		tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
		group2D->addChild(biasGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			biasGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
														minFilterModes[minFilter].name, "",
														COORDTYPE_BASIC_BIAS,
														minFilterModes[minFilter].mode,
														GL_REPEAT, GL_REPEAT,
														GL_RGBA, GL_UNSIGNED_BYTE,
														tex2DSizes[0].width, tex2DSizes[0].height));
	}

	// 2D mipmap generation variants.
	{
		tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
		group2D->addChild(genMipmapGroup);

		for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
		{
			for (int size = 0; size < DE_LENGTH_OF_ARRAY(tex2DSizes); size++)
			{
				for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
				{
					std::ostringstream name;
					name << formats[format].name;

					if (tex2DSizes[size].name)
						name << "_" << tex2DSizes[size].name;

					name << "_" << genHints[hint].name;

					genMipmapGroup->addChild(new Texture2DGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
																		formats[format].format, formats[format].dataType, genHints[hint].hint,
																		tex2DSizes[size].width, tex2DSizes[size].height));
				}
			}
		}
	}

	// 2D LOD controls.
	{
		// MIN_LOD
		tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
		group2D->addChild(minLodGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			minLodGroup->addChild(new Texture2DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// MAX_LOD
		tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
		group2D->addChild(maxLodGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			maxLodGroup->addChild(new Texture2DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// BASE_LEVEL
		tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
		group2D->addChild(baseLevelGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			baseLevelGroup->addChild(new Texture2DBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// MAX_LEVEL
		tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
		group2D->addChild(maxLevelGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			maxLevelGroup->addChild(new Texture2DMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
	}

	// 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));
		}
	}

	// Cubemap mipmap generation variants.
	{
		tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
		groupCube->addChild(genMipmapGroup);

		for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
		{
			for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
			{
				std::ostringstream name;
				name << formats[format].name
					 << "_" << genHints[hint].name;

				genMipmapGroup->addChild(new TextureCubeGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format, formats[format].dataType, genHints[hint].hint, cubeMapSize));
			}
		}
	}

	// Cubemap LOD controls.
	{
		// MIN_LOD
		tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
		groupCube->addChild(minLodGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			minLodGroup->addChild(new TextureCubeMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// MAX_LOD
		tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
		groupCube->addChild(maxLodGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			maxLodGroup->addChild(new TextureCubeMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// BASE_LEVEL
		tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
		groupCube->addChild(baseLevelGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			baseLevelGroup->addChild(new TextureCubeBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// MAX_LEVEL
		tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
		groupCube->addChild(maxLevelGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			maxLevelGroup->addChild(new TextureCubeMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
	}

	// 3D 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);
		group3D->addChild(coordTypeGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
		{
			for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
			{
				// Add other size variants to basic cases only.
				int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;

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

					if (tex3DSizes[size].name)
						name << "_" << tex3DSizes[size].name;

					coordTypeGroup->addChild(new Texture3DMipmapCase(m_context,
																	 name.str().c_str(), "",
																	 coordTypes[coordType].type,
																	 minFilterModes[minFilter].mode,
																	 wrapModes[wrapMode].mode,
																	 wrapModes[wrapMode].mode,
																	 wrapModes[wrapMode].mode,
																	 GL_RGBA8,
																	 tex3DSizes[size].width, tex3DSizes[size].height, tex3DSizes[size].depth));
				}
			}
		}
	}

	// 3D bias variants.
	{
		tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
		group3D->addChild(biasGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			biasGroup->addChild(new Texture3DMipmapCase(m_context,
														minFilterModes[minFilter].name, "",
														COORDTYPE_BASIC_BIAS,
														minFilterModes[minFilter].mode,
														GL_REPEAT, GL_REPEAT, GL_REPEAT,
														GL_RGBA8,
														tex3DSizes[0].width, tex3DSizes[0].height, tex3DSizes[0].depth));
	}

	// 3D LOD controls.
	{
		// MIN_LOD
		tcu::TestCaseGroup* minLodGroup = new tcu::TestCaseGroup(m_testCtx, "min_lod", "Lod control: min lod");
		group3D->addChild(minLodGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			minLodGroup->addChild(new Texture3DMinLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// MAX_LOD
		tcu::TestCaseGroup* maxLodGroup = new tcu::TestCaseGroup(m_testCtx, "max_lod", "Lod control: max lod");
		group3D->addChild(maxLodGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			maxLodGroup->addChild(new Texture3DMaxLodCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// BASE_LEVEL
		tcu::TestCaseGroup* baseLevelGroup = new tcu::TestCaseGroup(m_testCtx, "base_level", "Base level");
		group3D->addChild(baseLevelGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			baseLevelGroup->addChild(new Texture3DBaseLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));

		// MAX_LEVEL
		tcu::TestCaseGroup* maxLevelGroup = new tcu::TestCaseGroup(m_testCtx, "max_level", "Max level");
		group3D->addChild(maxLevelGroup);

		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
			maxLevelGroup->addChild(new Texture3DMaxLevelCase(m_context, minFilterModes[minFilter].name, "", minFilterModes[minFilter].mode));
	}
}

} // Functional
} // gles3
} // deqp
