/*-------------------------------------------------------------------------
 * 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 Vertex array and buffer tests
 *//*--------------------------------------------------------------------*/

#include "es3fVertexArrayTest.hpp"
#include "glsVertexArrayTests.hpp"

#include <sstream>

using namespace deqp::gls;

namespace deqp
{
namespace gles3
{
namespace Functional
{

class SingleVertexArrayUsageGroup : public TestCaseGroup
{
public:
									SingleVertexArrayUsageGroup		(Context& context, Array::Usage usage);
	virtual							~SingleVertexArrayUsageGroup	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayUsageGroup		(const SingleVertexArrayUsageGroup& other);
	SingleVertexArrayUsageGroup&	operator=						(const SingleVertexArrayUsageGroup& other);

	Array::Usage					m_usage;
};

SingleVertexArrayUsageGroup::SingleVertexArrayUsageGroup (Context& context, Array::Usage usage)
	: TestCaseGroup	(context, Array::usageTypeToString(usage).c_str(), Array::usageTypeToString(usage).c_str())
	, m_usage		(usage)
{
}

SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup (void)
{
}

template<class T>
static std::string typeToString (T t)
{
	std::stringstream strm;
	strm << t;
	return strm.str();
}

void SingleVertexArrayUsageGroup::init (void)
{
	int					counts[]		= {1, 256};
	int					strides[]		= {0, -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE};

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
		{
			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
			{
				const int			stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
				const bool			aligned	= (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
				const std::string	name	= "stride" + typeToString(stride) + "_" + Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_quads" + typeToString(counts[countNdx]);

				MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
																Array::OUTPUTTYPE_VEC2,
																Array::STORAGE_BUFFER,
																m_usage,
																2,
																0,
																stride,
																false,
																GLValue::getMinValue(inputTypes[inputTypeNdx]),
																GLValue::getMaxValue(inputTypes[inputTypeNdx]));

				MultiVertexArrayTest::Spec spec;
				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
				spec.drawCount	= counts[countNdx];
				spec.first		= 0;
				spec.arrays.push_back(arraySpec);

				if (aligned)
					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
			}
		}
	}
}

class SingleVertexArrayUsageTests : public TestCaseGroup
{
public:
									SingleVertexArrayUsageTests		(Context& context);
	virtual							~SingleVertexArrayUsageTests	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayUsageTests		(const SingleVertexArrayUsageTests& other);
	SingleVertexArrayUsageTests&	operator=						(const SingleVertexArrayUsageTests& other);
};

SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context)
	: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
{
}

SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void)
{
}

void SingleVertexArrayUsageTests::init (void)
{
	// Test usage
	Array::Usage		usages[]		= { Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW, Array::USAGE_STATIC_COPY, Array::USAGE_STREAM_COPY, Array::USAGE_DYNAMIC_COPY, Array::USAGE_STATIC_READ, Array::USAGE_STREAM_READ, Array::USAGE_DYNAMIC_READ };
	for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
	{
		addChild(new SingleVertexArrayUsageGroup(m_context, usages[usageNdx]));
	}
}

class SingleVertexArrayStrideGroup : public TestCaseGroup
{
public:
									SingleVertexArrayStrideGroup	(Context& context, Array::InputType type);
	virtual							~SingleVertexArrayStrideGroup	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayStrideGroup	(const SingleVertexArrayStrideGroup& other);
	SingleVertexArrayStrideGroup&	operator=						(const SingleVertexArrayStrideGroup& other);

	Array::InputType				m_type;
};

SingleVertexArrayStrideGroup::SingleVertexArrayStrideGroup (Context& context, Array::InputType type)
	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
	, m_type		(type)
{
}

SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup (void)
{
}

void SingleVertexArrayStrideGroup::init (void)
{
	Array::Storage		storages[]		= {Array::STORAGE_USER, Array::STORAGE_BUFFER};
	int					counts[]		= {1, 256};
	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.

	for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
	{
		for (int componentCount = 2; componentCount < 5; componentCount++)
		{
			for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
			{
				for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
				{
					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (16) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
					const bool	bufferUnaligned	= (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % alignment) != 0;

					std::string name = Array::storageToString(storages[storageNdx]) + "_stride" + typeToString(stride) + "_components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);

					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
						continue;

					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
																	Array::OUTPUTTYPE_VEC4,
																	storages[storageNdx],
																	Array::USAGE_DYNAMIC_DRAW,
																	componentCount,
																	0,
																	stride,
																	false,
																	GLValue::getMinValue(m_type),
																	GLValue::getMaxValue(m_type));

					MultiVertexArrayTest::Spec spec;
					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
					spec.drawCount	= counts[countNdx];
					spec.first		= 0;
					spec.arrays.push_back(arraySpec);

					if (!bufferUnaligned)
						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
				}
			}
		}
	}
}

class SingleVertexArrayStrideTests : public TestCaseGroup
{
public:
									SingleVertexArrayStrideTests	(Context& context);
	virtual							~SingleVertexArrayStrideTests	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayStrideTests	(const SingleVertexArrayStrideTests& other);
	SingleVertexArrayStrideTests&	operator=						(const SingleVertexArrayStrideTests& other);
};

SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context)
	: TestCaseGroup(context, "strides", "Single stride vertex atribute")
{
}

SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void)
{
}

void SingleVertexArrayStrideTests::init (void)
{
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED, Array::INPUTTYPE_INT_2_10_10_10 };

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		addChild(new SingleVertexArrayStrideGroup(m_context, inputTypes[inputTypeNdx]));
	}
}

class SingleVertexArrayFirstGroup : public TestCaseGroup
{
public:
									SingleVertexArrayFirstGroup	(Context& context, Array::InputType type);
	virtual							~SingleVertexArrayFirstGroup	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayFirstGroup	(const SingleVertexArrayFirstGroup& other);
	SingleVertexArrayFirstGroup&	operator=						(const SingleVertexArrayFirstGroup& other);
	Array::InputType				m_type;
};

SingleVertexArrayFirstGroup::SingleVertexArrayFirstGroup (Context& context, Array::InputType type)
	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
	, m_type		(type)
{
}

SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup (void)
{
}

void SingleVertexArrayFirstGroup::init (void)
{
	int					counts[]		= {5, 256};
	int					firsts[]		= {6, 24};
	int					offsets[]		= {1, 16, 17};
	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.

	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
	{
		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
		{
			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
			{
				for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++)
				{
					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
					const int	componentCount	= (packed) ? (4) : (2);
					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (8) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
					const bool	aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
					std::string name			= "first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);

					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
																	Array::OUTPUTTYPE_VEC2,
																	Array::STORAGE_BUFFER,
																	Array::USAGE_DYNAMIC_DRAW,
																	componentCount,
																	offsets[offsetNdx],
																	stride,
																	false,
																	GLValue::getMinValue(m_type),
																	GLValue::getMaxValue(m_type));

					MultiVertexArrayTest::Spec spec;
					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
					spec.drawCount	= counts[countNdx];
					spec.first		= firsts[firstNdx];
					spec.arrays.push_back(arraySpec);

					if (aligned)
						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
				}
			}
		}
	}
}

class SingleVertexArrayFirstTests : public TestCaseGroup
{
public:
									SingleVertexArrayFirstTests	(Context& context);
	virtual							~SingleVertexArrayFirstTests	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayFirstTests	(const SingleVertexArrayFirstTests& other);
	SingleVertexArrayFirstTests&	operator=						(const SingleVertexArrayFirstTests& other);
};

SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context)
	: TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays")
{
}

SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
{
}

void SingleVertexArrayFirstTests::init (void)
{
	// Test offset with different input types, component counts and storage, Usage(?)
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10 };

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		addChild(new SingleVertexArrayFirstGroup(m_context, inputTypes[inputTypeNdx]));
	}
}

class SingleVertexArrayOffsetGroup : public TestCaseGroup
{
public:
									SingleVertexArrayOffsetGroup	(Context& context, Array::InputType type);
	virtual							~SingleVertexArrayOffsetGroup	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayOffsetGroup	(const SingleVertexArrayOffsetGroup& other);
	SingleVertexArrayOffsetGroup&	operator=						(const SingleVertexArrayOffsetGroup& other);
	Array::InputType				m_type;
};

SingleVertexArrayOffsetGroup::SingleVertexArrayOffsetGroup (Context& context, Array::InputType type)
	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
	, m_type		(type)
{
}

SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup (void)
{
}

void SingleVertexArrayOffsetGroup::init (void)
{
	int					counts[]		= {1, 256};
	int					offsets[]		= {1, 4, 17, 32};
	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.

	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
	{
		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
		{
			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
			{
				const bool			packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
				const int			componentCount	= (packed) ? (4) : (2);
				const int			stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(m_type) * componentCount : strides[strideNdx]);
				const int			alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
				const bool			aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
				const std::string	name			= "offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);

				MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
																Array::OUTPUTTYPE_VEC2,
																Array::STORAGE_BUFFER,
																Array::USAGE_DYNAMIC_DRAW,
																componentCount,
																offsets[offsetNdx],
																stride,
																false,
																GLValue::getMinValue(m_type),
																GLValue::getMaxValue(m_type));

				MultiVertexArrayTest::Spec spec;
				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
				spec.drawCount	= counts[countNdx];
				spec.first		= 0;
				spec.arrays.push_back(arraySpec);

				if (aligned)
					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
			}
		}
	}
}

class SingleVertexArrayOffsetTests : public TestCaseGroup
{
public:
									SingleVertexArrayOffsetTests	(Context& context);
	virtual							~SingleVertexArrayOffsetTests	(void);

	virtual void					init							(void);

private:
									SingleVertexArrayOffsetTests	(const SingleVertexArrayOffsetTests& other);
	SingleVertexArrayOffsetTests&	operator=						(const SingleVertexArrayOffsetTests& other);
};

SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context)
	: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
{
}

SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void)
{
}

void SingleVertexArrayOffsetTests::init (void)
{
	// Test offset with different input types, component counts and storage, Usage(?)
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10 };

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		addChild(new SingleVertexArrayOffsetGroup(m_context, inputTypes[inputTypeNdx]));
	}
}

class SingleVertexArrayNormalizeGroup : public TestCaseGroup
{
public:
										SingleVertexArrayNormalizeGroup		(Context& context, Array::InputType type);
	virtual								~SingleVertexArrayNormalizeGroup	(void);

	virtual void						init								(void);

private:
										SingleVertexArrayNormalizeGroup		(const SingleVertexArrayNormalizeGroup& other);
	SingleVertexArrayNormalizeGroup&	operator=							(const SingleVertexArrayNormalizeGroup& other);
	Array::InputType					m_type;
};

SingleVertexArrayNormalizeGroup::SingleVertexArrayNormalizeGroup (Context& context, Array::InputType type)
	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
	, m_type		(type)
{
}

SingleVertexArrayNormalizeGroup::~SingleVertexArrayNormalizeGroup (void)
{
}

void SingleVertexArrayNormalizeGroup::init (void)
{
	int					counts[]		= {1, 256};

	for (int componentCount = 2; componentCount < 5; componentCount++)
	{
		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
		{
			if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
				continue;

			std::string name = "components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);

			MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
															Array::OUTPUTTYPE_VEC4,
															Array::STORAGE_USER,
															Array::USAGE_DYNAMIC_DRAW,
															componentCount,
															0,
															0,
															true,
															GLValue::getMinValue(m_type),
															GLValue::getMaxValue(m_type));

			MultiVertexArrayTest::Spec spec;
			spec.primitive	= Array::PRIMITIVE_TRIANGLES;
			spec.drawCount	= counts[countNdx];
			spec.first		= 0;
			spec.arrays.push_back(arraySpec);

			addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
		}
	}
}

class SingleVertexArrayNormalizeTests : public TestCaseGroup
{
public:
										SingleVertexArrayNormalizeTests		(Context& context);
	virtual								~SingleVertexArrayNormalizeTests	(void);

	virtual void						init								(void);

private:
										SingleVertexArrayNormalizeTests		(const SingleVertexArrayNormalizeTests& other);
	SingleVertexArrayNormalizeTests&	operator=							(const SingleVertexArrayNormalizeTests& other);
};

SingleVertexArrayNormalizeTests::SingleVertexArrayNormalizeTests (Context& context)
	: TestCaseGroup(context, "normalize", "Single normalize vertex atribute")
{
}

SingleVertexArrayNormalizeTests::~SingleVertexArrayNormalizeTests (void)
{
}

void SingleVertexArrayNormalizeTests::init (void)
{
	// Test normalization with different input types, component counts and storage
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT, Array::INPUTTYPE_HALF , Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10, Array::INPUTTYPE_INT_2_10_10_10 };

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		addChild(new SingleVertexArrayNormalizeGroup(m_context, inputTypes[inputTypeNdx]));
	}
}

class SingleVertexArrayOutputTypeGroup : public TestCaseGroup
{
public:
										SingleVertexArrayOutputTypeGroup	(Context& context, Array::InputType type);
	virtual								~SingleVertexArrayOutputTypeGroup	(void);

	virtual void						init								(void);

private:
										SingleVertexArrayOutputTypeGroup	(const SingleVertexArrayOutputTypeGroup& other);
	SingleVertexArrayOutputTypeGroup&	operator=							(const SingleVertexArrayOutputTypeGroup& other);
	Array::InputType					m_type;
};

SingleVertexArrayOutputTypeGroup::SingleVertexArrayOutputTypeGroup (Context& context, Array::InputType type)
	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
	, m_type		(type)
{
}

SingleVertexArrayOutputTypeGroup::~SingleVertexArrayOutputTypeGroup (void)
{
}

void SingleVertexArrayOutputTypeGroup::init (void)
{
	Array::OutputType	outputTypes[]	= {Array::OUTPUTTYPE_VEC2, Array::OUTPUTTYPE_VEC3, Array::OUTPUTTYPE_VEC4, Array::OUTPUTTYPE_IVEC2, Array::OUTPUTTYPE_IVEC3, Array::OUTPUTTYPE_IVEC4, Array::OUTPUTTYPE_UVEC2, Array::OUTPUTTYPE_UVEC3, Array::OUTPUTTYPE_UVEC4 };
	Array::Storage		storages[]		= {Array::STORAGE_USER};
	int					counts[]		= {1, 256};

	for (int outputTypeNdx = 0; outputTypeNdx < DE_LENGTH_OF_ARRAY(outputTypes); outputTypeNdx++)
	{
		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
		{
			for (int componentCount = 2; componentCount < 5; componentCount++)
			{
				for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
				{
					std::string name = "components" + typeToString(componentCount) + "_" + Array::outputTypeToString(outputTypes[outputTypeNdx]) + "_quads" + typeToString(counts[countNdx]);

					const bool inputIsSignedInteger		= m_type == Array::INPUTTYPE_INT || m_type == Array::INPUTTYPE_SHORT || m_type == Array::INPUTTYPE_BYTE;
					const bool inputIsUnignedInteger	= m_type == Array::INPUTTYPE_UNSIGNED_INT || m_type == Array::INPUTTYPE_UNSIGNED_SHORT || m_type == Array::INPUTTYPE_UNSIGNED_BYTE;
					const bool outputIsSignedInteger	= outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC2 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC3 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC4;
					const bool outputIsUnsignedInteger	= outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC2 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC3 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC4;

					// If input type is float type and output type is int type skip
					if ((m_type == Array::INPUTTYPE_FLOAT ||  m_type == Array::INPUTTYPE_HALF || m_type == Array::INPUTTYPE_FIXED) && (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
						continue;

					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
						continue;

					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
						continue;

					// Loading signed data as unsigned causes undefined values and vice versa
					if (inputIsSignedInteger && outputIsUnsignedInteger)
						continue;
					if (inputIsUnignedInteger && outputIsSignedInteger)
						continue;

					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
																	outputTypes[outputTypeNdx],
																	storages[storageNdx],
																	Array::USAGE_DYNAMIC_DRAW,
																	componentCount,
																	0,
																	0,
																	false,
																	GLValue::getMinValue(m_type),
																	GLValue::getMaxValue(m_type));

					MultiVertexArrayTest::Spec spec;
					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
					spec.drawCount	= counts[countNdx];
					spec.first		= 0;
					spec.arrays.push_back(arraySpec);

					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
				}
			}
		}
	}
}

class SingleVertexArrayOutputTypeTests : public TestCaseGroup
{
public:
										SingleVertexArrayOutputTypeTests	(Context& context);
	virtual								~SingleVertexArrayOutputTypeTests	(void);

	virtual void						init								(void);

private:
										SingleVertexArrayOutputTypeTests	(const SingleVertexArrayOutputTypeTests& other);
	SingleVertexArrayOutputTypeTests&	operator=							(const SingleVertexArrayOutputTypeTests& other);
};

SingleVertexArrayOutputTypeTests::SingleVertexArrayOutputTypeTests (Context& context)
	: TestCaseGroup(context, "output_types", "Single output type vertex atribute")
{
}

SingleVertexArrayOutputTypeTests::~SingleVertexArrayOutputTypeTests (void)
{
}

void SingleVertexArrayOutputTypeTests::init (void)
{
	// Test output types with different input types, component counts and storage, Usage?, Precision?, float?
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT, Array::INPUTTYPE_HALF, Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10, Array::INPUTTYPE_INT_2_10_10_10 };

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		addChild(new SingleVertexArrayOutputTypeGroup(m_context, inputTypes[inputTypeNdx]));
	}
}


class SingleVertexArrayTestGroup : public TestCaseGroup
{
public:
									SingleVertexArrayTestGroup	(Context& context);
	virtual							~SingleVertexArrayTestGroup	(void);

	virtual void					init						(void);

private:
									SingleVertexArrayTestGroup	(const SingleVertexArrayTestGroup& other);
	SingleVertexArrayTestGroup&		operator=					(const SingleVertexArrayTestGroup& other);
};

SingleVertexArrayTestGroup::SingleVertexArrayTestGroup (Context& context)
	: TestCaseGroup(context, "single_attribute", "Single vertex atribute")
{
}

SingleVertexArrayTestGroup::~SingleVertexArrayTestGroup (void)
{
}

void SingleVertexArrayTestGroup::init (void)
{
	addChild(new SingleVertexArrayStrideTests(m_context));
	addChild(new SingleVertexArrayNormalizeTests(m_context));
	addChild(new SingleVertexArrayOutputTypeTests(m_context));
	addChild(new SingleVertexArrayUsageTests(m_context));
	addChild(new SingleVertexArrayOffsetTests(m_context));
	addChild(new SingleVertexArrayFirstTests(m_context));
}

class MultiVertexArrayCountTests : public TestCaseGroup
{
public:
									MultiVertexArrayCountTests	(Context& context);
	virtual							~MultiVertexArrayCountTests	(void);

	virtual void					init						(void);

private:
									MultiVertexArrayCountTests	(const MultiVertexArrayCountTests& other);
	MultiVertexArrayCountTests&		operator=					(const MultiVertexArrayCountTests& other);

	std::string						getTestName					(const MultiVertexArrayTest::Spec& spec);
};

MultiVertexArrayCountTests::MultiVertexArrayCountTests (Context& context)
	: TestCaseGroup(context, "attribute_count", "Attribute counts")
{
}

MultiVertexArrayCountTests::~MultiVertexArrayCountTests (void)
{
}

std::string MultiVertexArrayCountTests::getTestName (const MultiVertexArrayTest::Spec& spec)
{
	std::stringstream name;
	name
		<< spec.arrays.size();

	return name.str();
}

void MultiVertexArrayCountTests::init (void)
{
	// Test attribute counts
	int arrayCounts[] = {2, 3, 4, 5, 6, 7, 8};

	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
	{
		MultiVertexArrayTest::Spec spec;

		spec.primitive	= Array::PRIMITIVE_TRIANGLES;
		spec.drawCount	= 256;
		spec.first		= 0;

		for (int arrayNdx = 0; arrayNdx < arrayCounts[arrayCountNdx]; arrayNdx++)
		{
			MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
															Array::OUTPUTTYPE_VEC2,
															Array::STORAGE_USER,
															Array::USAGE_DYNAMIC_DRAW,
															2,
															0,
															0,
															false,
															GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
															GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));

			spec.arrays.push_back(arraySpec);
		}

		std::string name = getTestName(spec);
		std::string desc = getTestName(spec);

		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
	}
}

class MultiVertexArrayStorageTests : public TestCaseGroup
{
public:
									MultiVertexArrayStorageTests	(Context& context);
	virtual							~MultiVertexArrayStorageTests	(void);

	virtual void					init							(void);

private:
									MultiVertexArrayStorageTests	(const MultiVertexArrayStorageTests& other);
	MultiVertexArrayStorageTests&	operator=						(const MultiVertexArrayStorageTests& other);

	void							addStorageCases					(MultiVertexArrayTest::Spec spec, int depth);
	std::string						getTestName						(const MultiVertexArrayTest::Spec& spec);
};

MultiVertexArrayStorageTests::MultiVertexArrayStorageTests (Context& context)
	: TestCaseGroup(context, "storage", "Attribute storages")
{
}

MultiVertexArrayStorageTests::~MultiVertexArrayStorageTests (void)
{
}

std::string MultiVertexArrayStorageTests::getTestName (const MultiVertexArrayTest::Spec& spec)
{
	std::stringstream name;
	name
		<< spec.arrays.size();

	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
	{
		name
			<< "_"
			<< Array::storageToString(spec.arrays[arrayNdx].storage);
	}

	return name.str();
}

void MultiVertexArrayStorageTests::addStorageCases (MultiVertexArrayTest::Spec spec, int depth)
{
	if (depth == 0)
	{
		// Skip trivial case, used elsewhere
		bool ok = false;
		for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
		{
			if (spec.arrays[arrayNdx].storage != Array::STORAGE_USER)
			{
				ok = true;
				break;
			}
		}

		if (!ok)
			return;

		std::string name = getTestName(spec);
		std::string desc = getTestName(spec);

		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
		return;
	}

	Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER};
	for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
	{
		MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
														Array::OUTPUTTYPE_VEC2,
														storages[storageNdx],
														Array::USAGE_DYNAMIC_DRAW,
														2,
														0,
														0,
														false,
														GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
														GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));

		MultiVertexArrayTest::Spec _spec = spec;
		_spec.arrays.push_back(arraySpec);
		addStorageCases(_spec, depth-1);
	}
}


void MultiVertexArrayStorageTests::init (void)
{
	// Test different storages
	int arrayCounts[] = {3};

	MultiVertexArrayTest::Spec spec;

	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
	spec.drawCount	= 256;
	spec.first		= 0;

	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
		addStorageCases(spec, arrayCounts[arrayCountNdx]);
}

class MultiVertexArrayStrideTests : public TestCaseGroup
{
public:
									MultiVertexArrayStrideTests		(Context& context);
	virtual							~MultiVertexArrayStrideTests	(void);

	virtual void					init							(void);

private:
									MultiVertexArrayStrideTests		(const MultiVertexArrayStrideTests& other);
	MultiVertexArrayStrideTests&	operator=						(const MultiVertexArrayStrideTests& other);

	void							addStrideCases					(MultiVertexArrayTest::Spec spec, int depth);
	std::string						getTestName						(const MultiVertexArrayTest::Spec& spec);
};

MultiVertexArrayStrideTests::MultiVertexArrayStrideTests (Context& context)
	: TestCaseGroup(context, "stride", "Strides")
{
}

MultiVertexArrayStrideTests::~MultiVertexArrayStrideTests (void)
{
}

std::string MultiVertexArrayStrideTests::getTestName (const MultiVertexArrayTest::Spec& spec)
{
	std::stringstream name;

	name
		<< spec.arrays.size();

	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
	{
		name
			<< "_"
			<< Array::inputTypeToString(spec.arrays[arrayNdx].inputType)
			<< spec.arrays[arrayNdx].componentCount << "_"
			<< spec.arrays[arrayNdx].stride;
	}

	return name.str();
}

void MultiVertexArrayStrideTests::init (void)
{
	// Test different strides, with multiple arrays, input types??
	int arrayCounts[] = {3};

	MultiVertexArrayTest::Spec spec;

	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
	spec.drawCount	= 256;
	spec.first		= 0;

	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
		addStrideCases(spec, arrayCounts[arrayCountNdx]);
}

void MultiVertexArrayStrideTests::addStrideCases (MultiVertexArrayTest::Spec spec, int depth)
{
	if (depth == 0)
	{
		std::string name = getTestName(spec);
		std::string desc = getTestName(spec);
		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
		return;
	}

	int strides[]	= {0, -1, 17, 32};

	for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
	{
		const int componentCount = 2;
		MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
														Array::OUTPUTTYPE_VEC2,
														Array::STORAGE_USER,
														Array::USAGE_DYNAMIC_DRAW,
														componentCount,
														0,
														(strides[strideNdx] >= 0 ? strides[strideNdx] : componentCount * Array::inputTypeSize(Array::INPUTTYPE_FLOAT)),
														false,
														GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
														GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));

		MultiVertexArrayTest::Spec _spec = spec;
		_spec.arrays.push_back(arraySpec);
		addStrideCases(_spec, depth-1);
	}
}

class MultiVertexArrayOutputTests : public TestCaseGroup
{
public:
										MultiVertexArrayOutputTests		(Context& context);
	virtual								~MultiVertexArrayOutputTests	(void);

	virtual void						init								(void);

private:
										MultiVertexArrayOutputTests		(const MultiVertexArrayOutputTests& other);
	MultiVertexArrayOutputTests&	operator=							(const MultiVertexArrayOutputTests& other);

	void								addInputTypeCases					(MultiVertexArrayTest::Spec spec, int depth);
	std::string							getTestName							(const MultiVertexArrayTest::Spec& spec);
};

MultiVertexArrayOutputTests::MultiVertexArrayOutputTests (Context& context)
	: TestCaseGroup(context, "input_types", "input types")
{
}

MultiVertexArrayOutputTests::~MultiVertexArrayOutputTests (void)
{
}

std::string MultiVertexArrayOutputTests::getTestName (const MultiVertexArrayTest::Spec& spec)
{
	std::stringstream name;

	name
		<< spec.arrays.size();

	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
	{
		name
			<< "_"
			<< Array::inputTypeToString(spec.arrays[arrayNdx].inputType)
			<< spec.arrays[arrayNdx].componentCount << "_"
			<< Array::outputTypeToString(spec.arrays[arrayNdx].outputType);
	}

	return name.str();
}

void MultiVertexArrayOutputTests::init (void)
{
	// Test different input types, with multiple arrays
	int arrayCounts[] = {3};

	MultiVertexArrayTest::Spec spec;

	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
	spec.drawCount	= 256;
	spec.first		= 0;

	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
		addInputTypeCases(spec, arrayCounts[arrayCountNdx]);
}

void MultiVertexArrayOutputTests::addInputTypeCases (MultiVertexArrayTest::Spec spec, int depth)
{
	if (depth == 0)
	{
		std::string name = getTestName(spec);
		std::string desc = getTestName(spec);
		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
		return;
	}

	Array::InputType inputTypes[] = {Array::INPUTTYPE_FIXED, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT};
	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
														Array::OUTPUTTYPE_VEC2,
														Array::STORAGE_USER,
														Array::USAGE_DYNAMIC_DRAW,
														2,
														0,
														0,
														false,
														GLValue::getMinValue(inputTypes[inputTypeNdx]),
														GLValue::getMaxValue(inputTypes[inputTypeNdx]));

		MultiVertexArrayTest::Spec _spec = spec;
		_spec.arrays.push_back(arraySpec);
		addInputTypeCases(_spec, depth-1);
	}
}

class MultiVertexArrayTestGroup : public TestCaseGroup
{
public:
									MultiVertexArrayTestGroup	(Context& context);
	virtual							~MultiVertexArrayTestGroup	(void);

	virtual void					init						(void);

private:
									MultiVertexArrayTestGroup	(const MultiVertexArrayTestGroup& other);
	MultiVertexArrayTestGroup&		operator=					(const MultiVertexArrayTestGroup& other);
};

MultiVertexArrayTestGroup::MultiVertexArrayTestGroup (Context& context)
	: TestCaseGroup(context, "multiple_attributes", "Multiple vertex atributes")
{
}

MultiVertexArrayTestGroup::~MultiVertexArrayTestGroup (void)
{
}

void MultiVertexArrayTestGroup::init (void)
{
	addChild(new MultiVertexArrayCountTests(m_context));
	addChild(new MultiVertexArrayStorageTests(m_context));
	addChild(new MultiVertexArrayStrideTests(m_context));
	addChild(new MultiVertexArrayOutputTests(m_context));
}

VertexArrayTestGroup::VertexArrayTestGroup (Context& context)
	: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
{
}

VertexArrayTestGroup::~VertexArrayTestGroup (void)
{
}

void VertexArrayTestGroup::init (void)
{
	addChild(new SingleVertexArrayTestGroup(m_context));
	addChild(new MultiVertexArrayTestGroup(m_context));
}

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