/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 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 Explicit uniform location tests
 *//*--------------------------------------------------------------------*/

#include "es31fUniformLocationTests.hpp"

#include "tcuTestLog.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "tcuCommandLine.hpp"

#include "glsShaderLibrary.hpp"
#include "glsTextureTestUtil.hpp"

#include "gluShaderProgram.hpp"
#include "gluTexture.hpp"
#include "gluPixelTransfer.hpp"
#include "gluVarType.hpp"
#include "gluVarTypeUtil.hpp"

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

#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"
#include "deString.h"
#include "deRandom.hpp"
#include "deInt32.h"

#include <set>
#include <map>

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{

using std::string;
using std::vector;
using std::map;
using de::UniquePtr;
using glu::VarType;

struct UniformInfo
{
	enum ShaderStage
	{
		SHADERSTAGE_NONE	= 0,
		SHADERSTAGE_VERTEX	= (1<<0),
		SHADERSTAGE_FRAGMENT= (1<<1),
		SHADERSTAGE_BOTH	= (SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT),
	};

	VarType			type;
	ShaderStage		declareLocation; // support declarations with/without layout qualifiers, needed for linkage testing
	ShaderStage		layoutLocation;
	ShaderStage		checkLocation;
	int				location; // -1 for unset

	UniformInfo (VarType type_, ShaderStage declareLocation_, ShaderStage layoutLocation_, ShaderStage checkLocation_, int location_ = -1)
		: type				(type_)
		, declareLocation	(declareLocation_)
		, layoutLocation	(layoutLocation_)
		, checkLocation		(checkLocation_)
		, location			(location_)
	{
	}
};

class UniformLocationCase : public tcu::TestCase
{
public:
								UniformLocationCase		(tcu::TestContext&			context,
														 glu::RenderContext&		renderContext,
														 const char*				name,
														 const char*				desc,
														 const vector<UniformInfo>&	uniformInfo);
	virtual						~UniformLocationCase	(void) {}

	virtual IterateResult		iterate					(void);

protected:
	IterateResult				run						(const vector<UniformInfo>& uniformList);
	static glu::ProgramSources	genShaderSources		(const vector<UniformInfo>& uniformList);
	bool						verifyLocations			(const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList);
	void						render					(const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList);
	static bool					verifyResult			(const tcu::ConstPixelBufferAccess& access);

	static float				getExpectedValue		(glu::DataType type, int id, const char* name);

	de::MovePtr<glu::Texture2D>	createTexture			(glu::DataType samplerType, float redChannelValue, int binding);

	glu::RenderContext&			m_renderCtx;

	const vector<UniformInfo>	m_uniformInfo;

	enum
	{
		RENDER_SIZE = 16
	};
};

string getUniformName (int ndx, const glu::VarType& type, const glu::TypeComponentVector& path)
{
	std::ostringstream buff;
	buff << "uni" << ndx << glu::TypeAccessFormat(type, path);

	return buff.str();
}

string getFirstComponentName (const glu::VarType& type)
{
	std::ostringstream buff;
	if (glu::isDataTypeVector(type.getBasicType()))
		buff << glu::TypeAccessFormat(type, glu::SubTypeAccess(type).component(0).getPath());
	else if (glu::isDataTypeMatrix(type.getBasicType()))
		buff << glu::TypeAccessFormat(type, glu::SubTypeAccess(type).column(0).component(0).getPath());

	return buff.str();
}

UniformLocationCase::UniformLocationCase (tcu::TestContext&				context,
										  glu::RenderContext&			renderContext,
										  const char*					name,
										  const char*					desc,
										  const vector<UniformInfo>&	uniformInfo)
	: TestCase			(context, name, desc)
	, m_renderCtx		(renderContext)
	, m_uniformInfo		(uniformInfo)
{
}

// [from, to]
std::vector<int> shuffledRange (int from, int to, int seed)
{
	const int	count	= to - from;

	vector<int> retval	(count);
	de::Random	rng		(seed);

	DE_ASSERT(count > 0);

	for (int ndx = 0; ndx < count; ndx++)
		retval[ndx] = ndx + from;

	rng.shuffle(retval.begin(), retval.end());
	return retval;
}

glu::DataType getDataTypeSamplerSampleType (glu::DataType type)
{
	using namespace glu;

	if (type >= TYPE_SAMPLER_1D && type <= TYPE_SAMPLER_3D)
		return TYPE_FLOAT_VEC4;
	else if (type >= TYPE_INT_SAMPLER_1D && type <= TYPE_INT_SAMPLER_3D)
		return TYPE_INT_VEC4;
	else if (type >= TYPE_UINT_SAMPLER_1D && type <= TYPE_UINT_SAMPLER_3D)
		return TYPE_UINT_VEC4;
	else if (type >= TYPE_SAMPLER_1D_SHADOW && type <=	TYPE_SAMPLER_2D_ARRAY_SHADOW)
		return TYPE_FLOAT;
	else
		DE_FATAL("Unknown sampler type");

	return TYPE_INVALID;
}

// A (hopefully) unique value for a uniform. For multi-component types creates only one value. Values are in the range [0,1] for floats, [-128, 127] for ints, [0,255] for uints and 0/1 for booleans. Samplers are treated according to the types they return.
float UniformLocationCase::getExpectedValue (glu::DataType type, int id, const char* name)
{
	const deUint32	hash			= deStringHash(name) + deInt32Hash(id);

	glu::DataType	adjustedType	= type;

	if (glu::isDataTypeSampler(type))
		adjustedType = getDataTypeSamplerSampleType(type);

	if (glu::isDataTypeIntOrIVec(adjustedType))
		return float(hash%128);
	else if (glu::isDataTypeUintOrUVec(adjustedType))
		return float(hash%255);
	else if (glu::isDataTypeFloatOrVec(adjustedType))
		return float(hash%255)/255.0f;
	else if (glu::isDataTypeBoolOrBVec(adjustedType))
		return float(hash%2);
	else
		DE_FATAL("Unkown primitive type");

	return glu::TYPE_INVALID;
}

UniformLocationCase::IterateResult UniformLocationCase::iterate (void)
{
	return run(m_uniformInfo);
}

UniformLocationCase::IterateResult UniformLocationCase::run (const vector<UniformInfo>& uniformList)
{
	using gls::TextureTestUtil::RandomViewport;

	const glu::ProgramSources	sources		= genShaderSources(uniformList);
	const glu::ShaderProgram	program		(m_renderCtx, sources);
	const int					baseSeed	= m_testCtx.getCommandLine().getBaseSeed();
	const glw::Functions&		gl			= m_renderCtx.getFunctions();
	const RandomViewport		viewport	(m_renderCtx.getRenderTarget(), RENDER_SIZE, RENDER_SIZE, deStringHash(getName()) + baseSeed);

	tcu::Surface				rendered	(RENDER_SIZE, RENDER_SIZE);

	if (!verifyLocations(program, uniformList))
		return STOP;

	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

	render(program, uniformList);

	glu::readPixels(m_renderCtx, viewport.x, viewport.y, rendered.getAccess());
	GLU_EXPECT_NO_ERROR(gl.getError(), "error in readPixels");

	if (!verifyResult(rendered.getAccess()))
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader produced incorrect result");
		return STOP;
	}

	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	return STOP;
}

glu::ProgramSources UniformLocationCase::genShaderSources (const vector<UniformInfo>& uniformList)
{
	std::ostringstream	vertDecl, vertMain, fragDecl, fragMain;

	vertDecl << "#version 310 es\n"
			 << "precision highp float;\n"
			 << "precision highp int;\n"
			 << "float verify(float val, float ref) { return float(abs(val-ref) < 0.05); }\n\n"
			 << "in highp vec4 a_position;\n"
			 << "out highp vec4 v_color;\n";
	fragDecl << "#version 310 es\n\n"
			 << "precision highp float;\n"
			 << "precision highp int;\n"
			 << "float verify(float val, float ref) { return float(abs(val-ref) < 0.05); }\n\n"
			 << "in highp vec4 v_color;\n"
			 << "layout(location = 0) out mediump vec4 o_color;\n\n";

	vertMain << "void main()\n{\n"
			 << "	gl_Position = a_position;\n"
			 << "	v_color = vec4(1.0);\n";

	fragMain << "void main()\n{\n"
			 << "	o_color = v_color;\n";

	std::set<const glu::StructType*> declaredStructs;

	// Declare uniforms
	for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
	{
		const UniformInfo&	uniformInfo = uniformList[uniformNdx];

		const bool			declareInVert	= (uniformInfo.declareLocation & UniformInfo::SHADERSTAGE_VERTEX)   != 0;
		const bool			declareInFrag	= (uniformInfo.declareLocation & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
		const bool			layoutInVert    = (uniformInfo.layoutLocation  & UniformInfo::SHADERSTAGE_VERTEX)   != 0;
		const bool			layoutInFrag    = (uniformInfo.layoutLocation  & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;
		const bool			checkInVert		= (uniformInfo.checkLocation   & UniformInfo::SHADERSTAGE_VERTEX)   != 0;
		const bool			checkInFrag		= (uniformInfo.checkLocation   & UniformInfo::SHADERSTAGE_FRAGMENT) != 0;

		const string		layout			= uniformInfo.location >= 0 ? "layout(location = " + de::toString(uniformInfo.location) + ") " : "";
		const string		uniName			= "uni" + de::toString(uniformNdx);

		int					location		= uniformInfo.location;
		int					subTypeIndex	= 0;

		DE_ASSERT((declareInVert && layoutInVert) || !layoutInVert); // Cannot have layout without declaration
		DE_ASSERT((declareInFrag && layoutInFrag) || !layoutInFrag);
		DE_ASSERT(location<0 || (layoutInVert || layoutInFrag)); // Cannot have location without layout

		// struct definitions
		if (uniformInfo.type.isStructType())
		{
			const glu::StructType* const structType = uniformInfo.type.getStructPtr();
			if (!declaredStructs.count(structType))
			{
				if (declareInVert)
					vertDecl << glu::declare(structType, 0) << ";\n";

				if (declareInFrag)
					fragDecl << glu::declare(structType, 0) << ";\n";

				declaredStructs.insert(structType);
			}
		}

		if (declareInVert)
			vertDecl << "uniform " << (layoutInVert ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";

		if (declareInFrag)
			fragDecl << "uniform " << (layoutInFrag ? layout : "") << glu::declare(uniformInfo.type, uniName) << ";\n";

		// Anything that needs to be done for each enclosed primitive type
		for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++, subTypeIndex++)
		{
			const glu::VarType	subType		= glu::getVarType(uniformInfo.type, subTypeIter.getPath());
			const glu::DataType	scalarType	= glu::getDataTypeScalarType(subType.getBasicType());
			const char* const	typeName	= glu::getDataTypeName(scalarType);
			const string		expectValue	= de::floatToString(getExpectedValue(scalarType, location >= 0 ? location+subTypeIndex : -1, typeName), 3);

			if (glu::isDataTypeSampler(scalarType))
			{
				if (checkInVert)
					vertMain << "	v_color.rgb *= verify(float( texture(" << uniName
							 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
							 << ", vec2(0.5)).r), " << expectValue << ");\n";
				if (checkInFrag)
					fragMain << "	o_color.rgb *= verify(float( texture(" << uniName
							 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
							 << ", vec2(0.5)).r), " << expectValue << ");\n";
			}
			else
			{
				if (checkInVert)
					vertMain << "	v_color.rgb *= verify(float(" << uniName
							 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
							 << getFirstComponentName(subType) << "), " << expectValue << ");\n";
				if (checkInFrag)
					fragMain << "	o_color.rgb *= verify(float(" << uniName
							 << glu::TypeAccessFormat(uniformInfo.type, subTypeIter.getPath())
							 << getFirstComponentName(subType) << "), " << expectValue << ");\n";
			}
		}
	}

	vertMain << "}\n";
	fragMain << "}\n";

	return glu::makeVtxFragSources(vertDecl.str() + vertMain.str(), fragDecl.str() + fragMain.str());
}

bool UniformLocationCase::verifyLocations (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
{
	using tcu::TestLog;

	const glw::Functions&	gl			= m_renderCtx.getFunctions();
	const bool				vertexOk	= program.getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk;
	const bool				fragmentOk	= program.getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk;
	const bool				linkOk		= program.getProgramInfo().linkOk;
	const deUint32			programID	= program.getProgram();

	TestLog&				log			= m_testCtx.getLog();
	std::set<int>			usedLocations;

	log << program;

	if (!vertexOk || !fragmentOk || !linkOk)
	{
		log << TestLog::Message << "ERROR: shader failed to compile/link" << TestLog::EndMessage;
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader failed to compile/link");
		return false;
	}

	for (int uniformNdx = 0; uniformNdx < int(uniformList.size()); uniformNdx++)
	{
		const UniformInfo&	uniformInfo		= uniformList[uniformNdx];
		int					subTypeIndex	= 0;

		for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++, subTypeIndex++)
		{
			const string		name		= getUniformName(uniformNdx, uniformInfo.type, subTypeIter.getPath());
			const int			gotLoc		= gl.getUniformLocation(programID, name.c_str());
			const int			expectLoc	= uniformInfo.location >= 0 ? uniformInfo.location+subTypeIndex : -1;

			if (expectLoc >= 0)
			{
				if (uniformInfo.checkLocation == 0 && gotLoc == -1)
					continue;

				if (gotLoc != expectLoc)
				{
					log << TestLog::Message << "ERROR: found uniform " << name << " in location " << gotLoc << " when it should have been in " << expectLoc << TestLog::EndMessage;
					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect uniform location");
					return false;
				}

				if (usedLocations.find(expectLoc) != usedLocations.end())
				{
					log << TestLog::Message << "ERROR: expected uniform " << name << " in location " << gotLoc << " but it has already been used" << TestLog::EndMessage;
					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Overlapping uniform location");
					return false;
				}

				usedLocations.insert(expectLoc);
			}
			else if (gotLoc >= 0)
			{
				if (usedLocations.count(gotLoc))
				{
					log << TestLog::Message << "ERROR: found uniform " << name << " in location " << gotLoc << " which has already been used" << TestLog::EndMessage;
					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Overlapping uniform location");
					return false;
				}

				usedLocations.insert(gotLoc);
			}
		}
	}

	return true;
}

// Check that shader output is white (or very close to it)
bool UniformLocationCase::verifyResult (const tcu::ConstPixelBufferAccess& access)
{
	using tcu::Vec4;

	const Vec4 threshold (0.1f, 0.1f, 0.1f, 0.1f);
	const Vec4 reference (1.0f, 1.0f, 1.0f, 1.0f);

	for (int y = 0; y < access.getHeight(); y++)
	{
		for (int x = 0; x < access.getWidth(); x++)
		{
			const Vec4 diff = abs(access.getPixel(x, y) - reference);

			if (!boolAll(lessThanEqual(diff, threshold)))
				return false;
		}
	}

	return true;
}

// get a 4 channel 8 bits each texture format that is usable by the given sampler type
deUint32 getTextureFormat (glu::DataType samplerType)
{
	using namespace glu;

	switch (samplerType)
	{
		case TYPE_SAMPLER_1D:
		case TYPE_SAMPLER_2D:
		case TYPE_SAMPLER_CUBE:
		case TYPE_SAMPLER_2D_ARRAY:
		case TYPE_SAMPLER_3D:
			return GL_RGBA8;

		case TYPE_INT_SAMPLER_1D:
		case TYPE_INT_SAMPLER_2D:
		case TYPE_INT_SAMPLER_CUBE:
		case TYPE_INT_SAMPLER_2D_ARRAY:
		case TYPE_INT_SAMPLER_3D:
			return GL_RGBA8I;

		case TYPE_UINT_SAMPLER_1D:
		case TYPE_UINT_SAMPLER_2D:
		case TYPE_UINT_SAMPLER_CUBE:
		case TYPE_UINT_SAMPLER_2D_ARRAY:
		case TYPE_UINT_SAMPLER_3D:
			return GL_RGBA8UI;

		default:
			DE_FATAL("Unsupported (sampler) type");
			return 0;
	}
}

// create a texture suitable for sampling by the given sampler type and bind it
de::MovePtr<glu::Texture2D> UniformLocationCase::createTexture (glu::DataType samplerType, float redChannelValue, int binding)
{
	using namespace glu;

	const glw::Functions&	gl		 = m_renderCtx.getFunctions();

	const deUint32			format	 = getTextureFormat(samplerType);
	de::MovePtr<Texture2D>	tex;

	tex = de::MovePtr<Texture2D>(new Texture2D(m_renderCtx, format, 16, 16));

	tex->getRefTexture().allocLevel(0);

	if (format == GL_RGBA8I || format == GL_RGBA8UI)
		tcu::clear(tex->getRefTexture().getLevel(0), tcu::IVec4(int(redChannelValue), 0, 0, 0));
	else
		tcu::clear(tex->getRefTexture().getLevel(0), tcu::Vec4(redChannelValue, 0.0f, 0.0f, 1.0f));

	gl.activeTexture(GL_TEXTURE0 + binding);
	tex->upload();

	gl.bindTexture(GL_TEXTURE_2D, tex->getGLTexture());
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase: texture upload");

	return tex;
}

void UniformLocationCase::render (const glu::ShaderProgram& program, const vector<UniformInfo>& uniformList)
{
	using glu::Texture2D;
	using de::MovePtr;
	typedef vector<Texture2D*> TextureList;

	const glw::Functions&	gl				= m_renderCtx.getFunctions();
	const deUint32			programID		= program.getProgram();
	const deInt32			posLoc			= gl.getAttribLocation(programID, "a_position");

	// Vertex data.
	const float position[] =
	{
		-1.0f, -1.0f, 0.1f,	1.0f,
		-1.0f,  1.0f, 0.1f,	1.0f,
		 1.0f, -1.0f, 0.1f,	1.0f,
		 1.0f,  1.0f, 0.1f,	1.0f
	};
	const void *			positionPtr		= &position[0];
	const deUint16			indices[]		= { 0, 1, 2, 2, 1, 3 };
	const void *			indicesPtr		= &indices[0];

	// some buffers to feed to the GPU, only the first element is relevant since the others are never verified
	float					floatBuf[16]	= {0.0f};
	deInt32					intBuf[4]		= {0};
	deUint32				uintBuf[4]		= {0};
	deUint32				vao				= 0;
	deUint32				attribVbo		= 0;
	deUint32				elementVbo		= 0;

	TextureList				texList;

	bool isGL45 = glu::contextSupports(m_renderCtx.getType(), glu::ApiType::core(4, 5));
	if (isGL45)
	{
		gl.genVertexArrays(1, &vao);
		gl.bindVertexArray(vao);

		gl.genBuffers(1, &attribVbo);
		gl.genBuffers(1, &elementVbo);

		gl.bindBuffer(GL_ARRAY_BUFFER, attribVbo);
		gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(DE_LENGTH_OF_ARRAY(position) * sizeof(float)), position, GL_STATIC_DRAW);
		GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase::render");

		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementVbo);
		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(DE_LENGTH_OF_ARRAY(indices) * sizeof(deUint16)), indices, GL_STATIC_DRAW);
		GLU_EXPECT_NO_ERROR(gl.getError(), "UniformLocationCase::render");

		positionPtr = 0;
		indicesPtr = 0;
	}

	TCU_CHECK(posLoc >= 0);
	gl.useProgram(programID);

	try
	{

		// Set uniforms
		for (unsigned int uniformNdx = 0; uniformNdx < uniformList.size(); uniformNdx++)
		{
			const UniformInfo&	uniformInfo			= uniformList[uniformNdx];
			int					expectedLocation	= uniformInfo.location;

			for (glu::BasicTypeIterator subTypeIter = glu::BasicTypeIterator::begin(&uniformInfo.type); subTypeIter != glu::BasicTypeIterator::end(&uniformInfo.type); subTypeIter++)
			{
				const glu::VarType	type			= glu::getVarType(uniformInfo.type, subTypeIter.getPath());
				const string		name			= getUniformName(uniformNdx, uniformInfo.type, subTypeIter.getPath());
				const int			gotLoc			= gl.getUniformLocation(programID, name.c_str());
				const glu::DataType	scalarType		= glu::getDataTypeScalarType(type.getBasicType());
				const char*	const	typeName		= glu::getDataTypeName(scalarType);
				const float			expectedValue	= getExpectedValue(scalarType, expectedLocation, typeName);

				if (glu::isDataTypeSampler(scalarType))
				{
					const int binding = (int)texList.size();

					texList.push_back(createTexture(scalarType, expectedValue, binding).release());
					gl.uniform1i(gotLoc, binding);
				}
				else if(gotLoc >= 0)
				{
					floatBuf[0] = expectedValue;
					intBuf[0]   = int(expectedValue);
					uintBuf[0]  = deUint32(expectedValue);

					m_testCtx.getLog() << tcu::TestLog::Message << "Set uniform " << name << " in location " << gotLoc << " to " << expectedValue << tcu::TestLog::EndMessage;

					switch (type.getBasicType())
					{
						case glu::TYPE_FLOAT:			gl.uniform1fv(gotLoc, 1, floatBuf);					break;
						case glu::TYPE_FLOAT_VEC2:		gl.uniform2fv(gotLoc, 1, floatBuf);					break;
						case glu::TYPE_FLOAT_VEC3:		gl.uniform3fv(gotLoc, 1, floatBuf);					break;
						case glu::TYPE_FLOAT_VEC4:		gl.uniform4fv(gotLoc, 1, floatBuf);					break;

						case glu::TYPE_INT:				gl.uniform1iv(gotLoc, 1, intBuf);					break;
						case glu::TYPE_INT_VEC2:		gl.uniform2iv(gotLoc, 1, intBuf);					break;
						case glu::TYPE_INT_VEC3:		gl.uniform3iv(gotLoc, 1, intBuf);					break;
						case glu::TYPE_INT_VEC4:		gl.uniform4iv(gotLoc, 1, intBuf);					break;

						case glu::TYPE_UINT:			gl.uniform1uiv(gotLoc, 1, uintBuf);					break;
						case glu::TYPE_UINT_VEC2:		gl.uniform2uiv(gotLoc, 1, uintBuf);					break;
						case glu::TYPE_UINT_VEC3:		gl.uniform3uiv(gotLoc, 1, uintBuf);					break;
						case glu::TYPE_UINT_VEC4:		gl.uniform4uiv(gotLoc, 1, uintBuf);					break;

						case glu::TYPE_BOOL:			gl.uniform1iv(gotLoc, 1, intBuf);					break;
						case glu::TYPE_BOOL_VEC2:		gl.uniform2iv(gotLoc, 1, intBuf);					break;
						case glu::TYPE_BOOL_VEC3:		gl.uniform3iv(gotLoc, 1, intBuf);					break;
						case glu::TYPE_BOOL_VEC4:		gl.uniform4iv(gotLoc, 1, intBuf);					break;

						case glu::TYPE_FLOAT_MAT2:		gl.uniformMatrix2fv(gotLoc, 1, false, floatBuf);	break;
						case glu::TYPE_FLOAT_MAT2X3:	gl.uniformMatrix2x3fv(gotLoc, 1, false, floatBuf);	break;
						case glu::TYPE_FLOAT_MAT2X4:	gl.uniformMatrix2x4fv(gotLoc, 1, false, floatBuf);	break;

						case glu::TYPE_FLOAT_MAT3X2:	gl.uniformMatrix3x2fv(gotLoc, 1, false, floatBuf);	break;
						case glu::TYPE_FLOAT_MAT3:		gl.uniformMatrix3fv(gotLoc, 1, false, floatBuf);	break;
						case glu::TYPE_FLOAT_MAT3X4:	gl.uniformMatrix3x4fv(gotLoc, 1, false, floatBuf);	break;

						case glu::TYPE_FLOAT_MAT4X2:	gl.uniformMatrix4x2fv(gotLoc, 1, false, floatBuf);	break;
						case glu::TYPE_FLOAT_MAT4X3:	gl.uniformMatrix4x3fv(gotLoc, 1, false, floatBuf);	break;
						case glu::TYPE_FLOAT_MAT4:		gl.uniformMatrix4fv(gotLoc, 1, false, floatBuf);	break;
						default:
							DE_ASSERT(false);
					}
				}

				expectedLocation += expectedLocation>=0;
			}
		}

		gl.enableVertexAttribArray(posLoc);
		GLU_EXPECT_NO_ERROR(gl.getError(), "error in glEnableVertexAttribArray");
		gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, positionPtr);
		GLU_EXPECT_NO_ERROR(gl.getError(), "error in glVertexAttribPointer");

		gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, indicesPtr);
		GLU_EXPECT_NO_ERROR(gl.getError(), "error in glDrawElements");

		gl.disableVertexAttribArray(posLoc);
		GLU_EXPECT_NO_ERROR(gl.getError(), "error in glDisableVertexAttribArray");

		if (isGL45)
		{
			gl.bindBuffer(GL_ARRAY_BUFFER, 0);
			gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

			gl.deleteBuffers(1, &attribVbo);
			gl.deleteBuffers(1, &elementVbo);
			gl.deleteVertexArrays(1, &vao);
		}
	}
	catch(...)
	{
		for (int i = 0; i < int(texList.size()); i++)
			delete texList[i];

		throw;
	}

	for (int i = 0; i < int(texList.size()); i++)
		delete texList[i];
}

class MaxUniformLocationCase : public UniformLocationCase
{
public:
								MaxUniformLocationCase		(tcu::TestContext&			context,
															 glu::RenderContext&		renderContext,
															 const char*				name,
															 const char*				desc,
															 const vector<UniformInfo>&	uniformInfo);
	virtual						~MaxUniformLocationCase		(void) {}
	virtual IterateResult		iterate						(void);
};

MaxUniformLocationCase::MaxUniformLocationCase (tcu::TestContext&			context,
												glu::RenderContext&			renderContext,
												const char*					name,
												const char*					desc,
												const vector<UniformInfo>&	uniformInfo)
	: UniformLocationCase(context, renderContext, name, desc, uniformInfo)
{
	DE_ASSERT(!uniformInfo.empty());
}

UniformLocationCase::IterateResult MaxUniformLocationCase::iterate (void)
{
	int					maxLocation = 1024;
	vector<UniformInfo>	uniformInfo = m_uniformInfo;

	m_renderCtx.getFunctions().getIntegerv(GL_MAX_UNIFORM_LOCATIONS, &maxLocation);

	uniformInfo[0].location = maxLocation-1;

	return UniformLocationCase::run(uniformInfo);
}

} // Anonymous

UniformLocationTests::UniformLocationTests (Context& context, bool isGL45)
	: TestCaseGroup(context, "uniform_location", "Explicit uniform locations")
	, m_isGL45(isGL45)
{
}

UniformLocationTests::~UniformLocationTests (void)
{
	for (int i = 0; i < int(structTypes.size()); i++)
		delete structTypes[i];
}

glu::VarType createVarType (glu::DataType type)
{
	return glu::VarType(type, glu::isDataTypeBoolOrBVec(type) ? glu::PRECISION_LAST : glu::PRECISION_HIGHP);
}

void UniformLocationTests::init (void)
{
	using namespace glu;

	const UniformInfo::ShaderStage checkStages[]	= { UniformInfo::SHADERSTAGE_VERTEX, UniformInfo::SHADERSTAGE_FRAGMENT };
	const char*						stageNames[]	= {"vertex", "fragment"};
	const int						maxLocations	= 1024;
	const int						baseSeed		= m_context.getTestContext().getCommandLine().getBaseSeed();

	const DataType					primitiveTypes[] =
	{
		TYPE_FLOAT,
		TYPE_FLOAT_VEC2,
		TYPE_FLOAT_VEC3,
		TYPE_FLOAT_VEC4,

		TYPE_INT,
		TYPE_INT_VEC2,
		TYPE_INT_VEC3,
		TYPE_INT_VEC4,

		TYPE_UINT,
		TYPE_UINT_VEC2,
		TYPE_UINT_VEC3,
		TYPE_UINT_VEC4,

		TYPE_BOOL,
		TYPE_BOOL_VEC2,
		TYPE_BOOL_VEC3,
		TYPE_BOOL_VEC4,

		TYPE_FLOAT_MAT2,
		TYPE_FLOAT_MAT2X3,
		TYPE_FLOAT_MAT2X4,
		TYPE_FLOAT_MAT3X2,
		TYPE_FLOAT_MAT3,
		TYPE_FLOAT_MAT3X4,
		TYPE_FLOAT_MAT4X2,
		TYPE_FLOAT_MAT4X3,
		TYPE_FLOAT_MAT4,

		TYPE_SAMPLER_2D,
		TYPE_INT_SAMPLER_2D,
		TYPE_UINT_SAMPLER_2D,
	};

	const int maxPrimitiveTypeNdx = DE_LENGTH_OF_ARRAY(primitiveTypes) - 4;
	DE_ASSERT(primitiveTypes[maxPrimitiveTypeNdx] == TYPE_FLOAT_MAT4);

	// Primitive type cases with trivial linkage
	{
		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(m_testCtx, "basic", "Location specified with use, single shader stage");
		de::Random					rng		(baseSeed + 0x1001);
		addChild(group);

		for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
		{
			const DataType		type	= primitiveTypes[primitiveNdx];

			for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
			{
				const string		name		= string(getDataTypeName(type)) + "_" + stageNames[stageNdx];

				vector<UniformInfo> config;

				UniformInfo			uniform	(createVarType(type),
											 checkStages[stageNdx],
											 checkStages[stageNdx],
											 checkStages[stageNdx],
											 rng.getInt(0, maxLocations-1));

				config.push_back(uniform);
				group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
			}
		}
	}

	// Arrays
	{
		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(m_testCtx, "array", "Array location specified with use, single shader stage");
		de::Random					rng		(baseSeed + 0x2001);
		addChild(group);

		for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
		{
			const DataType		type	= primitiveTypes[primitiveNdx];

			for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
			{

				const string		name	= string(getDataTypeName(type)) + "_" + stageNames[stageNdx];

				vector<UniformInfo> config;

				UniformInfo			uniform	(VarType(createVarType(type), 8),
												checkStages[stageNdx],
												checkStages[stageNdx],
												checkStages[stageNdx],
												rng.getInt(0, maxLocations-1-8));

				config.push_back(uniform);
				group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
			}
		}
	}

	// Nested Arrays
	{
		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(m_testCtx, "nested_array", "Array location specified with use, single shader stage");
		de::Random					rng		(baseSeed + 0x3001);
		addChild(group);

		for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
		{
			const DataType		type	= primitiveTypes[primitiveNdx];

			for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
			{
				const string		name		= string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
				// stay comfortably within minimum max uniform component count (896 in fragment) and sampler count with all types
				const int			arraySize	= (getDataTypeScalarSize(type) > 4 || isDataTypeSampler(type)) ? 3 : 7;

				vector<UniformInfo> config;

				UniformInfo			uniform	(VarType(VarType(createVarType(type), arraySize), arraySize),
											 checkStages[stageNdx],
											 checkStages[stageNdx],
											 checkStages[stageNdx],
											 rng.getInt(0, maxLocations-1-arraySize*arraySize));

				config.push_back(uniform);
				group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
			}
		}
	}

	// Structs
	{
		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(m_testCtx, "struct", "Struct location, random contents & declaration location");
		de::Random					rng		(baseSeed + 0x4001);
		addChild(group);

		for (int caseNdx = 0; caseNdx < 16; caseNdx++)
		{
			typedef UniformInfo::ShaderStage Stage;

			const string	name		= "case_" + de::toString(caseNdx);

			const Stage		layoutLoc	= Stage(rng.getUint32()&0x3);
			const Stage		declareLoc	= Stage((rng.getUint32()&0x3) | layoutLoc);
			const Stage		verifyLoc	= Stage((rng.getUint32()&0x3) & declareLoc);
			const int		location	= layoutLoc ? rng.getInt(0, maxLocations-1-5) : -1;

			StructType*		structProto = new StructType("S");

			structTypes.push_back(structProto);

			structProto->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			structProto->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			structProto->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			structProto->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			structProto->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));

			{
				vector<UniformInfo> config;

				config.push_back(UniformInfo(VarType(structProto),
											 declareLoc,
											 layoutLoc,
											 verifyLoc,
											 location));
				group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
			}
		}
	}

	// Nested Structs
	{
		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(m_testCtx, "nested_struct", "Struct location specified with use, single shader stage");
		de::Random					rng		(baseSeed + 0x5001);

		addChild(group);

		for (int caseNdx = 0; caseNdx < 16; caseNdx++)
		{
			typedef UniformInfo::ShaderStage Stage;

			const string	name		= "case_" + de::toString(caseNdx);
			const int		baseLoc		= rng.getInt(0, maxLocations-1-60);

			// Structs need to be added in the order of their declaration
			const Stage		layoutLocs[]=
			{
				Stage(rng.getUint32()&0x3),
				Stage(rng.getUint32()&0x3),
				Stage(rng.getUint32()&0x3),
				Stage(rng.getUint32()&0x3),
			};

			const deUint32	tempDecl[] =
			{
				(rng.getUint32()&0x3) | layoutLocs[0],
				(rng.getUint32()&0x3) | layoutLocs[1],
				(rng.getUint32()&0x3) | layoutLocs[2],
				(rng.getUint32()&0x3) | layoutLocs[3],
			};

			// Component structs need to be declared if anything using them is declared
			const Stage		declareLocs[] =
			{
				Stage(tempDecl[0] | tempDecl[1] | tempDecl[2] | tempDecl[3]),
				Stage(tempDecl[1] | tempDecl[2] | tempDecl[3]),
				Stage(tempDecl[2] | tempDecl[3]),
				Stage(tempDecl[3]),
			};

			const Stage		verifyLocs[] =
			{
				Stage(rng.getUint32()&0x3 & declareLocs[0]),
				Stage(rng.getUint32()&0x3 & declareLocs[1]),
				Stage(rng.getUint32()&0x3 & declareLocs[2]),
				Stage(rng.getUint32()&0x3 & declareLocs[3]),
			};

			StructType*		testTypes[]	=
			{
				new StructType("Type0"),
				new StructType("Type1"),
				new StructType("Type2"),
				new StructType("Type3"),
			};

			structTypes.push_back(testTypes[0]);
			structTypes.push_back(testTypes[1]);
			structTypes.push_back(testTypes[2]);
			structTypes.push_back(testTypes[3]);

			testTypes[0]->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[0]->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[0]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[0]->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[0]->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));

			testTypes[1]->addMember("a", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[1]->addMember("b", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[1]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[1]->addMember("d", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));
			testTypes[1]->addMember("e", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));

			testTypes[2]->addMember("a", VarType(testTypes[0]));
			testTypes[2]->addMember("b", VarType(testTypes[1]));
			testTypes[2]->addMember("c", createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]));

			testTypes[3]->addMember("a", VarType(testTypes[2]));

			{
				vector<UniformInfo> config;

				config.push_back(UniformInfo(VarType(testTypes[0]),
											 declareLocs[0],
											 layoutLocs[0],
											 verifyLocs[0],
											 layoutLocs[0] ? baseLoc : -1));

				config.push_back(UniformInfo(VarType(testTypes[1]),
											 declareLocs[1],
											 layoutLocs[1],
											 verifyLocs[1],
											 layoutLocs[1] ? baseLoc+5 : -1));

				config.push_back(UniformInfo(VarType(testTypes[2]),
											 declareLocs[2],
											 layoutLocs[2],
											 verifyLocs[2],
											 layoutLocs[2] ? baseLoc+16 : -1));

				config.push_back(UniformInfo(VarType(testTypes[3]),
											 declareLocs[3],
											 layoutLocs[3],
											 verifyLocs[3],
											 layoutLocs[3] ? baseLoc+27 : -1));

				group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
			}
		}
	}

	// Min/Max location
	{
		tcu::TestCaseGroup* const	group		= new tcu::TestCaseGroup(m_testCtx, "min_max", "Maximum & minimum location");

		addChild(group);

		for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveNdx++)
		{
			const DataType		type	= primitiveTypes[primitiveNdx];

			for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(checkStages); stageNdx++)
			{
				const string		name		= string(getDataTypeName(type)) + "_" + stageNames[stageNdx];
				vector<UniformInfo> config;

				config.push_back(UniformInfo(createVarType(type),
											 checkStages[stageNdx],
											 checkStages[stageNdx],
											 checkStages[stageNdx],
											 0));

				group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_min").c_str(), (name+"_min").c_str(), config));

				group->addChild(new MaxUniformLocationCase (m_testCtx, m_context.getRenderContext(), (name+"_max").c_str(), (name+"_max").c_str(), config));
			}
		}
	}

	// Link
	{
		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(m_testCtx, "link", "Location specified independently from use");
		de::Random					rng		(baseSeed + 0x82e1);

		addChild(group);

		for (int caseNdx = 0; caseNdx < 10; caseNdx++)
		{
			const string		name		= "case_" + de::toString(caseNdx);
			vector<UniformInfo> config;

			vector<int>			locations	= shuffledRange(0, maxLocations, 0x1234 + caseNdx*100);

			for (int count = 0; count < 32; count++)
			{
				typedef UniformInfo::ShaderStage Stage;

				const Stage			layoutLoc	= Stage(rng.getUint32()&0x3);
				const Stage			declareLoc	= Stage((rng.getUint32()&0x3) | layoutLoc);
				const Stage			verifyLoc	= Stage((rng.getUint32()&0x3) & declareLoc);

				const UniformInfo	uniform		(createVarType(primitiveTypes[rng.getInt(0, maxPrimitiveTypeNdx)]),
												 declareLoc,
												 layoutLoc,
												 verifyLoc,
												 (layoutLoc!=0) ? locations.back() : -1);

				config.push_back(uniform);
				locations.pop_back();
			}
			group->addChild(new UniformLocationCase (m_testCtx, m_context.getRenderContext(), name.c_str(), name.c_str(), config));
		}
	}

	// Negative
	{
		de::MovePtr<tcu::TestCaseGroup>	negativeGroup			(new tcu::TestCaseGroup(m_testCtx, "negative", "Negative tests"));

		{
			de::MovePtr<tcu::TestCaseGroup>	es31Group		(new tcu::TestCaseGroup(m_testCtx, "es31", "GLSL ES 3.1 Negative tests"));
			gls::ShaderLibrary				shaderLibrary   (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
			const vector<TestNode*>			negativeCases    = shaderLibrary.loadShaderFile("shaders/es31/uniform_location.test");

			for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
				es31Group->addChild(negativeCases[ndx]);

			negativeGroup->addChild(es31Group.release());
		}

		// ES only
		if (!m_isGL45)
		{
			de::MovePtr<tcu::TestCaseGroup>	es32Group		(new tcu::TestCaseGroup(m_testCtx, "es32", "GLSL ES 3.2 Negative tests"));
			gls::ShaderLibrary				shaderLibrary   (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
			const vector<TestNode*>			negativeCases    = shaderLibrary.loadShaderFile("shaders/es32/uniform_location.test");

			for (int ndx = 0; ndx < int(negativeCases.size()); ndx++)
				es32Group->addChild(negativeCases[ndx]);

			negativeGroup->addChild(es32Group.release());
		}

		addChild(negativeGroup.release());
	}
}

} // Functional
} // gles31
} // deqp
