/*-------------------------------------------------------------------------
 * 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 Buffer data upload tests.
 *//*--------------------------------------------------------------------*/

#include "es2fBufferWriteTests.hpp"
#include "es2fBufferTestUtil.hpp"
#include "tcuTestLog.hpp"
#include "gluStrUtil.hpp"
#include "deMemory.h"
#include "deString.h"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deMath.h"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"

#include <algorithm>
#include <list>

using std::set;
using std::vector;
using std::string;
using tcu::TestLog;
using tcu::IVec2;

namespace deqp
{
namespace gles2
{
namespace Functional
{

using namespace BufferTestUtil;

struct DataStoreSpec
{
	DataStoreSpec (void)
		: target	(0)
		, usage		(0)
		, size		(0)
	{
	}

	DataStoreSpec (deUint32 target_, deUint32 usage_, int size_)
		: target	(target_)
		, usage		(usage_)
		, size		(size_)
	{
	}

	deUint32	target;
	deUint32	usage;
	int			size;
};

struct DataStoreSpecVecBuilder
{
	std::vector<DataStoreSpec>& list;

	DataStoreSpecVecBuilder (std::vector<DataStoreSpec>& list_)
		: list(list_)
	{
	}

	DataStoreSpecVecBuilder& operator<< (const DataStoreSpec& spec)
	{
		list.push_back(spec);
		return *this;
	}
};

struct RangeVecBuilder
{
	std::vector<tcu::IVec2>& list;

	RangeVecBuilder (std::vector<tcu::IVec2>& list_)
		: list(list_)
	{
	}

	RangeVecBuilder& operator<< (const tcu::IVec2& vec)
	{
		list.push_back(vec);
		return *this;
	}
};

template<typename Iterator>
static bool isRangeListValid (Iterator begin, Iterator end)
{
	if (begin != end)
	{
		// Fetch first.
		tcu::IVec2 prev = *begin;
		++begin;

		for (; begin != end; ++begin)
		{
			tcu::IVec2 cur = *begin;
			if (cur.x() <= prev.x() || cur.x() <= prev.x()+prev.y())
				return false;
			prev = cur;
		}
	}

	return true;
}

inline bool rangesIntersect (const tcu::IVec2& a, const tcu::IVec2& b)
{
	return de::inRange(a.x(), b.x(), b.x()+b.y()) || de::inRange(a.x()+a.y(), b.x(), b.x()+b.y()) ||
		   de::inRange(b.x(), a.x(), a.x()+a.y()) || de::inRange(b.x()+b.y(), a.x(), a.x()+a.y());
}

inline tcu::IVec2 unionRanges (const tcu::IVec2& a, const tcu::IVec2& b)
{
	DE_ASSERT(rangesIntersect(a, b));

	int start	= de::min(a.x(), b.x());
	int end		= de::max(a.x()+a.y(), b.x()+b.y());

	return tcu::IVec2(start, end-start);
}

//! Updates range list (start, len) with a new range.
std::vector<tcu::IVec2> addRangeToList (const std::vector<tcu::IVec2>& oldList, const tcu::IVec2& newRange)
{
	DE_ASSERT(newRange.y() > 0);

	std::vector<tcu::IVec2>					newList;
	std::vector<tcu::IVec2>::const_iterator	oldListIter	= oldList.begin();

	// Append ranges that end before the new range.
	for (; oldListIter != oldList.end() && oldListIter->x()+oldListIter->y() < newRange.x(); ++oldListIter)
		newList.push_back(*oldListIter);

	// Join any ranges that intersect new range
	{
		tcu::IVec2 curRange = newRange;
		while (oldListIter != oldList.end() && rangesIntersect(curRange, *oldListIter))
		{
			curRange = unionRanges(curRange, *oldListIter);
			++oldListIter;
		}

		newList.push_back(curRange);
	}

	// Append remaining ranges.
	for (; oldListIter != oldList.end(); oldListIter++)
		newList.push_back(*oldListIter);

	DE_ASSERT(isRangeListValid(newList.begin(), newList.end()));

	return newList;
}

class BasicBufferDataCase : public BufferCase
{
public:
	BasicBufferDataCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, VerifyType verify)
		: BufferCase	(context, name, desc)
		, m_target		(target)
		, m_usage		(usage)
		, m_size		(size)
		, m_verify		(verify)
	{
	}

	IterateResult iterate (void)
	{
		const deUint32			dataSeed	= deStringHash(getName()) ^ 0x125;
		BufferVerifier			verifier	(m_context, m_verify);
		ReferenceBuffer			refBuf;
		bool					isOk		= false;

		refBuf.setSize(m_size);
		fillWithRandomBytes(refBuf.getPtr(), m_size, dataSeed);

		deUint32 buf = genBuffer();
		glBindBuffer(m_target, buf);
		glBufferData(m_target, m_size, refBuf.getPtr(), m_usage);

		checkError();

		isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_size);

		deleteBuffer(buf);

		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
								isOk ? "Pass"				: "Buffer verification failed");
		return STOP;
	}

private:
	deUint32		m_target;
	deUint32		m_usage;
	int				m_size;
	VerifyType		m_verify;
};

class RecreateBufferDataStoreCase : public BufferCase
{
public:
	RecreateBufferDataStoreCase (Context& context, const char* name, const char* desc, const DataStoreSpec* specs, int numSpecs, VerifyType verify)
		: BufferCase(context, name, desc)
		, m_specs	(specs, specs+numSpecs)
		, m_verify	(verify)
	{
	}

	IterateResult iterate (void)
	{
		const deUint32			baseSeed	= deStringHash(getName()) ^ 0xbeef;
		BufferVerifier			verifier	(m_context, m_verify);
		ReferenceBuffer			refBuf;
		const deUint32			buf			= genBuffer();

		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");

		for (vector<DataStoreSpec>::const_iterator spec = m_specs.begin(); spec != m_specs.end(); spec++)
		{
			bool iterOk = false;

			refBuf.setSize(spec->size);
			fillWithRandomBytes(refBuf.getPtr(), spec->size, baseSeed ^ deInt32Hash(spec->size+spec->target+spec->usage));

			glBindBuffer(spec->target, buf);
			glBufferData(spec->target, spec->size, refBuf.getPtr(), spec->usage);

			checkError();

			iterOk = verifier.verify(buf, refBuf.getPtr(), 0, spec->size);

			if (!iterOk)
			{
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
				break;
			}
		}

		deleteBuffer(buf);
		return STOP;
	}

private:
	std::vector<DataStoreSpec>	m_specs;
	VerifyType					m_verify;
};

class BasicBufferSubDataCase : public BufferCase
{
public:
	BasicBufferSubDataCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, int subDataOffs, int subDataSize, VerifyType verify)
		: BufferCase	(context, name, desc)
		, m_target		(target)
		, m_usage		(usage)
		, m_size		(size)
		, m_subDataOffs	(subDataOffs)
		, m_subDataSize	(subDataSize)
		, m_verify		(verify)
	{
		DE_ASSERT(de::inBounds(subDataOffs, 0, size) && de::inRange(subDataOffs+subDataSize, 0, size));
	}

	IterateResult iterate (void)
	{
		const deUint32			dataSeed	= deStringHash(getName());
		BufferVerifier			verifier	(m_context, m_verify);
		ReferenceBuffer			refBuf;
		bool					isOk		= false;

		refBuf.setSize(m_size);

		deUint32 buf = genBuffer();
		glBindBuffer(m_target, buf);

		// Initialize with glBufferData()
		fillWithRandomBytes(refBuf.getPtr(), m_size, dataSeed ^ 0x80354f);
		glBufferData(m_target, m_size, refBuf.getPtr(), m_usage);
		checkError();

		// Re-specify part of buffer
		fillWithRandomBytes(refBuf.getPtr()+m_subDataOffs, m_subDataSize, dataSeed ^ 0xfac425c);
		glBufferSubData(m_target, m_subDataOffs, m_subDataSize, refBuf.getPtr()+m_subDataOffs);

		isOk = verifier.verify(buf, refBuf.getPtr(), 0, m_size);

		deleteBuffer(buf);

		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
								isOk ? "Pass"				: "Buffer verification failed");
		return STOP;
	}

private:
	deUint32		m_target;
	deUint32		m_usage;
	int				m_size;
	int				m_subDataOffs;
	int				m_subDataSize;
	VerifyType		m_verify;
};

class SubDataToUndefinedCase : public BufferCase
{
public:
	SubDataToUndefinedCase (Context& context, const char* name, const char* desc, deUint32 target, deUint32 usage, int size, const tcu::IVec2* ranges, int numRanges, VerifyType verify)
		: BufferCase	(context, name, desc)
		, m_target		(target)
		, m_usage		(usage)
		, m_size		(size)
		, m_ranges		(ranges, ranges+numRanges)
		, m_verify		(verify)
	{
	}

	IterateResult iterate (void)
	{
		const deUint32			dataSeed	= deStringHash(getName());
		BufferVerifier			verifier	(m_context, m_verify);
		ReferenceBuffer			refBuf;
		bool					isOk		= true;
		std::vector<tcu::IVec2>	definedRanges;

		refBuf.setSize(m_size);

		deUint32 buf = genBuffer();
		glBindBuffer(m_target, buf);

		// Initialize storage with glBufferData()
		glBufferData(m_target, m_size, DE_NULL, m_usage);
		checkError();

		// Fill specified ranges with glBufferSubData()
		for (vector<tcu::IVec2>::const_iterator range = m_ranges.begin(); range != m_ranges.end(); range++)
		{
			fillWithRandomBytes(refBuf.getPtr()+range->x(), range->y(), dataSeed ^ deInt32Hash(range->x()+range->y()));
			glBufferSubData(m_target, range->x(), range->y(), refBuf.getPtr()+range->x());

			// Mark range as defined
			definedRanges = addRangeToList(definedRanges, *range);
		}

		// Verify defined parts
		for (vector<tcu::IVec2>::const_iterator range = definedRanges.begin(); range != definedRanges.end(); range++)
		{
			if (!verifier.verify(buf, refBuf.getPtr(), range->x(), range->y()))
				isOk = false;
		}

		deleteBuffer(buf);

		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
								isOk ? "Pass"				: "Buffer verification failed");
		return STOP;
	}

private:
	deUint32				m_target;
	deUint32				m_usage;
	int						m_size;
	std::vector<tcu::IVec2>	m_ranges;
	VerifyType				m_verify;
};

class RandomBufferWriteCase : public BufferCase
{
public:
	RandomBufferWriteCase (Context& context, const char* name, const char* desc, deUint32 seed)
		: BufferCase(context, name, desc)
		, m_seed		(seed)
		, m_verifier	(DE_NULL)
		, m_buffer		(0)
		, m_curSize		(0)
		, m_iterNdx		(0)
	{
	}

	~RandomBufferWriteCase (void)
	{
		delete m_verifier;
	}

	void init (void)
	{
		BufferCase::init();

		m_iterNdx	= 0;
		m_buffer	= genBuffer();
		m_curSize	= 0;
		m_verifier	= new BufferVerifier(m_context, VERIFY_AS_VERTEX_ARRAY);

		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	}

	void deinit (void)
	{
		deleteBuffer(m_buffer);
		m_refBuffer.setSize(0);

		delete m_verifier;
		m_verifier = DE_NULL;

		BufferCase::deinit();
	}

	IterateResult iterate (void)
	{
		// Parameters.
		const int	numIterations				= 5;
		const int	uploadsPerIteration			= 7;
		const int	minSize						= 12;
		const int	maxSize						= 32*1024;
		const float	respecifyProbability		= 0.07f;
		const float	respecifyDataProbability	= 0.2f;

		static const deUint32 bufferTargets[] =
		{
			GL_ARRAY_BUFFER,
			GL_ELEMENT_ARRAY_BUFFER
		};

		static const deUint32 usageHints[] =
		{
			GL_STREAM_DRAW,
			GL_STATIC_DRAW,
			GL_DYNAMIC_DRAW,
		};

		bool		iterOk					= true;
		deUint32	curBoundTarget			= GL_NONE;
		de::Random	rnd						(m_seed ^ deInt32Hash(m_iterNdx) ^ 0xacf92e);

		m_testCtx.getLog() << TestLog::Section(string("Iteration") + de::toString(m_iterNdx+1), string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(numIterations));

		for (int uploadNdx = 0; uploadNdx < uploadsPerIteration; uploadNdx++)
		{
			const deUint32	target		= bufferTargets[rnd.getInt(0, DE_LENGTH_OF_ARRAY(bufferTargets)-1)];
			const bool		respecify	= m_curSize == 0 || rnd.getFloat() < respecifyProbability;

			if (target != curBoundTarget)
			{
				glBindBuffer(target, m_buffer);
				curBoundTarget = target;
			}

			if (respecify)
			{
				const int		size			= rnd.getInt(minSize, maxSize);
				const deUint32	hint			= usageHints[rnd.getInt(0, DE_LENGTH_OF_ARRAY(usageHints)-1)];
				const bool		fillWithData	= rnd.getFloat() < respecifyDataProbability;

				m_refBuffer.setSize(size);
				if (fillWithData)
					fillWithRandomBytes(m_refBuffer.getPtr(), size, rnd.getUint32());

				glBufferData(target, size, fillWithData ? m_refBuffer.getPtr() : DE_NULL, hint);

				m_validRanges.clear();
				if (fillWithData)
					m_validRanges.push_back(tcu::IVec2(0, size));

				m_curSize = size;
			}
			else
			{
				// \note Non-uniform size distribution.
				const int	size	= de::clamp(deRoundFloatToInt32((float)m_curSize * deFloatPow(rnd.getFloat(0.0f, 0.7f), 3.0f)), minSize, m_curSize);
				const int	offset	= rnd.getInt(0, m_curSize-size);

				fillWithRandomBytes(m_refBuffer.getPtr()+offset, size, rnd.getUint32());
				glBufferSubData(target, offset, size, m_refBuffer.getPtr()+offset);

				m_validRanges = addRangeToList(m_validRanges, tcu::IVec2(offset, size));
			}
		}

		// Check error.
		{
			deUint32 err = glGetError();
			if (err != GL_NO_ERROR)
				throw tcu::TestError(string("Got ") + glu::getErrorStr(err).toString());
		}

		// Verify valid ranges.
		for (vector<IVec2>::const_iterator range = m_validRanges.begin(); range != m_validRanges.end(); range++)
		{
			if (!m_verifier->verify(m_buffer, m_refBuffer.getPtr(), range->x(), range->y()))
			{
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer verification failed");
				iterOk = false;
				break;
			}
		}

		m_testCtx.getLog() << TestLog::EndSection;

		DE_ASSERT(iterOk || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS);

		m_iterNdx += 1;
		return (iterOk && m_iterNdx < numIterations) ? CONTINUE : STOP;
	}

private:
	deUint32				m_seed;

	BufferVerifier*			m_verifier;
	deUint32				m_buffer;
	ReferenceBuffer			m_refBuffer;
	std::vector<tcu::IVec2>	m_validRanges;
	int						m_curSize;
	int						m_iterNdx;
};

BufferWriteTests::BufferWriteTests (Context& context)
	: TestCaseGroup(context, "write", "Buffer data upload tests")
{
}

BufferWriteTests::~BufferWriteTests (void)
{
}

void BufferWriteTests::init (void)
{
	static const deUint32 bufferTargets[] =
	{
		GL_ARRAY_BUFFER,
		GL_ELEMENT_ARRAY_BUFFER
	};

	static const deUint32 usageHints[] =
	{
		GL_STREAM_DRAW,
		GL_STATIC_DRAW,
		GL_DYNAMIC_DRAW
	};

	static const struct
	{
		const char*	name;
		VerifyType	verify;
	} verifyTypes[] =
	{
		{ "vertex_array",	VERIFY_AS_VERTEX_ARRAY	},
		{ "index_array",	VERIFY_AS_INDEX_ARRAY	}
	};

	// .basic
	{
		tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic upload with glBufferData()");
		addChild(basicGroup);

		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
		{
			for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageHints); usageNdx++)
			{
				const deUint32		target	= bufferTargets[targetNdx];
				const deUint32		usage	= usageHints[usageNdx];
				const int			size	= 1020;
				const VerifyType	verify	= VERIFY_AS_VERTEX_ARRAY;
				const string		name	= string(getBufferTargetName(target)) + "_" + getUsageHintName(usage);

				basicGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify));
			}
		}
	}

	// .use
	{
		tcu::TestCaseGroup* const useGroup = new tcu::TestCaseGroup(m_testCtx, "use", "Buffer uses");
		addChild(useGroup);

		for (int verifyNdx = 0; verifyNdx < DE_LENGTH_OF_ARRAY(verifyTypes); verifyNdx++)
		{
			tcu::TestCaseGroup* const verifyGroup = new tcu::TestCaseGroup(m_testCtx, verifyTypes[verifyNdx].name, "");
			useGroup->addChild(verifyGroup);

			for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
			{
				const deUint32		target	= bufferTargets[targetNdx];
				const deUint32		usage	= GL_STATIC_DRAW;
				const int			size	= 763;
				const VerifyType	verify	= verifyTypes[verifyNdx].verify;
				const string		name	= getBufferTargetName(target);

				verifyGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify));
			}
		}
	}

	// .recreate_store
	{
		tcu::TestCaseGroup* const recreateStoreGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_store", "Data store recreate using glBufferData()");
		addChild(recreateStoreGroup);

#define RECREATE_STORE_CASE(NAME, DESC, SPECLIST)																											\
		do {																																				\
			std::vector<DataStoreSpec> specs;																												\
			DataStoreSpecVecBuilder builder(specs);																											\
			builder SPECLIST;																																\
			recreateStoreGroup->addChild(new RecreateBufferDataStoreCase(m_context, #NAME, DESC, &specs[0], (int)specs.size(), VERIFY_AS_VERTEX_ARRAY));	\
		} while (deGetFalse())

		RECREATE_STORE_CASE(identical_1, "Recreate with identical parameters",
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996));

		RECREATE_STORE_CASE(identical_2, "Recreate with identical parameters",
			<< DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72)
			<< DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72)
			<< DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 72));

		RECREATE_STORE_CASE(different_target_1, "Recreate with different target",
			<< DataStoreSpec(GL_ARRAY_BUFFER,				GL_STATIC_DRAW, 504)
			<< DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER,		GL_STATIC_DRAW, 504));

		RECREATE_STORE_CASE(different_target_2, "Recreate with different target",
			<< DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER,		GL_STATIC_DRAW, 716)
			<< DataStoreSpec(GL_ARRAY_BUFFER,				GL_STATIC_DRAW, 716)
			<< DataStoreSpec(GL_ELEMENT_ARRAY_BUFFER,		GL_STATIC_DRAW, 716));

		RECREATE_STORE_CASE(different_usage, "Recreate with different usage",
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	1644)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW,	1644)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STATIC_DRAW,	1644)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	1644));

		RECREATE_STORE_CASE(different_size, "Recreate with different size",
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	1024)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	12)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	3327)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	92)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	12379)
			<< DataStoreSpec(GL_ARRAY_BUFFER, GL_STREAM_DRAW,	571));

#undef RECREATE_STORE_CASE

		// Random cases.
		{
			const int			numRandomCases		= 4;
			const int			numUploadsPerCase	= 10;
			const int			minSize				= 12;
			const int			maxSize				= 65536;
			const VerifyType	verify				= VERIFY_AS_VERTEX_ARRAY;
			de::Random			rnd					(23921);

			for (int caseNdx = 0; caseNdx < numRandomCases; caseNdx++)
			{
				vector<DataStoreSpec> specs(numUploadsPerCase);

				for (vector<DataStoreSpec>::iterator spec = specs.begin(); spec != specs.end(); spec++)
				{
					spec->target	= bufferTargets[rnd.getInt(0, DE_LENGTH_OF_ARRAY(bufferTargets)-1)];
					spec->usage		= usageHints[rnd.getInt(0, DE_LENGTH_OF_ARRAY(usageHints)-1)];
					spec->size		= rnd.getInt(minSize, maxSize);
				}

				recreateStoreGroup->addChild(new RecreateBufferDataStoreCase(m_context, (string("random_") + de::toString(caseNdx+1)).c_str(), "", &specs[0], (int)specs.size(), verify));
			}
		}
	}

	// .basic_subdata
	{
		tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic_subdata", "Basic glBufferSubData() usage");
		addChild(basicGroup);

		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(bufferTargets); targetNdx++)
		{
			for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageHints); usageNdx++)
			{
				const deUint32		target	= bufferTargets[targetNdx];
				const deUint32		usage	= usageHints[usageNdx];
				const int			size	= 1020;
				const VerifyType	verify	= VERIFY_AS_VERTEX_ARRAY;
				const string		name	= string(getBufferTargetName(target)) + "_" + getUsageHintName(usage);

				basicGroup->addChild(new BasicBufferDataCase(m_context, name.c_str(), "", target, usage, size, verify));
			}
		}
	}

	// .partial_specify
	{
		tcu::TestCaseGroup* const partialSpecifyGroup = new tcu::TestCaseGroup(m_testCtx, "partial_specify", "Partial buffer data specification with glBufferSubData()");
		addChild(partialSpecifyGroup);

#define PARTIAL_SPECIFY_CASE(NAME, DESC, TARGET, USAGE, SIZE, RANGELIST)																									\
		do {																																								\
			std::vector<tcu::IVec2> ranges;																																	\
			RangeVecBuilder builder(ranges);																																\
			builder RANGELIST;																																				\
			partialSpecifyGroup->addChild(new SubDataToUndefinedCase(m_context, #NAME, DESC, TARGET, USAGE, SIZE, &ranges[0], (int)ranges.size(), VERIFY_AS_VERTEX_ARRAY));	\
		} while (deGetFalse())

		PARTIAL_SPECIFY_CASE(whole_1, "Whole buffer specification with single glBufferSubData()", GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996,
			<< IVec2(0, 996));
		PARTIAL_SPECIFY_CASE(whole_2, "Whole buffer specification with two calls", GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1728,
			<< IVec2(729, 999)
			<< IVec2(0, 729));
		PARTIAL_SPECIFY_CASE(whole_3, "Whole buffer specification with three calls", GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1944,
			<< IVec2(0, 421)
			<< IVec2(1421, 523)
			<< IVec2(421, 1000));
		PARTIAL_SPECIFY_CASE(whole_4, "Whole buffer specification with three calls", GL_ELEMENT_ARRAY_BUFFER, GL_STREAM_DRAW, 1200,
			<< IVec2(0, 500)
			<< IVec2(429, 200)
			<< IVec2(513, 687));

		PARTIAL_SPECIFY_CASE(low_1, "Low part of buffer specified with single call", GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 1000,
			<< IVec2(0, 513));
		PARTIAL_SPECIFY_CASE(low_2, "Low part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STATIC_DRAW, 996,
			<< IVec2(0, 98)
			<< IVec2(98, 511));
		PARTIAL_SPECIFY_CASE(low_3, "Low part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1200,
			<< IVec2(0, 591)
			<< IVec2(371, 400));

		PARTIAL_SPECIFY_CASE(high_1, "High part of buffer specified with single call", GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 1000,
			<< IVec2(500, 500));
		PARTIAL_SPECIFY_CASE(high_2, "High part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1200,
			<< IVec2(600, 123)
			<< IVec2(723, 477));
		PARTIAL_SPECIFY_CASE(high_3, "High part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_STREAM_DRAW, 1200,
			<< IVec2(600, 200)
			<< IVec2(601, 599));

		PARTIAL_SPECIFY_CASE(middle_1, "Middle part of buffer specified with single call", GL_ELEMENT_ARRAY_BUFFER, GL_STREAM_DRAW, 2500,
			<< IVec2(1000, 799));
		PARTIAL_SPECIFY_CASE(middle_2, "Middle part of buffer specified with two calls", GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, 2500,
			<< IVec2(780, 220)
			<< IVec2(1000, 500));
		PARTIAL_SPECIFY_CASE(middle_3, "Middle part of buffer specified with two calls", GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 2500,
			<< IVec2(780, 321)
			<< IVec2(1000, 501));

#undef PARTIAL_SPECIFY_CASE
	}

	// .random
	{
		tcu::TestCaseGroup* const randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Randomized buffer data cases");
		addChild(randomGroup);

		for (int i = 0; i < 10; i++)
			randomGroup->addChild(new RandomBufferWriteCase(m_context, de::toString(i).c_str(), "", deInt32Hash(i)));
	}
}

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