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

#include "es2sVertexArrayTests.hpp"
#include "glsVertexArrayTests.hpp"

#include "glwEnums.hpp"

using namespace deqp::gls;

namespace deqp
{
namespace gles2
{
namespace Stress
{
namespace
{

template<class T>
static std::string typeToString (T t)
{
	std::stringstream strm;
	strm << t;
	return strm.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};
	int					counts[]		= {1, 256};
	int					strides[]		= {17};
	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++)
			{
				for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
				{
					const int	componentCount	= 2;
					const int	stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * componentCount : strides[strideNdx]);
					const bool	aligned			= (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
					MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
																	Array::OUTPUTTYPE_VEC2,
																	Array::STORAGE_BUFFER,
																	usages[usageNdx],
																	componentCount,
																	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);

					std::string name = spec.getName();

					if (!aligned)
						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)
{
	// Test strides with different input types, component counts and storage, Usage(?)
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED};
	Array::Storage		storages[]		= {Array::STORAGE_BUFFER};
	int					counts[]		= {1, 256};
	int					strides[]		= {17};

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		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 int	stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * componentCount : strides[strideNdx]);
						const bool	bufferUnaligned	= (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) != 0;

						MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
																		Array::OUTPUTTYPE_VEC4,
																		storages[storageNdx],
																		Array::USAGE_DYNAMIC_DRAW,
																		componentCount,
																		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);

						std::string name = spec.getName();
						if (bufferUnaligned)
							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 atribute different first values")
{
}

SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
{
}

void SingleVertexArrayFirstTests::init (void)
{
	// Test strides with different input types, component counts and storage, Usage(?)
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_FIXED};
	int					counts[]		= {5, 256};
	int					firsts[]		= {6, 24};
	int					offsets[]		= {1, 17};
	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.

	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		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 int	stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
						const bool	aligned	= ((stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0) && (offsets[offsetNdx] % Array::inputTypeSize(inputTypes[inputTypeNdx]) == 0);

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

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

						std::string name = Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
						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 strides with different input types, component counts and storage, Usage(?)
	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_FIXED};
	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 inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
	{
		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 int	stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
					const bool	aligned	= ((stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0) && ((offsets[offsetNdx] % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0);

					MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
																	Array::OUTPUTTYPE_VEC2,
																	Array::STORAGE_BUFFER,
																	Array::USAGE_DYNAMIC_DRAW,
																	2,
																	offsets[offsetNdx],
																	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);

					std::string name = spec.getName();
					if (!aligned)
						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
				}
			}
		}
	}
}

} // anonymous

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

VertexArrayTests::~VertexArrayTests (void)
{
}

void VertexArrayTests::init (void)
{
	tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "single_attribute", "Single attribute");
	addChild(group);

	// .single_attribute
	{
		group->addChild(new SingleVertexArrayStrideTests(m_context));
		group->addChild(new SingleVertexArrayUsageTests(m_context));
		group->addChild(new SingleVertexArrayOffsetTests(m_context));
		group->addChild(new SingleVertexArrayFirstTests(m_context));
	}
}

} // Stress
} // gles2
} // deqp
