/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) 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 Random shader test case.
 *//*--------------------------------------------------------------------*/

#include "glsRandomShaderCase.hpp"

#include "gluShaderProgram.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTextureUtil.hpp"

#include "tcuImageCompare.hpp"
#include "tcuTestLog.hpp"
#include "deRandom.hpp"

#include "rsgProgramGenerator.hpp"
#include "rsgProgramExecutor.hpp"
#include "rsgUtils.hpp"

#include "tcuTextureUtil.hpp"
#include "tcuRenderTarget.hpp"

#include "glw.h"

using std::vector;
using std::string;
using std::pair;
using std::map;

namespace deqp
{
namespace gls
{

enum
{
	VIEWPORT_WIDTH			= 64,
	VIEWPORT_HEIGHT			= 64,

	TEXTURE_2D_WIDTH		= 64,
	TEXTURE_2D_HEIGHT		= 64,
	TEXTURE_2D_FORMAT		= GL_RGBA,
	TEXTURE_2D_DATA_TYPE	= GL_UNSIGNED_BYTE,

	TEXTURE_CUBE_SIZE		= 16,
	TEXTURE_CUBE_FORMAT		= GL_RGBA,
	TEXTURE_CUBE_DATA_TYPE	= GL_UNSIGNED_BYTE,

	TEXTURE_WRAP_S			= GL_CLAMP_TO_EDGE,
	TEXTURE_WRAP_T			= GL_CLAMP_TO_EDGE,

	TEXTURE_MIN_FILTER		= GL_LINEAR,
	TEXTURE_MAG_FILTER		= GL_LINEAR
};

VertexArray::VertexArray (const rsg::ShaderInput* input, int numVertices)
	: m_input			(input)
	, m_vertices		(input->getVariable()->getType().getNumElements() * numVertices)
{
}

TextureManager::TextureManager (void)
{
}

TextureManager::~TextureManager (void)
{
}

void TextureManager::bindTexture (int unit, const glu::Texture2D* tex2D)
{
	m_tex2D[unit] = tex2D;
}

void TextureManager::bindTexture (int unit, const glu::TextureCube* texCube)
{
	m_texCube[unit] = texCube;
}

inline vector<pair<int, const glu::Texture2D*> > TextureManager::getBindings2D (void) const
{
	vector<pair<int, const glu::Texture2D*> > bindings;
	for (map<int, const glu::Texture2D*>::const_iterator i = m_tex2D.begin(); i != m_tex2D.end(); i++)
		bindings.push_back(*i);
	return bindings;
}

inline vector<pair<int, const glu::TextureCube*> > TextureManager::getBindingsCube (void) const
{
	vector<pair<int, const glu::TextureCube*> > bindings;
	for (map<int, const glu::TextureCube*>::const_iterator i = m_texCube.begin(); i != m_texCube.end(); i++)
		bindings.push_back(*i);
	return bindings;
}

RandomShaderCase::RandomShaderCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, const rsg::ProgramParameters& params)
	: tcu::TestCase		(testCtx, name, description)
	, m_renderCtx		(renderCtx)
	, m_parameters		(params)
	, m_gridWidth		(1)
	, m_gridHeight		(1)
	, m_vertexShader	(rsg::Shader::TYPE_VERTEX)
	, m_fragmentShader	(rsg::Shader::TYPE_FRAGMENT)
	, m_tex2D			(DE_NULL)
	, m_texCube			(DE_NULL)
{
}

RandomShaderCase::~RandomShaderCase (void)
{
	delete m_tex2D;
	delete m_texCube;
}

void RandomShaderCase::init (void)
{
	// Generate shaders
	rsg::ProgramGenerator programGenerator;
	programGenerator.generate(m_parameters, m_vertexShader, m_fragmentShader);

	// Compute uniform values
	std::vector<const rsg::ShaderInput*>	unifiedUniforms;
	de::Random								rnd(m_parameters.seed);
	rsg::computeUnifiedUniforms(m_vertexShader, m_fragmentShader, unifiedUniforms);
	rsg::computeUniformValues(rnd, m_uniforms, unifiedUniforms);

	// Generate vertices
	const vector<rsg::ShaderInput*>&	inputs		= m_vertexShader.getInputs();
	int									numVertices	= (m_gridWidth+1)*(m_gridHeight+1);

	for (vector<rsg::ShaderInput*>::const_iterator i = inputs.begin(); i != inputs.end(); i++)
	{
		const rsg::ShaderInput*			input			= *i;
		rsg::ConstValueRangeAccess		valueRange		= input->getValueRange();
		int								numComponents	= input->getVariable()->getType().getNumElements();
		VertexArray						vtxArray(input, numVertices);
		bool							isPosition		= string(input->getVariable()->getName()) == "dEQP_Position";

		TCU_CHECK(input->getVariable()->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT);

		for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx++)
		{
			int		y	= vtxNdx / (m_gridWidth+1);
			int		x	= vtxNdx - y*(m_gridWidth+1);
			float	xf	= (float)x / (float)m_gridWidth;
			float	yf	= (float)y / (float)m_gridHeight;
			float*	dst	= &vtxArray.getVertices()[vtxNdx*numComponents];

			if (isPosition)
			{
				// Position attribute gets special interpolation handling.
				DE_ASSERT(numComponents == 4);
				dst[0] = -1.0f + xf *  2.0f;
				dst[1] =  1.0f + yf * -2.0f;
				dst[2] = 0.0f;
				dst[3] = 1.0f;
			}
			else
			{
				for (int compNdx = 0; compNdx < numComponents; compNdx++)
				{
					float	minVal	= valueRange.getMin().component(compNdx).asFloat();
					float	maxVal	= valueRange.getMax().component(compNdx).asFloat();
					float	xd, yd;

					rsg::getVertexInterpolationCoords(xd, yd, xf, yf, compNdx);

					float	f		= (xd+yd) / 2.0f;

					dst[compNdx] = minVal + f * (maxVal-minVal);
				}
			}
		}

		m_vertexArrays.push_back(vtxArray);
	}

	// Generate indices
	int numQuads	= m_gridWidth*m_gridHeight;
	int numIndices	= numQuads*6;
	m_indices.resize(numIndices);
	for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
	{
		int	quadY	= quadNdx / (m_gridWidth);
		int quadX	= quadNdx - quadY*m_gridWidth;

		m_indices[quadNdx*6+0] = quadX + quadY*(m_gridWidth+1);
		m_indices[quadNdx*6+1] = quadX + (quadY+1)*(m_gridWidth+1);
		m_indices[quadNdx*6+2] = quadX + quadY*(m_gridWidth+1) + 1;
		m_indices[quadNdx*6+3] = m_indices[quadNdx*6+2];
		m_indices[quadNdx*6+4] = m_indices[quadNdx*6+1];
		m_indices[quadNdx*6+5] = quadX + (quadY+1)*(m_gridWidth+1) + 1;
	}

	// Create textures.
	for (vector<rsg::VariableValue>::const_iterator uniformIter = m_uniforms.begin(); uniformIter != m_uniforms.end(); uniformIter++)
	{
		const rsg::VariableType& type = uniformIter->getVariable()->getType();

		if (!type.isSampler())
			continue;

		int unitNdx = uniformIter->getValue().asInt(0);

		if (type == rsg::VariableType(rsg::VariableType::TYPE_SAMPLER_2D, 1))
			m_texManager.bindTexture(unitNdx, getTex2D());
		else if (type == rsg::VariableType(rsg::VariableType::TYPE_SAMPLER_CUBE, 1))
			m_texManager.bindTexture(unitNdx, getTexCube());
		else
			DE_ASSERT(DE_FALSE);
	}
}

const glu::Texture2D* RandomShaderCase::getTex2D (void)
{
	if (!m_tex2D)
	{
		m_tex2D = new glu::Texture2D(m_renderCtx, TEXTURE_2D_FORMAT, TEXTURE_2D_DATA_TYPE, TEXTURE_2D_WIDTH, TEXTURE_2D_HEIGHT);

		m_tex2D->getRefTexture().allocLevel(0);
		tcu::fillWithComponentGradients(m_tex2D->getRefTexture().getLevel(0), tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
		m_tex2D->upload();

		// Setup parameters.
		glBindTexture(GL_TEXTURE_2D, m_tex2D->getGLTexture());
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		TEXTURE_WRAP_S);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		TEXTURE_WRAP_T);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	TEXTURE_MIN_FILTER);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	TEXTURE_MAG_FILTER);

		GLU_CHECK();
	}

	return m_tex2D;
}

const glu::TextureCube* RandomShaderCase::getTexCube (void)
{
	if (!m_texCube)
	{
		m_texCube = new glu::TextureCube(m_renderCtx, TEXTURE_CUBE_FORMAT, TEXTURE_CUBE_DATA_TYPE, TEXTURE_CUBE_SIZE);

		static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
		{
			{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
			{ tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
			{ tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
			{ tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
			{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
			{ tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
		};

		// Fill level 0.
		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
		{
			m_texCube->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
			tcu::fillWithComponentGradients(m_texCube->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), gradients[face][0], gradients[face][1]);
		}

		m_texCube->upload();

		// Setup parameters.
		glBindTexture(GL_TEXTURE_CUBE_MAP, m_texCube->getGLTexture());
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		TEXTURE_WRAP_S);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		TEXTURE_WRAP_T);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	TEXTURE_MIN_FILTER);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	TEXTURE_MAG_FILTER);

		GLU_CHECK();
	}

	return m_texCube;
}

void RandomShaderCase::deinit (void)
{
	delete m_tex2D;
	delete m_texCube;

	m_tex2D		= DE_NULL;
	m_texCube	= DE_NULL;

	// Free up memory
	m_vertexArrays.clear();
	m_indices.clear();
}

namespace
{

void setUniformValue (int location, rsg::ConstValueAccess value)
{
	DE_STATIC_ASSERT(sizeof(rsg::Scalar) == sizeof(float));
	DE_STATIC_ASSERT(sizeof(rsg::Scalar) == sizeof(int));

	switch (value.getType().getBaseType())
	{
		case rsg::VariableType::TYPE_FLOAT:
			switch (value.getType().getNumElements())
			{
				case 1:		glUniform1fv(location, 1, (float*)value.value().getValuePtr());		break;
				case 2:		glUniform2fv(location, 1, (float*)value.value().getValuePtr());		break;
				case 3:		glUniform3fv(location, 1, (float*)value.value().getValuePtr());		break;
				case 4:		glUniform4fv(location, 1, (float*)value.value().getValuePtr());		break;
				default:	TCU_FAIL("Unsupported type");										break;
			}
			break;

		case rsg::VariableType::TYPE_INT:
		case rsg::VariableType::TYPE_BOOL:
		case rsg::VariableType::TYPE_SAMPLER_2D:
		case rsg::VariableType::TYPE_SAMPLER_CUBE:
			switch (value.getType().getNumElements())
			{
				case 1:		glUniform1iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 2:		glUniform2iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 3:		glUniform3iv(location, 1, (int*)value.value().getValuePtr());		break;
				case 4:		glUniform4iv(location, 1, (int*)value.value().getValuePtr());		break;
				default:	TCU_FAIL("Unsupported type");										break;
			}
			break;

		default:
			TCU_FAIL("Unsupported type");
	}
}

tcu::MessageBuilder& operator<< (tcu::MessageBuilder& message, rsg::ConstValueAccess value)
{
	const char*	scalarType	= DE_NULL;
	const char* vecType		= DE_NULL;

	switch (value.getType().getBaseType())
	{
		case rsg::VariableType::TYPE_FLOAT:			scalarType = "float";	vecType	= "vec";	break;
		case rsg::VariableType::TYPE_INT:			scalarType = "int";		vecType = "ivec";	break;
		case rsg::VariableType::TYPE_BOOL:			scalarType = "bool";	vecType = "bvec";	break;
		case rsg::VariableType::TYPE_SAMPLER_2D:	scalarType = "sampler2D";					break;
		case rsg::VariableType::TYPE_SAMPLER_CUBE:	scalarType = "samplerCube";					break;
		default:
			TCU_FAIL("Unsupported type.");
	}

	int numElements = value.getType().getNumElements();
	if (numElements == 1)
		message << scalarType << "(";
	else
		message << vecType << numElements << "(";

	for (int elementNdx = 0; elementNdx < numElements; elementNdx++)
	{
		if (elementNdx > 0)
			message << ", ";

		switch (value.getType().getBaseType())
		{
			case rsg::VariableType::TYPE_FLOAT:			message << value.component(elementNdx).asFloat();						break;
			case rsg::VariableType::TYPE_INT:			message << value.component(elementNdx).asInt();							break;
			case rsg::VariableType::TYPE_BOOL:			message << (value.component(elementNdx).asBool() ? "true" : "false");	break;
			case rsg::VariableType::TYPE_SAMPLER_2D:	message << value.component(elementNdx).asInt();							break;
			case rsg::VariableType::TYPE_SAMPLER_CUBE:	message << value.component(elementNdx).asInt();							break;
			default:
				DE_ASSERT(DE_FALSE);
		}
	}

	message << ")";

	return message;
}

tcu::MessageBuilder& operator<< (tcu::MessageBuilder& message, rsg::ConstValueRangeAccess valueRange)
{
	return message << valueRange.getMin() << " -> " << valueRange.getMax();
}

} // anonymous

RandomShaderCase::IterateResult RandomShaderCase::iterate (void)
{
	tcu::TestLog& log = m_testCtx.getLog();

	// Compile program
	glu::ShaderProgram program(m_renderCtx, glu::makeVtxFragSources(m_vertexShader.getSource(), m_fragmentShader.getSource()));
	log << program;

	if (!program.isOk())
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
		return STOP;
	}

	// Compute random viewport
	de::Random				rnd				(m_parameters.seed);
	int						viewportWidth	= de::min<int>(VIEWPORT_WIDTH,	m_renderCtx.getRenderTarget().getWidth());
	int						viewportHeight	= de::min<int>(VIEWPORT_HEIGHT,	m_renderCtx.getRenderTarget().getHeight());
	int						viewportX		= rnd.getInt(0, m_renderCtx.getRenderTarget().getWidth()	- viewportWidth);
	int						viewportY		= rnd.getInt(0, m_renderCtx.getRenderTarget().getHeight()	- viewportHeight);
	bool					hasAlpha		= m_renderCtx.getRenderTarget().getPixelFormat().alphaBits > 0;
	tcu::TextureLevel		rendered		(tcu::TextureFormat(hasAlpha ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), viewportWidth, viewportHeight);
	tcu::TextureLevel		reference		(tcu::TextureFormat(hasAlpha ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), viewportWidth, viewportHeight);

	// Reference program executor.
	rsg::ProgramExecutor	executor		(reference.getAccess(), m_gridWidth, m_gridHeight);

	GLU_CHECK_CALL(glUseProgram(program.getProgram()));

	// Set up attributes
	for (vector<VertexArray>::const_iterator attribIter = m_vertexArrays.begin(); attribIter != m_vertexArrays.end(); attribIter++)
	{
		GLint location = glGetAttribLocation(program.getProgram(), attribIter->getName());

		// Print to log.
		log << tcu::TestLog::Message << "attribute[" << location << "]: " << attribIter->getName() << " = " << attribIter->getValueRange() << tcu::TestLog::EndMessage;

		if (location >= 0)
		{
			glVertexAttribPointer(location, attribIter->getNumComponents(), GL_FLOAT, GL_FALSE, 0, &attribIter->getVertices()[0]);
			glEnableVertexAttribArray(location);
		}
	}
	GLU_CHECK_MSG("After attribute setup");

	// Uniforms
	for (vector<rsg::VariableValue>::const_iterator uniformIter = m_uniforms.begin(); uniformIter != m_uniforms.end(); uniformIter++)
	{
		GLint location = glGetUniformLocation(program.getProgram(), uniformIter->getVariable()->getName());

		log << tcu::TestLog::Message << "uniform[" << location << "]: " << uniformIter->getVariable()->getName() << " = " << uniformIter->getValue() << tcu::TestLog::EndMessage;

		if (location >= 0)
			setUniformValue(location, uniformIter->getValue());
	}
	GLU_CHECK_MSG("After uniform setup");

	// Textures
	vector<pair<int, const glu::Texture2D*> >	tex2DBindings		= m_texManager.getBindings2D();
	vector<pair<int, const glu::TextureCube*> >	texCubeBindings		= m_texManager.getBindingsCube();

	for (vector<pair<int, const glu::Texture2D*> >::const_iterator i = tex2DBindings.begin(); i != tex2DBindings.end(); i++)
	{
		int						unitNdx		= i->first;
		const glu::Texture2D*	texture		= i->second;

		glActiveTexture(GL_TEXTURE0 + unitNdx);
		glBindTexture(GL_TEXTURE_2D, texture->getGLTexture());

		executor.setTexture(unitNdx, &texture->getRefTexture(), glu::mapGLSampler(TEXTURE_WRAP_S, TEXTURE_WRAP_T, TEXTURE_MIN_FILTER, TEXTURE_MAG_FILTER));
	}
	GLU_CHECK_MSG("After 2D texture setup");

	for (vector<pair<int, const glu::TextureCube*> >::const_iterator i = texCubeBindings.begin(); i != texCubeBindings.end(); i++)
	{
		int						unitNdx		= i->first;
		const glu::TextureCube*	texture		= i->second;

		glActiveTexture(GL_TEXTURE0 + unitNdx);
		glBindTexture(GL_TEXTURE_CUBE_MAP, texture->getGLTexture());

		executor.setTexture(unitNdx, &texture->getRefTexture(), glu::mapGLSampler(TEXTURE_WRAP_S, TEXTURE_WRAP_T, TEXTURE_MIN_FILTER, TEXTURE_MAG_FILTER));
	}
	GLU_CHECK_MSG("After cubemap setup");

	// Draw and read
	glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
	glDrawElements(GL_TRIANGLES, (GLsizei)m_indices.size(), GL_UNSIGNED_SHORT, &m_indices[0]);
	glFlush();
	GLU_CHECK_MSG("Draw");

	// Render reference while GPU is doing work
	executor.execute(m_vertexShader, m_fragmentShader, m_uniforms);

	if (rendered.getFormat().order != tcu::TextureFormat::RGBA || rendered.getFormat().type != tcu::TextureFormat::UNORM_INT8)
	{
		// Read as GL_RGBA8
		tcu::TextureLevel readBuf(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), rendered.getWidth(), rendered.getHeight());
		glu::readPixels(m_renderCtx, viewportX, viewportY, readBuf.getAccess());
		GLU_CHECK_MSG("Read pixels");
		tcu::copy(rendered, readBuf);
	}
	else
		glu::readPixels(m_renderCtx, viewportX, viewportY, rendered.getAccess());

	// Compare
	{
		float	threshold	= 0.02f;
		bool	imagesOk	= tcu::fuzzyCompare(log, "Result", "Result images", reference.getAccess(), rendered.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);

		if (imagesOk)
			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
		else
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
	}

	return STOP;
}

} // gls
} // deqp
