/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2016 Google Inc.
 * Copyright (c) 2016 The Khronos Group Inc.
 *
 * 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 Shader execute test.
 */ /*-------------------------------------------------------------------*/

#include "glcShaderRenderCase.hpp"

#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuSurface.hpp"
#include "tcuTestLog.hpp"
#include "tcuVector.hpp"

#include "gluDrawUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTexture.hpp"
#include "gluTextureUtil.hpp"

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

#include "deMath.h"
#include "deMemory.h"
#include "deRandom.hpp"
#include "deString.h"
#include "deStringUtil.hpp"

#include <stdio.h>
#include <string>
#include <vector>

namespace deqp
{

using namespace std;
using namespace tcu;
using namespace glu;

static const int	   GRID_SIZE		   = 64;
static const int	   MAX_RENDER_WIDTH	= 128;
static const int	   MAX_RENDER_HEIGHT   = 112;
static const tcu::Vec4 DEFAULT_CLEAR_COLOR = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);

inline RGBA toRGBA(const Vec4& a)
{
	return RGBA(
		deClamp32(deRoundFloatToInt32(a.x() * 255.0f), 0, 255), deClamp32(deRoundFloatToInt32(a.y() * 255.0f), 0, 255),
		deClamp32(deRoundFloatToInt32(a.z() * 255.0f), 0, 255), deClamp32(deRoundFloatToInt32(a.w() * 255.0f), 0, 255));
}

inline tcu::Vec4 toVec(const RGBA& c)
{
	return tcu::Vec4(static_cast<float>(c.getRed()) / 255.0f, static_cast<float>(c.getGreen()) / 255.0f,
					 static_cast<float>(c.getBlue()) / 255.0f, static_cast<float>(c.getAlpha()) / 255.0f);
}

// TextureBinding

TextureBinding::TextureBinding(const glu::Texture2D* tex2D, const tcu::Sampler& sampler)
	: m_type(TYPE_2D), m_sampler(sampler)
{
	m_binding.tex2D = tex2D;
}

TextureBinding::TextureBinding(const glu::TextureCube* texCube, const tcu::Sampler& sampler)
	: m_type(TYPE_CUBE_MAP), m_sampler(sampler)
{
	m_binding.texCube = texCube;
}

TextureBinding::TextureBinding(const glu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler)
	: m_type(TYPE_2D_ARRAY), m_sampler(sampler)
{
	m_binding.tex2DArray = tex2DArray;
}

TextureBinding::TextureBinding(const glu::Texture3D* tex3D, const tcu::Sampler& sampler)
	: m_type(TYPE_3D), m_sampler(sampler)
{
	m_binding.tex3D = tex3D;
}

TextureBinding::TextureBinding(void) : m_type(TYPE_NONE)
{
	m_binding.tex2D = DE_NULL;
}

TextureBinding::TextureBinding(const glu::TextureCubeArray* texCubeArray, const tcu::Sampler& sampler)
	: m_type(TYPE_CUBE_MAP_ARRAY), m_sampler(sampler)
{
	m_binding.texCubeArray = texCubeArray;
}

void TextureBinding::setSampler(const tcu::Sampler& sampler)
{
	m_sampler = sampler;
}

void TextureBinding::setTexture(const glu::Texture2D* tex2D)
{
	m_type			= TYPE_2D;
	m_binding.tex2D = tex2D;
}

void TextureBinding::setTexture(const glu::TextureCube* texCube)
{
	m_type			  = TYPE_CUBE_MAP;
	m_binding.texCube = texCube;
}

void TextureBinding::setTexture(const glu::Texture2DArray* tex2DArray)
{
	m_type				 = TYPE_2D_ARRAY;
	m_binding.tex2DArray = tex2DArray;
}

void TextureBinding::setTexture(const glu::Texture3D* tex3D)
{
	m_type			= TYPE_3D;
	m_binding.tex3D = tex3D;
}

void TextureBinding::setTexture(const glu::TextureCubeArray* texCubeArray)
{
	m_type				   = TYPE_CUBE_MAP_ARRAY;
	m_binding.texCubeArray = texCubeArray;
}

// QuadGrid.

class QuadGrid
{
public:
	QuadGrid(int gridSize, int screenWidth, int screenHeight, const Vec4& constCoords,
			 const vector<Mat4>& userAttribTransforms, const vector<TextureBinding>& textures);
	~QuadGrid(void);

	int getGridSize(void) const
	{
		return m_gridSize;
	}
	int getNumVertices(void) const
	{
		return m_numVertices;
	}
	int getNumTriangles(void) const
	{
		return m_numTriangles;
	}
	const Vec4& getConstCoords(void) const
	{
		return m_constCoords;
	}
	const vector<Mat4> getUserAttribTransforms(void) const
	{
		return m_userAttribTransforms;
	}
	const vector<TextureBinding>& getTextures(void) const
	{
		return m_textures;
	}

	const Vec4* getPositions(void) const
	{
		return &m_positions[0];
	}
	const float* getAttribOne(void) const
	{
		return &m_attribOne[0];
	}
	const Vec4* getCoords(void) const
	{
		return &m_coords[0];
	}
	const Vec4* getUnitCoords(void) const
	{
		return &m_unitCoords[0];
	}
	const Vec4* getUserAttrib(int attribNdx) const
	{
		return &m_userAttribs[attribNdx][0];
	}
	const deUint16* getIndices(void) const
	{
		return &m_indices[0];
	}

	Vec4 getCoords(float sx, float sy) const;
	Vec4 getUnitCoords(float sx, float sy) const;

	int getNumUserAttribs(void) const
	{
		return (int)m_userAttribTransforms.size();
	}
	Vec4 getUserAttrib(int attribNdx, float sx, float sy) const;

private:
	int					   m_gridSize;
	int					   m_numVertices;
	int					   m_numTriangles;
	Vec4				   m_constCoords;
	vector<Mat4>		   m_userAttribTransforms;
	vector<TextureBinding> m_textures;

	vector<Vec4>	 m_screenPos;
	vector<Vec4>	 m_positions;
	vector<Vec4>	 m_coords;	 //!< Near-unit coordinates, roughly [-2.0 .. 2.0].
	vector<Vec4>	 m_unitCoords; //!< Positive-only coordinates [0.0 .. 1.5].
	vector<float>	m_attribOne;
	vector<Vec4>	 m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
	vector<deUint16> m_indices;
};

QuadGrid::QuadGrid(int gridSize, int width, int height, const Vec4& constCoords,
				   const vector<Mat4>& userAttribTransforms, const vector<TextureBinding>& textures)
	: m_gridSize(gridSize)
	, m_numVertices((gridSize + 1) * (gridSize + 1))
	, m_numTriangles(gridSize * gridSize * 2)
	, m_constCoords(constCoords)
	, m_userAttribTransforms(userAttribTransforms)
	, m_textures(textures)
{
	Vec4 viewportScale = Vec4((float)width, (float)height, 0.0f, 0.0f);

	// Compute vertices.
	m_positions.resize(m_numVertices);
	m_coords.resize(m_numVertices);
	m_unitCoords.resize(m_numVertices);
	m_attribOne.resize(m_numVertices);
	m_screenPos.resize(m_numVertices);

	// User attributes.
	for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_userAttribs); i++)
		m_userAttribs[i].resize(m_numVertices);

	for (int y = 0; y < gridSize + 1; y++)
		for (int x = 0; x < gridSize + 1; x++)
		{
			float sx	 = static_cast<float>(x) / static_cast<float>(gridSize);
			float sy	 = static_cast<float>(y) / static_cast<float>(gridSize);
			float fx	 = 2.0f * sx - 1.0f;
			float fy	 = 2.0f * sy - 1.0f;
			int   vtxNdx = ((y * (gridSize + 1)) + x);

			m_positions[vtxNdx]  = Vec4(fx, fy, 0.0f, 1.0f);
			m_attribOne[vtxNdx]  = 1.0f;
			m_screenPos[vtxNdx]  = Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
			m_coords[vtxNdx]	 = getCoords(sx, sy);
			m_unitCoords[vtxNdx] = getUnitCoords(sx, sy);

			for (int attribNdx					 = 0; attribNdx < getNumUserAttribs(); attribNdx++)
				m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
		}

	// Compute indices.
	m_indices.resize(3 * m_numTriangles);
	for (int y = 0; y < gridSize; y++)
		for (int x = 0; x < gridSize; x++)
		{
			int stride = gridSize + 1;
			int v00	= (y * stride) + x;
			int v01	= (y * stride) + x + 1;
			int v10	= ((y + 1) * stride) + x;
			int v11	= ((y + 1) * stride) + x + 1;

			int baseNdx			   = ((y * gridSize) + x) * 6;
			m_indices[baseNdx + 0] = static_cast<deUint16>(v10);
			m_indices[baseNdx + 1] = static_cast<deUint16>(v00);
			m_indices[baseNdx + 2] = static_cast<deUint16>(v01);

			m_indices[baseNdx + 3] = static_cast<deUint16>(v10);
			m_indices[baseNdx + 4] = static_cast<deUint16>(v01);
			m_indices[baseNdx + 5] = static_cast<deUint16>(v11);
		}
}

QuadGrid::~QuadGrid(void)
{
}

inline Vec4 QuadGrid::getCoords(float sx, float sy) const
{
	float fx = 2.0f * sx - 1.0f;
	float fy = 2.0f * sy - 1.0f;
	return Vec4(fx, fy, -fx + 0.33f * fy, -0.275f * fx - fy);
}

inline Vec4 QuadGrid::getUnitCoords(float sx, float sy) const
{
	return Vec4(sx, sy, 0.33f * sx + 0.5f * sy, 0.5f * sx + 0.25f * sy);
}

inline Vec4 QuadGrid::getUserAttrib(int attribNdx, float sx, float sy) const
{
	// homogeneous normalized screen-space coordinates
	return m_userAttribTransforms[attribNdx] * Vec4(sx, sy, 0.0f, 1.0f);
}

// ShaderEvalContext.

ShaderEvalContext::ShaderEvalContext(const QuadGrid& quadGrid_)
	: constCoords(quadGrid_.getConstCoords()), isDiscarded(false), quadGrid(quadGrid_)
{
	const vector<TextureBinding>& bindings = quadGrid.getTextures();
	DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);

	// Fill in texture array.
	for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
	{
		const TextureBinding& binding = bindings[ndx];

		if (binding.getType() == TextureBinding::TYPE_NONE)
			continue;

		textures[ndx].sampler = binding.getSampler();

		switch (binding.getType())
		{
		case TextureBinding::TYPE_2D:
			textures[ndx].tex2D = &binding.get2D()->getRefTexture();
			break;
		case TextureBinding::TYPE_CUBE_MAP:
			textures[ndx].texCube = &binding.getCube()->getRefTexture();
			break;
		case TextureBinding::TYPE_2D_ARRAY:
			textures[ndx].tex2DArray = &binding.get2DArray()->getRefTexture();
			break;
		case TextureBinding::TYPE_3D:
			textures[ndx].tex3D = &binding.get3D()->getRefTexture();
			break;
		case TextureBinding::TYPE_CUBE_MAP_ARRAY:
			textures[ndx].texCubeArray = &binding.getCubeArray()->getRefTexture();
			break;
		default:
			DE_ASSERT(DE_FALSE);
		}
	}
}

ShaderEvalContext::~ShaderEvalContext(void)
{
}

void ShaderEvalContext::reset(float sx, float sy)
{
	// Clear old values
	color		= Vec4(0.0f, 0.0f, 0.0f, 1.0f);
	isDiscarded = false;

	// Compute coords
	coords	 = quadGrid.getCoords(sx, sy);
	unitCoords = quadGrid.getUnitCoords(sx, sy);

	// Compute user attributes.
	int numAttribs = quadGrid.getNumUserAttribs();
	DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
	for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
		in[attribNdx]  = quadGrid.getUserAttrib(attribNdx, sx, sy);
}

tcu::Vec4 ShaderEvalContext::texture2D(int unitNdx, const tcu::Vec2& texCoords)
{
	if (textures[unitNdx].tex2D)
		return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
	else
		return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
}

// ShaderEvaluator

ShaderEvaluator::ShaderEvaluator(void) : m_evalFunc(DE_NULL)
{
}

ShaderEvaluator::ShaderEvaluator(ShaderEvalFunc evalFunc) : m_evalFunc(evalFunc)
{
}

ShaderEvaluator::~ShaderEvaluator(void)
{
}

void ShaderEvaluator::evaluate(ShaderEvalContext& ctx)
{
	DE_ASSERT(m_evalFunc);
	m_evalFunc(ctx);
}

// ShaderRenderCase.

ShaderRenderCase::ShaderRenderCase(TestContext& testCtx, RenderContext& renderCtx, const ContextInfo& ctxInfo,
								   const char* name, const char* description, bool isVertexCase,
								   ShaderEvalFunc evalFunc)
	: TestCase(testCtx, name, description)
	, m_renderCtx(renderCtx)
	, m_ctxInfo(ctxInfo)
	, m_isVertexCase(isVertexCase)
	, m_defaultEvaluator(evalFunc)
	, m_evaluator(m_defaultEvaluator)
	, m_clearColor(DEFAULT_CLEAR_COLOR)
	, m_program(DE_NULL)
{
}

ShaderRenderCase::ShaderRenderCase(TestContext& testCtx, RenderContext& renderCtx, const ContextInfo& ctxInfo,
								   const char* name, const char* description, bool isVertexCase,
								   ShaderEvaluator& evaluator)
	: TestCase(testCtx, name, description)
	, m_renderCtx(renderCtx)
	, m_ctxInfo(ctxInfo)
	, m_isVertexCase(isVertexCase)
	, m_defaultEvaluator(DE_NULL)
	, m_evaluator(evaluator)
	, m_clearColor(DEFAULT_CLEAR_COLOR)
	, m_program(DE_NULL)
{
}

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

void ShaderRenderCase::init(void)
{
	TestLog&			  log = m_testCtx.getLog();
	const glw::Functions& gl  = m_renderCtx.getFunctions();

	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderRenderCase::init() begin");

	DE_ASSERT(!m_program);
	m_program =
		new ShaderProgram(m_renderCtx, glu::makeVtxFragSources(m_vertShaderSource.c_str(), m_fragShaderSource.c_str()));

	try
	{
		log << *m_program; // Always log shader program.

		if (!m_program->isOk())
			TCU_FAIL("Failed to compile shader program");

		GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderRenderCase::init() end");
	}
	catch (const std::exception&)
	{
		// Clean up.
		ShaderRenderCase::deinit();
		throw;
	}
}

void ShaderRenderCase::deinit(void)
{
	delete m_program;
	m_program = DE_NULL;
}

tcu::IVec2 ShaderRenderCase::getViewportSize(void) const
{
	return tcu::IVec2(de::min(m_renderCtx.getRenderTarget().getWidth(), MAX_RENDER_WIDTH),
					  de::min(m_renderCtx.getRenderTarget().getHeight(), MAX_RENDER_HEIGHT));
}

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

	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderRenderCase::iterate() begin");

	DE_ASSERT(m_program);
	deUint32 programID = m_program->getProgram();
	gl.useProgram(programID);

	// Create quad grid.
	IVec2 viewportSize = getViewportSize();
	int   width		   = viewportSize.x();
	int   height	   = viewportSize.y();

	// \todo [petri] Better handling of constCoords (render in multiple chunks, vary coords).
	QuadGrid quadGrid(m_isVertexCase ? GRID_SIZE : 4, width, height, Vec4(0.0f, 0.0f, 0.0f, 1.0f),
					  m_userAttribTransforms, m_textures);

	// Render result.
	Surface resImage(width, height);
	render(resImage, programID, quadGrid);

	// Compute reference.
	Surface refImage(width, height);
	if (m_isVertexCase)
		computeVertexReference(refImage, quadGrid);
	else
		computeFragmentReference(refImage, quadGrid);

	// Compare.
	bool testOk = compareImages(resImage, refImage, 0.07f);

	// De-initialize.
	gl.useProgram(0);

	m_testCtx.setTestResult(testOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, testOk ? "Pass" : "Fail");
	return TestNode::STOP;
}

void ShaderRenderCase::setup(deUint32 programID)
{
	DE_UNREF(programID);
}

void ShaderRenderCase::setupUniforms(deUint32 programID, const Vec4& constCoords)
{
	DE_UNREF(programID);
	DE_UNREF(constCoords);
}

void ShaderRenderCase::setupDefaultInputs(int programID)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	// SETUP UNIFORMS.

	setupDefaultUniforms(m_renderCtx, programID);

	GLU_EXPECT_NO_ERROR(gl.getError(), "post uniform setup");

	// SETUP TEXTURES.

	for (int ndx = 0; ndx < (int)m_textures.size(); ndx++)
	{
		const TextureBinding& tex		= m_textures[ndx];
		const tcu::Sampler&   sampler   = tex.getSampler();
		deUint32			  texTarget = GL_NONE;
		deUint32			  texObj	= 0;

		if (tex.getType() == TextureBinding::TYPE_NONE)
			continue;

		// Feature check.
		if (m_renderCtx.getType().getAPI() == glu::ApiType(2, 0, glu::PROFILE_ES))
		{
			if (tex.getType() == TextureBinding::TYPE_2D_ARRAY)
				throw tcu::NotSupportedError("2D array texture binding is not supported");

			if (tex.getType() == TextureBinding::TYPE_3D)
				throw tcu::NotSupportedError("3D texture binding is not supported");

			if (sampler.compare != tcu::Sampler::COMPAREMODE_NONE)
				throw tcu::NotSupportedError("Shadow lookups are not supported");
		}

		switch (tex.getType())
		{
		case TextureBinding::TYPE_2D:
			texTarget = GL_TEXTURE_2D;
			texObj	= tex.get2D()->getGLTexture();
			break;
		case TextureBinding::TYPE_CUBE_MAP:
			texTarget = GL_TEXTURE_CUBE_MAP;
			texObj	= tex.getCube()->getGLTexture();
			break;
		case TextureBinding::TYPE_2D_ARRAY:
			texTarget = GL_TEXTURE_2D_ARRAY;
			texObj	= tex.get2DArray()->getGLTexture();
			break;
		case TextureBinding::TYPE_3D:
			texTarget = GL_TEXTURE_3D;
			texObj	= tex.get3D()->getGLTexture();
			break;
		case TextureBinding::TYPE_CUBE_MAP_ARRAY:
			texTarget = GL_TEXTURE_CUBE_MAP_ARRAY;
			texObj	= tex.getCubeArray()->getGLTexture();
			break;
		default:
			DE_ASSERT(DE_FALSE);
		}

		gl.activeTexture(GL_TEXTURE0 + ndx);
		gl.bindTexture(texTarget, texObj);
		gl.texParameteri(texTarget, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(sampler.wrapS));
		gl.texParameteri(texTarget, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(sampler.wrapT));
		gl.texParameteri(texTarget, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(sampler.minFilter));
		gl.texParameteri(texTarget, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(sampler.magFilter));

		if (texTarget == GL_TEXTURE_3D)
			gl.texParameteri(texTarget, GL_TEXTURE_WRAP_R, glu::getGLWrapMode(sampler.wrapR));

		if (sampler.compare != tcu::Sampler::COMPAREMODE_NONE)
		{
			gl.texParameteri(texTarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
			gl.texParameteri(texTarget, GL_TEXTURE_COMPARE_FUNC, glu::getGLCompareFunc(sampler.compare));
		}
	}

	GLU_EXPECT_NO_ERROR(gl.getError(), "texture sampler setup");
}

static void getDefaultVertexArrays(const glw::Functions& gl, const QuadGrid& quadGrid, deUint32 program,
								   vector<VertexArrayBinding>& vertexArrays)
{
	const int numElements = quadGrid.getNumVertices();

	vertexArrays.push_back(va::Float("a_position", 4, numElements, 0, (const float*)quadGrid.getPositions()));
	vertexArrays.push_back(va::Float("a_coords", 4, numElements, 0, (const float*)quadGrid.getCoords()));
	vertexArrays.push_back(va::Float("a_unitCoords", 4, numElements, 0, (const float*)quadGrid.getUnitCoords()));
	vertexArrays.push_back(va::Float("a_one", 1, numElements, 0, quadGrid.getAttribOne()));

	// a_inN.
	for (int userNdx = 0; userNdx < quadGrid.getNumUserAttribs(); userNdx++)
	{
		string name = string("a_in") + de::toString(userNdx);
		vertexArrays.push_back(va::Float(name, 4, numElements, 0, (const float*)quadGrid.getUserAttrib(userNdx)));
	}

	// Matrix attributes - these are set by location
	static const struct
	{
		const char* name;
		int			numCols;
		int			numRows;
	} matrices[] = { { "a_mat2", 2, 2 },   { "a_mat2x3", 2, 3 }, { "a_mat2x4", 2, 4 },
					 { "a_mat3x2", 3, 2 }, { "a_mat3", 3, 3 },   { "a_mat3x4", 3, 4 },
					 { "a_mat4x2", 4, 2 }, { "a_mat4x3", 4, 3 }, { "a_mat4", 4, 4 } };

	for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
	{
		int loc = gl.getAttribLocation(program, matrices[matNdx].name);

		if (loc < 0)
			continue; // Not used in shader.

		int numRows = matrices[matNdx].numRows;
		int numCols = matrices[matNdx].numCols;

		for (int colNdx = 0; colNdx < numCols; colNdx++)
			vertexArrays.push_back(va::Float(loc + colNdx, numRows, numElements, 4 * (int)sizeof(float),
											 (const float*)quadGrid.getUserAttrib(colNdx)));
	}
}

void ShaderRenderCase::render(Surface& result, int programID, const QuadGrid& quadGrid)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();

	GLU_EXPECT_NO_ERROR(gl.getError(), "pre render");

	// Buffer info.
	int width  = result.getWidth();
	int height = result.getHeight();

	int xOffsetMax = m_renderCtx.getRenderTarget().getWidth() - width;
	int yOffsetMax = m_renderCtx.getRenderTarget().getHeight() - height;

	deUint32   hash = deStringHash(m_vertShaderSource.c_str()) + deStringHash(m_fragShaderSource.c_str());
	de::Random rnd(hash);

	int xOffset = rnd.getInt(0, xOffsetMax);
	int yOffset = rnd.getInt(0, yOffsetMax);

	gl.viewport(xOffset, yOffset, width, height);

	// Setup program.
	setupUniforms(programID, quadGrid.getConstCoords());
	setupDefaultInputs(programID);

	// Disable dither.
	gl.disable(GL_DITHER);

	// Clear.
	gl.clearColor(m_clearColor.x(), m_clearColor.y(), m_clearColor.z(), m_clearColor.w());
	gl.clear(GL_COLOR_BUFFER_BIT);

	// Draw.
	{
		std::vector<VertexArrayBinding> vertexArrays;
		const int						numElements = quadGrid.getNumTriangles() * 3;

		getDefaultVertexArrays(gl, quadGrid, programID, vertexArrays);
		draw(m_renderCtx, programID, (int)vertexArrays.size(), &vertexArrays[0],
			 pr::Triangles(numElements, quadGrid.getIndices()));
	}
	GLU_EXPECT_NO_ERROR(gl.getError(), "draw");

	// Read back results.
	glu::readPixels(m_renderCtx, xOffset, yOffset, result.getAccess());

	GLU_EXPECT_NO_ERROR(gl.getError(), "post render");
}

void ShaderRenderCase::computeVertexReference(Surface& result, const QuadGrid& quadGrid)
{
	// Buffer info.
	int				  width	= result.getWidth();
	int				  height   = result.getHeight();
	int				  gridSize = quadGrid.getGridSize();
	int				  stride   = gridSize + 1;
	bool			  hasAlpha = m_renderCtx.getRenderTarget().getPixelFormat().alphaBits > 0;
	ShaderEvalContext evalCtx(quadGrid);

	// Evaluate color for each vertex.
	vector<Vec4> colors((gridSize + 1) * (gridSize + 1));
	for (int y = 0; y < gridSize + 1; y++)
		for (int x = 0; x < gridSize + 1; x++)
		{
			float sx	 = static_cast<float>(x) / static_cast<float>(gridSize);
			float sy	 = static_cast<float>(y) / static_cast<float>(gridSize);
			int   vtxNdx = ((y * (gridSize + 1)) + x);

			evalCtx.reset(sx, sy);
			m_evaluator.evaluate(evalCtx);
			DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
			Vec4 color = evalCtx.color;

			if (!hasAlpha)
				color.w() = 1.0f;

			colors[vtxNdx] = color;
		}

	// Render quads.
	for (int y = 0; y < gridSize; y++)
		for (int x = 0; x < gridSize; x++)
		{
			float x0 = static_cast<float>(x) / static_cast<float>(gridSize);
			float x1 = static_cast<float>(x + 1) / static_cast<float>(gridSize);
			float y0 = static_cast<float>(y) / static_cast<float>(gridSize);
			float y1 = static_cast<float>(y + 1) / static_cast<float>(gridSize);

			float sx0  = x0 * (float)width;
			float sx1  = x1 * (float)width;
			float sy0  = y0 * (float)height;
			float sy1  = y1 * (float)height;
			float oosx = 1.0f / (sx1 - sx0);
			float oosy = 1.0f / (sy1 - sy0);

			int ix0 = deCeilFloatToInt32(sx0 - 0.5f);
			int ix1 = deCeilFloatToInt32(sx1 - 0.5f);
			int iy0 = deCeilFloatToInt32(sy0 - 0.5f);
			int iy1 = deCeilFloatToInt32(sy1 - 0.5f);

			int  v00 = (y * stride) + x;
			int  v01 = (y * stride) + x + 1;
			int  v10 = ((y + 1) * stride) + x;
			int  v11 = ((y + 1) * stride) + x + 1;
			Vec4 c00 = colors[v00];
			Vec4 c01 = colors[v01];
			Vec4 c10 = colors[v10];
			Vec4 c11 = colors[v11];

			//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);

			for (int iy = iy0; iy < iy1; iy++)
				for (int ix = ix0; ix < ix1; ix++)
				{
					DE_ASSERT(deInBounds32(ix, 0, width));
					DE_ASSERT(deInBounds32(iy, 0, height));

					float sfx = (float)ix + 0.5f;
					float sfy = (float)iy + 0.5f;
					float fx1 = deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
					float fy1 = deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);

					// Triangle quad interpolation.
					bool		tri   = fx1 + fy1 <= 1.0f;
					float		tx	= tri ? fx1 : (1.0f - fx1);
					float		ty	= tri ? fy1 : (1.0f - fy1);
					const Vec4& t0	= tri ? c00 : c11;
					const Vec4& t1	= tri ? c01 : c10;
					const Vec4& t2	= tri ? c10 : c01;
					Vec4		color = t0 + (t1 - t0) * tx + (t2 - t0) * ty;

					// Quantizing for 1-bit alpha
					if ((m_renderCtx.getRenderTarget().getPixelFormat().alphaBits) == 1)
						color.w() = deFloatRound(color.w());

					result.setPixel(ix, iy, toRGBA(color));
				}
		}
}

void ShaderRenderCase::computeFragmentReference(Surface& result, const QuadGrid& quadGrid)
{
	// Buffer info.
	int				  width	= result.getWidth();
	int				  height   = result.getHeight();
	bool			  hasAlpha = m_renderCtx.getRenderTarget().getPixelFormat().alphaBits > 0;
	ShaderEvalContext evalCtx(quadGrid);

	// Render.
	for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
		{
			float sx = ((float)x + 0.5f) / (float)width;
			float sy = ((float)y + 0.5f) / (float)height;

			evalCtx.reset(sx, sy);
			m_evaluator.evaluate(evalCtx);
			// Select either clear color or computed color based on discarded bit.
			Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;

			if (!hasAlpha)
				color.w() = 1.0f;

			// Quantizing for 1-bit alpha
			if ((m_renderCtx.getRenderTarget().getPixelFormat().alphaBits) == 1)
				color.w() = deFloatRound(color.w());

			result.setPixel(x, y, toRGBA(color));
		}
}

bool ShaderRenderCase::compareImages(const Surface& resImage, const Surface& refImage, float errorThreshold)
{
	return tcu::fuzzyCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", refImage, resImage,
							 errorThreshold, tcu::COMPARE_LOG_RESULT);
}

// Uniform name helpers.

const char* getIntUniformName(int number)
{
	switch (number)
	{
	case 0:
		return "ui_zero";
	case 1:
		return "ui_one";
	case 2:
		return "ui_two";
	case 3:
		return "ui_three";
	case 4:
		return "ui_four";
	case 5:
		return "ui_five";
	case 6:
		return "ui_six";
	case 7:
		return "ui_seven";
	case 8:
		return "ui_eight";
	case 101:
		return "ui_oneHundredOne";
	default:
		DE_ASSERT(false);
		return "";
	}
}

const char* getFloatUniformName(int number)
{
	switch (number)
	{
	case 0:
		return "uf_zero";
	case 1:
		return "uf_one";
	case 2:
		return "uf_two";
	case 3:
		return "uf_three";
	case 4:
		return "uf_four";
	case 5:
		return "uf_five";
	case 6:
		return "uf_six";
	case 7:
		return "uf_seven";
	case 8:
		return "uf_eight";
	default:
		DE_ASSERT(false);
		return "";
	}
}

const char* getFloatFractionUniformName(int number)
{
	switch (number)
	{
	case 1:
		return "uf_one";
	case 2:
		return "uf_half";
	case 3:
		return "uf_third";
	case 4:
		return "uf_fourth";
	case 5:
		return "uf_fifth";
	case 6:
		return "uf_sixth";
	case 7:
		return "uf_seventh";
	case 8:
		return "uf_eighth";
	default:
		DE_ASSERT(false);
		return "";
	}
}

void setupDefaultUniforms(const glu::RenderContext& context, deUint32 programID)
{
	const glw::Functions& gl = context.getFunctions();

	// Bool.
	struct BoolUniform
	{
		const char* name;
		bool		value;
	};
	static const BoolUniform s_boolUniforms[] = {
		{ "ub_true", true }, { "ub_false", false },
	};

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_boolUniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_boolUniforms[i].name);
		if (uniLoc != -1)
			gl.uniform1i(uniLoc, s_boolUniforms[i].value);
	}

	// BVec4.
	struct BVec4Uniform
	{
		const char* name;
		BVec4		value;
	};
	static const BVec4Uniform s_bvec4Uniforms[] = {
		{ "ub4_true", BVec4(true) }, { "ub4_false", BVec4(false) },
	};

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_bvec4Uniforms); i++)
	{
		const BVec4Uniform& uni = s_bvec4Uniforms[i];
		int					arr[4];
		arr[0]	 = (int)uni.value.x();
		arr[1]	 = (int)uni.value.y();
		arr[2]	 = (int)uni.value.z();
		arr[3]	 = (int)uni.value.w();
		int uniLoc = gl.getUniformLocation(programID, uni.name);
		if (uniLoc != -1)
			gl.uniform4iv(uniLoc, 1, &arr[0]);
	}

	// Int.
	struct IntUniform
	{
		const char* name;
		int			value;
	};
	static const IntUniform s_intUniforms[] = {
		{ "ui_minusOne", -1 },		{ "ui_zero", 0 }, { "ui_one", 1 }, { "ui_two", 2 },   { "ui_three", 3 },
		{ "ui_four", 4 },			{ "ui_five", 5 }, { "ui_six", 6 }, { "ui_seven", 7 }, { "ui_eight", 8 },
		{ "ui_oneHundredOne", 101 }
	};

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_intUniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_intUniforms[i].name);
		if (uniLoc != -1)
			gl.uniform1i(uniLoc, s_intUniforms[i].value);
	}

	// IVec2.
	struct IVec2Uniform
	{
		const char* name;
		IVec2		value;
	};
	static const IVec2Uniform s_ivec2Uniforms[] = { { "ui2_minusOne", IVec2(-1) }, { "ui2_zero", IVec2(0) },
													{ "ui2_one", IVec2(1) },	   { "ui2_two", IVec2(2) },
													{ "ui2_four", IVec2(4) },	  { "ui2_five", IVec2(5) } };

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_ivec2Uniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_ivec2Uniforms[i].name);
		if (uniLoc != -1)
			gl.uniform2iv(uniLoc, 1, s_ivec2Uniforms[i].value.getPtr());
	}

	// IVec3.
	struct IVec3Uniform
	{
		const char* name;
		IVec3		value;
	};
	static const IVec3Uniform s_ivec3Uniforms[] = { { "ui3_minusOne", IVec3(-1) }, { "ui3_zero", IVec3(0) },
													{ "ui3_one", IVec3(1) },	   { "ui3_two", IVec3(2) },
													{ "ui3_four", IVec3(4) },	  { "ui3_five", IVec3(5) } };

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_ivec3Uniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_ivec3Uniforms[i].name);
		if (uniLoc != -1)
			gl.uniform3iv(uniLoc, 1, s_ivec3Uniforms[i].value.getPtr());
	}

	// IVec4.
	struct IVec4Uniform
	{
		const char* name;
		IVec4		value;
	};
	static const IVec4Uniform s_ivec4Uniforms[] = { { "ui4_minusOne", IVec4(-1) }, { "ui4_zero", IVec4(0) },
													{ "ui4_one", IVec4(1) },	   { "ui4_two", IVec4(2) },
													{ "ui4_four", IVec4(4) },	  { "ui4_five", IVec4(5) } };

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_ivec4Uniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_ivec4Uniforms[i].name);
		if (uniLoc != -1)
			gl.uniform4iv(uniLoc, 1, s_ivec4Uniforms[i].value.getPtr());
	}

	// Float.
	struct FloatUniform
	{
		const char* name;
		float		value;
	};
	static const FloatUniform s_floatUniforms[] = {
		{ "uf_zero", 0.0f },		 { "uf_one", 1.0f },		  { "uf_two", 2.0f },
		{ "uf_three", 3.0f },		 { "uf_four", 4.0f },		  { "uf_five", 5.0f },
		{ "uf_six", 6.0f },			 { "uf_seven", 7.0f },		  { "uf_eight", 8.0f },
		{ "uf_half", 1.0f / 2.0f },  { "uf_third", 1.0f / 3.0f }, { "uf_fourth", 1.0f / 4.0f },
		{ "uf_fifth", 1.0f / 5.0f }, { "uf_sixth", 1.0f / 6.0f }, { "uf_seventh", 1.0f / 7.0f },
		{ "uf_eighth", 1.0f / 8.0f }
	};

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_floatUniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_floatUniforms[i].name);
		if (uniLoc != -1)
			gl.uniform1f(uniLoc, s_floatUniforms[i].value);
	}

	// Vec2.
	struct Vec2Uniform
	{
		const char* name;
		Vec2		value;
	};
	static const Vec2Uniform s_vec2Uniforms[] = {
		{ "uv2_minusOne", Vec2(-1.0f) }, { "uv2_zero", Vec2(0.0f) }, { "uv2_half", Vec2(0.5f) },
		{ "uv2_one", Vec2(1.0f) },		 { "uv2_two", Vec2(2.0f) },
	};

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_vec2Uniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_vec2Uniforms[i].name);
		if (uniLoc != -1)
			gl.uniform2fv(uniLoc, 1, s_vec2Uniforms[i].value.getPtr());
	}

	// Vec3.
	struct Vec3Uniform
	{
		const char* name;
		Vec3		value;
	};
	static const Vec3Uniform s_vec3Uniforms[] = {
		{ "uv3_minusOne", Vec3(-1.0f) }, { "uv3_zero", Vec3(0.0f) }, { "uv3_half", Vec3(0.5f) },
		{ "uv3_one", Vec3(1.0f) },		 { "uv3_two", Vec3(2.0f) },
	};

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_vec3Uniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_vec3Uniforms[i].name);
		if (uniLoc != -1)
			gl.uniform3fv(uniLoc, 1, s_vec3Uniforms[i].value.getPtr());
	}

	// Vec4.
	struct Vec4Uniform
	{
		const char* name;
		Vec4		value;
	};
	static const Vec4Uniform s_vec4Uniforms[] = {
		{ "uv4_minusOne", Vec4(-1.0f) },
		{ "uv4_zero", Vec4(0.0f) },
		{ "uv4_half", Vec4(0.5f) },
		{ "uv4_one", Vec4(1.0f) },
		{ "uv4_two", Vec4(2.0f) },
		{ "uv4_black", Vec4(0.0f, 0.0f, 0.0f, 1.0f) },
		{ "uv4_gray", Vec4(0.5f, 0.5f, 0.5f, 1.0f) },
		{ "uv4_white", Vec4(1.0f, 1.0f, 1.0f, 1.0f) },
	};

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_vec4Uniforms); i++)
	{
		int uniLoc = gl.getUniformLocation(programID, s_vec4Uniforms[i].name);
		if (uniLoc != -1)
			gl.uniform4fv(uniLoc, 1, s_vec4Uniforms[i].value.getPtr());
	}
}

} // deqp
