/*-------------------------------------------------------------------------
 * 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 Texture unit usage tests.
 *
 * \todo [2012-07-12 nuutti] Come up with a good way to make these tests faster.
 *//*--------------------------------------------------------------------*/

#include "es3fTextureUnitTests.hpp"
#include "glsTextureTestUtil.hpp"
#include "gluTextureUtil.hpp"
#include "gluContextInfo.hpp"
#include "gluTextureUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuMatrix.hpp"
#include "tcuRenderTarget.hpp"
#include "sglrContextUtil.hpp"
#include "sglrReferenceContext.hpp"
#include "sglrGLContext.hpp"
#include "deMath.h"
#include "deRandom.hpp"
#include "deStringUtil.hpp"

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

using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec3;
using tcu::Mat3;
using tcu::Mat4;
using std::vector;
using std::string;
using namespace glw; // GL types

namespace deqp
{

using namespace gls::TextureTestUtil;

namespace gles3
{
namespace Functional
{

static const int VIEWPORT_WIDTH				= 128;
static const int VIEWPORT_HEIGHT			= 128;

static const int TEXTURE_WIDTH_2D			= 128;
static const int TEXTURE_HEIGHT_2D			= 128;

// \note Cube map texture size is larger in order to make minifications possible - otherwise would need to display different faces at same time.
static const int TEXTURE_WIDTH_CUBE			= 256;
static const int TEXTURE_HEIGHT_CUBE		= 256;

static const int TEXTURE_WIDTH_2D_ARRAY		= 64;
static const int TEXTURE_HEIGHT_2D_ARRAY	= 64;
static const int TEXTURE_LAYERS_2D_ARRAY	= 4;

static const int TEXTURE_WIDTH_3D			= 32;
static const int TEXTURE_HEIGHT_3D			= 32;
static const int TEXTURE_DEPTH_3D			= 32;

static const int GRID_CELL_SIZE				= 8;

static const GLenum s_testSizedInternalFormats[] =
{
	GL_RGBA32F,
	GL_RGBA32I,
	GL_RGBA32UI,
	GL_RGBA16F,
	GL_RGBA16I,
	GL_RGBA16UI,
	GL_RGBA8,
	GL_RGBA8I,
	GL_RGBA8UI,
	GL_SRGB8_ALPHA8,
	GL_RGB10_A2,
	GL_RGB10_A2UI,
	GL_RGBA4,
	GL_RGB5_A1,
	GL_RGBA8_SNORM,
	GL_RGB8,
	GL_RGB565,
	GL_R11F_G11F_B10F,
	GL_RGB32F,
	GL_RGB32I,
	GL_RGB32UI,
	GL_RGB16F,
	GL_RGB16I,
	GL_RGB16UI,
	GL_RGB8_SNORM,
	GL_RGB8I,
	GL_RGB8UI,
	GL_SRGB8,
	GL_RGB9_E5,
	GL_RG32F,
	GL_RG32I,
	GL_RG32UI,
	GL_RG16F,
	GL_RG16I,
	GL_RG16UI,
	GL_RG8,
	GL_RG8I,
	GL_RG8UI,
	GL_RG8_SNORM,
	GL_R32F,
	GL_R32I,
	GL_R32UI,
	GL_R16F,
	GL_R16I,
	GL_R16UI,
	GL_R8,
	GL_R8I,
	GL_R8UI,
	GL_R8_SNORM
};

static const GLenum s_testWrapModes[] =
{
	GL_CLAMP_TO_EDGE,
	GL_REPEAT,
	GL_MIRRORED_REPEAT,
};

static const GLenum s_testMinFilters[] =
{
	GL_NEAREST,
	GL_LINEAR,
	GL_NEAREST_MIPMAP_NEAREST,
	GL_LINEAR_MIPMAP_NEAREST,
	GL_NEAREST_MIPMAP_LINEAR,
	GL_LINEAR_MIPMAP_LINEAR
};

static const GLenum s_testNonMipmapMinFilters[] =
{
	GL_NEAREST,
	GL_LINEAR
};

static const GLenum s_testNearestMinFilters[] =
{
	GL_NEAREST,
	GL_NEAREST_MIPMAP_NEAREST
};

static const GLenum s_testMagFilters[] =
{
	GL_NEAREST,
	GL_LINEAR
};

static const GLenum s_cubeFaceTargets[] =
{
	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};

// Extend a 3x3 transformation matrix to an equivalent 4x4 transformation matrix (i.e. 1.0 in right-down cell, 0.0's in other new cells).
static Mat4 matExtend3To4 (const Mat3& mat)
{
	Mat4 res;
	for (int rowNdx = 0; rowNdx < 3; rowNdx++)
	{
		Vec3 row = mat.getRow(rowNdx);
		res.setRow(rowNdx, Vec4(row.x(), row.y(), row.z(), 0.0f));
	}
	res.setRow(3, Vec4(0.0f, 0.0f, 0.0f, 1.0f));

	return res;
}

static string generateMultiTexFragmentShader (int numUnits, const vector<GLenum>& unitTypes, const vector<glu::DataType>& samplerTypes)
{
	// The fragment shader calculates the average of a set of textures.

	string samplersStr;
	string matricesStr;
	string scalesStr;
	string biasesStr;
	string lookupsStr;

	string colorMultiplier = "(1.0/" + de::toString(numUnits) + ".0)";

	for (int ndx = 0; ndx < numUnits; ndx++)
	{
		string ndxStr				= de::toString(ndx);
		string samplerName			= "u_sampler" + ndxStr;
		string transformationName	= "u_trans" + ndxStr;
		string scaleName			= "u_texScale" + ndxStr;
		string biasName				= "u_texBias" + ndxStr;

		samplersStr += string("") + "uniform highp " + glu::getDataTypeName(samplerTypes[ndx]) + " " + samplerName + ";\n";
		matricesStr += "uniform highp mat4 " + transformationName + ";\n";
		scalesStr += "uniform highp vec4 " + scaleName + ";\n";
		biasesStr += "uniform highp vec4 " + biasName + ";\n";

		string lookupCoord = transformationName + "*vec4(v_coord, 1.0, 1.0)";

		if (unitTypes[ndx] == GL_TEXTURE_2D)
			lookupCoord = "vec2(" + lookupCoord + ")";
		else
			lookupCoord = "vec3(" + lookupCoord + ")";

		lookupsStr += "\tcolor += " + colorMultiplier + "*(vec4(texture(" + samplerName + ", " + lookupCoord + "))*" + scaleName + " + " + biasName + ");\n";
	}

	return "#version 300 es\n"
		   "layout(location = 0) out mediump vec4 o_color;\n" +
		   samplersStr +
		   matricesStr +
		   scalesStr +
		   biasesStr +
		   "in highp vec2 v_coord;\n"
		   "\n"
		   "void main (void)\n"
		   "{\n"
		   "	mediump vec4 color = vec4(0.0);\n" +
		   lookupsStr +
		   "	o_color = color;\n"
		   "}\n";
}

static sglr::pdec::ShaderProgramDeclaration generateShaderProgramDeclaration (int numUnits, const vector<GLenum>& unitTypes, const vector<glu::DataType>& samplerTypes)
{
	sglr::pdec::ShaderProgramDeclaration decl;

	decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
	decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
	decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);

	for (int ndx = 0; ndx < numUnits; ++ndx)
	{
		string samplerName			= "u_sampler" + de::toString(ndx);
		string transformationName	= "u_trans" + de::toString(ndx);
		string scaleName			= "u_texScale" + de::toString(ndx);
		string biasName				= "u_texBias" + de::toString(ndx);

		decl << sglr::pdec::Uniform(samplerName, samplerTypes[ndx]);
		decl << sglr::pdec::Uniform(transformationName, glu::TYPE_FLOAT_MAT4);
		decl << sglr::pdec::Uniform(scaleName, glu::TYPE_FLOAT_VEC4);
		decl << sglr::pdec::Uniform(biasName, glu::TYPE_FLOAT_VEC4);
	}

	decl << sglr::pdec::VertexSource("#version 300 es\n"
									 "in highp vec4 a_position;\n"
									 "in highp vec2 a_coord;\n"
									 "out highp vec2 v_coord;\n"
									 "\n"
									 "void main (void)\n"
									 "{\n"
									 "	gl_Position = a_position;\n"
									 "	v_coord = a_coord;\n"
									 "}\n");
	decl << sglr::pdec::FragmentSource(generateMultiTexFragmentShader(numUnits, unitTypes, samplerTypes));

	return decl;
}

// Calculates values that will be used in calculateLod().
static tcu::Vector<tcu::Vec2, 3> calculateLodDerivateParts (const Mat4& transformation)
{
	// Calculate transformed coordinates of three screen corners.
	Vec3 trans00 = (transformation * Vec4(0.0f, 0.0f, 1.0f, 1.0f)).xyz();
	Vec3 trans01 = (transformation * Vec4(0.0f, 1.0f, 1.0f, 1.0f)).xyz();
	Vec3 trans10 = (transformation * Vec4(1.0f, 0.0f, 1.0f, 1.0f)).xyz();

	return tcu::Vector<tcu::Vec2, 3>(Vec2(trans10.x() - trans00.x(), trans01.x() - trans00.x()),
									 Vec2(trans10.y() - trans00.y(), trans01.y() - trans00.y()),
									 Vec2(trans10.z() - trans00.z(), trans01.z() - trans00.z()));
}

// Calculates the maximum allowed lod from derivates
static float calculateLodMax(const tcu::Vector<tcu::Vec2, 3>& derivateParts, const tcu::IVec3& textureSize, const Vec2& screenDerivate)
{
	float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
	float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
	float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
	float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
	float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
	float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();

	const float mu = de::max(de::abs(dudx), de::abs(dudy));
	const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
	const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
	return deFloatLog2(mu + mv + mw);
}

// Calculates the minimum allowed lod from derivates
static float calculateLodMin(const tcu::Vector<tcu::Vec2, 3>& derivateParts, const tcu::IVec3& textureSize, const Vec2& screenDerivate)
{
	float dudx = derivateParts[0].x() * (float)textureSize.x() * screenDerivate.x();
	float dudy = derivateParts[0].y() * (float)textureSize.x() * screenDerivate.y();
	float dvdx = derivateParts[1].x() * (float)textureSize.y() * screenDerivate.x();
	float dvdy = derivateParts[1].y() * (float)textureSize.y() * screenDerivate.y();
	float dwdx = derivateParts[2].x() * (float)textureSize.z() * screenDerivate.x();
	float dwdy = derivateParts[2].y() * (float)textureSize.z() * screenDerivate.y();

	const float mu = de::max(de::abs(dudx), de::abs(dudy));
	const float mv = de::max(de::abs(dvdx), de::abs(dvdy));
	const float mw = de::max(de::abs(dwdx), de::abs(dwdy));
	return deFloatLog2(de::max(mu, de::max(mv, mw)));
}

class MultiTexShader : public sglr::ShaderProgram
{
public:
							MultiTexShader	(deUint32 randSeed,
											 int numUnits,
											 const vector<GLenum>& unitTypes,
											 const vector<glu::DataType>& samplerTypes,
											 const vector<Vec4>& texScales,
											 const vector<Vec4>& texBiases,
											 const vector<int>& num2dArrayLayers); // \note 2d array layer "coordinate" isn't normalized, so this is needed here.

	void					setUniforms		(sglr::Context& context, deUint32 program) const;
	void					makeSafeLods	(const vector<IVec3>& textureSizes, const IVec2& viewportSize); // Modifies texture coordinates so that LODs aren't too close to x.5 or 0.0 .

private:
	void					shadeVertices	(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
	void					shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;

	int									m_numUnits;
	vector<GLenum>						m_unitTypes;		// 2d, cube map, 2d array or 3d.
	vector<Vec4>						m_texScales;
	vector<Vec4>						m_texBiases;
	vector<Mat4>						m_transformations;
	vector<tcu::Vector<tcu::Vec2, 3> >	m_lodDerivateParts;	// Parts of lod derivates; computed in init(), used in eval().
};

MultiTexShader::MultiTexShader (deUint32 randSeed,
								int numUnits,
								const vector<GLenum>& unitTypes,
								const vector<glu::DataType>& samplerTypes,
								const vector<Vec4>& texScales,
								const vector<Vec4>& texBiases,
								const vector<int>& num2dArrayLayers)
		: sglr::ShaderProgram	(generateShaderProgramDeclaration(numUnits, unitTypes, samplerTypes))
		, m_numUnits		(numUnits)
		, m_unitTypes		(unitTypes)
		, m_texScales		(texScales)
		, m_texBiases		(texBiases)
{
	// 2d-to-cube-face transformations.
	// \note 2d coordinates range from 0 to 1 and cube face coordinates from -1 to 1, so scaling is done as well.
	static const float s_cubeTransforms[][3*3] =
	{
		// Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
		{  0.0f,  0.0f, -1.0f,
		   0.0f, -2.0f,  1.0f,
		   2.0f,  0.0f, -1.0f },
		// Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
		{  0.0f,  0.0f,  1.0f,
		   0.0f, -2.0f,  1.0f,
		  -2.0f,  0.0f,  1.0f },
		// Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
		{  2.0f,  0.0f, -1.0f,
		   0.0f,  0.0f, -1.0f,
		   0.0f, -2.0f,  1.0f },
		// Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
		{  2.0f,  0.0f, -1.0f,
		   0.0f,  0.0f,  1.0f,
		   0.0f,  2.0f, -1.0f },
		// Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
		{ -2.0f,  0.0f,  1.0f,
		   0.0f, -2.0f,  1.0f,
		   0.0f,  0.0f, -1.0f },
		// Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
		{  2.0f,  0.0f, -1.0f,
		   0.0f, -2.0f,  1.0f,
		   0.0f,  0.0f,  1.0f }
	};

	// Generate transformation matrices.

	de::Random rnd(randSeed);

	m_transformations.reserve(m_numUnits);
	m_lodDerivateParts.reserve(m_numUnits);

	int tex2dArrayNdx = 0; // Keep track of 2d texture array index.

	DE_ASSERT((int)m_unitTypes.size() == m_numUnits);

	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
	{
		if (m_unitTypes[unitNdx] == GL_TEXTURE_2D)
		{
			float rotAngle				= rnd.getFloat(0.0f, 2.0f*DE_PI);
			float xScaleFactor			= rnd.getFloat(0.7f, 1.5f);
			float yScaleFactor			= rnd.getFloat(0.7f, 1.5f);
			float xShearAmount			= rnd.getFloat(0.0f, 0.5f);
			float yShearAmount			= rnd.getFloat(0.0f, 0.5f);
			float xTranslationAmount	= rnd.getFloat(-0.5f, 0.5f);
			float yTranslationAmount	= rnd.getFloat(-0.5f, 0.5f);

			static const float tempOffsetData[3*3] = // For temporarily centering the coordinates to get nicer transformations.
			{
				1.0f,  0.0f, -0.5f,
				0.0f,  1.0f, -0.5f,
				0.0f,  0.0f,  1.0f
			};
			float rotTransfData[3*3] =
			{
				deFloatCos(rotAngle),	-deFloatSin(rotAngle),	0.0f,
				deFloatSin(rotAngle),	deFloatCos(rotAngle),	0.0f,
				0.0f,					0.0f,					1.0f
			};
			float scaleTransfData[3*3] =
			{
				xScaleFactor,	0.0f,			0.0f,
				0.0f,			yScaleFactor,	0.0f,
				0.0f,			0.0f,			1.0f
			};
			float xShearTransfData[3*3] =
			{
				1.0f,			xShearAmount,	0.0f,
				0.0f,			1.0f,			0.0f,
				0.0f,			0.0f,			1.0f
			};
			float yShearTransfData[3*3] =
			{
				1.0f,			0.0f,			0.0f,
				yShearAmount,	1.0f,			0.0f,
				0.0f,			0.0f,			1.0f
			};
			float translationTransfData[3*3] =
			{
				1.0f,	0.0f,	xTranslationAmount,
				0.0f,	1.0f,	yTranslationAmount,
				0.0f,	0.0f,	1.0f
			};

			Mat4 transformation = matExtend3To4(Mat3(tempOffsetData) *
												Mat3(translationTransfData) *
												Mat3(rotTransfData) *
												Mat3(scaleTransfData) *
												Mat3(xShearTransfData) *
												Mat3(yShearTransfData) *
												(Mat3(tempOffsetData) * (-1.0f)));

			m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
			m_transformations.push_back(transformation);
		}
		else if (m_unitTypes[unitNdx] == GL_TEXTURE_CUBE_MAP)
		{
			DE_STATIC_ASSERT((int)tcu::CUBEFACE_LAST == DE_LENGTH_OF_ARRAY(s_cubeTransforms));

			float planarTransData[3*3];

			// In case of a cube map, we only want to render one face, so the transformation needs to be restricted - only enlarging scaling is done.

			for (int i = 0; i < DE_LENGTH_OF_ARRAY(planarTransData); i++)
			{
				if (i == 0 || i == 4)
					planarTransData[i] = rnd.getFloat(0.1f, 0.9f); // Two first diagonal cells control the scaling.
				else if (i == 8)
					planarTransData[i] = 1.0f;
				else
					planarTransData[i] = 0.0f;
			}

			int		faceNdx			= rnd.getInt(0, (int)tcu::CUBEFACE_LAST - 1);
			Mat3	planarTrans		(planarTransData);												// Planar, face-agnostic transformation.
			Mat4	finalTrans		= matExtend3To4(Mat3(s_cubeTransforms[faceNdx]) * planarTrans);	// Final transformation from planar to cube map coordinates, including the transformation just generated.
			Mat4	planarTrans4x4	= matExtend3To4(planarTrans);

			m_lodDerivateParts.push_back(calculateLodDerivateParts(planarTrans4x4));
			m_transformations.push_back(finalTrans);
		}
		else
		{
			DE_ASSERT(m_unitTypes[unitNdx] == GL_TEXTURE_3D || m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY);

			float transData[4*4];

			for (int i = 0; i < 4*4; i++)
			{
				float sign = rnd.getBool() ? 1.0f : -1.0f;
				transData[i] = rnd.getFloat(0.7f, 1.4f) * sign;
			}

			Mat4 transformation(transData);

			if (m_unitTypes[unitNdx] == GL_TEXTURE_2D_ARRAY)
			{
				// Z direction: Translate by 0.5 and scale by layer amount.

				float numLayers = (float)num2dArrayLayers[tex2dArrayNdx];

				static const float zTranslationTransfData[4*4] =
				{
					1.0f, 0.0f, 0.0f, 0.0f,
					0.0f, 1.0f, 0.0f, 0.0f,
					0.0f, 0.0f, 1.0f, 0.5f,
					0.0f, 0.0f, 0.0f, 1.0f
				};

				float zScaleTransfData[4*4] =
				{
					1.0f,		0.0f,		0.0f,		0.0f,
					0.0f,		1.0f,		0.0f,		0.0f,
					0.0f,		0.0f,		numLayers,	0.0f,
					0.0f,		0.0f,		0.0f,		1.0f
				};

				transformation = transformation * Mat4(zScaleTransfData) * Mat4(zTranslationTransfData);

				tex2dArrayNdx++;
			}

			m_lodDerivateParts.push_back(calculateLodDerivateParts(transformation));
			m_transformations.push_back(Mat4(transformation));
		}
	}
}

void MultiTexShader::setUniforms (sglr::Context& ctx, deUint32 program) const
{
	ctx.useProgram(program);

	// Sampler and matrix uniforms.

	for (int ndx = 0; ndx < m_numUnits; ndx++)
	{
		string			ndxStr		= de::toString(ndx);

		ctx.uniform1i(ctx.getUniformLocation(program, ("u_sampler" + ndxStr).c_str()), ndx);
		ctx.uniformMatrix4fv(ctx.getUniformLocation(program, ("u_trans" + ndxStr).c_str()), 1, GL_FALSE, (GLfloat*)&m_transformations[ndx].getColumnMajorData()[0]);
		ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texScale" + ndxStr).c_str()), 1, m_texScales[ndx].getPtr());
		ctx.uniform4fv(ctx.getUniformLocation(program, ("u_texBias" + ndxStr).c_str()), 1, m_texBiases[ndx].getPtr());
	}
}

void MultiTexShader::makeSafeLods (const vector<IVec3>& textureSizes, const IVec2& viewportSize)
{
	DE_ASSERT((int)textureSizes.size() == m_numUnits);

	static const float shrinkScaleMat2dData[3*3] =
	{
		0.95f,	0.0f,	0.0f,
		0.0f,	0.95f,	0.0f,
		0.0f,	0.0f,	1.0f
	};
	static const float shrinkScaleMat3dData[3*3] =
	{
		0.95f,	0.0f,	0.0f,
		0.0f,	0.95f,	0.0f,
		0.0f,	0.0f,	0.95f
	};
	Mat4 shrinkScaleMat2d = matExtend3To4(Mat3(shrinkScaleMat2dData));
	Mat4 shrinkScaleMat3d = matExtend3To4(Mat3(shrinkScaleMat3dData));

	Vec2 screenDerivate(1.0f / (float)viewportSize.x(), 1.0f / (float)viewportSize.y());

	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
	{
		// As long as LOD is too close to 0.0 or is positive and too close to a something-and-a-half (0.5, 1.5, 2.5 etc) or allowed lod range could round to different levels, zoom in a little to get a safer LOD.
		for (;;)
		{
			const float threshold = 0.1f;
			const float epsilon	= 0.01f;

			const float lodMax = calculateLodMax(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);
			const float lodMin = calculateLodMin(m_lodDerivateParts[unitNdx], textureSizes[unitNdx], screenDerivate);

			const deInt32 maxLevel = (lodMax + epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMax + epsilon + 0.5f) - 1);
			const deInt32 minLevel = (lodMin - epsilon < 0.5f) ? (0) : (deCeilFloatToInt32(lodMin - epsilon + 0.5f) - 1);

			if (de::abs(lodMax) < threshold || (lodMax > 0.0f && de::abs(deFloatFrac(lodMax) - 0.5f) < threshold) ||
				de::abs(lodMin) < threshold || (lodMin > 0.0f && de::abs(deFloatFrac(lodMin) - 0.5f) < threshold) ||
				maxLevel != minLevel)
			{
				m_transformations[unitNdx] = (m_unitTypes[unitNdx] == GL_TEXTURE_3D ? shrinkScaleMat3d : shrinkScaleMat2d) * m_transformations[unitNdx];
				m_lodDerivateParts[unitNdx] = calculateLodDerivateParts(m_transformations[unitNdx]);
			}
			else
				break;
		}
	}
}

void MultiTexShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
{
	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
	{
		rr::VertexPacket& packet = *(packets[packetNdx]);

		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
	}
}

void MultiTexShader::shadeFragments	(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
{
	DE_ASSERT((int)m_unitTypes.size() == m_numUnits);
	DE_ASSERT((int)m_transformations.size() == m_numUnits);
	DE_ASSERT((int)m_lodDerivateParts.size() == m_numUnits);

	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
	{
		rr::FragmentPacket& packet				= packets[packetNdx];
		const float			colorMultiplier		= 1.0f / (float)m_numUnits;
		Vec4				outColors[4]		= { Vec4(0.0f), Vec4(0.0f), Vec4(0.0f), Vec4(0.0f) };

		for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
		{
			tcu::Vec4 texSamples[4];

			// Read tex coords
			const tcu::Vec2 texCoords[4] =
			{
				rr::readTriangleVarying<float>(packet, context, 0, 0).xy(),
				rr::readTriangleVarying<float>(packet, context, 0, 1).xy(),
				rr::readTriangleVarying<float>(packet, context, 0, 2).xy(),
				rr::readTriangleVarying<float>(packet, context, 0, 3).xy(),
			};

			// Transform
			tcu::Vec3 coords3D[4] =
			{
				(m_transformations[unitNdx] * Vec4(texCoords[0].x(), texCoords[0].y(), 1.0f, 1.0f)).xyz(),
				(m_transformations[unitNdx] * Vec4(texCoords[1].x(), texCoords[1].y(), 1.0f, 1.0f)).xyz(),
				(m_transformations[unitNdx] * Vec4(texCoords[2].x(), texCoords[2].y(), 1.0f, 1.0f)).xyz(),
				(m_transformations[unitNdx] * Vec4(texCoords[3].x(), texCoords[3].y(), 1.0f, 1.0f)).xyz(),
			};

			// To 2D
			const tcu::Vec2 coords2D[4] =
			{
				coords3D[0].xy(),
				coords3D[1].xy(),
				coords3D[2].xy(),
				coords3D[3].xy(),
			};

			// Sample
			switch (m_unitTypes[unitNdx])
			{
				case GL_TEXTURE_2D:			m_uniforms[4*unitNdx].sampler.tex2D->sample4(texSamples, coords2D);			break;
				case GL_TEXTURE_CUBE_MAP:	m_uniforms[4*unitNdx].sampler.texCube->sample4(texSamples, coords3D);		break;
				case GL_TEXTURE_2D_ARRAY:	m_uniforms[4*unitNdx].sampler.tex2DArray->sample4(texSamples, coords3D);	break;
				case GL_TEXTURE_3D:			m_uniforms[4*unitNdx].sampler.tex3D->sample4(texSamples, coords3D);			break;
				default:
					DE_ASSERT(DE_FALSE);
			}

			// Add to sum
			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
				outColors[fragNdx] += colorMultiplier * (texSamples[fragNdx]*m_texScales[unitNdx] + m_texBiases[unitNdx]);
		}

		// output
		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, outColors[fragNdx]);
	}
}

class TextureUnitCase : public TestCase
{
public:
	enum CaseType
	{
		CASE_ONLY_2D = 0,
		CASE_ONLY_CUBE,
		CASE_ONLY_2D_ARRAY,
		CASE_ONLY_3D,
		CASE_MIXED,

		CASE_LAST
	};
								TextureUnitCase		(Context& context, const char* name, const char* desc, int numUnits /* \note If non-positive, use all units */, CaseType caseType, deUint32 randSeed);
								~TextureUnitCase	(void);

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

private:
	struct TextureParameters
	{
		GLenum internalFormat;
		GLenum wrapModeS;
		GLenum wrapModeT;
		GLenum wrapModeR;
		GLenum minFilter;
		GLenum magFilter;
	};

									TextureUnitCase			(const TextureUnitCase& other);
	TextureUnitCase&				operator=				(const TextureUnitCase& other);

	void							upload2dTexture			(int texNdx, sglr::Context& context);
	void							uploadCubeTexture		(int texNdx, sglr::Context& context);
	void							upload2dArrayTexture	(int texNdx, sglr::Context& context);
	void							upload3dTexture			(int texNdx, sglr::Context& context);

	void							render					(sglr::Context& context);

	const int						m_numUnitsParam;
	const CaseType					m_caseType;
	const deUint32					m_randSeed;

	int								m_numTextures;	//!< \note Needed in addition to m_numUnits since same texture may be bound to many texture units.
	int								m_numUnits;		//!< = m_numUnitsParam > 0 ? m_numUnitsParam : implementationDefinedMaximum

	vector<GLenum>					m_textureTypes;
	vector<TextureParameters>		m_textureParams;
	vector<tcu::Texture2D*>			m_textures2d;
	vector<tcu::TextureCube*>		m_texturesCube;
	vector<tcu::Texture2DArray*>	m_textures2dArray;
	vector<tcu::Texture3D*>			m_textures3d;
	vector<int>						m_unitTextures;	//!< Which texture is used in a particular unit.
	vector<int>						m_ndxTexType;	//!< Index of a texture in m_textures2d, m_texturesCube, m_textures2dArray or m_textures3d, depending on texture type.
	MultiTexShader*					m_shader;
};

TextureUnitCase::TextureUnitCase (Context& context, const char* name, const char* desc, int numUnits, CaseType caseType, deUint32 randSeed)
	: TestCase			(context, tcu::NODETYPE_SELF_VALIDATE, name, desc)
	, m_numUnitsParam	(numUnits)
	, m_caseType		(caseType)
	, m_randSeed		(randSeed)
	, m_numTextures		(0)
	, m_numUnits		(0)
	, m_shader			(DE_NULL)
{
}

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

void TextureUnitCase::deinit (void)
{
	for (vector<tcu::Texture2D*>::iterator i = m_textures2d.begin(); i != m_textures2d.end(); i++)
		delete *i;
	m_textures2d.clear();

	for (vector<tcu::TextureCube*>::iterator i = m_texturesCube.begin(); i != m_texturesCube.end(); i++)
		delete *i;
	m_texturesCube.clear();

	for (vector<tcu::Texture2DArray*>::iterator i = m_textures2dArray.begin(); i != m_textures2dArray.end(); i++)
		delete *i;
	m_textures2dArray.clear();

	for (vector<tcu::Texture3D*>::iterator i = m_textures3d.begin(); i != m_textures3d.end(); i++)
		delete *i;
	m_textures3d.clear();

	delete m_shader;
	m_shader = DE_NULL;
}

void TextureUnitCase::init (void)
{
	m_numUnits = m_numUnitsParam > 0 ? m_numUnitsParam : m_context.getContextInfo().getInt(GL_MAX_TEXTURE_IMAGE_UNITS);

	// Make the textures.

	try
	{
		tcu::TestLog&	log	= m_testCtx.getLog();
		de::Random		rnd	(m_randSeed);

		if (rnd.getFloat() < 0.7f)
			m_numTextures = m_numUnits;											// In most cases use one unit per texture.
		else
			m_numTextures = rnd.getInt(deMax32(1, m_numUnits - 2), m_numUnits);	// Sometimes assign same texture to multiple units.

		log << tcu::TestLog::Message << ("Using " + de::toString(m_numUnits) + " texture unit(s) and " + de::toString(m_numTextures) + " texture(s)").c_str() << tcu::TestLog::EndMessage;

		m_textureTypes.reserve(m_numTextures);
		m_textureParams.reserve(m_numTextures);
		m_ndxTexType.reserve(m_numTextures);

		// Generate textures.

		for (int texNdx = 0; texNdx < m_numTextures; texNdx++)
		{
			// Either fixed or randomized target types, and randomized parameters for every texture.

			TextureParameters	params;

			DE_STATIC_ASSERT(CASE_ONLY_2D == 0 && CASE_MIXED + 1 == CASE_LAST);

			int						texType			= m_caseType == CASE_MIXED ? rnd.getInt(0, (int)CASE_MIXED - 1) : (int)m_caseType;
			bool					is2dTex			= texType == 0;
			bool					isCubeTex		= texType == 1;
			bool					is2dArrayTex	= texType == 2;
			bool					is3dTex			= texType == 3;

			DE_ASSERT(is2dTex || isCubeTex || is2dArrayTex || is3dTex);

			GLenum					type			= is2dTex		? GL_TEXTURE_2D		: isCubeTex ? GL_TEXTURE_CUBE_MAP	: is2dArrayTex ? GL_TEXTURE_2D_ARRAY		: GL_TEXTURE_3D;
			const int				texWidth		= is2dTex		? TEXTURE_WIDTH_2D	: isCubeTex ? TEXTURE_WIDTH_CUBE	: is2dArrayTex ? TEXTURE_WIDTH_2D_ARRAY		: TEXTURE_WIDTH_3D;
			const int				texHeight		= is2dTex		? TEXTURE_HEIGHT_2D	: isCubeTex ? TEXTURE_HEIGHT_CUBE	: is2dArrayTex ? TEXTURE_HEIGHT_2D_ARRAY	: TEXTURE_HEIGHT_3D;

			const int				texDepth		= is3dTex ? TEXTURE_DEPTH_3D : 1;
			const int				texLayers		= is2dArrayTex ? TEXTURE_LAYERS_2D_ARRAY : 1;

			bool					mipmaps			= (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight) && deIsPowerOfTwo32(texDepth));
			int						numLevels		= mipmaps ? deLog2Floor32(de::max(de::max(texWidth, texHeight), texDepth))+1 : 1;

			params.internalFormat = s_testSizedInternalFormats[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testSizedInternalFormats) - 1)];

			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(params.internalFormat);

			params.wrapModeS = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
			params.wrapModeT = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];
			params.wrapModeR = s_testWrapModes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testWrapModes) - 1)];

			params.magFilter = isFilterable ? s_testMagFilters[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMagFilters) - 1)] : GL_NEAREST;

			if (mipmaps)
				params.minFilter = isFilterable ?
					s_testMinFilters			[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testMinFilters) - 1)] :
					s_testNearestMinFilters		[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNearestMinFilters) - 1)];
			else
				params.minFilter = isFilterable ?
					s_testNonMipmapMinFilters	[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_testNonMipmapMinFilters) - 1)] :
					GL_NEAREST;

			m_textureTypes.push_back(type);
			m_textureParams.push_back(params);

			// Create new texture.

			tcu::TextureFormat texFormat = glu::mapGLInternalFormat((deUint32)params.internalFormat);

			if (is2dTex)
			{
				m_ndxTexType.push_back((int)m_textures2d.size()); // Remember the index this texture has in the 2d texture vector.
				m_textures2d.push_back(new tcu::Texture2D(texFormat, texWidth, texHeight));
			}
			else if (isCubeTex)
			{
				m_ndxTexType.push_back((int)m_texturesCube.size()); // Remember the index this texture has in the cube texture vector.
				DE_ASSERT(texWidth == texHeight);
				m_texturesCube.push_back(new tcu::TextureCube(texFormat, texWidth));
			}
			else if (is2dArrayTex)
			{
				m_ndxTexType.push_back((int)m_textures2dArray.size()); // Remember the index this texture has in the 2d array texture vector.
				m_textures2dArray.push_back(new tcu::Texture2DArray(texFormat, texWidth, texHeight, texLayers));
			}
			else
			{
				m_ndxTexType.push_back((int)m_textures3d.size()); // Remember the index this texture has in the 3d vector.
				m_textures3d.push_back(new tcu::Texture3D(texFormat, texWidth, texHeight, texDepth));
			}

			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
			Vec4					cBias		= fmtInfo.valueMin;
			Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;

			// Fill with grid texture.

			int numFaces = isCubeTex ? (int)tcu::CUBEFACE_LAST : 1;

			for (int face = 0; face < numFaces; face++)
			{
				deUint32 rgb	= rnd.getUint32() & 0x00ffffff;
				deUint32 alpha	= 0xff000000;

				deUint32 colorA = alpha | rgb;
				deUint32 colorB = alpha | ((~rgb) & 0x00ffffff);

				for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
				{
					if (is2dTex)
						m_textures2d.back()->allocLevel(levelNdx);
					else if (isCubeTex)
						m_texturesCube.back()->allocLevel((tcu::CubeFace)face, levelNdx);
					else if (is2dArrayTex)
						m_textures2dArray.back()->allocLevel(levelNdx);
					else
						m_textures3d.back()->allocLevel(levelNdx);

					int curCellSize = deMax32(1, GRID_CELL_SIZE >> levelNdx); // \note Scale grid cell size for mipmaps.

					tcu::PixelBufferAccess access = is2dTex			? m_textures2d.back()->getLevel(levelNdx)
												  : isCubeTex		? m_texturesCube.back()->getLevelFace(levelNdx, (tcu::CubeFace)face)
												  : is2dArrayTex	? m_textures2dArray.back()->getLevel(levelNdx)
												  :					  m_textures3d.back()->getLevel(levelNdx);

					tcu::fillWithGrid(access, curCellSize, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
				}
			}
		}

		// Assign a texture index to each unit.

		m_unitTextures.reserve(m_numUnits);

		// \note Every texture is used at least once.
		for (int i = 0; i < m_numTextures; i++)
			m_unitTextures.push_back(i);

		// Assign a random texture to remaining units.
		while ((int)m_unitTextures.size() < m_numUnits)
			m_unitTextures.push_back(rnd.getInt(0, m_numTextures - 1));

		rnd.shuffle(m_unitTextures.begin(), m_unitTextures.end());

		// Generate information for shader.

		vector<GLenum>			unitTypes;
		vector<Vec4>			texScales;
		vector<Vec4>			texBiases;
		vector<glu::DataType>	samplerTypes;
		vector<int>				num2dArrayLayers;

		unitTypes.reserve(m_numUnits);
		texScales.reserve(m_numUnits);
		texBiases.reserve(m_numUnits);
		samplerTypes.reserve(m_numUnits);
		num2dArrayLayers.reserve(m_numUnits);

		for (int i = 0; i < m_numUnits; i++)
		{
			int						texNdx		= m_unitTextures[i];
			GLenum					type		= m_textureTypes[texNdx];
			tcu::TextureFormat		fmt			= glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat);
			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(fmt);

			unitTypes.push_back(type);

			if (type == GL_TEXTURE_2D_ARRAY)
				num2dArrayLayers.push_back(m_textures2dArray[m_ndxTexType[texNdx]]->getNumLayers());

			texScales.push_back(fmtInfo.lookupScale);
			texBiases.push_back(fmtInfo.lookupBias);

			switch (type)
			{
				case GL_TEXTURE_2D:			samplerTypes.push_back(glu::getSampler2DType(fmt));			break;
				case GL_TEXTURE_CUBE_MAP:	samplerTypes.push_back(glu::getSamplerCubeType(fmt));		break;
				case GL_TEXTURE_2D_ARRAY:	samplerTypes.push_back(glu::getSampler2DArrayType(fmt));	break;
				case GL_TEXTURE_3D:			samplerTypes.push_back(glu::getSampler3DType(fmt));			break;
				default:
					DE_ASSERT(DE_FALSE);
			}
		}

		// Create shader.

		DE_ASSERT(m_shader == DE_NULL);
		m_shader = new MultiTexShader(rnd.getUint32(), m_numUnits, unitTypes, samplerTypes, texScales, texBiases, num2dArrayLayers);
	}
	catch (const std::exception&)
	{
		// Clean up to save memory.
		TextureUnitCase::deinit();
		throw;
	}
}

TextureUnitCase::IterateResult TextureUnitCase::iterate (void)
{
	glu::RenderContext&			renderCtx			= m_context.getRenderContext();
	const tcu::RenderTarget&	renderTarget		= renderCtx.getRenderTarget();
	tcu::TestLog&				log					= m_testCtx.getLog();
	de::Random					rnd					(m_randSeed);

	int							viewportWidth		= deMin32(VIEWPORT_WIDTH, renderTarget.getWidth());
	int							viewportHeight		= deMin32(VIEWPORT_HEIGHT, renderTarget.getHeight());
	int							viewportX			= rnd.getInt(0, renderTarget.getWidth() - viewportWidth);
	int							viewportY			= rnd.getInt(0, renderTarget.getHeight() - viewportHeight);

	tcu::Surface				gles3Frame			(viewportWidth, viewportHeight);
	tcu::Surface				refFrame			(viewportWidth, viewportHeight);

	{
		// First we do some tricks to make the LODs safer wrt. precision issues. See MultiTexShader::makeSafeLods().

		vector<IVec3> texSizes;
		texSizes.reserve(m_numUnits);

		for (int i = 0; i < m_numUnits; i++)
		{
			int		texNdx			= m_unitTextures[i];
			int		texNdxInType	= m_ndxTexType[texNdx];
			GLenum	type			= m_textureTypes[texNdx];

			switch (type)
			{
				case GL_TEXTURE_2D:			texSizes.push_back(IVec3(m_textures2d[texNdxInType]->getWidth(),		m_textures2d[texNdxInType]->getHeight(),		0));										break;
				case GL_TEXTURE_CUBE_MAP:	texSizes.push_back(IVec3(m_texturesCube[texNdxInType]->getSize(),		m_texturesCube[texNdxInType]->getSize(),		0));										break;
				case GL_TEXTURE_2D_ARRAY:	texSizes.push_back(IVec3(m_textures2dArray[texNdxInType]->getWidth(),	m_textures2dArray[texNdxInType]->getHeight(),	0));										break;
				case GL_TEXTURE_3D:			texSizes.push_back(IVec3(m_textures3d[texNdxInType]->getWidth(),		m_textures3d[texNdxInType]->getHeight(),		m_textures3d[texNdxInType]->getDepth()));	break;
				default:
					DE_ASSERT(DE_FALSE);
			}
		}

		m_shader->makeSafeLods(texSizes, IVec2(viewportWidth, viewportHeight));
	}

	// Render using GLES3.
	{
		sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS|sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(viewportX, viewportY, viewportWidth, viewportHeight));

		render(context);

		context.readPixels(gles3Frame, 0, 0, viewportWidth, viewportHeight);
	}

	// Render reference image.
	{
		sglr::ReferenceContextBuffers	buffers	(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, viewportWidth, viewportHeight);
		sglr::ReferenceContext			context	(sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());

		render(context);

		context.readPixels(refFrame, 0, 0, viewportWidth, viewportHeight);
	}

	// Compare images.
	const float		threshold	= 0.001f;
	bool			isOk		= tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles3Frame, threshold, tcu::COMPARE_LOG_RESULT);

	// Store test result.
	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
							isOk ? "Pass"				: "Image comparison failed");

	return STOP;
}

void TextureUnitCase::upload2dTexture (int texNdx, sglr::Context& context)
{
	int						ndx2d		= m_ndxTexType[texNdx];
	const tcu::Texture2D*	texture		= m_textures2d[ndx2d];
	glu::TransferFormat		formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));

	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);

	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
	{
		if (texture->isLevelEmpty(levelNdx))
			continue;

		tcu::ConstPixelBufferAccess		access	= texture->getLevel(levelNdx);
		int								width	= access.getWidth();
		int								height	= access.getHeight();

		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);

		context.texImage2D(GL_TEXTURE_2D, levelNdx, m_textureParams[texNdx].internalFormat, width, height, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
		GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d texture image data");
	}
}

void TextureUnitCase::uploadCubeTexture (int texNdx, sglr::Context& context)
{
	int							ndxCube		= m_ndxTexType[texNdx];
	const tcu::TextureCube*		texture		= m_texturesCube[ndxCube];
	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));

	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);

	for (int face = 0; face < (int)tcu::CUBEFACE_LAST; face++)
	{
		for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
		{
			if (texture->isLevelEmpty((tcu::CubeFace)face, levelNdx))
				continue;

			tcu::ConstPixelBufferAccess		access	= texture->getLevelFace(levelNdx, (tcu::CubeFace)face);
			int								width	= access.getWidth();
			int								height	= access.getHeight();

			DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);

			context.texImage2D(s_cubeFaceTargets[face], levelNdx, m_textureParams[texNdx].internalFormat, width, height, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
			GLU_EXPECT_NO_ERROR(context.getError(), "Set cube map image data");
		}
	}
}

void TextureUnitCase::upload2dArrayTexture (int texNdx, sglr::Context& context)
{
	int							ndx2dArray	= m_ndxTexType[texNdx];
	const tcu::Texture2DArray*	texture		= m_textures2dArray[ndx2dArray];
	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));

	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);

	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
	{
		if (texture->isLevelEmpty(levelNdx))
			continue;

		tcu::ConstPixelBufferAccess	access	= texture->getLevel(levelNdx);
		int							width	= access.getWidth();
		int							height	= access.getHeight();
		int							layers	= access.getDepth();

		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*width*height);

		context.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_textureParams[texNdx].internalFormat, width, height, layers, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
		GLU_EXPECT_NO_ERROR(context.getError(), "Set 2d array texture image data");
	}
}

void TextureUnitCase::upload3dTexture (int texNdx, sglr::Context& context)
{
	int							ndx3d		= m_ndxTexType[texNdx];
	const tcu::Texture3D*		texture		= m_textures3d[ndx3d];
	glu::TransferFormat			formatGl	= glu::getTransferFormat(glu::mapGLInternalFormat(m_textureParams[texNdx].internalFormat));

	context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);

	for (int levelNdx = 0; levelNdx < texture->getNumLevels(); levelNdx++)
	{
		if (texture->isLevelEmpty(levelNdx))
			continue;

		tcu::ConstPixelBufferAccess	access	= texture->getLevel(levelNdx);
		int							width	= access.getWidth();
		int							height	= access.getHeight();
		int							depth	= access.getDepth();

		DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*width);
		DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*width*height);

		context.texImage3D(GL_TEXTURE_3D, levelNdx, m_textureParams[texNdx].internalFormat, width, height, depth, 0 /* border */, formatGl.format, formatGl.dataType, access.getDataPtr());
		GLU_EXPECT_NO_ERROR(context.getError(), "Set 3d texture image data");
	}
}

void TextureUnitCase::render (sglr::Context& context)
{
	// Setup textures.

	vector<deUint32>	textureGLNames;
	vector<bool>		isTextureSetUp(m_numTextures, false); // \note Same texture may be bound to multiple units, but we only want to set up parameters and data once per texture.

	textureGLNames.resize(m_numTextures);
	context.genTextures(m_numTextures, &textureGLNames[0]);
	GLU_EXPECT_NO_ERROR(context.getError(), "Generate textures");

	for (int unitNdx = 0; unitNdx < m_numUnits; unitNdx++)
	{
		int texNdx = m_unitTextures[unitNdx];

		// Bind texture to unit.
		context.activeTexture(GL_TEXTURE0 + unitNdx);
		GLU_EXPECT_NO_ERROR(context.getError(), "Set active texture");
		context.bindTexture(m_textureTypes[texNdx], textureGLNames[texNdx]);
		GLU_EXPECT_NO_ERROR(context.getError(), "Bind texture");

		if (!isTextureSetUp[texNdx])
		{
			// Binding this texture for first time, so set parameters and data.

			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_S, m_textureParams[texNdx].wrapModeS);
			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_T, m_textureParams[texNdx].wrapModeT);
			if (m_textureTypes[texNdx] == GL_TEXTURE_3D)
				context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_WRAP_R, m_textureParams[texNdx].wrapModeR);
			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MIN_FILTER, m_textureParams[texNdx].minFilter);
			context.texParameteri(m_textureTypes[texNdx], GL_TEXTURE_MAG_FILTER, m_textureParams[texNdx].magFilter);
			GLU_EXPECT_NO_ERROR(context.getError(), "Set texture parameters");

			switch (m_textureTypes[texNdx])
			{
				case GL_TEXTURE_2D:			upload2dTexture(texNdx, context);		break;
				case GL_TEXTURE_CUBE_MAP:	uploadCubeTexture(texNdx, context);		break;
				case GL_TEXTURE_2D_ARRAY:	upload2dArrayTexture(texNdx, context);	break;
				case GL_TEXTURE_3D:			upload3dTexture(texNdx, context);		break;
				default:
					DE_ASSERT(DE_FALSE);
			}

			isTextureSetUp[texNdx] = true; // Don't set up this texture's parameters and data again later.
		}
	}

	GLU_EXPECT_NO_ERROR(context.getError(), "Set textures");

	// Setup shader

	deUint32 shaderID = context.createProgram(m_shader);

	// Draw.

	context.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
	context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	m_shader->setUniforms(context, shaderID);
	sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
	GLU_EXPECT_NO_ERROR(context.getError(), "Draw");

	// Delete previously generated texture names.

	context.deleteTextures(m_numTextures, &textureGLNames[0]);
	GLU_EXPECT_NO_ERROR(context.getError(), "Delete textures");
}

TextureUnitTests::TextureUnitTests (Context& context)
	: TestCaseGroup(context, "units", "Texture Unit Usage Tests")
{
}

TextureUnitTests::~TextureUnitTests (void)
{
}

void TextureUnitTests::init (void)
{
	const int numTestsPerGroup = 10;

	static const int unitCounts[] =
	{
		2,
		4,
		8,
		-1 // \note Negative stands for the implementation-specified maximum.
	};

	for (int unitCountNdx = 0; unitCountNdx < DE_LENGTH_OF_ARRAY(unitCounts); unitCountNdx++)
	{
		int numUnits = unitCounts[unitCountNdx];

		string countGroupName = (unitCounts[unitCountNdx] < 0 ? "all" : de::toString(numUnits)) + "_units";

		tcu::TestCaseGroup* countGroup = new tcu::TestCaseGroup(m_testCtx, countGroupName.c_str(), "");
		addChild(countGroup);

		DE_STATIC_ASSERT((int)TextureUnitCase::CASE_ONLY_2D == 0);

		for (int caseType = (int)TextureUnitCase::CASE_ONLY_2D; caseType < (int)TextureUnitCase::CASE_LAST; caseType++)
		{
			const char* caseTypeGroupName = (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D		? "only_2d"
										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_CUBE		? "only_cube"
										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_2D_ARRAY	? "only_2d_array"
										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_ONLY_3D		? "only_3d"
										  : (TextureUnitCase::CaseType)caseType == TextureUnitCase::CASE_MIXED			? "mixed"
										  : DE_NULL;

			DE_ASSERT(caseTypeGroupName != DE_NULL);

			tcu::TestCaseGroup* caseTypeGroup = new tcu::TestCaseGroup(m_testCtx, caseTypeGroupName, "");
			countGroup->addChild(caseTypeGroup);

			for (int testNdx = 0; testNdx < numTestsPerGroup; testNdx++)
				caseTypeGroup->addChild(new TextureUnitCase(m_context, de::toString(testNdx).c_str(), "", numUnits, (TextureUnitCase::CaseType)caseType, deUint32Hash((deUint32)testNdx)));
		}
	}
}

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