/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 2.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 Default vertex attribute test
 *//*--------------------------------------------------------------------*/

#include "es2fDefaultVertexAttributeTests.hpp"
#include "tcuVector.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuSurface.hpp"
#include "tcuTextureUtil.hpp"
#include "gluRenderContext.hpp"
#include "gluCallLogWrapper.hpp"
#include "gluShaderProgram.hpp"
#include "gluObjectWrapper.hpp"
#include "gluPixelTransfer.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "deMath.h"
#include "deStringUtil.hpp"
#include "deString.h"

#include <limits>

namespace deqp
{
namespace gles2
{
namespace Functional
{
namespace
{

static const int s_valueRange = 10;

static const char* const s_passThroughFragmentShaderSource =	"varying mediump vec4 v_color;\n"
																"void main (void)\n"
																"{\n"
																"	gl_FragColor = v_color;\n"
																"}\n";

template <typename T1, int S1, typename T2, int S2>
tcu::Vector<T1, S1> convertToTypeVec (const tcu::Vector<T2, S2>& v)
{
	tcu::Vector<T1, S1> retVal;

	for (int ndx = 0; ndx < S1; ++ndx)
		retVal[ndx] = T1(0);

	if (S1 == 4)
		retVal[3] = T1(1);

	for (int ndx = 0; ndx < de::min(S1, S2); ++ndx)
		retVal[ndx] = T1(v[ndx]);

	return retVal;
}

class FloatLoader
{
public:
	virtual				~FloatLoader	(void) {}

	// returns the value loaded
	virtual tcu::Vec4	load			(glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const = 0;
};

#define GEN_DIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME, VALUES)				\
	class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader						\
	{																					\
	public:																				\
		enum																			\
		{																				\
			NORMALIZING = 0,															\
		};																				\
		enum																			\
		{																				\
			COMPONENTS = (COMPS)														\
		};																				\
		typedef TYPE Type;																\
																						\
		tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const	\
		{																				\
			tcu::Vector<TYPE, COMPONENTS> value;										\
			value = convertToTypeVec<Type, COMPONENTS>(v);								\
																						\
			gl.glVertexAttrib ##COMPS ##TYPECODE VALUES;								\
			return convertToTypeVec<float, 4>(value);									\
		}																				\
																						\
		static const char* getCaseName (void)											\
		{																				\
			return CASENAME;															\
		}																				\
																						\
		static const char* getName (void)												\
		{																				\
			return "VertexAttrib" #COMPS #TYPECODE;										\
		}																				\
	}

#define GEN_INDIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME)						\
	class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader						\
	{																					\
	public:																				\
		enum																			\
		{																				\
			NORMALIZING = 0,															\
		};																				\
		enum																			\
		{																				\
			COMPONENTS = (COMPS)														\
		};																				\
		typedef TYPE Type;																\
																						\
		tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const	\
		{																				\
			tcu::Vector<TYPE, COMPONENTS> value;										\
			value = convertToTypeVec<Type, COMPONENTS>(v);								\
																						\
			gl.glVertexAttrib ##COMPS ##TYPECODE (index, value.getPtr());				\
			return convertToTypeVec<float, 4>(value);									\
		}																				\
																						\
		static const char* getCaseName (void)											\
		{																				\
			return CASENAME;															\
		}																				\
																						\
		static const char* getName (void)												\
		{																				\
			return "VertexAttrib" #COMPS #TYPECODE;										\
		}																				\
	}

GEN_DIRECT_FLOAT_LOADER(float, 1, f, "vertex_attrib_1f", (index, value.x()));
GEN_DIRECT_FLOAT_LOADER(float, 2, f, "vertex_attrib_2f", (index, value.x(), value.y()));
GEN_DIRECT_FLOAT_LOADER(float, 3, f, "vertex_attrib_3f", (index, value.x(), value.y(), value.z()));
GEN_DIRECT_FLOAT_LOADER(float, 4, f, "vertex_attrib_4f", (index, value.x(), value.y(), value.z(), value.w()));

GEN_INDIRECT_FLOAT_LOADER(float, 1, fv, "vertex_attrib_1fv");
GEN_INDIRECT_FLOAT_LOADER(float, 2, fv, "vertex_attrib_2fv");
GEN_INDIRECT_FLOAT_LOADER(float, 3, fv, "vertex_attrib_3fv");
GEN_INDIRECT_FLOAT_LOADER(float, 4, fv, "vertex_attrib_4fv");

class AttributeCase : public TestCase
{
									AttributeCase			(Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType);
public:
	template<typename LoaderType>
	static AttributeCase*			create					(Context& ctx, glu::DataType dataType);
									~AttributeCase			(void);

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

	glu::DataType					getTargetType			(void) const;
	std::string						genVertexSource			(void) const;
	bool							renderWithValue			(const tcu::Vec4& v);
	tcu::Vec4						computeColor			(const tcu::Vec4& value);
	bool							verifyUnicoloredBuffer	(const tcu::Surface& scene, const tcu::Vec4& refValue);

	const bool						m_normalizing;
	const bool						m_useNegativeValues;
	const char* const				m_funcName;
	const glu::DataType				m_dataType;
	const FloatLoader*				m_loader;
	glu::ShaderProgram*				m_program;
	deUint32						m_bufID;
	bool							m_allIterationsPassed;
	int								m_iteration;

	enum
	{
		RENDER_SIZE = 32
	};
};

AttributeCase::AttributeCase (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType)
	: TestCase				(ctx, name, desc)
	, m_normalizing			(normalizing)
	, m_useNegativeValues	(useNegative)
	, m_funcName			(funcName)
	, m_dataType			(dataType)
	, m_loader				(DE_NULL)
	, m_program				(DE_NULL)
	, m_bufID				(0)
	, m_allIterationsPassed	(true)
	, m_iteration			(0)
{
}

template<typename LoaderType>
AttributeCase* AttributeCase::create (Context& ctx, glu::DataType dataType)
{
	AttributeCase* retVal = new AttributeCase(ctx,
											  LoaderType::getCaseName(),
											  (std::string("Test ") + LoaderType::getName()).c_str(),
											  LoaderType::getName(),
											  LoaderType::NORMALIZING != 0,
											  std::numeric_limits<typename LoaderType::Type>::is_signed,
											  dataType);
	retVal->m_loader = new LoaderType();
	return retVal;
}

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

void AttributeCase::init (void)
{
	if (m_context.getRenderTarget().getWidth() < RENDER_SIZE || m_context.getRenderTarget().getHeight() < RENDER_SIZE)
		throw tcu::NotSupportedError("Render target must be at least " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE));

	// log test info

	{
		const float			maxRange		= (m_normalizing) ? (1.0f) : (s_valueRange);
		const float			minRange		= (m_useNegativeValues) ? (-maxRange) : (0.0f);

		m_testCtx.getLog()
			<< tcu::TestLog::Message
			<< "Loading attribute values using " << m_funcName << "\n"
			<< "Attribute type: " << glu::getDataTypeName(m_dataType) << "\n"
			<< "Attribute value range: [" << minRange << ", " << maxRange << "]"
			<< tcu::TestLog::EndMessage;
	}

	// gen shader and base quad

	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource()) << glu::FragmentSource(s_passThroughFragmentShaderSource));
	m_testCtx.getLog() << *m_program;
	if (!m_program->isOk())
		throw tcu::TestError("could not build program");

	{
		const tcu::Vec4 fullscreenQuad[] =
		{
			tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
			tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
			tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
			tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
		};

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

		gl.genBuffers(1, &m_bufID);
		gl.bindBuffer(GL_ARRAY_BUFFER, m_bufID);
		gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW);
		GLU_EXPECT_NO_ERROR(gl.getError(), "fill buffer");
	}
}

void AttributeCase::deinit (void)
{
	delete m_loader;
	m_loader = DE_NULL;

	delete m_program;
	m_program = DE_NULL;

	if (m_bufID)
	{
		m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_bufID);
		m_bufID = 0;
	}
}

AttributeCase::IterateResult AttributeCase::iterate (void)
{
	static const tcu::Vec4 testValues[] =
	{
		tcu::Vec4(0.0f, 0.5f, 0.2f, 1.0f),
		tcu::Vec4(0.1f, 0.7f, 1.0f, 0.6f),
		tcu::Vec4(0.4f, 0.2f, 0.0f, 0.5f),
		tcu::Vec4(0.5f, 0.0f, 0.9f, 0.1f),
		tcu::Vec4(0.6f, 0.2f, 0.2f, 0.9f),
		tcu::Vec4(0.9f, 1.0f, 0.0f, 0.0f),
		tcu::Vec4(1.0f, 0.5f, 0.3f, 0.8f),
	};

	const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", "Iteration " + de::toString(m_iteration+1) + "/" + de::toString(DE_LENGTH_OF_ARRAY(testValues)));

	// Test normalizing transfers with whole range, non-normalizing with up to s_valueRange
	const tcu::Vec4 testValue = ((m_useNegativeValues) ? (testValues[m_iteration] * 2.0f - tcu::Vec4(1.0f)) : (testValues[m_iteration])) * ((m_normalizing) ? (1.0f) : ((float)s_valueRange));

	if (!renderWithValue(testValue))
		m_allIterationsPassed = false;

	// continue

	if (++m_iteration < DE_LENGTH_OF_ARRAY(testValues))
		return CONTINUE;

	if (m_allIterationsPassed)
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	else
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected values");

	return STOP;
}

std::string AttributeCase::genVertexSource (void) const
{
	const int			vectorSize	= (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeScalarSize(m_dataType)) : (-1);
	const char* const	vectorType	= glu::getDataTypeName((glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) : (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) : (glu::TYPE_FLOAT));
	const int			components	= (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType));
	std::ostringstream	buf;

	buf <<	"attribute highp vec4 a_position;\n"
			"attribute highp " << glu::getDataTypeName(m_dataType) << " a_value;\n"
			"varying highp vec4 v_color;\n"
			"void main (void)\n"
			"{\n"
			"	gl_Position = a_position;\n"
			"\n";

	if (m_normalizing)
		buf << "	highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ");\n";
	else
		buf << "	highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ") / float(" << s_valueRange << ");\n";

	if (m_useNegativeValues)
		buf << "	highp " << vectorType << " positiveNormalizedValue = (normalizedValue + " << vectorType << "(1.0)) / 2.0;\n";
	else
		buf << "	highp " << vectorType << " positiveNormalizedValue = normalizedValue;\n";

	if (components == 1)
		buf << "	v_color = vec4(positiveNormalizedValue, 0.0, 0.0, 1.0);\n";
	else if (components == 2)
		buf << "	v_color = vec4(positiveNormalizedValue.xy, 0.0, 1.0);\n";
	else if (components == 3)
		buf << "	v_color = vec4(positiveNormalizedValue.xyz, 1.0);\n";
	else if (components == 4)
		buf << "	v_color = vec4((positiveNormalizedValue.xy + positiveNormalizedValue.zz) / 2.0, positiveNormalizedValue.w, 1.0);\n";
	else
		DE_ASSERT(DE_FALSE);

	buf << "}\n";

	return buf.str();
}

bool AttributeCase::renderWithValue (const tcu::Vec4& v)
{
	glu::CallLogWrapper	gl				(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());

	gl.enableLogging(true);

	const int			positionIndex	= gl.glGetAttribLocation(m_program->getProgram(), "a_position");
	const int			valueIndex		= gl.glGetAttribLocation(m_program->getProgram(), "a_value");
	tcu::Surface		dest			(RENDER_SIZE, RENDER_SIZE);
	tcu::Vec4			loadedValue;

	gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	gl.glClear(GL_COLOR_BUFFER_BIT);
	gl.glViewport(0, 0, RENDER_SIZE, RENDER_SIZE);
	GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");

	gl.glBindBuffer(GL_ARRAY_BUFFER, m_bufID);
	gl.glVertexAttribPointer(positionIndex, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
	gl.glEnableVertexAttribArray(positionIndex);
	GLU_EXPECT_NO_ERROR(gl.glGetError(), "position va");

	// transfer test value. Load to the second column in the matrix case
	loadedValue = m_loader->load(gl, (glu::isDataTypeMatrix(m_dataType)) ? (valueIndex + 1) : (valueIndex), v);
	GLU_EXPECT_NO_ERROR(gl.glGetError(), "default va");

	gl.glUseProgram(m_program->getProgram());
	gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	gl.glUseProgram(0);
	GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");

	glu::readPixels(m_context.getRenderContext(), 0, 0, dest.getAccess());

	// check whole result is colored correctly
	return verifyUnicoloredBuffer(dest, computeColor(loadedValue));
}

tcu::Vec4 AttributeCase::computeColor (const tcu::Vec4& value)
{
	const tcu::Vec4 normalizedValue			= value / ((m_normalizing) ? (1.0f) : ((float)s_valueRange));
	const tcu::Vec4 positiveNormalizedValue = ((m_useNegativeValues) ? ((normalizedValue + tcu::Vec4(1.0f)) / 2.0f) : (normalizedValue));
	const int		components				= (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType));

	if (components == 1)
		return tcu::Vec4(positiveNormalizedValue.x(), 0.0f, 0.0f, 1.0f);
	else if (components == 2)
		return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), 0.0f, 1.0f);
	else if (components == 3)
		return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), positiveNormalizedValue.z(), 1.0f);
	else if (components == 4)
		return tcu::Vec4((positiveNormalizedValue.x() + positiveNormalizedValue.z()) / 2.0f, (positiveNormalizedValue.y() + positiveNormalizedValue.z()) / 2.0f, positiveNormalizedValue.w(), 1.0f);
	else
		DE_ASSERT(DE_FALSE);

	return tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
}

bool AttributeCase::verifyUnicoloredBuffer (const tcu::Surface& scene, const tcu::Vec4& refValue)
{
	tcu::Surface	errorMask		(RENDER_SIZE, RENDER_SIZE);
	const tcu::RGBA	refColor		(refValue);
	const int		resultThreshold	= 2;
	const tcu::RGBA	colorThreshold	= m_context.getRenderTarget().getPixelFormat().getColorThreshold() * resultThreshold;
	bool			error			= false;

	tcu::RGBA		exampleColor;
	tcu::IVec2		examplePos;

	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());

	m_testCtx.getLog() << tcu::TestLog::Message << "Verifying rendered image. Expecting color " << refColor << ", threshold " << colorThreshold << tcu::TestLog::EndMessage;

	for (int y = 0; y < RENDER_SIZE; ++y)
	for (int x = 0; x < RENDER_SIZE; ++x)
	{
		const tcu::RGBA color = scene.getPixel(x, y);

		if (de::abs(color.getRed()   - refColor.getRed())   > colorThreshold.getRed()   ||
			de::abs(color.getGreen() - refColor.getGreen()) > colorThreshold.getGreen() ||
			de::abs(color.getBlue()  - refColor.getBlue())  > colorThreshold.getBlue())
		{
			// first error
			if (!error)
			{
				exampleColor = color;
				examplePos = tcu::IVec2(x, y);
			}

			error = true;
			errorMask.setPixel(x, y, tcu::RGBA::red());
		}
	}

	if (!error)
		m_testCtx.getLog() << tcu::TestLog::Message << "Rendered image is valid." << tcu::TestLog::EndMessage;
	else
	{
		m_testCtx.getLog()	<< tcu::TestLog::Message
							<< "Found invalid pixel(s).\n"
							<< "Pixel at (" << examplePos.x() << ", " << examplePos.y() << ") color: " << exampleColor
							<< tcu::TestLog::EndMessage
							<< tcu::TestLog::ImageSet("Result", "Render result")
							<< tcu::TestLog::Image("Result", "Result", scene)
							<< tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask)
							<< tcu::TestLog::EndImageSet;
	}

	return !error;
}

} // anonymous

DefaultVertexAttributeTests::DefaultVertexAttributeTests (Context& context)
	: TestCaseGroup(context, "default_vertex_attrib", "Test default vertex attributes")
{
}

DefaultVertexAttributeTests::~DefaultVertexAttributeTests (void)
{
}

void DefaultVertexAttributeTests::init (void)
{
	struct Target
	{
		const char*		name;
		glu::DataType	dataType;
		bool			reducedTestSets;	// !< use reduced coverage
	};

	static const Target floatTargets[] =
	{
		{ "float",	glu::TYPE_FLOAT,		false	},
		{ "vec2",	glu::TYPE_FLOAT_VEC2,	true	},
		{ "vec3",	glu::TYPE_FLOAT_VEC3,	true	},
		{ "vec4",	glu::TYPE_FLOAT_VEC4,	false	},
		{ "mat2",	glu::TYPE_FLOAT_MAT2,	true	},
		{ "mat3",	glu::TYPE_FLOAT_MAT3,	true	},
		{ "mat4",	glu::TYPE_FLOAT_MAT4,	false	},
	};

	// float targets

	for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(floatTargets); ++targetNdx)
	{
		tcu::TestCaseGroup* const	group	= new tcu::TestCaseGroup(m_testCtx, floatTargets[targetNdx].name, (std::string("test with ") + floatTargets[targetNdx].name).c_str());
		const bool					fullSet	= !floatTargets[targetNdx].reducedTestSets;

#define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, floatTargets[targetNdx].dataType))
#define ADD_REDUCED_CASE(X)	if (fullSet) ADD_CASE(X)

		ADD_CASE		(LoaderVertexAttrib1f);
		ADD_REDUCED_CASE(LoaderVertexAttrib2f);
		ADD_REDUCED_CASE(LoaderVertexAttrib3f);
		ADD_CASE		(LoaderVertexAttrib4f);

		ADD_CASE		(LoaderVertexAttrib1fv);
		ADD_REDUCED_CASE(LoaderVertexAttrib2fv);
		ADD_REDUCED_CASE(LoaderVertexAttrib3fv);
		ADD_CASE		(LoaderVertexAttrib4fv);

#undef ADD_CASE
#undef ADD_REDUCED_CASE

		addChild(group);
	}
}

} // Functional
} // gles2
} // deqp
