/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) 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 Parametrized, long-running stress case.
 *
 * \todo [2013-06-27 nuutti] Do certain things in a cleaner and less
 *							 confusing way, such as the "redundant buffer
 *							 factor" thing in LongStressCase.
 *//*--------------------------------------------------------------------*/

#include "glsLongStressCase.hpp"
#include "tcuTestLog.hpp"
#include "tcuCommandLine.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVector.hpp"
#include "tcuVectorUtil.hpp"
#include "glsTextureTestUtil.hpp"
#include "gluPixelTransfer.hpp"
#include "gluTextureUtil.hpp"
#include "tcuStringTemplate.hpp"
#include "gluStrUtil.hpp"
#include "gluShaderProgram.hpp"
#include "deRandom.hpp"
#include "deStringUtil.hpp"
#include "deString.h"
#include "deSharedPtr.hpp"
#include "deClock.h"

#include "glw.h"

#include <limits>
#include <vector>
#include <iomanip>
#include <map>
#include <iomanip>

using tcu::TestLog;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::IVec2;
using tcu::IVec3;
using tcu::IVec4;
using tcu::TextureLevel;
using tcu::TextureFormat;
using tcu::ConstPixelBufferAccess;
using tcu::CubeFace;
using de::SharedPtr;
using de::Random;
using de::toString;

using std::vector;
using std::string;
using std::map;

namespace deqp
{
namespace gls
{

using glu::TextureTestUtil::TextureType;
using glu::TextureTestUtil::TEXTURETYPE_2D;
using glu::TextureTestUtil::TEXTURETYPE_CUBE;

static const float Mi = (float)(1<<20);

static const deUint32 bufferUsages[] =
{
	GL_STATIC_DRAW,
	GL_STREAM_DRAW,
	GL_DYNAMIC_DRAW,

	GL_STATIC_READ,
	GL_STREAM_READ,
	GL_DYNAMIC_READ,

	GL_STATIC_COPY,
	GL_STREAM_COPY,
	GL_DYNAMIC_COPY
};

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

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

	GL_COPY_READ_BUFFER,
	GL_COPY_WRITE_BUFFER,
	GL_PIXEL_PACK_BUFFER,
	GL_PIXEL_UNPACK_BUFFER,
	GL_TRANSFORM_FEEDBACK_BUFFER,
	GL_UNIFORM_BUFFER
};

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

static inline int computePixelStore (const TextureFormat& format)
{
	const int pixelSize = format.getPixelSize();
	if (deIsPowerOfTwo32(pixelSize))
		return de::min(pixelSize, 8);
	else
		return 1;
}

static inline int getNumIterations (const tcu::TestContext& testCtx, const int defaultNumIterations)
{
	const int cmdLineVal = testCtx.getCommandLine().getTestIterationCount();
	return cmdLineVal == 0 ? defaultNumIterations : cmdLineVal;
}

static inline float triangleArea (const Vec2& a, const Vec2& b, const Vec2& c)
{
	const Vec2 ab = b-a;
	const Vec2 ac = c-a;
	return 0.5f * tcu::length(ab.x()*ac.y() - ab.y()*ac.x());
}

static inline string mangleShaderNames (const string& source, const string& manglingSuffix)
{
	map<string, string> m;
	m["NS"] = manglingSuffix;
	return tcu::StringTemplate(source.c_str()).specialize(m);
}

template <typename T, int N>
static inline T randomChoose (Random& rnd, const T (&arr)[N])
{
	return rnd.choose<T>(DE_ARRAY_BEGIN(arr), DE_ARRAY_END(arr));
}

static inline int nextDivisible (const int x, const int div)
{
	DE_ASSERT(x >= 0);
	DE_ASSERT(div >= 1);
	return x == 0 ? 0 : x-1 + div - (x-1) % div;
}

static inline string getTimeStr (const deUint64 seconds)
{
	const deUint64		m = seconds / 60;
	const deUint64		h = m / 60;
	const deUint64		d = h / 24;
	std::ostringstream	res;

	res << d << "d " << h%24 << "h " << m%60 << "m " << seconds%60 << "s";
	return res.str();
}

static inline string probabilityStr (const float prob)
{
	return prob == 0.0f ? "never"	:
		   prob == 1.0f ? "ALWAYS"	:
		   de::floatToString(prob*100.0f, 0) + "%";
}

static inline deUint32 randomBufferTarget (Random& rnd, const bool isGLES3)
{
	return isGLES3 ? randomChoose(rnd, bufferTargets) : randomChoose(rnd, bufferTargetsGLES2);
}

static inline deUint32 randomBufferUsage (Random& rnd, const bool isGLES3)
{
	return isGLES3 ? randomChoose(rnd, bufferUsages) : randomChoose(rnd, bufferUsagesGLES2);
}

static inline deUint32 cubeFaceToGLFace (tcu::CubeFace face)
{
	switch (face)
	{
		case tcu::CUBEFACE_NEGATIVE_X: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
		case tcu::CUBEFACE_POSITIVE_X: return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
		case tcu::CUBEFACE_NEGATIVE_Y: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
		case tcu::CUBEFACE_POSITIVE_Y: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
		case tcu::CUBEFACE_NEGATIVE_Z: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
		case tcu::CUBEFACE_POSITIVE_Z: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
		default:
			DE_ASSERT(false);
			return GL_NONE;
	}
}

#if defined(DE_DEBUG)
static inline bool isMatchingGLInternalFormat (const deUint32 internalFormat, const TextureFormat& texFormat)
{
	switch (internalFormat)
	{
		// Unsized formats.

		case GL_RGBA:				return texFormat.order == TextureFormat::RGBA &&
											   (texFormat.type == TextureFormat::UNORM_INT8			||
												texFormat.type == TextureFormat::UNORM_SHORT_4444	||
												texFormat.type == TextureFormat::UNORM_SHORT_5551);

		case GL_RGB:				return texFormat.order == TextureFormat::RGB &&
											   (texFormat.type == TextureFormat::UNORM_INT8			||
												texFormat.type == TextureFormat::UNORM_SHORT_565);

		case GL_LUMINANCE_ALPHA:	return texFormat.order == TextureFormat::LA && texFormat.type == TextureFormat::UNORM_INT8;
		case GL_LUMINANCE:			return texFormat.order == TextureFormat::L && texFormat.type == TextureFormat::UNORM_INT8;
		case GL_ALPHA:				return texFormat.order == TextureFormat::A && texFormat.type == TextureFormat::UNORM_INT8;

		// Sized formats.

		default:					return glu::mapGLInternalFormat(internalFormat) == texFormat;
	}
}
#endif // DE_DEBUG

static inline bool compileShader (const deUint32 shaderGL)
{
	glCompileShader(shaderGL);

	int success = GL_FALSE;
	glGetShaderiv(shaderGL, GL_COMPILE_STATUS, &success);

	return success == GL_TRUE;
}

static inline bool linkProgram (const deUint32 programGL)
{
	glLinkProgram(programGL);

	int success = GL_FALSE;
	glGetProgramiv(programGL, GL_LINK_STATUS, &success);

	return success == GL_TRUE;
}

static inline string getShaderInfoLog (const deUint32 shaderGL)
{
	int				infoLogLen = 0;
	vector<char>	infoLog;
	glGetShaderiv(shaderGL, GL_INFO_LOG_LENGTH, &infoLogLen);
	infoLog.resize(infoLogLen+1);
	glGetShaderInfoLog(shaderGL, (int)infoLog.size(), DE_NULL, &infoLog[0]);
	return &infoLog[0];
}

static inline string getProgramInfoLog (const deUint32 programGL)
{
	int				infoLogLen = 0;
	vector<char>	infoLog;
	glGetProgramiv(programGL, GL_INFO_LOG_LENGTH, &infoLogLen);
	infoLog.resize(infoLogLen+1);
	glGetProgramInfoLog(programGL, (int)infoLog.size(), DE_NULL, &infoLog[0]);
	return &infoLog[0];
}

namespace LongStressCaseInternal
{

// A hacky-ish class for drawing text on screen as GL quads.
class DebugInfoRenderer
{
public:
								DebugInfoRenderer		(const glu::RenderContext& ctx);
								~DebugInfoRenderer		(void) { delete m_prog; }

	void						drawInfo				(deUint64 secondsElapsed, int texMem, int maxTexMem, int bufMem, int maxBufMem, int iterNdx);

private:
								DebugInfoRenderer		(const DebugInfoRenderer&);
	DebugInfoRenderer&			operator=				(const DebugInfoRenderer&);

	void						render					(void);
	void						addTextToBuffer			(const string& text, int yOffset);

	const glu::RenderContext&	m_ctx;
	const glu::ShaderProgram*	m_prog;
	vector<float>				m_posBuf;
	vector<deUint16>			m_ndxBuf;
};

void DebugInfoRenderer::drawInfo (const deUint64 secondsElapsed, const int texMem, const int maxTexMem, const int bufMem, const int maxBufMem, const int iterNdx)
{
	const deUint64 m = secondsElapsed / 60;
	const deUint64 h = m / 60;
	const deUint64 d = h / 24;

	{
		std::ostringstream text;

		text << std::setw(2) << std::setfill('0') << d << ":"
			 << std::setw(2) << std::setfill('0') << h % 24 << ":"
			 << std::setw(2) << std::setfill('0') << m % 60 << ":"
			 << std::setw(2) << std::setfill('0') << secondsElapsed % 60;
		addTextToBuffer(text.str(), 0);
		text.str("");

		text << std::fixed << std::setprecision(2) << (float)texMem/Mi << "/" << (float)maxTexMem/Mi;
		addTextToBuffer(text.str(), 1);
		text.str("");

		text << std::fixed << std::setprecision(2) << (float)bufMem/Mi << "/" << (float)maxBufMem/Mi;
		addTextToBuffer(text.str(), 2);
		text.str("");

		text << std::setw(0) << iterNdx;
		addTextToBuffer(text.str(), 3);
	}

	render();
}

DebugInfoRenderer::DebugInfoRenderer (const glu::RenderContext& ctx)
	: m_ctx			(ctx)
	, m_prog		(DE_NULL)
{
	DE_ASSERT(!m_prog);
	m_prog = new glu::ShaderProgram(ctx, glu::makeVtxFragSources(
		"attribute highp vec2 a_pos;\n"
		"void main (void)\n"
		"{\n"
		"	gl_Position = vec4(a_pos, -1.0, 1.0);\n"
		"}\n",

		"void main(void)\n"
		"{\n"
		"	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
		"}\n"));
}

void DebugInfoRenderer::addTextToBuffer (const string& text, const int yOffset)
{
	static const char		characters[]	= "0123456789.:/";
	const int				numCharacters	= DE_LENGTH_OF_ARRAY(characters)-1; // \note -1 for null byte.
	const int				charWid			= 6;
	const int				charHei			= 6;
	static const string		charsStr		(characters);

	static const char font[numCharacters*charWid*charHei + 1]=
		" #### ""   #  "" #### ""##### ""   #  ""######"" #####""######"" #### "" #### ""      ""  ##  ""     #"
		"#    #""  ##  ""#    #""     #""  #   ""#     ""#     ""    # ""#    #""#    #""      ""  ##  ""    # "
		"#    #""   #  ""    # ""  ### "" #  # "" #### ""# ### ""   #  "" #### "" #####""      ""      ""   #  "
		"#    #""   #  ""   #  ""     #""######""     #""##   #""  #   ""#    #""     #""      ""  ##  ""  #   "
		"#    #""   #  ""  #   ""#    #""    # ""#    #""#    #"" #    ""#    #""   ## ""  ##  ""  ##  "" #    "
		" #### ""  ### ""######"" #### ""    # "" #### "" #### ""#     "" #### ""###   ""  ##  ""      ""#     ";

	for (int ndxInText = 0; ndxInText < (int)text.size(); ndxInText++)
	{
		const int ndxInCharset	= (int)charsStr.find(text[ndxInText]);
		DE_ASSERT(ndxInCharset < numCharacters);
		const int fontXStart	= ndxInCharset*charWid;

		for (int y = 0; y < charHei; y++)
		{
			float ay = -1.0f + (float)(y + 0 + yOffset*(charHei+2))*0.1f/(float)(charHei+2);
			float by = -1.0f + (float)(y + 1 + yOffset*(charHei+2))*0.1f/(float)(charHei+2);
			for (int x = 0; x < charWid; x++)
			{
				// \note Text is mirrored in x direction since on most(?) mobile devices the image is mirrored(?).
				float ax = 1.0f - (float)(x + 0 + ndxInText*(charWid+2))*0.1f/(float)(charWid+2);
				float bx = 1.0f - (float)(x + 1 + ndxInText*(charWid+2))*0.1f/(float)(charWid+2);

				if (font[y*numCharacters*charWid + fontXStart + x] != ' ')
				{
					const int vtxNdx = (int)m_posBuf.size()/2;

					m_ndxBuf.push_back(deUint16(vtxNdx+0));
					m_ndxBuf.push_back(deUint16(vtxNdx+1));
					m_ndxBuf.push_back(deUint16(vtxNdx+2));

					m_ndxBuf.push_back(deUint16(vtxNdx+2));
					m_ndxBuf.push_back(deUint16(vtxNdx+1));
					m_ndxBuf.push_back(deUint16(vtxNdx+3));

					m_posBuf.push_back(ax);
					m_posBuf.push_back(ay);

					m_posBuf.push_back(bx);
					m_posBuf.push_back(ay);

					m_posBuf.push_back(ax);
					m_posBuf.push_back(by);

					m_posBuf.push_back(bx);
					m_posBuf.push_back(by);
				}
			}
		}
	}
}

void DebugInfoRenderer::render (void)
{
	const int prog		= m_prog->getProgram();
	const int posloc	= glGetAttribLocation(prog, "a_pos");

	glUseProgram(prog);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glEnableVertexAttribArray(posloc);
	glVertexAttribPointer(posloc, 2, GL_FLOAT, 0, 0, &m_posBuf[0]);
	glDrawElements(GL_TRIANGLES, (int)m_ndxBuf.size(), GL_UNSIGNED_SHORT, &m_ndxBuf[0]);
	glDisableVertexAttribArray(posloc);

	m_posBuf.clear();
	m_ndxBuf.clear();
}

/*--------------------------------------------------------------------*//*!
 * \brief Texture object helper class
 *
 * Each Texture owns a GL texture object that is created when the Texture
 * is constructed and deleted when it's destructed. The class provides some
 * convenience interface functions to e.g. upload texture data to the GL.
 *
 * In addition, the class tracks the approximate amount of GL memory likely
 * used by the corresponding GL texture object; get this with
 * getApproxMemUsage(). Also, getApproxMemUsageDiff() returns N-M, where N
 * is the value that getApproxMemUsage() would return after a call to
 * setData() with arguments corresponding to those given to
 * getApproxMemUsageDiff(), and M is the value currently returned by
 * getApproxMemUsage(). This can be used to check if we need to free some
 * other memory before performing the setData() call, in case we have an
 * upper limit on the amount of memory we want to use.
 *//*--------------------------------------------------------------------*/
class Texture
{
public:
						Texture					(TextureType type);
						~Texture				(void);

	// Functions that may change the value returned by getApproxMemUsage().
	void				setData					(const ConstPixelBufferAccess& src, int width, int height, deUint32 internalFormat, bool useMipmap);

	// Functions that don't change the value returned by getApproxMemUsage().
	void				setSubData				(const ConstPixelBufferAccess& src, int xOff, int yOff, int width, int height) const;
	void				toUnit					(int unit) const;
	void				setFilter				(deUint32 min, deUint32 mag) const;
	void				setWrap					(deUint32 s, deUint32 t) const;

	int					getApproxMemUsage		(void) const { return m_dataSizeApprox; }
	int					getApproxMemUsageDiff	(int width, int height, deUint32 internalFormat, bool useMipmap) const;

private:
						Texture					(const Texture&); // Not allowed.
	Texture&			operator=				(const Texture&); // Not allowed.

	static deUint32		genTexture				(void) { deUint32 tex = 0; glGenTextures(1, &tex); return tex; }

	deUint32			getGLBindTarget			(void) const { DE_ASSERT(m_type == TEXTURETYPE_2D || m_type == TEXTURETYPE_CUBE); return m_type == TEXTURETYPE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP; }

	const TextureType	m_type;
	const deUint32		m_textureGL;

	int					m_numMipLevels;
	deUint32			m_internalFormat;
	int					m_dataSizeApprox;
};

Texture::Texture (const TextureType type)
	: m_type			(type)
	, m_textureGL		(genTexture())
	, m_numMipLevels	(0)
	, m_internalFormat	(0)
	, m_dataSizeApprox	(0)
{
}

Texture::~Texture (void)
{
	glDeleteTextures(1, &m_textureGL);
}

int Texture::getApproxMemUsageDiff (const int width, const int height, const deUint32 internalFormat, const bool useMipmap) const
{
	const int	numLevels				= useMipmap ? deLog2Floor32(de::max(width, height))+1 : 1;
	const int	pixelSize				= internalFormat == GL_RGBA		? 4
										: internalFormat == GL_RGB		? 3
										: internalFormat == GL_ALPHA	? 1
										: glu::mapGLInternalFormat(internalFormat).getPixelSize();
	int			memUsageApproxAfter		= 0;

	for (int level = 0; level < numLevels; level++)
		memUsageApproxAfter += de::max(1, width>>level) * de::max(1, height>>level) * pixelSize * (m_type == TEXTURETYPE_CUBE ? 6 : 1);

	return memUsageApproxAfter - getApproxMemUsage();
}

void Texture::setData (const ConstPixelBufferAccess& src, const int width, const int height, const deUint32 internalFormat, const bool useMipmap)
{
	DE_ASSERT(m_type != TEXTURETYPE_CUBE || width == height);
	DE_ASSERT(!useMipmap || (deIsPowerOfTwo32(width) && deIsPowerOfTwo32(height)));

	const TextureFormat&		format		= src.getFormat();
	const glu::TransferFormat	transfer	= glu::getTransferFormat(format);

	m_numMipLevels = useMipmap ? deLog2Floor32(de::max(width, height))+1 : 1;

	m_internalFormat = internalFormat;
	m_dataSizeApprox = width * height * format.getPixelSize() * (m_type == TEXTURETYPE_CUBE ? 6 : 1);

	DE_ASSERT(src.getRowPitch() == format.getPixelSize()*src.getWidth());
	DE_ASSERT(isMatchingGLInternalFormat(internalFormat, format));
	DE_ASSERT(width <= src.getWidth() && height <= src.getHeight());

	glPixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(format));

	if (m_type == TEXTURETYPE_2D)
	{
		m_dataSizeApprox = 0;

		glBindTexture(GL_TEXTURE_2D, m_textureGL);
		for (int level = 0; level < m_numMipLevels; level++)
		{
			const int levelWid = de::max(1, width>>level);
			const int levelHei = de::max(1, height>>level);
			m_dataSizeApprox += levelWid * levelHei * format.getPixelSize();
			glTexImage2D(GL_TEXTURE_2D, level, internalFormat, levelWid, levelHei, 0, transfer.format, transfer.dataType, src.getDataPtr());
		}
	}
	else if (m_type == TEXTURETYPE_CUBE)
	{
		m_dataSizeApprox = 0;

		glBindTexture(GL_TEXTURE_CUBE_MAP, m_textureGL);
		for (int level = 0; level < m_numMipLevels; level++)
		{
			const int levelWid = de::max(1, width>>level);
			const int levelHei = de::max(1, height>>level);
			m_dataSizeApprox += 6 * levelWid * levelHei * format.getPixelSize();
			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
				glTexImage2D(cubeFaceToGLFace((CubeFace)face), level, internalFormat, levelWid, levelHei, 0, transfer.format, transfer.dataType, src.getDataPtr());
		}
	}
	else
		DE_ASSERT(false);
}

void Texture::setSubData (const ConstPixelBufferAccess& src, const int xOff, const int yOff, const int width, const int height) const
{
	const TextureFormat&		format		= src.getFormat();
	const glu::TransferFormat	transfer	= glu::getTransferFormat(format);

	DE_ASSERT(src.getRowPitch() == format.getPixelSize()*src.getWidth());
	DE_ASSERT(isMatchingGLInternalFormat(m_internalFormat, format));
	DE_ASSERT(width <= src.getWidth() && height <= src.getHeight());

	glPixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(format));

	if (m_type == TEXTURETYPE_2D)
	{
		glBindTexture(GL_TEXTURE_2D, m_textureGL);
		for (int level = 0; level < m_numMipLevels; level++)
			glTexSubImage2D(GL_TEXTURE_2D, level, xOff>>level, yOff>>level, de::max(1, width>>level), de::max(1, height>>level), transfer.format, transfer.dataType, src.getDataPtr());
	}
	else if (m_type == TEXTURETYPE_CUBE)
	{
		glBindTexture(GL_TEXTURE_CUBE_MAP, m_textureGL);
		for (int level = 0; level < m_numMipLevels; level++)
		{
			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
				glTexSubImage2D(cubeFaceToGLFace((CubeFace)face), level, xOff>>level, yOff>>level, de::max(1, width>>level), de::max(1, height>>level), transfer.format, transfer.dataType, src.getDataPtr());
		}
	}
	else
		DE_ASSERT(false);
}

void Texture::setFilter (const deUint32 min, const deUint32 mag) const
{
	glBindTexture(getGLBindTarget(), m_textureGL);
	glTexParameteri(getGLBindTarget(), GL_TEXTURE_MIN_FILTER, min);
	glTexParameteri(getGLBindTarget(), GL_TEXTURE_MAG_FILTER, mag);
}

void Texture::setWrap (const deUint32 s, const deUint32 t) const
{
	glBindTexture(getGLBindTarget(), m_textureGL);
	glTexParameteri(getGLBindTarget(), GL_TEXTURE_WRAP_S, s);
	glTexParameteri(getGLBindTarget(), GL_TEXTURE_WRAP_T, t);
}

void Texture::toUnit (const int unit) const
{
	glActiveTexture(GL_TEXTURE0 + unit);
	glBindTexture(getGLBindTarget(), m_textureGL);
}

/*--------------------------------------------------------------------*//*!
 * \brief Buffer object helper class
 *
 * Each Buffer owns a GL buffer object that is created when the Buffer
 * is constructed and deleted when it's destructed. The class provides some
 * convenience interface functions to e.g. upload buffer data to the GL.
 *
 * In addition, the class tracks the approximate amount of GL memory,
 * similarly to the Texture class (see above). The getApproxMemUsageDiff()
 * is also analoguous.
 *//*--------------------------------------------------------------------*/
class Buffer
{
public:
						Buffer					(void);
						~Buffer					(void);

	// Functions that may change the value returned by getApproxMemUsage().
	template <typename T>
	void				setData					(const vector<T>& src, const deUint32 target, const deUint32 usage) { setData(&src[0], (int)(src.size()*sizeof(T)), target, usage); }
	void				setData					(const void* src, int size, deUint32 target, deUint32 usage);

	// Functions that don't change the value returned by getApproxMemUsage().
	template <typename T>
	void				setSubData				(const vector<T>& src, const int offsetElems, const int numElems, const deUint32 target) { setSubData(&src[offsetElems], offsetElems*(int)sizeof(T), numElems*(int)sizeof(T), target); }
	void				setSubData				(const void* src, int offsetBytes, int sizeBytes, deUint32 target) const;
	void				bind					(const deUint32 target) const { glBindBuffer(target, m_bufferGL); }

	int					getApproxMemUsage		(void) const { return m_dataSizeApprox; }
	template <typename T>
	int					getApproxMemUsageDiff	(const vector<T>& src) const { return getApproxMemUsageDiff((int)(src.size()*sizeof(T))); }
	int					getApproxMemUsageDiff	(const int sizeBytes) const { return sizeBytes - getApproxMemUsage(); }

private:
						Buffer					(const Buffer&); // Not allowed.
	Buffer&				operator=				(const Buffer&); // Not allowed.

	static deUint32		genBuffer				(void) { deUint32 buf = 0; glGenBuffers(1, &buf); return buf; }

	const deUint32		m_bufferGL;
	int					m_dataSizeApprox;
};

Buffer::Buffer (void)
	: m_bufferGL		(genBuffer())
	, m_dataSizeApprox	(0)
{
}

Buffer::~Buffer (void)
{
	glDeleteBuffers(1, &m_bufferGL);
}

void Buffer::setData (const void* const src, const int size, const deUint32 target, const deUint32 usage)
{
	bind(target);
	glBufferData(target, size, src, usage);
	glBindBuffer(target, 0);

	m_dataSizeApprox = size;
}

void Buffer::setSubData (const void* const src, const int offsetBytes, const int sizeBytes, const deUint32 target) const
{
	bind(target);
	glBufferSubData(target, offsetBytes, sizeBytes, src);
	glBindBuffer(target, 0);
}

class Program
{
public:
						Program					(void);
						~Program				(void);

	void				setSources				(const string& vertSource, const string& fragSource);
	void				build					(TestLog& log);
	void				use						(void) const { DE_ASSERT(m_isBuilt); glUseProgram(m_programGL); }
	void				setRandomUniforms		(const vector<VarSpec>& uniforms, const string& shaderNameManglingSuffix, Random& rnd) const;
	void				setAttribute			(const Buffer& attrBuf, int attrBufOffset, const VarSpec& attrSpec, const string& shaderNameManglingSuffix) const;
	void				setAttributeClientMem	(const void* attrData, const VarSpec& attrSpec, const string& shaderNameManglingSuffix) const;
	void				disableAttributeArray	(const VarSpec& attrSpec, const string& shaderNameManglingSuffix) const;

private:
						Program				(const Program&); // Not allowed.
	Program&			operator=			(const Program&); // Not allowed.

	string				m_vertSource;
	string				m_fragSource;

	const deUint32		m_vertShaderGL;
	const deUint32		m_fragShaderGL;
	const deUint32		m_programGL;
	bool				m_hasSources;
	bool				m_isBuilt;
};

Program::Program (void)
	: m_vertShaderGL	(glCreateShader(GL_VERTEX_SHADER))
	, m_fragShaderGL	(glCreateShader(GL_FRAGMENT_SHADER))
	, m_programGL		(glCreateProgram())
	, m_hasSources		(false)
	, m_isBuilt			(false)
{
	glAttachShader(m_programGL, m_vertShaderGL);
	glAttachShader(m_programGL, m_fragShaderGL);
}

Program::~Program (void)
{
	glDeleteShader(m_vertShaderGL);
	glDeleteShader(m_fragShaderGL);
	glDeleteProgram(m_programGL);
}

void Program::setSources (const string& vertSource, const string& fragSource)
{
	const char* const vertSourceCstr = vertSource.c_str();
	const char* const fragSourceCstr = fragSource.c_str();

	m_vertSource = vertSource;
	m_fragSource = fragSource;

	// \note In GLES2 api the source parameter type lacks one const.
	glShaderSource(m_vertShaderGL, 1, (const char**)&vertSourceCstr, DE_NULL);
	glShaderSource(m_fragShaderGL, 1, (const char**)&fragSourceCstr, DE_NULL);

	m_hasSources = true;
}

void Program::build (TestLog& log)
{
	DE_ASSERT(m_hasSources);

	const bool vertCompileOk	= compileShader(m_vertShaderGL);
	const bool fragCompileOk	= compileShader(m_fragShaderGL);
	const bool attemptLink		= vertCompileOk && fragCompileOk;
	const bool linkOk			= attemptLink && linkProgram(m_programGL);

	if (!(vertCompileOk && fragCompileOk && linkOk))
	{
		log << TestLog::ShaderProgram(linkOk, attemptLink ? getProgramInfoLog(m_programGL) : string(""))
			<< TestLog::Shader(QP_SHADER_TYPE_VERTEX, m_vertSource, vertCompileOk, getShaderInfoLog(m_vertShaderGL))
			<< TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, m_fragSource, fragCompileOk, getShaderInfoLog(m_fragShaderGL))
			<< TestLog::EndShaderProgram;

		throw tcu::TestError("Program build failed");
	}

	m_isBuilt = true;
}

void Program::setRandomUniforms (const vector<VarSpec>& uniforms, const string& shaderNameManglingSuffix, Random& rnd) const
{
	use();

	for (int unifNdx = 0; unifNdx < (int)uniforms.size(); unifNdx++)
	{
		const VarSpec&	spec			= uniforms[unifNdx];
		const int		typeScalarSize	= glu::getDataTypeScalarSize(spec.type);
		const int		location		= glGetUniformLocation(m_programGL, mangleShaderNames(spec.name, shaderNameManglingSuffix).c_str());
		if (location < 0)
			continue;

		if (glu::isDataTypeFloatOrVec(spec.type))
		{
			float val[4];
			for (int i = 0; i < typeScalarSize; i++)
				val[i] = rnd.getFloat(spec.minValue.f[i], spec.maxValue.f[i]);

			switch (spec.type)
			{
				case glu::TYPE_FLOAT:		glUniform1f(location, val[0]);							break;
				case glu::TYPE_FLOAT_VEC2:	glUniform2f(location, val[0], val[1]);					break;
				case glu::TYPE_FLOAT_VEC3:	glUniform3f(location, val[0], val[1], val[2]);			break;
				case glu::TYPE_FLOAT_VEC4:	glUniform4f(location, val[0], val[1], val[2], val[3]);	break;
				default: DE_ASSERT(false);
			}
		}
		else if (glu::isDataTypeMatrix(spec.type))
		{
			float val[4*4];
			for (int i = 0; i < typeScalarSize; i++)
				val[i] = rnd.getFloat(spec.minValue.f[i], spec.maxValue.f[i]);

			switch (spec.type)
			{
				case glu::TYPE_FLOAT_MAT2:		glUniformMatrix2fv		(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT3:		glUniformMatrix3fv		(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT4:		glUniformMatrix4fv		(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT2X3:	glUniformMatrix2x3fv	(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT2X4:	glUniformMatrix2x4fv	(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT3X2:	glUniformMatrix3x2fv	(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT3X4:	glUniformMatrix3x4fv	(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT4X2:	glUniformMatrix4x2fv	(location, 1, GL_FALSE, &val[0]); break;
				case glu::TYPE_FLOAT_MAT4X3:	glUniformMatrix4x3fv	(location, 1, GL_FALSE, &val[0]); break;
				default: DE_ASSERT(false);
			}
		}
		else if (glu::isDataTypeIntOrIVec(spec.type))
		{
			int val[4];
			for (int i = 0; i < typeScalarSize; i++)
				val[i] = rnd.getInt(spec.minValue.i[i], spec.maxValue.i[i]);

			switch (spec.type)
			{
				case glu::TYPE_INT:			glUniform1i(location, val[0]);							break;
				case glu::TYPE_INT_VEC2:	glUniform2i(location, val[0], val[1]);					break;
				case glu::TYPE_INT_VEC3:	glUniform3i(location, val[0], val[1], val[2]);			break;
				case glu::TYPE_INT_VEC4:	glUniform4i(location, val[0], val[1], val[2], val[3]);	break;
				default: DE_ASSERT(false);
			}
		}
		else if (glu::isDataTypeUintOrUVec(spec.type))
		{
			deUint32 val[4];
			for (int i = 0; i < typeScalarSize; i++)
			{
				DE_ASSERT(spec.minValue.i[i] >= 0 && spec.maxValue.i[i] >= 0);
				val[i] = (deUint32)rnd.getInt(spec.minValue.i[i], spec.maxValue.i[i]);
			}

			switch (spec.type)
			{
				case glu::TYPE_UINT:		glUniform1ui(location, val[0]);							break;
				case glu::TYPE_UINT_VEC2:	glUniform2ui(location, val[0], val[1]);					break;
				case glu::TYPE_UINT_VEC3:	glUniform3ui(location, val[0], val[1], val[2]);			break;
				case glu::TYPE_UINT_VEC4:	glUniform4ui(location, val[0], val[1], val[2], val[3]);	break;
				default: DE_ASSERT(false);
			}
		}
		else
			DE_ASSERT(false);
	}
}

void Program::setAttribute (const Buffer& attrBuf, const int attrBufOffset, const VarSpec& attrSpec, const string& shaderNameManglingSuffix) const
{
	const int attrLoc = glGetAttribLocation(m_programGL, mangleShaderNames(attrSpec.name, shaderNameManglingSuffix).c_str());

	glEnableVertexAttribArray(attrLoc);
	attrBuf.bind(GL_ARRAY_BUFFER);

	if (glu::isDataTypeFloatOrVec(attrSpec.type))
		glVertexAttribPointer(attrLoc, glu::getDataTypeScalarSize(attrSpec.type), GL_FLOAT, GL_FALSE, 0, (GLvoid*)(deIntptr)attrBufOffset);
	else
		DE_ASSERT(false);
}

void Program::setAttributeClientMem (const void* const attrData, const VarSpec& attrSpec, const string& shaderNameManglingSuffix) const
{
	const int attrLoc = glGetAttribLocation(m_programGL, mangleShaderNames(attrSpec.name, shaderNameManglingSuffix).c_str());

	glEnableVertexAttribArray(attrLoc);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	if (glu::isDataTypeFloatOrVec(attrSpec.type))
		glVertexAttribPointer(attrLoc, glu::getDataTypeScalarSize(attrSpec.type), GL_FLOAT, GL_FALSE, 0, attrData);
	else
		DE_ASSERT(false);
}

void Program::disableAttributeArray (const VarSpec& attrSpec, const string& shaderNameManglingSuffix) const
{
	const int attrLoc = glGetAttribLocation(m_programGL, mangleShaderNames(attrSpec.name, shaderNameManglingSuffix).c_str());

	glDisableVertexAttribArray(attrLoc);
}

/*--------------------------------------------------------------------*//*!
 * \brief Container class for managing GL objects
 *
 * GLObjectManager can be used for objects of class Program, Buffer or
 * Texture. In the manager, each such object is associated with a name that
 * is used to access it.
 *
 * In addition to the making, getting and removing functions, the manager
 * supports marking objects as "garbage", meaning they're not yet
 * destroyed, but can be later destroyed with removeRandomGarbage(). The
 * idea is that if we want to stress test with high memory usage, we can
 * continuously move objects to garbage after using them, and when a memory
 * limit is reached, we can call removeGarbageUntilUnder(limit, rnd). This
 * way we can approximately keep our memory usage at just under the wanted
 * limit.
 *
 * The manager also supports querying the approximate amount of GL memory
 * used by its objects.
 *
 * \note The memory usage related functions are not currently supported
 *		 for Program objects.
 *//*--------------------------------------------------------------------*/
template <typename T>
class GLObjectManager
{
public:
	void						make						(const string& name)								{ DE_ASSERT(!has(name)); m_objects[name] = SharedPtr<T>(new T); }
	void						make						(const string& name, gls::TextureType texType)		{ DE_ASSERT(!has(name)); m_objects[name] = SharedPtr<T>(new T(texType)); }
	bool						has							(const string& name) const	{ return m_objects.find(name) != m_objects.end(); }
	const T&					get							(const string& name) const;
	T&							get							(const string& name)		{ return const_cast<T&>(((const GLObjectManager<T>*)this)->get(name)); }
	void						remove						(const string& name)		{ const int removed = (int)m_objects.erase(name); DE_ASSERT(removed); DE_UNREF(removed); }
	int							computeApproxMemUsage		(void) const;
	void						markAsGarbage				(const string& name);
	int							removeRandomGarbage			(Random& rnd);
	void						removeGarbageUntilUnder		(int limit, Random& rnd);

private:
	static const char*			objTypeName					(void);

	map<string, SharedPtr<T> >	m_objects;
	vector<SharedPtr<T> >		m_garbageObjects;
};

template <> const char* GLObjectManager<Buffer>::objTypeName	(void) { return "buffer"; }
template <> const char* GLObjectManager<Texture>::objTypeName	(void) { return "texture"; }
template <> const char* GLObjectManager<Program>::objTypeName	(void) { return "program"; }

template <typename T>
const T& GLObjectManager<T>::get (const string& name) const
{
	const typename map<string, SharedPtr<T> >::const_iterator it = m_objects.find(name);
	DE_ASSERT(it != m_objects.end());
	return *it->second;
}

template <typename T>
int GLObjectManager<T>::computeApproxMemUsage (void) const
{
	int result = 0;

	for (typename map<string, SharedPtr<T> >::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
		result += it->second->getApproxMemUsage();

	for (typename vector<SharedPtr<T> >::const_iterator it = m_garbageObjects.begin(); it != m_garbageObjects.end(); ++it)
		result += (*it)->getApproxMemUsage();

	return result;
}

template <typename T>
void GLObjectManager<T>::markAsGarbage (const string& name)
{
	const typename map<string, SharedPtr<T> >::iterator it = m_objects.find(name);
	DE_ASSERT(it != m_objects.end());
	m_garbageObjects.push_back(it->second);
	m_objects.erase(it);
}

template <typename T>
int GLObjectManager<T>::removeRandomGarbage (Random& rnd)
{
	if (m_garbageObjects.empty())
		return -1;

	const int removeNdx		= rnd.getInt(0, (int)m_garbageObjects.size()-1);
	const int memoryFreed	= m_garbageObjects[removeNdx]->getApproxMemUsage();
	m_garbageObjects.erase(m_garbageObjects.begin() + removeNdx);
	return memoryFreed;
}

template <typename T>
void GLObjectManager<T>::removeGarbageUntilUnder (const int limit, Random& rnd)
{
	int memUsage = computeApproxMemUsage();

	while (memUsage > limit)
	{
		const int memReleased = removeRandomGarbage(rnd);
		if (memReleased < 0)
			throw tcu::InternalError(string("") + "Given " + objTypeName() + " memory usage limit exceeded, and no unneeded " + objTypeName() + " resources available to release");
		memUsage -= memReleased;
		DE_ASSERT(memUsage == computeApproxMemUsage());
	}
}

} // LongStressCaseInternal

using namespace LongStressCaseInternal;

static int generateRandomAttribData (vector<deUint8>& attrDataBuf, int& dataSizeBytesDst, const VarSpec& attrSpec, const int numVertices, Random& rnd)
{
	const bool	isFloat			= glu::isDataTypeFloatOrVec(attrSpec.type);
	const int	numComponents	= glu::getDataTypeScalarSize(attrSpec.type);
	const int	componentSize	= (int)(isFloat ? sizeof(GLfloat) : sizeof(GLint));
	const int	offsetInBuf		= nextDivisible((int)attrDataBuf.size(), componentSize); // Round up for alignment.

	DE_STATIC_ASSERT(sizeof(GLint) == sizeof(int));
	DE_STATIC_ASSERT(sizeof(GLfloat) == sizeof(float));

	dataSizeBytesDst = numComponents*componentSize*numVertices;

	attrDataBuf.resize(offsetInBuf + dataSizeBytesDst);

	if (isFloat)
	{
		float* const data = (float*)&attrDataBuf[offsetInBuf];

		for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx++)
			for (int compNdx = 0; compNdx < numComponents; compNdx++)
				data[vtxNdx*numComponents + compNdx] = rnd.getFloat(attrSpec.minValue.f[compNdx], attrSpec.maxValue.f[compNdx]);
	}
	else
	{
		DE_ASSERT(glu::isDataTypeIntOrIVec(attrSpec.type));

		int* const data = (int*)&attrDataBuf[offsetInBuf];

		for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx++)
			for (int compNdx = 0; compNdx < numComponents; compNdx++)
				data[vtxNdx*numComponents + compNdx] = rnd.getInt(attrSpec.minValue.i[compNdx], attrSpec.maxValue.i[compNdx]);
	}

	return offsetInBuf;
}

static int generateRandomPositionAttribData (vector<deUint8>& attrDataBuf, int& dataSizeBytesDst, const VarSpec& attrSpec, const int numVertices, Random& rnd)
{
	DE_ASSERT(glu::isDataTypeFloatOrVec(attrSpec.type));

	const int numComponents = glu::getDataTypeScalarSize(attrSpec.type);
	DE_ASSERT(numComponents >= 2);
	const int offsetInBuf = generateRandomAttribData(attrDataBuf, dataSizeBytesDst, attrSpec, numVertices, rnd);

	if (numComponents > 2)
	{
		float* const data = (float*)&attrDataBuf[offsetInBuf];

		for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx++)
			data[vtxNdx*numComponents + 2] = -1.0f;

		for (int triNdx = 0; triNdx < numVertices-2; triNdx++)
		{
			float* const	vtxAComps	= &data[(triNdx+0)*numComponents];
			float* const	vtxBComps	= &data[(triNdx+1)*numComponents];
			float* const	vtxCComps	= &data[(triNdx+2)*numComponents];

			const float		triArea		= triangleArea(Vec2(vtxAComps[0], vtxAComps[1]),
													   Vec2(vtxBComps[0], vtxBComps[1]),
													   Vec2(vtxCComps[0], vtxCComps[1]));
			const float		t			= triArea / (triArea + 1.0f);
			const float		z			= (1.0f-t)*attrSpec.minValue.f[2] + t*attrSpec.maxValue.f[2];

			vtxAComps[2] = de::max(vtxAComps[2], z);
			vtxBComps[2] = de::max(vtxBComps[2], z);
			vtxCComps[2] = de::max(vtxCComps[2], z);
		}
	}

	return offsetInBuf;
}

static void generateAttribs (vector<deUint8>& attrDataBuf, vector<int>& attrDataOffsets, vector<int>& attrDataSizes, const vector<VarSpec>& attrSpecs, const string& posAttrName, const int numVertices, Random& rnd)
{
	attrDataBuf.clear();
	attrDataOffsets.clear();
	attrDataSizes.resize(attrSpecs.size());

	for (int i = 0; i < (int)attrSpecs.size(); i++)
	{
		if (attrSpecs[i].name == posAttrName)
			attrDataOffsets.push_back(generateRandomPositionAttribData(attrDataBuf, attrDataSizes[i], attrSpecs[i], numVertices, rnd));
		else
			attrDataOffsets.push_back(generateRandomAttribData(attrDataBuf, attrDataSizes[i], attrSpecs[i], numVertices, rnd));
	}
}

LongStressCase::LongStressCase (tcu::TestContext&				testCtx,
								const glu::RenderContext&		renderCtx,
								const char* const				name,
								const char* const				desc,
								const int						maxTexMemoryUsageBytes,
								const int						maxBufMemoryUsageBytes,
								const int						numDrawCallsPerIteration,
								const int						numTrianglesPerDrawCall,
								const vector<ProgramContext>&	programContexts,
								const FeatureProbabilities&		probabilities,
								const deUint32					indexBufferUsage,
								const deUint32					attrBufferUsage,
								const int						redundantBufferFactor,
								const bool						showDebugInfo)
	: tcu::TestCase					(testCtx, name, desc)
	, m_renderCtx					(renderCtx)
	, m_maxTexMemoryUsageBytes		(maxTexMemoryUsageBytes)
	, m_maxBufMemoryUsageBytes		(maxBufMemoryUsageBytes)
	, m_numDrawCallsPerIteration	(numDrawCallsPerIteration)
	, m_numTrianglesPerDrawCall		(numTrianglesPerDrawCall)
	, m_numVerticesPerDrawCall		(numTrianglesPerDrawCall+2) // \note Triangle strips are used.
	, m_programContexts				(programContexts)
	, m_probabilities				(probabilities)
	, m_indexBufferUsage			(indexBufferUsage)
	, m_attrBufferUsage				(attrBufferUsage)
	, m_redundantBufferFactor		(redundantBufferFactor)
	, m_showDebugInfo				(showDebugInfo)
	, m_numIterations				(getNumIterations(testCtx, 5))
	, m_isGLES3						(contextSupports(renderCtx.getType(), glu::ApiType::es(3,0)))
	, m_currentIteration			(0)
	, m_startTimeSeconds			((deUint64)-1)
	, m_lastLogTime					((deUint64)-1)
	, m_lastLogIteration			(0)
	, m_currentLogEntryNdx			(0)
	, m_rnd							(deStringHash(getName()) ^ testCtx.getCommandLine().getBaseSeed())
	, m_programs					(DE_NULL)
	, m_buffers						(DE_NULL)
	, m_textures					(DE_NULL)
	, m_debugInfoRenderer			(DE_NULL)
{
	DE_ASSERT(m_numVerticesPerDrawCall <= (int)std::numeric_limits<deUint16>::max()+1); // \note Vertices are referred to with 16-bit indices.
	DE_ASSERT(m_redundantBufferFactor > 0);
}

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

void LongStressCase::init (void)
{
	// Generate dummy texture data for each texture spec in m_programContexts.

	DE_ASSERT(!m_programContexts.empty());
	DE_ASSERT(m_programResources.empty());
	m_programResources.resize(m_programContexts.size());

	for (int progCtxNdx = 0; progCtxNdx < (int)m_programContexts.size(); progCtxNdx++)
	{
		const ProgramContext&	progCtx = m_programContexts[progCtxNdx];
		ProgramResources&		progRes = m_programResources[progCtxNdx];

		for (int texSpecNdx = 0; texSpecNdx < (int)progCtx.textureSpecs.size(); texSpecNdx++)
		{
			const TextureSpec&		spec	= progCtx.textureSpecs[texSpecNdx];
			const TextureFormat		format	= glu::mapGLTransferFormat(spec.format, spec.dataType);

			// If texture data with the same format has already been generated, re-use that (don't care much about contents).

			SharedPtr<TextureLevel> dummyTex;

			for (int prevProgCtxNdx = 0; prevProgCtxNdx < (int)m_programResources.size(); prevProgCtxNdx++)
			{
				const vector<SharedPtr<TextureLevel> >& prevProgCtxTextures = m_programResources[prevProgCtxNdx].dummyTextures;

				for (int texNdx = 0; texNdx < (int)prevProgCtxTextures.size(); texNdx++)
				{
					if (prevProgCtxTextures[texNdx]->getFormat() == format)
					{
						dummyTex = prevProgCtxTextures[texNdx];
						break;
					}
				}
			}

			if (!dummyTex)
				dummyTex = SharedPtr<TextureLevel>(new TextureLevel(format));

			if (dummyTex->getWidth() < spec.width || dummyTex->getHeight() < spec.height)
			{
				dummyTex->setSize(spec.width, spec.height);
				tcu::fillWithComponentGradients(dummyTex->getAccess(), spec.minValue, spec.maxValue);
			}

			progRes.dummyTextures.push_back(dummyTex);
		}
	}

	m_vertexIndices.clear();
	for (int i = 0; i < m_numVerticesPerDrawCall; i++)
		m_vertexIndices.push_back((deUint16)i);
	m_rnd.shuffle(m_vertexIndices.begin(), m_vertexIndices.end());

	DE_ASSERT(!m_programs && !m_buffers && !m_textures);
	m_programs = new GLObjectManager<Program>;
	m_buffers = new GLObjectManager<Buffer>;
	m_textures = new GLObjectManager<Texture>;

	m_currentIteration = 0;

	{
		TestLog& log = m_testCtx.getLog();

		log << TestLog::Message << "Number of iterations: "										<< (m_numIterations > 0 ? toString(m_numIterations) : "infinite")				<< TestLog::EndMessage
			<< TestLog::Message << "Number of draw calls per iteration: "						<< m_numDrawCallsPerIteration													<< TestLog::EndMessage
			<< TestLog::Message << "Number of triangles per draw call: "						<< m_numTrianglesPerDrawCall													<< TestLog::EndMessage
			<< TestLog::Message << "Using triangle strips"																														<< TestLog::EndMessage
			<< TestLog::Message << "Approximate texture memory usage limit: "					<< de::floatToString((float)m_maxTexMemoryUsageBytes / Mi, 2) << " MiB"			<< TestLog::EndMessage
			<< TestLog::Message << "Approximate buffer memory usage limit: "					<< de::floatToString((float)m_maxBufMemoryUsageBytes / Mi, 2) << " MiB"			<< TestLog::EndMessage
			<< TestLog::Message << "Default vertex attribute data buffer usage parameter: "		<< glu::getUsageName(m_attrBufferUsage)											<< TestLog::EndMessage
			<< TestLog::Message << "Default vertex index data buffer usage parameter: "			<< glu::getUsageName(m_indexBufferUsage)										<< TestLog::EndMessage

			<< TestLog::Section("ProbabilityParams", "Per-iteration probability parameters")
			<< TestLog::Message << "Program re-build: "															<< probabilityStr(m_probabilities.rebuildProgram)				<< TestLog::EndMessage
			<< TestLog::Message << "Texture re-upload: "														<< probabilityStr(m_probabilities.reuploadTexture)				<< TestLog::EndMessage
			<< TestLog::Message << "Buffer re-upload: "															<< probabilityStr(m_probabilities.reuploadBuffer)				<< TestLog::EndMessage
			<< TestLog::Message << "Use glTexImage* instead of glTexSubImage* when uploading texture: "			<< probabilityStr(m_probabilities.reuploadWithTexImage)			<< TestLog::EndMessage
			<< TestLog::Message << "Use glBufferData* instead of glBufferSubData* when uploading buffer: "		<< probabilityStr(m_probabilities.reuploadWithBufferData)		<< TestLog::EndMessage
			<< TestLog::Message << "Delete texture after using it, even if could re-use it: "					<< probabilityStr(m_probabilities.deleteTexture)				<< TestLog::EndMessage
			<< TestLog::Message << "Delete buffer after using it, even if could re-use it: "					<< probabilityStr(m_probabilities.deleteBuffer)					<< TestLog::EndMessage
			<< TestLog::Message << "Don't re-use texture, and only delete if memory limit is hit: "				<< probabilityStr(m_probabilities.wastefulTextureMemoryUsage)	<< TestLog::EndMessage
			<< TestLog::Message << "Don't re-use buffer, and only delete if memory limit is hit: "				<< probabilityStr(m_probabilities.wastefulBufferMemoryUsage)	<< TestLog::EndMessage
			<< TestLog::Message << "Use client memory (instead of GL buffers) for vertex attribute data: "		<< probabilityStr(m_probabilities.clientMemoryAttributeData)	<< TestLog::EndMessage
			<< TestLog::Message << "Use client memory (instead of GL buffers) for vertex index data: "			<< probabilityStr(m_probabilities.clientMemoryIndexData)		<< TestLog::EndMessage
			<< TestLog::Message << "Use random target parameter when uploading buffer data: "					<< probabilityStr(m_probabilities.randomBufferUploadTarget)		<< TestLog::EndMessage
			<< TestLog::Message << "Use random usage parameter when uploading buffer data: "					<< probabilityStr(m_probabilities.randomBufferUsage)			<< TestLog::EndMessage
			<< TestLog::Message << "Use glDrawArrays instead of glDrawElements: "								<< probabilityStr(m_probabilities.useDrawArrays)				<< TestLog::EndMessage
			<< TestLog::Message << "Use separate buffers for each attribute, instead of one array for all: "	<< probabilityStr(m_probabilities.separateAttributeBuffers)		<< TestLog::EndMessage
			<< TestLog::EndSection
			<< TestLog::Message << "Using " << m_programContexts.size() << " program(s)" << TestLog::EndMessage;

		bool anyProgramsFailed = false;
		for (int progCtxNdx = 0; progCtxNdx < (int)m_programContexts.size(); progCtxNdx++)
		{
			const ProgramContext& progCtx = m_programContexts[progCtxNdx];
			glu::ShaderProgram prog(m_renderCtx, glu::makeVtxFragSources(mangleShaderNames(progCtx.vertexSource, ""), mangleShaderNames(progCtx.fragmentSource, "")));
			log << TestLog::Section("ShaderProgram" + toString(progCtxNdx), "Shader program " + toString(progCtxNdx)) << prog << TestLog::EndSection;
			if (!prog.isOk())
				anyProgramsFailed = true;
		}

		if (anyProgramsFailed)
			throw tcu::TestError("One or more shader programs failed to compile");
	}

	DE_ASSERT(!m_debugInfoRenderer);
	if (m_showDebugInfo)
		m_debugInfoRenderer = new DebugInfoRenderer(m_renderCtx);
}

void LongStressCase::deinit (void)
{
	m_programResources.clear();

	delete m_programs;
	m_programs = DE_NULL;

	delete m_buffers;
	m_buffers = DE_NULL;

	delete m_textures;
	m_textures = DE_NULL;

	delete m_debugInfoRenderer;
	m_debugInfoRenderer = DE_NULL;
}

LongStressCase::IterateResult LongStressCase::iterate (void)
{
	TestLog&					log							= m_testCtx.getLog();
	const int					renderWidth					= m_renderCtx.getRenderTarget().getWidth();
	const int					renderHeight				= m_renderCtx.getRenderTarget().getHeight();
	const bool					useClientMemoryIndexData	= m_rnd.getFloat() < m_probabilities.clientMemoryIndexData;
	const bool					useDrawArrays				= m_rnd.getFloat() < m_probabilities.useDrawArrays;
	const bool					separateAttributeBuffers	= m_rnd.getFloat() < m_probabilities.separateAttributeBuffers;
	const int					progContextNdx				= m_rnd.getInt(0, (int)m_programContexts.size()-1);
	const ProgramContext&		programContext				= m_programContexts[progContextNdx];
	ProgramResources&			programResources			= m_programResources[progContextNdx];
	const string				programName					= "prog" + toString(progContextNdx);
	const string				textureNamePrefix			= "tex" + toString(progContextNdx) + "_";
	const string				unitedAttrBufferNamePrefix	= "attrBuf" + toString(progContextNdx) + "_";
	const string				indexBufferName				= "indexBuf" + toString(progContextNdx);
	const string				separateAttrBufNamePrefix	= "attrBuf" + toString(progContextNdx) + "_";

	if (m_currentIteration == 0)
		m_lastLogTime = m_startTimeSeconds = deGetTime();

	// Make or re-compile programs.
	{
		const bool hadProgram = m_programs->has(programName);

		if (!hadProgram)
			m_programs->make(programName);

		Program& prog = m_programs->get(programName);

		if (!hadProgram || m_rnd.getFloat() < m_probabilities.rebuildProgram)
		{
			programResources.shaderNameManglingSuffix = toString((deUint16)deUint64Hash((deUint64)m_currentIteration ^ deGetTime()));

			prog.setSources(mangleShaderNames(programContext.vertexSource, programResources.shaderNameManglingSuffix),
							mangleShaderNames(programContext.fragmentSource, programResources.shaderNameManglingSuffix));

			prog.build(log);
		}

		prog.use();
	}

	Program& program = m_programs->get(programName);

	// Make or re-upload textures.

	for (int texNdx = 0; texNdx < (int)programContext.textureSpecs.size(); texNdx++)
	{
		const string		texName		= textureNamePrefix + toString(texNdx);
		const bool			hadTexture	= m_textures->has(texName);
		const TextureSpec&	spec		= programContext.textureSpecs[texNdx];

		if (!hadTexture)
			m_textures->make(texName, spec.textureType);

		if (!hadTexture || m_rnd.getFloat() < m_probabilities.reuploadTexture)
		{
			Texture& texture = m_textures->get(texName);

			m_textures->removeGarbageUntilUnder(m_maxTexMemoryUsageBytes - texture.getApproxMemUsageDiff(spec.width, spec.height, spec.internalFormat, spec.useMipmap), m_rnd);

			if (!hadTexture || m_rnd.getFloat() < m_probabilities.reuploadWithTexImage)
				texture.setData(programResources.dummyTextures[texNdx]->getAccess(), spec.width, spec.height, spec.internalFormat, spec.useMipmap);
			else
				texture.setSubData(programResources.dummyTextures[texNdx]->getAccess(), 0, 0, spec.width, spec.height);

			texture.toUnit(0);
			texture.setWrap(spec.sWrap, spec.tWrap);
			texture.setFilter(spec.minFilter, spec.magFilter);
		}
	}

	// Bind textures to units, in random order (because when multiple texture specs have same unit, we want to pick one randomly).

	{
		vector<int> texSpecIndices(programContext.textureSpecs.size());
		for (int i = 0; i < (int)texSpecIndices.size(); i++)
			texSpecIndices[i] = i;
		m_rnd.shuffle(texSpecIndices.begin(), texSpecIndices.end());
		for (int i = 0; i < (int)texSpecIndices.size(); i++)
			m_textures->get(textureNamePrefix + toString(texSpecIndices[i])).toUnit(programContext.textureSpecs[i].textureUnit);
	}

	// Make or re-upload index buffer.

	if (!useDrawArrays)
	{
		m_rnd.shuffle(m_vertexIndices.begin(), m_vertexIndices.end());

		if (!useClientMemoryIndexData)
		{
			const bool hadIndexBuffer = m_buffers->has(indexBufferName);

			if (!hadIndexBuffer)
				m_buffers->make(indexBufferName);

			Buffer& indexBuf = m_buffers->get(indexBufferName);

			if (!hadIndexBuffer || m_rnd.getFloat() < m_probabilities.reuploadBuffer)
			{
				m_buffers->removeGarbageUntilUnder(m_maxBufMemoryUsageBytes - indexBuf.getApproxMemUsageDiff(m_vertexIndices), m_rnd);
				const deUint32 target = m_rnd.getFloat() < m_probabilities.randomBufferUploadTarget ? randomBufferTarget(m_rnd, m_isGLES3) : GL_ELEMENT_ARRAY_BUFFER;

				if (!hadIndexBuffer || m_rnd.getFloat() < m_probabilities.reuploadWithBufferData)
					indexBuf.setData(m_vertexIndices, target, m_rnd.getFloat() < m_probabilities.randomBufferUsage ? randomBufferUsage(m_rnd, m_isGLES3) : m_indexBufferUsage);
				else
					indexBuf.setSubData(m_vertexIndices, 0, m_numVerticesPerDrawCall, target);
			}
		}
	}

	// Set vertex attributes. If not using client-memory data, make or re-upload attribute buffers.

	generateAttribs(programResources.attrDataBuf, programResources.attrDataOffsets, programResources.attrDataSizes,
					programContext.attributes, programContext.positionAttrName, m_numVerticesPerDrawCall, m_rnd);

	if (!(m_rnd.getFloat() < m_probabilities.clientMemoryAttributeData))
	{
		if (separateAttributeBuffers)
		{
			for (int attrNdx = 0; attrNdx < (int)programContext.attributes.size(); attrNdx++)
			{
				const int usedRedundantBufferNdx = m_rnd.getInt(0, m_redundantBufferFactor-1);

				for (int redundantBufferNdx = 0; redundantBufferNdx < m_redundantBufferFactor; redundantBufferNdx++)
				{
					const string	curAttrBufName		= separateAttrBufNamePrefix + toString(attrNdx) + "_" + toString(redundantBufferNdx);
					const bool		hadCurAttrBuffer	= m_buffers->has(curAttrBufName);

					if (!hadCurAttrBuffer)
						m_buffers->make(curAttrBufName);

					Buffer& curAttrBuf = m_buffers->get(curAttrBufName);

					if (!hadCurAttrBuffer || m_rnd.getFloat() < m_probabilities.reuploadBuffer)
					{
						m_buffers->removeGarbageUntilUnder(m_maxBufMemoryUsageBytes - curAttrBuf.getApproxMemUsageDiff(programResources.attrDataSizes[attrNdx]), m_rnd);
						const deUint32 target = m_rnd.getFloat() < m_probabilities.randomBufferUploadTarget ? randomBufferTarget(m_rnd, m_isGLES3) : GL_ARRAY_BUFFER;

						if (!hadCurAttrBuffer || m_rnd.getFloat() < m_probabilities.reuploadWithBufferData)
							curAttrBuf.setData(&programResources.attrDataBuf[programResources.attrDataOffsets[attrNdx]], programResources.attrDataSizes[attrNdx], target,
											   m_rnd.getFloat() < m_probabilities.randomBufferUsage ? randomBufferUsage(m_rnd, m_isGLES3) : m_attrBufferUsage);
						else
							curAttrBuf.setSubData(&programResources.attrDataBuf[programResources.attrDataOffsets[attrNdx]], 0, programResources.attrDataSizes[attrNdx], target);
					}

					if (redundantBufferNdx == usedRedundantBufferNdx)
						program.setAttribute(curAttrBuf, 0, programContext.attributes[attrNdx], programResources.shaderNameManglingSuffix);
				}
			}
		}
		else
		{
			const int usedRedundantBufferNdx = m_rnd.getInt(0, m_redundantBufferFactor-1);

			for (int redundantBufferNdx = 0; redundantBufferNdx < m_redundantBufferFactor; redundantBufferNdx++)
			{
				const string	attrBufName		= unitedAttrBufferNamePrefix + toString(redundantBufferNdx);
				const bool		hadAttrBuffer	= m_buffers->has(attrBufName);

				if (!hadAttrBuffer)
					m_buffers->make(attrBufName);

				Buffer& attrBuf = m_buffers->get(attrBufName);

				if (!hadAttrBuffer || m_rnd.getFloat() < m_probabilities.reuploadBuffer)
				{
					m_buffers->removeGarbageUntilUnder(m_maxBufMemoryUsageBytes - attrBuf.getApproxMemUsageDiff(programResources.attrDataBuf), m_rnd);
					const deUint32 target = m_rnd.getFloat() < m_probabilities.randomBufferUploadTarget ? randomBufferTarget(m_rnd, m_isGLES3) : GL_ARRAY_BUFFER;

					if (!hadAttrBuffer || m_rnd.getFloat() < m_probabilities.reuploadWithBufferData)
						attrBuf.setData(programResources.attrDataBuf, target, m_rnd.getFloat() < m_probabilities.randomBufferUsage ? randomBufferUsage(m_rnd, m_isGLES3) : m_attrBufferUsage);
					else
						attrBuf.setSubData(programResources.attrDataBuf, 0, (int)programResources.attrDataBuf.size(), target);
				}

				if (redundantBufferNdx == usedRedundantBufferNdx)
				{
					for (int i = 0; i < (int)programContext.attributes.size(); i++)
						program.setAttribute(attrBuf, programResources.attrDataOffsets[i], programContext.attributes[i], programResources.shaderNameManglingSuffix);
				}
			}
		}
	}
	else
	{
		for (int i = 0; i < (int)programContext.attributes.size(); i++)
			program.setAttributeClientMem(&programResources.attrDataBuf[programResources.attrDataOffsets[i]], programContext.attributes[i], programResources.shaderNameManglingSuffix);
	}

	// Draw.

	glViewport(0, 0, renderWidth, renderHeight);

	glClearDepthf(1.0f);
	glClear(GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	for (int i = 0; i < m_numDrawCallsPerIteration; i++)
	{
		program.use();
		program.setRandomUniforms(programContext.uniforms, programResources.shaderNameManglingSuffix, m_rnd);

		if (useDrawArrays)
			glDrawArrays(GL_TRIANGLE_STRIP, 0, m_numVerticesPerDrawCall);
		else
		{
			if (useClientMemoryIndexData)
			{
				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
				glDrawElements(GL_TRIANGLE_STRIP, m_numVerticesPerDrawCall, GL_UNSIGNED_SHORT, &m_vertexIndices[0]);
			}
			else
			{
				m_buffers->get(indexBufferName).bind(GL_ELEMENT_ARRAY_BUFFER);
				glDrawElements(GL_TRIANGLE_STRIP, m_numVerticesPerDrawCall, GL_UNSIGNED_SHORT, DE_NULL);
			}
		}
	}

	for(int i = 0; i < (int)programContext.attributes.size(); i++)
		program.disableAttributeArray(programContext.attributes[i], programResources.shaderNameManglingSuffix);

	if (m_showDebugInfo)
		m_debugInfoRenderer->drawInfo(deGetTime()-m_startTimeSeconds, m_textures->computeApproxMemUsage(), m_maxTexMemoryUsageBytes, m_buffers->computeApproxMemUsage(), m_maxBufMemoryUsageBytes, m_currentIteration);

	if (m_currentIteration > 0)
	{
		// Log if a certain amount of time has passed since last log entry (or if this is the last iteration).

		const deUint64	loggingIntervalSeconds	= 10;
		const deUint64	time					= deGetTime();
		const deUint64	timeDiff				= time - m_lastLogTime;
		const int		iterDiff				= m_currentIteration - m_lastLogIteration;

		if (timeDiff >= loggingIntervalSeconds || m_currentIteration == m_numIterations-1)
		{
			log << TestLog::Section("LogEntry" + toString(m_currentLogEntryNdx), "Log entry " + toString(m_currentLogEntryNdx))
				<< TestLog::Message << "Time elapsed: " << getTimeStr(time - m_startTimeSeconds) << TestLog::EndMessage
				<< TestLog::Message << "Frame number: " << m_currentIteration << TestLog::EndMessage
				<< TestLog::Message << "Time since last log entry: " << timeDiff << "s" << TestLog::EndMessage
				<< TestLog::Message << "Frames since last log entry: " << iterDiff << TestLog::EndMessage
				<< TestLog::Message << "Average frame time since last log entry: " << de::floatToString((float)timeDiff / (float)iterDiff, 2) << "s" << TestLog::EndMessage
				<< TestLog::Message << "Approximate texture memory usage: "
									<< de::floatToString((float)m_textures->computeApproxMemUsage() / Mi, 2) << " MiB / "
									<< de::floatToString((float)m_maxTexMemoryUsageBytes / Mi, 2) << " MiB"
									<< TestLog::EndMessage
				<< TestLog::Message << "Approximate buffer memory usage: "
										<< de::floatToString((float)m_buffers->computeApproxMemUsage() / Mi, 2) << " MiB / "
										<< de::floatToString((float)m_maxBufMemoryUsageBytes / Mi, 2) << " MiB"
										<< TestLog::EndMessage
				<< TestLog::EndSection;

			m_lastLogTime		= time;
			m_lastLogIteration	= m_currentIteration;
			m_currentLogEntryNdx++;
		}
	}

	// Possibly remove or set-as-garbage some objects, depending on given probabilities.

	for (int texNdx = 0; texNdx < (int)programContext.textureSpecs.size(); texNdx++)
	{
		const string texName = textureNamePrefix + toString(texNdx);
		if (m_rnd.getFloat() < m_probabilities.deleteTexture)
			m_textures->remove(texName);
		else if (m_rnd.getFloat() < m_probabilities.wastefulTextureMemoryUsage)
			m_textures->markAsGarbage(texName);

	}

	if (m_buffers->has(indexBufferName))
	{
		if (m_rnd.getFloat() < m_probabilities.deleteBuffer)
			m_buffers->remove(indexBufferName);
		else if (m_rnd.getFloat() < m_probabilities.wastefulBufferMemoryUsage)
			m_buffers->markAsGarbage(indexBufferName);

	}

	if (separateAttributeBuffers)
	{
		for (int attrNdx = 0; attrNdx < (int)programContext.attributes.size(); attrNdx++)
		{
			const string curAttrBufNamePrefix = separateAttrBufNamePrefix + toString(attrNdx) + "_";

			if (m_buffers->has(curAttrBufNamePrefix + "0"))
			{
				if (m_rnd.getFloat() < m_probabilities.deleteBuffer)
				{
					for (int i = 0; i < m_redundantBufferFactor; i++)
						m_buffers->remove(curAttrBufNamePrefix + toString(i));
				}
				else if (m_rnd.getFloat() < m_probabilities.wastefulBufferMemoryUsage)
				{
					for (int i = 0; i < m_redundantBufferFactor; i++)
						m_buffers->markAsGarbage(curAttrBufNamePrefix + toString(i));
				}
			}
		}
	}
	else
	{
		if (m_buffers->has(unitedAttrBufferNamePrefix + "0"))
		{
			if (m_rnd.getFloat() < m_probabilities.deleteBuffer)
			{
				for (int i = 0; i < m_redundantBufferFactor; i++)
					m_buffers->remove(unitedAttrBufferNamePrefix + toString(i));
			}
			else if (m_rnd.getFloat() < m_probabilities.wastefulBufferMemoryUsage)
			{
				for (int i = 0; i < m_redundantBufferFactor; i++)
					m_buffers->markAsGarbage(unitedAttrBufferNamePrefix + toString(i));
			}
		}
	}

	GLU_CHECK_MSG("End of LongStressCase::iterate()");

	m_currentIteration++;
	if (m_currentIteration == m_numIterations)
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Passed");
		return STOP;
	}
	else
		return CONTINUE;
}

} // gls
} // deqp
