/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Default vertex attribute test
 *//*--------------------------------------------------------------------*/

#include "es3fDefaultVertexAttributeTests.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 gles3
{
namespace Functional
{
namespace
{

static const int s_valueRange = 10;

static const char* const s_passThroughFragmentShaderSource =	"#version 300 es\n"
																"layout(location = 0) out mediump vec4 fragColor;\n"
																"in mediump vec4 v_color;\n"
																"void main (void)\n"
																"{\n"
																"	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;										\
		}																				\
	}

#define GEN_DIRECT_INTEGER_LOADER(TYPE, COMPS, TYPECODE, CASENAME, VALUES)				\
	class LoaderVertexAttribI##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.glVertexAttribI ##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_INTEGER_LOADER(TYPE, COMPS, TYPECODE, CASENAME)					\
	class LoaderVertexAttribI##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.glVertexAttribI ##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");

GEN_DIRECT_INTEGER_LOADER(deInt32, 4, i, "vertex_attribi_4i", (index, value.x(), value.y(), value.z(), value.w()));
GEN_INDIRECT_INTEGER_LOADER(deInt32, 4, iv, "vertex_attribi_4iv");

GEN_DIRECT_INTEGER_LOADER(deUint32, 4, ui, "vertex_attribi_4ui", (index, value.x(), value.y(), value.z(), value.w()));
GEN_INDIRECT_INTEGER_LOADER(deUint32, 4, uiv, "vertex_attribi_4uiv");

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 <<	"#version 300 es\n"
			"in highp vec4 a_position;\n"
			"in highp " << glu::getDataTypeName(m_dataType) << " a_value;\n"
			"out 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	},
		{ "mat2x3",	glu::TYPE_FLOAT_MAT2X3,	true	},
		{ "mat2x4",	glu::TYPE_FLOAT_MAT2X4,	true	},
		{ "mat3",	glu::TYPE_FLOAT_MAT3,	true	},
		{ "mat3x2",	glu::TYPE_FLOAT_MAT3X2,	true	},
		{ "mat3x4",	glu::TYPE_FLOAT_MAT3X4,	true	},
		{ "mat4",	glu::TYPE_FLOAT_MAT4,	false	},
		{ "mat4x2",	glu::TYPE_FLOAT_MAT4X2,	true	},
		{ "mat4x3",	glu::TYPE_FLOAT_MAT4X3,	true	},
	};

	static const Target intTargets[] =
	{
		{ "int",	glu::TYPE_INT,			false	},
		{ "ivec2",	glu::TYPE_INT_VEC2,		true	},
		{ "ivec3",	glu::TYPE_INT_VEC3,		true	},
		{ "ivec4",	glu::TYPE_INT_VEC4,		false	},
	};

	static const Target uintTargets[] =
	{
		{ "uint",	glu::TYPE_UINT,			false	},
		{ "uvec2",	glu::TYPE_UINT_VEC2,	true	},
		{ "uvec3",	glu::TYPE_UINT_VEC3,	true	},
		{ "uvec4",	glu::TYPE_UINT_VEC4,	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);
	}

	// int targets

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

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

		ADD_CASE		(LoaderVertexAttribI4i);
		ADD_CASE		(LoaderVertexAttribI4iv);

#undef ADD_CASE

		addChild(group);
	}

	// uint targets

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

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

		ADD_CASE		(LoaderVertexAttribI4ui);
		ADD_CASE		(LoaderVertexAttribI4uiv);

#undef ADD_CASE

		addChild(group);
	}
}

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